How to save frames to a JPEG file in deepstream_app.c ?

Is there a C example for saving images to disk instead of Cpp ? I tried modifying the deepstream_app.c to save JPEG, but I get an image with white pixels(see attached). What am I doing wrong here ?

I am running this on NVIDIA Xavier with a CSI Camera

int write_jpeg_file( char *filename, unsigned char* rgb_image , int width, int height, int bytes_per_pixel, J_COLOR_SPACE color_space )
{

	struct jpeg_compress_struct cinfo;
	struct jpeg_error_mgr jerr;
	
	JSAMPROW row_pointer[1];
	FILE *outfile = fopen( filename, "wb" );
	
	if ( !outfile )
	{
		printf("Error opening output jpeg file %s\n!", filename );
		return -1;
	}
	cinfo.err = jpeg_std_error( &jerr );
	jpeg_create_compress(&cinfo);
	jpeg_stdio_dest(&cinfo, outfile);

	cinfo.image_width = width;	
	cinfo.image_height = height;
	cinfo.input_components = bytes_per_pixel;
	cinfo.in_color_space = color_space; //JCS_RGB

	jpeg_set_defaults( &cinfo );

	jpeg_start_compress( &cinfo, TRUE );

	while( cinfo.next_scanline < cinfo.image_height )
	{
		row_pointer[0] = &rgb_image[ cinfo.next_scanline * cinfo.image_width *  cinfo.input_components];
		jpeg_write_scanlines( &cinfo, row_pointer, 1 );
	}

	jpeg_finish_compress( &cinfo );
	jpeg_destroy_compress( &cinfo );
	fclose( outfile );

	return 1;
}

/**
 * Function which processes the inferred buffer and its metadata.
 * It also gives opportunity to attach application specific
 * metadata (e.g. clock, analytics output etc.).
 */

static void
process_buffer (GstBuffer * buf, AppCtx * appCtx, guint index)
{
  NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta (buf);

  NvDsMetaList *l_frame = NULL;
  NvDsMetaList *l_obj = NULL;
  NvDsMetaList * l_user_meta = NULL;
  NvDsDisplayMeta *display_meta = NULL;
  NvDsObjectMeta *obj_meta = NULL;

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

    int imgpix=0;
    int txtstep;
    unsigned char *totalpix;
    char *totalpix1;
    unsigned int *totalpix2;
    long unsigned int *totalpix3;

    //g_print("loaded surface");

if (!batch_meta) {
    NVGSTDS_WARN_MSG_V ("Batch meta not found for buffer %p", buf);
    return;
  }
  process_meta (appCtx, batch_meta);
  NvDsInstanceData *data = &appCtx->instance_data[index];
  guint i;

    data->frame_num++;

for (l_frame = batch_meta->frame_meta_list; l_frame != NULL;
       l_frame = l_frame->next)
  {
    NvDsFrameMeta *frame_meta = (NvDsFrameMeta *)(l_frame->data);
    NvDsUserMeta *user_meta = NULL;

    //call this every X frames
    if(data->frame_num % 90 == 0) {

      g_print("saving JPEG now.");
        src_data = (char*) malloc(surface->surfaceList[frame_meta->batch_id].dataSize);
        if(src_data == NULL) {
            g_print("Error: failed to malloc src_data \n");
            continue;
        }

#ifdef PLATFORM_TEGRA
        NvBufSurfaceMap (surface, -1, -1, NVBUF_MAP_READ);
        NvBufSurfacePlaneParams *pParams = &surface->surfaceList[frame_meta->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[frame_meta->batch_id].mappedAddr.addr[num_planes]+h*pParams->pitch[num_planes]),
                    pParams->bytesPerPix[num_planes]*pParams->width[num_planes]
                    );
            }
        }
        NvBufSurfaceSyncForDevice (surface, -1, -1);
        NvBufSurfaceUnMap (surface, -1, -1);
#else
        cudaMemcpy((void*)src_data,
                   (void*)surface->surfaceList[frame_meta->batch_id].dataPtr,
                   surface->surfaceList[frame_meta->batch_id].dataSize,
                   cudaMemcpyDeviceToHost);
#endif  

        char filename[200];
        uint32_t frame_width  =  surface->surfaceList[frame_meta->batch_id].width;
	      uint32_t frame_height =  surface->surfaceList[frame_meta->batch_id].height;
      	uint32_t Y_stride     =  surface->surfaceList[frame_meta->batch_id].pitch;
	      uint32_t buffer_size = surface->surfaceList[frame_meta->batch_id].dataSize;
	      uint32_t est_size = frame_width*frame_height;

        sprintf(filename,"file_y_%dx%d_%ld.jpg",frame_width,frame_height, data->frame_num);
        printf("Buffer size : %d,%d\n", buffer_size,Y_stride);
        printf("Estimated size : %d\n", est_size);
	      printf("frame_width : %d\n", frame_width);
	      printf("frame_height : %d\n", frame_height);
        printf("dataPtr : %p\n", surface->surfaceList[frame_meta->batch_id].dataPtr);
        printf("src_size:%ld\n",sizeof(char));
        printf("totalpix1:%ld\n",sizeof(unsigned char));
        printf("totalpix2:%ld\n",sizeof(unsigned int));
        printf("totalpix3:%ld\n",sizeof(long unsigned int));

        totalpix=src_data;
        printf("!%ln!",(long unsigned int*) src_data);
        printf("-%ln-",(long unsigned int*) src_data);
        printf("=%s=",(char*) src_data);
        sprintf(filename,"file_y_%dx%d_%d.jpg",frame_width,frame_height,outnumber);

        write_jpeg_file( filename, src_data , frame_width, frame_height, 1, JCS_GRAYSCALE );

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

/* Opportunity to modify the processed metadata or do analytics based on
   * type of object e.g. maintaining count of particular type of car.
   */
  if (appCtx->all_bbox_generated_cb) {
    appCtx->all_bbox_generated_cb (appCtx, buf, batch_meta, index);
  }
  //data->bbox_list_size = 0;

  /*
   * callback to attach application specific additional metadata.
   */
  if (appCtx->overlay_graphics_cb) {
    appCtx->overlay_graphics_cb (appCtx, buf, batch_meta, index);
  }
}

I was able to solve this problem by referring to this post - https://devtalk.nvidia.com/default/topic/1061985/deepstream-sdk/depstream-decoded-data/post/5379066/#5379066

Instead of modifying the deepstream_app.c, I used the gst_dsexample plugin, modified the code in gstdsexample.cpp and it worked.