Request for Assistance in Improving Output Render Quality

Please provide complete information as applicable to your setup.

• Hardware Platform (Jetson Orin NX)
• DeepStream Version: 7.0

I am currently working with a code that performs various operations like cropping, resizing, denoising, and sharpening on video frames. While the code itself is functioning correctly and processing the frames as expected, the output render does not appear as visually appealing as I had hoped.

Could you kindly help me identify the potential cause of this issue , Your assistance in resolving this would be greatly appreciated. Here I attaching my code and output.

#include <gst/gst.h>

#include <opencv2/opencv.hpp>

#include <cuda_runtime.h>

#include "gstnvdsmeta.h"

#include "nvdsmeta.h"

static GstPadProbeReturn nvvidconv_src_pad_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) {
    GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER(info);
    if (!buf) {
        g_print("No buffer found.\n");
        return GST_PAD_PROBE_OK;
    }

    GstMapInfo inmap = GST_MAP_INFO_INIT;
    if (!gst_buffer_map(buf, &inmap, GST_MAP_READWRITE)) {
        g_print("Failed to map buffer.\n");
        return GST_PAD_PROBE_OK;
    }

    NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf);
    if (!batch_meta) {
        g_print("No batch meta found.\n");
        gst_buffer_unmap(buf, &inmap);
        return GST_PAD_PROBE_OK;
    }

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

        guint width = frame_meta->source_frame_width;
        guint height = frame_meta->source_frame_height;

        if (width == 0 || height == 0) {
            g_print("Invalid frame dimensions: %d x %d\n", width, height);
            continue;
        }

        // Convert NV12 to BGR
        cv::Mat nv12_mat(height * 3 / 2, width, CV_8UC1, inmap.data);
        cv::Mat bgr_frame;
        cv::cvtColor(nv12_mat, bgr_frame, cv::COLOR_YUV2BGR_NV12);

        // Define cropping parameters
        int x = 300, y = 300;
        int crop_width = 60, crop_height = 60;

        int x_start = std::max(0, x - crop_width / 2);
        int y_start = std::max(0, y - crop_height / 2);
        guint x_end = std::min((guint)width, (guint)(x + crop_width / 2));
        guint y_end = std::min((guint)height, (guint)(y + crop_height / 2));

        int crop_width_actual = x_end - x_start;
        int crop_height_actual = y_end - y_start;
        crop_width_actual = std::min(crop_width_actual, crop_width);
        crop_height_actual = std::min(crop_height_actual, crop_height);

        // Perform the cropping operation
        cv::Rect crop_roi(x_start, y_start, crop_width_actual, crop_height_actual);
        cv::Mat cropped_frame = bgr_frame(crop_roi);

        // Resize the cropped frame
        cv::Mat resized_frame;
        cv::resize(cropped_frame, resized_frame, cv::Size(cropped_frame.cols * 2, cropped_frame.rows * 2), 0, 0, cv::INTER_CUBIC);

        // Denoise the resized frame
        //cv::fastNlMeansDenoising(resized_frame, resized_frame, 7, 7, 21);

        // Apply sharpening kernel
        cv::Mat sharpening_kernel = (cv::Mat_<float>(3, 3) << 
            0, -1, 0, 
            -1, 5, -1, 
            0, -1, 0);
        cv::filter2D(resized_frame, resized_frame, -1, sharpening_kernel);

        // Draw a red boundary around the resized frame
        cv::rectangle(resized_frame, cv::Point(0, 0), cv::Point(resized_frame.cols, resized_frame.rows), cv::Scalar(0, 0, 255), 4);

        // Overlay the resized frame back onto the original frame
        int overlay_x = std::max(0, x_start);  // Ensure overlay starts within frame
        int overlay_y = std::max(0, y_start);

        int overlay_width = std::min(resized_frame.cols, bgr_frame.cols - overlay_x);
        int overlay_height = std::min(resized_frame.rows, bgr_frame.rows - overlay_y);

        if (overlay_width > 0 && overlay_height > 0) {
            resized_frame(cv::Rect(0, 0, overlay_width, overlay_height))
                .copyTo(bgr_frame(cv::Rect(overlay_x, overlay_y, overlay_width, overlay_height)));
        }

        // Convert the final frame back to NV12
         cv::Mat nv12_converted;
         cv::cvtColor(bgr_frame, nv12_converted, cv::COLOR_BGR2YUV_YV12);
         memcpy(inmap.data, nv12_converted.data, nv12_converted.total());
    }

    gst_buffer_unmap(buf, &inmap);
    return GST_PAD_PROBE_OK;
}

static gboolean
bus_call (GstBus * bus, GstMessage * msg, gpointer data)
{
  GMainLoop *loop = (GMainLoop *) data;
  switch (GST_MESSAGE_TYPE (msg)) {
    case GST_MESSAGE_EOS:
      g_print ("End of stream\n");
      g_main_loop_quit (loop);
      break;
    case GST_MESSAGE_ERROR:{
      gchar *debug;
      GError *error;
      gst_message_parse_error (msg, &error, &debug);
      g_printerr ("ERROR from element %s: %s\n",
          GST_OBJECT_NAME (msg->src), error->message);
      if (debug)
        g_printerr ("Error details: %s\n", debug);
      g_free (debug);
      g_error_free (error);
      g_main_loop_quit (loop);
      break;
    }
    default:
      break;
  }
  return TRUE;
}

int main(int argc, char *argv[]) {
    GMainLoop *loop = NULL;
    GstElement *pipeline = NULL, *source = NULL, *h264parser = NULL, *decoder = NULL,
        *streammux = NULL, *sink = NULL, *nvvidconv = NULL, *nvosd = NULL, *capsfilter = NULL;

  GstBus *bus = NULL;
  guint bus_watch_id;
  GstPad *nvvidconv_sink_pad = NULL;
  gboolean yaml_config = FALSE;
  //NvDsGieType pgie_type = NVDS_GIE_PLUGIN_INFER;

  int current_device = -1;
  cudaGetDevice(&current_device);
  struct cudaDeviceProp prop;
  cudaGetDeviceProperties(&prop, current_device);

  if (argc != 2) {
      g_printerr("Usage: %s <yml file>\n", argv[0]);
      g_printerr("OR: %s <H264 filename>\n", argv[0]);
      return -1;
  }

  gst_init(&argc, &argv);
  loop = g_main_loop_new(NULL, FALSE);

  yaml_config = (g_str_has_suffix(argv[1], ".yml") ||
                 g_str_has_suffix(argv[1], ".yaml"));

  pipeline = gst_pipeline_new("dstest1-pipeline");

  source = gst_element_factory_make("filesrc", "file-source");
  h264parser = gst_element_factory_make("h264parse", "h264-parser");
  decoder = gst_element_factory_make("nvv4l2decoder", "nvv4l2-decoder");
  streammux = gst_element_factory_make("nvstreammux", "stream-muxer");

  nvvidconv = gst_element_factory_make("nvvideoconvert", "nvvideo-converter");
  nvosd = gst_element_factory_make("nvdsosd", "nv-onscreendisplay");
  capsfilter = gst_element_factory_make("capsfilter", "filter");
  g_object_set(G_OBJECT(capsfilter), "caps", gst_caps_from_string("video/x-raw"), NULL);

  if (prop.integrated) {
      sink = gst_element_factory_make("nv3dsink", "nv3d-sink");
  } else {
      sink = gst_element_factory_make("nv3dsink", "nvvideo-renderer");
  }

  if (!source || !h264parser || !decoder || !nvvidconv ||  !sink || !capsfilter) {
      g_printerr("One element could not be created. Exiting.\n");
      return -1;
  }

  g_object_set(G_OBJECT(source), "location", argv[1], NULL);
  g_object_set(G_OBJECT(streammux), "batch-size", 1, NULL);
  g_object_set(G_OBJECT(streammux), "width", 1280, "height", 720, "batched-push-timeout", 4000000, NULL);

  bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
  bus_watch_id = gst_bus_add_watch(bus, bus_call, loop);
  gst_object_unref(bus);

  gst_bin_add_many(GST_BIN(pipeline), source, h264parser, decoder, streammux, nvosd,nvvidconv, capsfilter, sink, NULL);

  GstPad *sinkpad, *srcpad;
  gchar pad_name_sink[16] = "sink_0";
  gchar pad_name_src[16] = "src";

  sinkpad = gst_element_request_pad_simple(streammux, pad_name_sink);
  if (!sinkpad) {
      g_printerr("Streammux request sink pad failed. Exiting.\n");
      return -1;
  }

  srcpad = gst_element_get_static_pad(decoder, pad_name_src);
  if (!srcpad) {
      g_printerr("Decoder request src pad failed. Exiting.\n");
      return -1;
  }

  if (gst_pad_link(srcpad, sinkpad) != GST_PAD_LINK_OK) {
      g_printerr("Failed to link decoder to stream muxer. Exiting.\n");
      return -1;
  }

  gst_object_unref(sinkpad);
  gst_object_unref(srcpad);

  if (!gst_element_link_many(source, h264parser, decoder, NULL)) {
      g_printerr("Elements could not be linked: 1. Exiting.\n");
      return -1;
  }

  // Adjusted pipeline linking order with probe at nvvidconv
  if (!gst_element_link_many(streammux, nvosd,nvvidconv, capsfilter, sink, NULL)) {
      g_printerr("Elements could not be linked: 2. Exiting.\n");
      return -1;
  }

  // Add probe to nvvidconv's source pad
  nvvidconv_sink_pad = gst_element_get_static_pad(nvvidconv, "src");
  if (nvvidconv_sink_pad) {
      gst_pad_add_probe(nvvidconv_sink_pad, GST_PAD_PROBE_TYPE_BUFFER, nvvidconv_src_pad_buffer_probe, NULL, NULL);
      gst_object_unref(nvvidconv_sink_pad);
  }

  gst_element_set_state(pipeline, GST_STATE_PLAYING);
  g_main_loop_run(loop);

  gst_element_set_state(pipeline, GST_STATE_NULL);
  gst_object_unref(GST_OBJECT(pipeline));
  g_source_remove(bus_watch_id);
  g_main_loop_unref(loop);

  return 0;
  }

Output of streaming:

Thank you in advance for your time and support.

Best regards,
Abdul Manaf PV

please refer to this topic for how to dump nv12 on Jetson.

Sorry, i didnt understand anything can you help me where in my code i want to change and edit

On jetson, y data and uv data are not continuous. you can copy the y,uv data separately to one buffer. please read the comment on
Jun 14 in the topic above.

when I update my code to this method(y data and uv data are not continuous. you can copy the y,uv data separately to one buffer)but my output is not good, here i attach my update code

static GstPadProbeReturn nvvidconv_src_pad_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) {
    GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER(info);
    if (!buf) {
        g_print("No buffer found.\n");
        return GST_PAD_PROBE_OK;
    }

    GstMapInfo inmap = GST_MAP_INFO_INIT;
    if (!gst_buffer_map(buf, &inmap, GST_MAP_READWRITE)) {
        g_print("Failed to map buffer.\n");
        return GST_PAD_PROBE_OK;
    }

    NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf);
    if (!batch_meta) {
        g_print("No batch meta found.\n");
        gst_buffer_unmap(buf, &inmap);
        return GST_PAD_PROBE_OK;
    }

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

        guint width = frame_meta->source_frame_width;
        guint height = frame_meta->source_frame_height;

        if (width == 0 || height == 0) {
            g_print("Invalid frame dimensions: %d x %d\n", width, height);
            continue;
        }

        // NV12 format has Y plane followed by UV plane
        cv::Mat y_plane(height, width, CV_8UC1, inmap.data);  // Y plane
        cv::Mat uv_plane(height / 2, width, CV_8UC2, inmap.data + height * width);  // UV plane (interleaved U+V)

        // Convert Y and UV separately to BGR
        cv::Mat bgr_frame;
        cv::cvtColor(y_plane, bgr_frame, cv::COLOR_YUV2BGR_NV12, 3);

        // Define cropping parameters
        int x = 300, y = 300;
        int crop_width = 60, crop_height = 60;

        int x_start = std::max(0, x - crop_width / 2);
        int y_start = std::max(0, y - crop_height / 2);
        guint x_end = std::min((guint)width, (guint)(x + crop_width / 2));
        guint y_end = std::min((guint)height, (guint)(y + crop_height / 2));

        int crop_width_actual = x_end - x_start;
        int crop_height_actual = y_end - y_start;
        crop_width_actual = std::min(crop_width_actual, crop_width);
        crop_height_actual = std::min(crop_height_actual, crop_height);

        // Perform the cropping operation
        cv::Rect crop_roi(x_start, y_start, crop_width_actual, crop_height_actual);
        cv::Mat cropped_frame = bgr_frame(crop_roi);

        // Resize the cropped frame
        cv::Mat resized_frame;
        cv::resize(cropped_frame, resized_frame, cv::Size(cropped_frame.cols * 2, cropped_frame.rows * 2), 0, 0, cv::INTER_CUBIC);

        // Apply sharpening kernel
        cv::Mat sharpening_kernel = (cv::Mat_<float>(3, 3) << 
            0, -1, 0, 
            -1, 5, -1, 
            0, -1, 0);
        cv::filter2D(resized_frame, resized_frame, -1, sharpening_kernel);

        // Draw a red boundary around the resized frame
        cv::rectangle(resized_frame, cv::Point(0, 0), cv::Point(resized_frame.cols, resized_frame.rows), cv::Scalar(0, 0, 255), 4);

        // Overlay the resized frame back onto the original frame
        int overlay_x = std::max(0, x_start);  // Ensure overlay starts within frame
        int overlay_y = std::max(0, y_start);

        int overlay_width = std::min(resized_frame.cols, bgr_frame.cols - overlay_x);
        int overlay_height = std::min(resized_frame.rows, bgr_frame.rows - overlay_y);

        if (overlay_width > 0 && overlay_height > 0) {
            resized_frame(cv::Rect(0, 0, overlay_width, overlay_height))
                .copyTo(bgr_frame(cv::Rect(overlay_x, overlay_y, overlay_width, overlay_height)));
        }

        // Convert the final frame back to NV12, separately for Y and UV
        cv::Mat nv12_converted(height * 3 / 2, width, CV_8UC1); // NV12 format
        cv::Mat y_out = nv12_converted.rowRange(0, height);
        cv::Mat uv_out = nv12_converted.rowRange(height, height + height / 2);

        // Copy Y data (processed BGR to Y)
        cv::cvtColor(bgr_frame, y_out, cv::COLOR_BGR2YUV_YV12);
        
        // Copy UV data back (note that UV is interleaved)
        uv_out = uv_plane;  // Just copying UV plane directly
        
        // Copy back the final NV12 data into the buffer
        memcpy(inmap.data, nv12_converted.data, nv12_converted.total());
    }

    gst_buffer_unmap(buf, &inmap);
    return GST_PAD_PROBE_OK;
}

This my output when i use this code :

y and uv is not consecutive. please use “mAddr->addr[p]” to access the data pointer. please refer to the ready-made code on Jun 14 in the topic above.

When i update my function like this, i am getting error , now i cant see output, This is my code ,

static GstPadProbeReturn nvvidconv_src_pad_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) {
    GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER(info);
    if (!buf) {
        g_print("No buffer found.\n");
        return GST_PAD_PROBE_OK;
    }

    GstMapInfo inmap = GST_MAP_INFO_INIT;
    if (!gst_buffer_map(buf, &inmap, GST_MAP_READWRITE)) {
        g_print("Failed to map buffer.\n");
        return GST_PAD_PROBE_OK;
    }

    NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf);
    if (!batch_meta) {
        g_print("No batch meta found.\n");
        gst_buffer_unmap(buf, &inmap);
        return GST_PAD_PROBE_OK;
    }

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

        guint width = frame_meta->source_frame_width;
        guint height = frame_meta->source_frame_height;

        if (width == 0 || height == 0) {
            g_print("Invalid frame dimensions: %d x %d\n", width, height);
            continue;
        }

        // Map the surface for CPU access
        NvBufSurface *surface = (NvBufSurface *)inmap.data;
        int ret = NvBufSurfaceMap(surface, -1, -1, NVBUF_MAP_READ);
        if (ret != 0) {
            g_print("Failed to map surface. Error code: %d\n", ret);
            continue;
        }

        // Ensure that the batch_id is valid before accessing the surface
        int batch_id = frame_meta->batch_id;
        if (batch_id < 0 || batch_id >= surface->numFilled) {
            g_print("Invalid batch_id: %d\n", batch_id);
            continue;
        }

        // Access surface list for the specific batch
        NvBufSurfaceParams *params = &surface->surfaceList[batch_id];
        
        // Check surface parameters
        g_print("Surface parameters: pitch = %d, width = %d, height = %d\n", params->pitch, params->width, params->height);

        // Synchronize for CPU access
        NvBufSurfaceSyncForCpu(surface, 0, 0);

        // Dynamically allocate memory for nv12_data if not already allocated
        static char* nv12_data = NULL;
        if (nv12_data == NULL) {
            nv12_data = (char*) malloc(width * height * 3 / 2);
        }
        
        char* pnv12 = nv12_data;
        NvBufSurfaceMappedAddr *mAddr = &(surface->surfaceList[0].mappedAddr);
        NvBufSurfacePlaneParams *planeParams = &(surface->surfaceList[batch_id].planeParams);
        int bs = 0;

        // Extract NV12 data from the surface and write to nv12_data
        for (int p = 0; p < planeParams->num_planes; p++) {
            size_t bytes_to_write = planeParams->bytesPerPix[p] * planeParams->width[p];
            char *data = (char *) mAddr->addr[p];
            for (int j = 0; j < planeParams->height[p]; j++) {
                memcpy(pnv12, data, bytes_to_write);
                data += planeParams->pitch[p];
                pnv12 += bytes_to_write;
            }
        }

        // Create OpenCV Mat from NV12 data
        cv::Mat nv12_mat(height * 3 / 2, width, CV_8UC1, nv12_data);
        
        // Convert NV12 to BGR (using OpenCV)
        cv::Mat bgr_frame;
        cv::cvtColor(nv12_mat, bgr_frame, cv::COLOR_YUV2BGR_NV12);

        // Define cropping parameters (e.g., centered at (x, y) with given crop size)
        int x = 300, y = 300;
        int crop_width = 60, crop_height = 60;

        int x_start = std::max(0, x - crop_width / 2);
        int y_start = std::max(0, y - crop_height / 2);
        guint x_end = std::min((guint)width, (guint)(x + crop_width / 2));
        guint y_end = std::min((guint)height, (guint)(y + crop_height / 2));

        int crop_width_actual = x_end - x_start;
        int crop_height_actual = y_end - y_start;
        crop_width_actual = std::min(crop_width_actual, crop_width);
        crop_height_actual = std::min(crop_height_actual, crop_height);

        // Perform cropping operation using OpenCV
        cv::Rect crop_roi(x_start, y_start, crop_width_actual, crop_height_actual);
        cv::Mat cropped_frame = bgr_frame(crop_roi);

        // Resize the cropped frame
        cv::Mat resized_frame;
        cv::resize(cropped_frame, resized_frame, cv::Size(cropped_frame.cols * 2, cropped_frame.rows * 2), 0, 0, cv::INTER_CUBIC);

        // Apply denoising (Gaussian Blur)
        cv::Mat denoised_frame;
        cv::GaussianBlur(resized_frame, denoised_frame, cv::Size(5, 5), 0);

        // Apply sharpening filter
        cv::Mat sharpening_kernel = (cv::Mat_<float>(3, 3) << 
            0, -1, 0, 
            -1, 5, -1, 
            0, -1, 0);
        cv::filter2D(denoised_frame, denoised_frame, -1, sharpening_kernel);

        // Draw a red boundary around the resized frame
        cv::rectangle(denoised_frame, cv::Point(0, 0), cv::Point(denoised_frame.cols, denoised_frame.rows), cv::Scalar(0, 0, 255), 4);

        // Overlay the resized frame back onto the original frame
        int overlay_x = std::max(0, x_start);  // Ensure overlay starts within frame
        int overlay_y = std::max(0, y_start);

        int overlay_width = std::min(denoised_frame.cols, bgr_frame.cols - overlay_x);
        int overlay_height = std::min(denoised_frame.rows, bgr_frame.rows - overlay_y);

        if (overlay_width > 0 && overlay_height > 0) {
            denoised_frame(cv::Rect(0, 0, overlay_width, overlay_height))
                .copyTo(bgr_frame(cv::Rect(overlay_x, overlay_y, overlay_width, overlay_height)));
        }

        // Convert the final frame back to NV12 using OpenCV
        cv::Mat nv12_converted;
        cv::cvtColor(bgr_frame, nv12_converted, cv::COLOR_BGR2YUV_YV12);

        // Copy the processed data back into the GstBuffer
        memcpy(inmap.data, nv12_converted.data, nv12_converted.total());

        // Unmap the surface
        NvBufSurfaceUnMap(surface, 0, 0);
    }

    gst_buffer_unmap(buf, &inmap);
    return GST_PAD_PROBE_OK;
}

This is the output i am getting :

nvbufsurface: error in mapping
Failed to map surface. Error code: -1
nvbufsurface: mapping of memory type (1970632053) not supported
nvbufsurface: error in mapping
Failed to map surface. Error code: -1
nvbufsurface: mapping of memory type (1970632053) not supported
nvbufsurface: error in mapping
Failed to map surface. Error code: -1
nvbufsurface: mapping of memory type (1970632053) not supported
nvbufsurface: error in mapping
Failed to map surface. Error code: -1
nvbufsurface: mapping of memory type (1970632053) not supported
nvbufsurface: error in mapping
Failed to map surface. Error code: -1
nvbufsurface: mapping of memory type (1970632053) not supported
nvbufsurface: error in mapping
Failed to map surface. Error code: -1
nvbufsurface: mapping of memory type (1970632053) not supported
nvbufsurface: error in mapping
Failed to map surface. Error code: -1
nvbufsurface: mapping of memory type (1970632053) not supported
nvbufsurface: error in mapping
Failed to map surface. Error code: -1
nvbufsurface: mapping of memory type (1953789044) not supported
nvbufsurface: error in mapping
Failed to map surface. Error code: -1

please move NvBufSurfaceMap and NvBufSurfaceSyncForCpu to outside of for loop. please refer to the faq for “Dump NV12 NvBufSurface into a YUV file”.

I am sorry, i didnt understand how to solve my issue till yet, can you help me by correcting my this function:

static GstPadProbeReturn nvvidconv_src_pad_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) {
    GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER(info);
    if (!buf) {
        g_print("No buffer found.\n");
        return GST_PAD_PROBE_OK;
    }

  GstMapInfo inmap = GST_MAP_INFO_INIT;
  if (!gst_buffer_map(buf, &inmap, GST_MAP_READWRITE)) {
      g_print("Failed to map buffer.\n");
      return GST_PAD_PROBE_OK;
  }

  NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf);
  if (!batch_meta) {
      g_print("No batch meta found.\n");
      gst_buffer_unmap(buf, &inmap);
      return GST_PAD_PROBE_OK;
  }

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

      guint width = frame_meta->source_frame_width;
      guint height = frame_meta->source_frame_height;

      if (width == 0 || height == 0) {
          g_print("Invalid frame dimensions: %d x %d\n", width, height);
          continue;
      }

      // Convert NV12 to BGR
      cv::Mat nv12_mat(height * 3 / 2, width, CV_8UC1, inmap.data);
      cv::Mat bgr_frame;
      cv::cvtColor(nv12_mat, bgr_frame, cv::COLOR_YUV2BGR_NV12);

      // Define cropping parameters
      int x = 300, y = 300;
      int crop_width = 60, crop_height = 60;

      int x_start = std::max(0, x - crop_width / 2);
      int y_start = std::max(0, y - crop_height / 2);
      guint x_end = std::min((guint)width, (guint)(x + crop_width / 2));
      guint y_end = std::min((guint)height, (guint)(y + crop_height / 2));

      int crop_width_actual = x_end - x_start;
      int crop_height_actual = y_end - y_start;
      crop_width_actual = std::min(crop_width_actual, crop_width);
      crop_height_actual = std::min(crop_height_actual, crop_height);

      // Perform the cropping operation
      cv::Rect crop_roi(x_start, y_start, crop_width_actual, crop_height_actual);
      cv::Mat cropped_frame = bgr_frame(crop_roi);

      // Resize the cropped frame
      cv::Mat resized_frame;
      cv::resize(cropped_frame, resized_frame, cv::Size(cropped_frame.cols * 2, cropped_frame.rows * 2), 0, 0, cv::INTER_CUBIC);

      // Denoise the resized frame
      //cv::fastNlMeansDenoising(resized_frame, resized_frame, 7, 7, 21);

      // Apply sharpening kernel
      cv::Mat sharpening_kernel = (cv::Mat_<float>(3, 3) << 
          0, -1, 0, 
          -1, 5, -1, 
          0, -1, 0);
      cv::filter2D(resized_frame, resized_frame, -1, sharpening_kernel);

      // Draw a red boundary around the resized frame
      cv::rectangle(resized_frame, cv::Point(0, 0), cv::Point(resized_frame.cols, resized_frame.rows), cv::Scalar(0, 0, 255), 4);

      // Overlay the resized frame back onto the original frame
      int overlay_x = std::max(0, x_start);  // Ensure overlay starts within frame
      int overlay_y = std::max(0, y_start);

      int overlay_width = std::min(resized_frame.cols, bgr_frame.cols - overlay_x);
      int overlay_height = std::min(resized_frame.rows, bgr_frame.rows - overlay_y);

      if (overlay_width > 0 && overlay_height > 0) {
          resized_frame(cv::Rect(0, 0, overlay_width, overlay_height))
              .copyTo(bgr_frame(cv::Rect(overlay_x, overlay_y, overlay_width, overlay_height)));
      }

      // Convert the final frame back to NV12
       cv::Mat nv12_converted;
       cv::cvtColor(bgr_frame, nv12_converted, cv::COLOR_BGR2YUV_YV12);
       memcpy(inmap.data, nv12_converted.data, nv12_converted.total());
  }

  gst_buffer_unmap(buf, &inmap);
  return GST_PAD_PROBE_OK;
 }

When I use this function also, i am getting error

using namespace cv;


static GstPadProbeReturn nvvidconv_src_pad_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer u_data) {
    GstBuffer *buf = GST_PAD_PROBE_INFO_BUFFER(info);
    if (!buf) {
        g_print("No buffer found.\n");
        return GST_PAD_PROBE_OK;
    }

    // Retrieve batch meta data
    NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf);
    if (!batch_meta) {
        g_print("No batch meta found.\n");
        return GST_PAD_PROBE_OK;
    }

    // Map the buffer for reading
    GstMapInfo in_map_info;
    if (!gst_buffer_map(buf, &in_map_info, GST_MAP_READ)) {
        g_print("Error: Failed to map gst buffer\n");
        return GST_PAD_PROBE_OK;
    }

    // Cast to NvBufSurface
    NvBufSurface *surface = (NvBufSurface *)in_map_info.data;
    if (!surface) {
        g_print("Error: NvBufSurface is NULL\n");
        gst_buffer_unmap(buf, &in_map_info);
        return GST_PAD_PROBE_OK;
    }

    // Iterate over frame meta list
    for (NvDsMetaList *l_frame = batch_meta->frame_meta_list; l_frame != NULL; l_frame = l_frame->next) {
        NvDsFrameMeta *frame_meta = (NvDsFrameMeta *)l_frame->data;

        // Map the surface for reading and writing
        if (NvBufSurfaceMap(surface, frame_meta->batch_id, -1, NVBUF_MAP_READ_WRITE) != 0) {
            g_print("Error: NvBufSurfaceMap failed for batch_id %d\n", frame_meta->batch_id);
            continue;
        }

        // Synchronize for CPU access
        NvBufSurfaceSyncForCpu(surface, frame_meta->batch_id, 0);

        guint width = surface->surfaceList[frame_meta->batch_id].width;
        guint height = surface->surfaceList[frame_meta->batch_id].height;

        // Debugging: Print surface details
        g_print("DEBUG: Surface dimensions: %d x %d\n", width, height);

        // Create NV12 Mat from NvBufSurface
        cv::Mat nv12_mat(height * 3 / 2, width, CV_8UC1,
                         surface->surfaceList[frame_meta->batch_id].mappedAddr.addr[0],
                         surface->surfaceList[frame_meta->batch_id].pitch);

        // Convert NV12 to BGR
        cv::Mat bgr_frame;
        cv::cvtColor(nv12_mat, bgr_frame, cv::COLOR_YUV2BGR_NV12);

        // Define cropping region
        int x = 300, y = 300;  // Crop center
        int crop_width = 60, crop_height = 60;

        int x_start = std::max(0, x - crop_width / 2);
        int y_start = std::max(0, y - crop_height / 2);
        int x_end = std::min((int)width, x + crop_width / 2);
        int y_end = std::min((int)height, y + crop_height / 2);

        cv::Rect crop_roi(x_start, y_start, x_end - x_start, y_end - y_start);
        cv::Mat cropped_frame = bgr_frame(crop_roi);

        // Resize cropped frame
        cv::Mat resized_frame;
        cv::resize(cropped_frame, resized_frame, cv::Size(cropped_frame.cols * 2, cropped_frame.rows * 2), 0, 0, cv::INTER_CUBIC);

        // Sharpen the frame
        cv::Mat sharpening_kernel = (cv::Mat_<float>(3, 3) << 
                                     0, -1, 0,
                                    -1, 5, -1,
                                     0, -1, 0);
        cv::filter2D(resized_frame, resized_frame, -1, sharpening_kernel);

        // Draw a red boundary
        cv::rectangle(resized_frame, cv::Point(0, 0), cv::Point(resized_frame.cols, resized_frame.rows), cv::Scalar(0, 0, 255), 4);

        // Overlay the processed frame back onto the original BGR frame
        int overlay_x = x_start;
        int overlay_y = y_start;

        int overlay_width = std::min(resized_frame.cols, bgr_frame.cols - overlay_x);
        int overlay_height = std::min(resized_frame.rows, bgr_frame.rows - overlay_y);

        if (overlay_width > 0 && overlay_height > 0) {
            resized_frame(cv::Rect(0, 0, overlay_width, overlay_height))
                .copyTo(bgr_frame(cv::Rect(overlay_x, overlay_y, overlay_width, overlay_height)));
        }

        // Write back the modified BGR frame into NvBufSurface
        cv::Mat nv12_output;
        cv::cvtColor(bgr_frame, nv12_output, cv::COLOR_BGR2YUV_I420);

        cudaMemcpy(surface->surfaceList[frame_meta->batch_id].mappedAddr.addr[0],
                   nv12_output.data, nv12_output.total(), cudaMemcpyHostToDevice);

        // Optionally dump the processed frame to a file
        char file_name[128];
        sprintf(file_name, "processed_frame_%03d_stream_%02d.jpg", frame_meta->frame_num, frame_meta->source_id);
        imwrite(file_name, bgr_frame);

        // Synchronize for device access after the modification
        NvBufSurfaceSyncForDevice(surface, frame_meta->batch_id, 0);
        NvBufSurfaceUnMap(surface, frame_meta->batch_id, -1);
    }

    // Unmap the buffer after processing
    gst_buffer_unmap(buf, &in_map_info);
    return GST_PAD_PROBE_OK;
}

this is the error:

Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping
Error: NvBufSurfaceMap failed for batch_id 0
nvbufsurface: mapping of memory type (269488144) not supported
nvbufsurface: error in mapping

please refer to my last comment. you can get the correct use of NvBufSurfaceMap and NvBufSurfaceSyncForCpu in the sample “Dump NV12 NvBufSurface into a YUV file”. please refer to the parameter explanation of NvBufSurfaceMap and NvBufSurfaceSyncForCpu in this link.