On JetsonNX, a segmentation fault occurred when using NvBufSurfTransform!

Hello, my program uses DeepStream5.0 to process live video on JetsonNX devices. I need to do object detection on the video and save the full image with the detection box. When I saved the image, I found that the color format is NVBUF_COLOR_FORMAT_NV12_709_ER. So I need to convert colorFormat to RGBA first, and then save it as JPG via OpenCV. But a segmentation fault occurred when I converted the color format using NvBufSurfTransform. This segmentation fault may have occurred during the NvBufSurfTransform or for some other reason, I’m not sure. Please help me. Thank you very much.
Here is the code snippet:

NvDsMetaList *l_frame = NULL;
NvDsMetaList *l_obj = NULL;
//NvDsMetaList *l_usr_meta = NULL;
NvDsObjectMeta *obj_meta = NULL;

// Get original raw data
GstMapInfo in_map_info = GST_MAP_INFO_INIT;
if (!gst_buffer_map(buf, &in_map_info, GST_MAP_READ)) {
    g_print ("Error: Failed to map gst buffer\n");
    return;
}
NvBufSurface *surface = (NvBufSurface *)in_map_info.data;
//gst_buffer_unmap (buf, &in_map_info);

uint32_t frame_data_size = 0;
unsigned char* src_data = NULL;
std::vector<cv::Rect> objsRect;

static std::map<uint32_t, std::vector<cv::Rect>> lastObjsRect;

NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf);
for (l_frame = batch_meta->frame_meta_list; l_frame != NULL; l_frame = l_frame->next)
{
    NvDsFrameMeta *frame_meta = (NvDsFrameMeta *)(l_frame->data);
    guint object_num = 0, person_num = 0, train_num = 0;
    
    if (frame_data_size < surface->surfaceList[frame_meta->batch_id].dataSize)
    {
        if (src_data != NULL) {
            std::cout << "test debug src_data size changed!" << std::endl;
            free(src_data);
            src_data = NULL;
        }
        src_data = (unsigned char*)malloc(surface->surfaceList[frame_meta->batch_id].dataSize);
        if (src_data == NULL) {
            g_print("Error: failed to malloc src_data \n");
            return;
        }
        frame_data_size = surface->surfaceList[frame_meta->batch_id].dataSize;
    }
    memset(src_data, 0, frame_data_size);
    printf("frame_data_size = %d \n", frame_data_size);
    
  // add object bbox in objsRect
  ...
  
    gint frame_width = (gint)surface->surfaceList[frame_meta->batch_id].width;
    gint frame_height = (gint)surface->surfaceList[frame_meta->batch_id].height;
    gint frame_step = surface->surfaceList[frame_meta->batch_id].pitch;
    gint color_format = surface->surfaceList[frame_meta->batch_id].colorFormat;

    uint source_id = frame_meta->source_id;
    uint32_t batch_size = surface->batchSize;
    uint batch_id = frame_meta->batch_id;
    printf("\nbatch_id = %d, batch_size = %d \n", batch_id, batch_size);

    if (color_format != NVBUF_COLOR_FORMAT_NV12 && color_format != NVBUF_COLOR_FORMAT_RGBA)
    {
  	    static int loop = 0;
  	    // transform NVBUF_COLOR_FORMAT_NV12_709_ER or NVBUF_COLOR_FORMAT_NV12_709 colorFormat
        NvBufSurfTransformRect src_rect, dst_rect;
        NvBufSurfTransformParams nvbufsurface_params;
        NvBufSurface *dst_surface = NULL;
        NvBufSurfaceCreateParams nvbufsurface_create_params;
        cudaError_t cuda_err;
        cudaStream_t cuda_stream;
        gint create_result;
        NvBufSurfTransformConfigParams transform_config_params;
        NvBufSurfTransform_Error err;
        cv::Mat bgr_frame, in_mat;

        src_rect.top   = 0;
        src_rect.left  = 0;
        src_rect.width = (guint) surface->surfaceList[batch_id].width;
        src_rect.height = (guint) surface->surfaceList[batch_id].height;

        dst_rect.top   = 0;
        dst_rect.left  = 0;
        dst_rect.width = (guint) surface->surfaceList[batch_id].width;
        dst_rect.height = (guint) surface->surfaceList[batch_id].height;

        nvbufsurface_params.src_rect = &src_rect;
        nvbufsurface_params.dst_rect = &dst_rect;
        nvbufsurface_params.transform_flag =  NVBUFSURF_TRANSFORM_CROP_SRC | NVBUFSURF_TRANSFORM_CROP_DST;
        nvbufsurface_params.transform_filter = NvBufSurfTransformInter_Default;

        nvbufsurface_create_params.gpuId  = surface->gpuId;
        nvbufsurface_create_params.width  = (guint) surface->surfaceList[batch_id].width;
        nvbufsurface_create_params.height = (guint) surface->surfaceList[batch_id].height;
        nvbufsurface_create_params.size = 0;
        nvbufsurface_create_params.isContiguous = true;
        nvbufsurface_create_params.colorFormat = NVBUF_COLOR_FORMAT_RGBA;
        nvbufsurface_create_params.layout = NVBUF_LAYOUT_PITCH;

        // THE memType PARAM IS SET TO CUDA UNIFIED IN dGPU DEVICES COMMENT IT out
        // AND USE THE IMMEDIATE NEXT LINE TO SET THE memType PARAM FOR JETSON DEVICES
    #ifdef PLATFORM_TEGRA
        nvbufsurface_create_params.memType = NVBUF_MEM_DEFAULT;
    #else
        nvbufsurface_create_params.memType = NVBUF_MEM_CUDA_UNIFIED;
    #endif
        cuda_err = cudaSetDevice (surface->gpuId);
        cuda_err = cudaStreamCreate(&cuda_stream);
        create_result = NvBufSurfaceCreate(&dst_surface, batch_size, &nvbufsurface_create_params);
        if (create_result) {
            GST_ERROR_OBJECT (nullptr, "NvBufSurfaceCreate failed.\n");
        }

        transform_config_params.compute_mode = NvBufSurfTransformCompute_Default;
        transform_config_params.gpu_id = surface->gpuId;
        transform_config_params.cuda_stream = cuda_stream;
        err = NvBufSurfTransformSetSessionParams (&transform_config_params);

        NvBufSurfaceMemSet (dst_surface, batch_id, -1, 0);
  	    printf("src_color_format: %d, dst_color_format: %d, gpu_id: %d, datasize: %d, %dx%d, pitch: %d, num_planes: %d, loop: %d \n",
               surface->surfaceList[batch_id].colorFormat, dst_surface->surfaceList[batch_id].colorFormat, surface->gpuId,
               surface->surfaceList->dataSize, surface->surfaceList->width, surface->surfaceList->height,
               surface->surfaceList->pitch, surface->surfaceList->planeParams.num_planes, loop++);
  		   
        err = NvBufSurfTransform (surface, dst_surface, &nvbufsurface_params);
        if (err != NvBufSurfTransformError_Success) {
           g_print ("NvBufSurfTransform failed with error %d while converting buffer\n", err);
        }
        else {
            printf("NvBufSurfTransform ok.\n");
        }

 #ifdef PLATFORM_TEGRA
  	    NvBufSurfaceMap(dst_surface/*surface*/, batch_id, -1, NVBUF_MAP_READ);
  	    NvBufSurfacePlaneParams *pParams = &dst_surface->surfaceList[batch_id].planeParams;
  	    unsigned int offset = 0;
  	    for (unsigned int num_planes=0; num_planes < pParams->num_planes; num_planes++) {
  		    if (num_planes>0)
  			    offset += pParams->height[num_planes-1]*(pParams->bytesPerPix[num_planes-1]*pParams->width[num_planes-1]);
  		    for (unsigned int h = 0; h < pParams->height[num_planes]; h++) {
  			    memcpy((void *)(src_data+offset+h*pParams->bytesPerPix[num_planes]*pParams->width[num_planes]),
  				    (void *)((char *)dst_surface->surfaceList[batch_id].mappedAddr.addr[num_planes]+h*pParams->pitch[num_planes]),
  				pParams->bytesPerPix[num_planes]*pParams->width[num_planes]);
  		    }
  	    }
  	    printf("debug0: ----------- \n");
  	    NvBufSurfaceSyncForDevice(dst_surface, batch_id, -1);
  	    NvBufSurfaceUnMap(dst_surface, batch_id, -1);
#endif

        color_format = dst_surface->surfaceList[batch_id].colorFormat;
        if (color_fmt == NVBUF_COLOR_FORMAT_NV12)
            printf("test_color_format: NVBUF_COLOR_FORMAT_NV12 \n");
        else if (color_fmt == NVBUF_COLOR_FORMAT_NV12_ER)
            printf("test_color_format: NVBUF_COLOR_FORMAT_NV12_ER \n");
        else if (color_fmt == NVBUF_COLOR_FORMAT_NV12_709)
            printf("test_color_format: NVBUF_COLOR_FORMAT_NV12_709 \n");
        else if (color_fmt == NVBUF_COLOR_FORMAT_NV12_709_ER)
            printf("test_color_format: NVBUF_COLOR_FORMAT_NV12_709_ER \n");
        else if (color_fmt == NVBUF_COLOR_FORMAT_RGBA)
            printf("test_color_format: NVBUF_COLOR_FORMAT_RGBA \n");
        else
            printf("test_color_format: other: %d \n", color_fmt);

  	    printf("debug1: ----------- \n");
        NvBufSurfaceDestroy(dst_surface);
        cudaStreamDestroy (cuda_stream);
  	    printf("debug2: ----------- \n");
    }
    else
    {
#ifdef PLATFORM_TEGRA
  	    NvBufSurfaceMap(surface, batch_id, -1, NVBUF_MAP_READ);
  	    NvBufSurfacePlaneParams *pParams = &surface->surfaceList[batch_id].planeParams;
  	    unsigned int offset = 0;
  	    for (unsigned int num_planes=0; num_planes < pParams->num_planes; num_planes++) {
  		    if (num_planes>0)
  			    offset += pParams->height[num_planes-1]*(pParams->bytesPerPix[num_planes-1]*pParams->width[num_planes-1]);
  		    for (unsigned int h = 0; h < pParams->height[num_planes]; h++) {
  			    memcpy((void *)(src_data+offset+h*pParams->bytesPerPix[num_planes]*pParams->width[num_planes]),
  				    (void *)((char *)surface->surfaceList[batch_id].mappedAddr.addr[num_planes]+h*pParams->pitch[num_planes]),
  				    pParams->bytesPerPix[num_planes]*pParams->width[num_planes]);
  		    }
  	    }
  	    NvBufSurfaceSyncForDevice(surface, batch_id, -1);
  	    NvBufSurfaceUnMap(surface, batch_id, -1);
  	    printf("debug2-2: ----------- \n");
 #endif
    }

    cv::Mat frame;
    cv::Mat out_mat = cv::Mat(cv::Size(frame_width, frame_height), CV_8UC3);
    switch (color_format)
    {
    case NVBUF_COLOR_FORMAT_NV12:
        frame = cv::Mat(frame_height * 3 / 2, frame_width, CV_8UC1, src_data, frame_step);
        cv::cvtColor(frame, out_mat, CV_YUV2BGR_NV12);
        break;
    case NVBUF_COLOR_FORMAT_RGBA:
        frame = cv::Mat(frame_height, frame_width, CV_8UC4, src_data, frame_step);
        cv::cvtColor(frame, out_mat, CV_RGBA2BGR);
        break;
    default:
        std::cout << "warning: color_format = " << color_format << std::endl;
        break;
    }
    
    printf("debug3: ----------- \n");
    for (uint i = 0; i < objsRect.size(); ++i)
    {
        cv::rectangle(out_mat, objsRect[i], cv::Scalar(0,255,0), 1);
    }
    printf("debug4: ----------- \n");

    char filePath[FILE_NAME_SIZE] = {0};
    snprintf((char*)filePath, FILE_NAME_SIZE, "./srci_%d_%d.jpg", source_id, batch_id);
    cv::Mat tmp_mat = out_mat.clone();
    cv::imwrite(filePath, tmp_mat);
    printf("debug5: ----------- \n");
}

if (src_data != NULL) {
    free(src_data);
    src_data = NULL;
}
gst_buffer_unmap (buf, &in_map_info);

• Hardware Platform:Jetson NX
• DeepStream: 5.0
• JetPack Version: 4.4

Here is the configuration file information:

[application]
enable-perf-measurement=1
perf-measurement-interval-sec=5
#gie-kitti-output-dir=streamscl

[tiled-display]
enable=1
rows=3
columns=2
width=1280
height=720
gpu-id=0
nvbuf-memory-type=0

[source0]
enable=1
## Type: 1=CameraV4L2 2=URI 3=MultiURI
type=3
uri=rtsp://admin:******@xx.xx.xx.xx/h264/ch1/main/av_stream
num-sources=4
camera-id=0
gpu-id=0
cudadec-memtype=0

[sink0]
enable=1
## Type: 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming
type=2
sync=0
source-id=0
gpu-id=0
nvbuf-memory-type=0

[sink1]
enable=1
## Type: 1=FakeSink 2=EglSink 3=File 4=RTSPStreaming
type=4
rtsp-port=8554
udp-port=5400
sync=0
source-id=0
gpu-id=0
nvbuf-memory-type=0
## 1=h264 2=h265
codec=1

[osd]
enable=1
gpu-id=0
border-width=1
text-size=12
text-color=1;1;1;1;
text-bg-color=0.3;0.3;0.3;1
font=Serif
show-clock=0
clock-x-offset=800
clock-y-offset=820
clock-text-size=12
clock-color=1;0;0;0
nvbuf-memory-type=0

[streammux]
gpu-id=0
live-source=0
batch-size=8
batched-push-timeout=40000
width=1920
height=1080
enable-padding=0
nvbuf-memory-type=0

[primary-gie]
enable=1
gpu-id=0
model-engine-file=yolov5s-zj.engine
labelfile-path=labels.txt
batch-size=8
#Required by the app for OSD, not a plugin property
bbox-border-color0=1;0;0;1
bbox-border-color1=0;1;1;1
bbox-border-color2=0;0;1;1
bbox-border-color3=0;1;0;1
interval=0
gie-unique-id=1
nvbuf-memory-type=0
config-file=config_infer_primary_yoloV5.txt

[tracker]
enable=1
gpu-id=0
tracker-width=960
tracker-height=540
ll-lib-file=/opt/nvidia/deepstream/deepstream-5.0/lib/libnvds_mot_klt.so
display-tracking-id=1

[nvds-analytics]
enable=1
config-file=config_nvdsanalytics.txt

[tests]
file-loop=0

The following is the exception information:

When I comment out the code for saving the image at the end of above code, the segment fault appears to occur a few lines later, and NvBufSurfTransform seems to have executed successfully, but the commented out code has nothing to do with the color transform. I am not sure whether it is an internal GPU error, or is it related to data synchronization between GPU and CPU?

The following is the error output after commenting out the imwrite code:
segment-2

Please upgrade to latest DeepStream SDK 6.0.

There is already NvBufSurfTransform and opencv sample in
/opt/nvidia/deepstream/deepstream/sources/gst-plugins/gst-dsexample

But is the above problem a bug of deepstream5.0 ? Is there no solution?

The older version deepstream is not supported now. Please use latest deepstream.