CUDA resource initialization and release issue in NvBufSurface, EGLImage and CUgraphicsResource

Please provide complete information as applicable to your setup.

• Hardware Platform Jetson
• DeepStream Version 7.1.0
• JetPack Version 6.2
• TensorRT Version 10.3
• Issue Type questions, bug
• When I use apply_image_processing,which is the function defined by myself, its seems to fail to initialize correctly every time.(The output result seems to be that the input of this function is the processing result of this function last time)

I use gstreamer to do the image processing for each frame of RTSP stream.
pipline is

"( rtspsrc location=" + std::string(SOURCE_RTSP_URI) + " latency=0 ! "
        "application/x-rtp, media=video, payload=96, encoding-name=H265 ! "
        "rtph265depay ! h265parse ! "
        "nvv4l2decoder latency=10 ! "       
        "nvvidconv name=format_conv format=NV12 ! "  
        "queue max-size-buffers=10 ! " 
        "identity name=stats_identity ! "
        "queue max-size-buffers=10 ! "
        "nvv4l2h265enc insert-sps-pps=true bitrate=4000000 ! "
        "h265parse ! "
        "rtph265pay name=pay0 pt=96 config-interval=-1 )"

callback function handoff_handler is in the identity

static void handoff_handler(GstElement* identity, GstBuffer* buffer, GstPad* pad, gpointer user_data) {
    // 确保 CUDA 设备已初始化
    static bool cuda_initialized = false;
    if (!cuda_initialized) {
        cudaSetDevice(0);
        // cudaFree(0); 
        cuda_initialized = true;
    }
    
    // 打印内存信息
    size_t free_memory, total_memory;
    cudaMemGetInfo(&free_memory, &total_memory);
    printf("GPU Memory: %zu MB free, %zu MB total\n", free_memory / (1024 * 1024), total_memory / (1024 * 1024));

    frame_count++;
    gint64 current_time = g_get_monotonic_time();
    
    // FPS计算
    if (current_time - last_print_time > G_USEC_PER_SEC) {
        gdouble fps = (gdouble)frame_count * G_USEC_PER_SEC / (current_time - last_print_time);
        printf("FPS: %.2f\n", fps);
        frame_count = 0;
        last_print_time = current_time;
    }

    // 从 GstBuffer 获取 NvBufSurface
    NvBufSurface* surf = nullptr;
    // 获取 NvBufSurface
    GstMapInfo map_info;
    if (!gst_buffer_map(buffer, &map_info, GST_MAP_READWRITE)) {
        printf("Failed to map buffer\n");
        return;
    }
    
    // 获取 NvBufSurface 指针
    surf = (NvBufSurface*)map_info.data;
    if (!surf || surf->numFilled <= 0) {
        printf("Failed to get NvBufSurface\n");
        gst_buffer_unmap(buffer, &map_info);
        return;
    }  
    // 打印bufer信息
    int p;
    printf("identity->surf : \n");
    printf("  batchSize = %d\n", surf->batchSize);
    printf("  numFilled = %d\n", surf->numFilled);
    printf("  memType = %d\n", surf->memType);
    for (int bs = 0; bs < surf->batchSize; bs++) {
        NvBufSurfaceParams *sur = &(surf->surfaceList[bs]);
        if (sur == NULL)
            break;
        printf("  surfaceList[%d]:\n", bs);
        printf("    width = %d\n", sur->width);
        printf("    height = %d\n", sur->height);
        printf("    pitch = %d\n", sur->pitch);
        printf("    layout = %d\n", sur->layout);
        printf("    colorFormat = %d\n", sur->colorFormat);
        printf("    bufferDesc = %lu\n", sur->bufferDesc);
        printf("    dataSize = %d\n", sur->dataSize);
        printf("    dataPtr = %p\n", sur->dataPtr);
        if(sur->colorFormat == NVBUF_COLOR_FORMAT_NV12_ER)
            printf("it's NVBUF_COLOR_FORMAT_NV12_ER!\n");
        else
            printf("it's not NVBUF_COLOR_FORMAT_NV12_ER(%d)\n", NVBUF_COLOR_FORMAT_NV12_ER);
        NvBufSurfacePlaneParams *planeParams = &(sur->planeParams);
        printf("    NvBufSurfaceParams->planeParams:\n");
        printf("      num_planes = %d\n", planeParams->num_planes);
        for (p = 0; p < planeParams->num_planes; p++) {
            printf("      width[%d] = %u\n", p, planeParams->width[p]);
            printf("      height[%d] = %u\n", p, planeParams->height[p]);
            printf("      pitch[%d] = %u\n", p, planeParams->pitch[p]);
            printf("      offset[%d] = %u\n", p, planeParams->offset[p]);
            printf("      psize[%d] = %u\n", p, planeParams->psize[p]);
            printf("      bytesPerPix[%d] = %u\n", p, planeParams->bytesPerPix[p]);
        }

        NvBufSurfaceMappedAddr *mAddr = &(sur->mappedAddr);
        printf("    NvBufSurfaceParams->mappedAddr:\n");
        for (p = 0; p < NVBUF_MAX_PLANES; p++) {
            if (!mAddr->addr) {
            printf("      mappedAddr->addr[%d] is NULL\n", p);
            break;
            }
            printf("      mappedAddr->addr[%d] = %p\n", p, mAddr->addr[p]);
        }

        if (mAddr->eglImage == NULL)
            printf("      mappedAddr->eglImage is NULL\n");
        else
            printf("      mappedAddr->eglImage is %p\n", mAddr->eglImage);
    }
    // ---------------------------------------------------------------------------- CUDA 版本 ---------------------------------------------------------------------------------
    // map EGLImage
    if (NvBufSurfaceMapEglImage(surf, 0) != 0) {
        printf("Failed to map EGLImage");
        gst_buffer_unmap(buffer, &map_info);
        return;
    }
    
    // 从 surf 结构中获取Y平面 EGLImage
    EGLImageKHR egl_image_y = surf->surfaceList[0].mappedAddr.eglImage;
    if (egl_image_y == EGL_NO_IMAGE_KHR) {
        printf("EGLImage is NULL after mapping\n");
        NvBufSurfaceUnMapEglImage(surf, 0);
        gst_buffer_unmap(buffer, &map_info);
        return;
    }

    // 使用CUDA接口注册EGLImage
    CUgraphicsResource cuResource;
    CUresult cuRes = cuGraphicsEGLRegisterImage(&cuResource, egl_image_y, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
    if (cuRes != CUDA_SUCCESS) {
        printf("cuGraphicsEGLRegisterImage failed: %d\n", cuRes);
        NvBufSurfaceUnMapEglImage(surf, 0);
        gst_buffer_unmap(buffer, &map_info);
        return;
    }
    printf("CUDA EGL registration successful\n");
    
    // 映射CUDA资源
    CUeglFrame egl_frame_y;
    cuRes = cuGraphicsResourceGetMappedEglFrame(&egl_frame_y, cuResource, 0, 0);
    if (cuRes != CUDA_SUCCESS) {
        printf("cuGraphicsResourceGetMappedEglFrame failed with error code %d\n", cuRes);
        cuGraphicsUnmapResources(1,&cuResource,0);
        cuGraphicsUnregisterResource(cuResource);
        NvBufSurfaceUnMapEglImage(surf, 0);
        gst_buffer_unmap(buffer, &map_info);
        return;
    }
    printf("cuGraphicsResourceGetMappedEglFrame successful\n");
    printf("  frame.width = %d\n", egl_frame_y.width);
    printf("  frame.height = %d\n", egl_frame_y.height);

    // 获取 cuArray
    CUarray cuArray_y = egl_frame_y.frame.pArray[0];
    int width = surf->surfaceList[0].width;
    int height = surf->surfaceList[0].height;
    // 打印调试信息
    printf("CUDA Array: %p\n", (void*)cuArray_y);
    printf("Image dimensions: %d x %d\n", width, height);
    // 控制标志
    bool applyClahe = true;
    bool applyBrightness = false;
    float clipLimit = 0.1f;
    int tileGridX = 8, tileGridY = 8;
    float brightnessFactor = 1.5f;

    // 调用统一处理函数
    cudaError_t process_err = apply_image_processing(&cuArray_y, width, height, applyClahe, applyBrightness, clipLimit, tileGridX, tileGridY, brightnessFactor);

    if (process_err != cudaSuccess) {
        printf("Image processing failed: %s\n", cudaGetErrorString(process_err));
    }
    // --------------------------------------------------------------- CUDA end --------------------------------------------------------------------------------
    // 同步设备
    cudaDeviceSynchronize();

    cuRes = cuGraphicsUnmapResources(1, &cuResource, 0);
    if (cuRes != CUDA_SUCCESS) {
        printf("Unmap failed: %d\n", cuRes);
    }
    
    cuRes = cuGraphicsUnregisterResource(cuResource);
    if (cuRes != CUDA_SUCCESS) {
        printf("cuGraphicsUnregisterResource failed: %d\n", cuRes);
    }
    
    if (NvBufSurfaceUnMapEglImage(surf, 0) != 0) {
        printf("NvBufSurfaceUnMapEglImage failed\n");
    }
    
    gst_buffer_unmap(buffer, &map_info);
    
}

The bash output(the following output is the output for processing one frame) is

GPU Memory: 25891 MB free, 30697 MB total
identity->surf : 
  batchSize = 1
  numFilled = 1
  memType = 4
  surfaceList[0]:
    width = 5120
    height = 1440
    pitch = 5120
    layout = 1
    colorFormat = 7
    bufferDesc = 61
    dataSize = 11796480
    dataPtr = 0xffff380632b0
it's NVBUF_COLOR_FORMAT_NV12_ER!
    NvBufSurfaceParams->planeParams:
      num_planes = 2
      width[0] = 5120
      height[0] = 1440
      pitch[0] = 5120
      offset[0] = 0
      psize[0] = 7864320
      bytesPerPix[0] = 1
      width[1] = 2560
      height[1] = 720
      pitch[1] = 5120
      offset[1] = 7864320
      psize[1] = 3932160
      bytesPerPix[1] = 2
    NvBufSurfaceParams->mappedAddr:
      mappedAddr->addr[0] = (nil)
      mappedAddr->addr[1] = (nil)
      mappedAddr->addr[2] = (nil)
      mappedAddr->addr[3] = (nil)
      mappedAddr->eglImage is NULL
CUDA EGL registration successful
cuGraphicsResourceGetMappedEglFrame successful
  frame.width = 5120
  frame.height = 1440
CUDA Array: 0xffff7494b800
Image dimensions: 5120 x 1440

===== Starting Image Processing =====
Image size: 5120 x 1440
Apply CLAHE: YES
Apply Brightness: NO
CLAHE parameters:
  Clip limit: 0.10
  Tile grid: 8 x 8

[CLAHE] Starting processing for 5120x1440 image
[CLAHE] Tile configuration: 8x8 tiles
[CLAHE] Clip limit: 0.10
[CLAHE] Tile size: 640x180 pixels
[CLAHE] Total tiles: 64
[CUDA] Using CUDA array: 0xffff7494b800
[CUDA] Texture object created: 0x1 (0.00 ms)
[CUDA] Surface object created: 0x2 (0.01 ms)
[MEM] Allocating histogram: 0.06 MB
[MEM] Histogram allocated: 0x205ce0000 (0.21 ms)
[MEM] Allocating CDF: 0.06 MB
[MEM] CDF allocated: 0x205cf0000 (0.01 ms)
[INIT] Zeroing histogram and CDF memory
[INIT] Histogram and CDF zeroed (0.06 ms)
[KERNEL] Launching computeHistogramKernel
         Grid: (8, 8, 1)
         Block: (256, 1, 1)
         Shared memory: 1024 bytes
[KERNEL] computeHistogramKernel completed (0.50 ms)
[KERNEL] Launching clipAndComputeCDFKernel
         Grid: (1, 1, 1)
         Block: (256, 1, 1)
[KERNEL] clipAndComputeCDFKernel completed (0.28 ms)
[KERNEL] Launching applyEqualizationKernel
         Grid: (320, 90, 1)
         Block: (16, 16, 1)
[KERNEL] applyEqualizationKernel completed (0.78 ms)
[CLEANUP] Releasing resources
[CLEANUP] Resources released (0.22 ms)
[CLAHE] Processing completed successfully
Total processing time: 0.003 seconds
===== Image Processing Complete =====

Unmap failed: 999

You do not need to call cuGraphicsUnmapResources, which may make the nvbufsurface unavailable in downstream elements.

In addition, NvBufSurfacerepresents the entire batch. If you want to use CUDA to process a batch, please refer to /opt/nvidia/deepstream/deepstream/sources/gst-plugins/gst-nvinfer/gstnvinfer_allocator.cpp

Thank you for your reminder, I deleted cuGraphicsUnmapResources and cuGraphicsUnregisterResource, and corrected the processing of the entire batch for nvbufsurface, but it seems that the problem (The output result seems to be that the input of this function is the processing result of this function last time) I mentioned has not been improved.

new callback function handoff_handler is

static void handoff_handler(GstElement* identity, GstBuffer* buffer, GstPad* pad, gpointer user_data) {
    // 确保 CUDA 设备已初始化
    static bool cuda_initialized = false;
    if (!cuda_initialized) {
        cudaSetDevice(0);
        // cudaFree(0); 
        cuda_initialized = true;
    }
    
    // // 打印内存信息
    // size_t free_memory, total_memory;
    // cudaMemGetInfo(&free_memory, &total_memory);
    // printf("GPU Memory: %zu MB free, %zu MB total\n", free_memory / (1024 * 1024), total_memory / (1024 * 1024));

    frame_count++;
    gint64 current_time = g_get_monotonic_time();
    
    // FPS计算
    if (current_time - last_print_time > G_USEC_PER_SEC) {
        gdouble fps = (gdouble)frame_count * G_USEC_PER_SEC / (current_time - last_print_time);
        printf("FPS: %.2f\n", fps);
        frame_count = 0;
        last_print_time = current_time;
    }

    // 从 GstBuffer 获取 NvBufSurface
    NvBufSurface* surf = nullptr;
    // 获取 NvBufSurface
    GstMapInfo map_info;
    if (!gst_buffer_map(buffer, &map_info, GST_MAP_READWRITE)) {
        printf("Failed to map buffer\n");
        return;
    }
    
    // 获取 NvBufSurface 指针
    surf = (NvBufSurface*)map_info.data;
    if (!surf || surf->numFilled <= 0 || surf->batchSize <= 0) {
        printf("Failed to get NvBufSurface\n");
        gst_buffer_unmap(buffer, &map_info);
        return;
    }  
    // 打印bufer信息
    int p;
    printf("identity->surf : \n");
    printf("  batchSize = %d\n", surf->batchSize);
    printf("  numFilled = %d\n", surf->numFilled);
    printf("  memType = %d\n", surf->memType);
    // 遍历整个batch
    for (int bs = 0; bs < surf->batchSize; bs++) { 
        NvBufSurfaceParams *sur = &(surf->surfaceList[bs]);
        if (sur == NULL)
            break;
        printf("  surfaceList[%d]:\n", bs);
        printf("    width = %d\n", sur->width);
        printf("    height = %d\n", sur->height);
        printf("    pitch = %d\n", sur->pitch);
        printf("    layout = %d\n", sur->layout);
        printf("    colorFormat = %d\n", sur->colorFormat);
        printf("    bufferDesc = %lu\n", sur->bufferDesc);
        printf("    dataSize = %d\n", sur->dataSize);
        printf("    dataPtr = %p\n", sur->dataPtr);
        if(sur->colorFormat == NVBUF_COLOR_FORMAT_NV12_ER)
            printf("it's NVBUF_COLOR_FORMAT_NV12_ER!\n");
        else
            printf("it's not NVBUF_COLOR_FORMAT_NV12_ER(%d)\n", NVBUF_COLOR_FORMAT_NV12_ER);
        NvBufSurfacePlaneParams *planeParams = &(sur->planeParams);
        printf("    NvBufSurfaceParams->planeParams:\n");
        printf("      num_planes = %d\n", planeParams->num_planes);
        for (p = 0; p < planeParams->num_planes; p++) {
            printf("      width[%d] = %u\n", p, planeParams->width[p]);
            printf("      height[%d] = %u\n", p, planeParams->height[p]);
            printf("      pitch[%d] = %u\n", p, planeParams->pitch[p]);
            printf("      offset[%d] = %u\n", p, planeParams->offset[p]);
            printf("      psize[%d] = %u\n", p, planeParams->psize[p]);
            printf("      bytesPerPix[%d] = %u\n", p, planeParams->bytesPerPix[p]);
        }

        NvBufSurfaceMappedAddr *mAddr = &(sur->mappedAddr);
        printf("    NvBufSurfaceParams->mappedAddr:\n");
        for (p = 0; p < NVBUF_MAX_PLANES; p++) {
            if (!mAddr->addr) {
            printf("      mappedAddr->addr[%d] is NULL\n", p);
            break;
            }
            printf("      mappedAddr->addr[%d] = %p\n", p, mAddr->addr[p]);
        }

        if (mAddr->eglImage == NULL)
            printf("      mappedAddr->eglImage is NULL\n");
        else
            printf("      mappedAddr->eglImage is %p\n", mAddr->eglImage);
        
        // ---------------------------------------------------------------------------- CUDA 版本 ---------------------------------------------------------------------------------
        // map EGLImage
        if (NvBufSurfaceMapEglImage(surf, bs) != 0) {
            printf("Failed to map EGLImage for surface %d\n", bs);
            gst_buffer_unmap(buffer, &map_info);
            continue;
        }
        
        // 从 surf 结构中获取Y平面 EGLImage
        EGLImageKHR egl_image_y = surf->surfaceList[bs].mappedAddr.eglImage;
        if (egl_image_y == EGL_NO_IMAGE_KHR) {
            printf("EGLImage is NULL after mapping for surface %d\n", bs);
            NvBufSurfaceUnMapEglImage(surf, bs);
            gst_buffer_unmap(buffer, &map_info);
            continue;
        }

        // 使用CUDA接口注册EGLImage
        CUgraphicsResource cuResource;
        CUresult cuRes = cuGraphicsEGLRegisterImage(&cuResource, egl_image_y, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
        if (cuRes != CUDA_SUCCESS) {
            printf("cuGraphicsEGLRegisterImage failed for surface %d: %d\n", bs, cuRes);
            NvBufSurfaceUnMapEglImage(surf, bs);
            gst_buffer_unmap(buffer, &map_info);
            continue;
        }
        printf("CUDA EGL registration successful for surface %d\n", bs);
        
        // 映射CUDA资源
        CUeglFrame egl_frame_y;
        cuRes = cuGraphicsResourceGetMappedEglFrame(&egl_frame_y, cuResource, 0, 0);
        if (cuRes != CUDA_SUCCESS) {
            printf("cuGraphicsResourceGetMappedEglFrame failed for surface %d with error code %d\n", bs, cuRes);
            cuGraphicsUnmapResources(1,&cuResource,0);
            cuGraphicsUnregisterResource(cuResource);
            NvBufSurfaceUnMapEglImage(surf, bs);
            gst_buffer_unmap(buffer, &map_info);
            continue;
        }
        printf("cuGraphicsResourceGetMappedEglFrame successful for surface %d\n", bs);
        printf("  frame.width = %d\n", egl_frame_y.width);
        printf("  frame.height = %d\n", egl_frame_y.height);

        // 获取 cuArray
        CUarray cuArray_y = egl_frame_y.frame.pArray[0];
        int width = surf->surfaceList[0].width;
        int height = surf->surfaceList[0].height;
        // 打印调试信息
        printf("CUDA Array for surface %d: %p\n", bs, (void*)cuArray_y);
        printf("Image dimensions for surface %d: %d x %d\n", bs, width, height);
        // 控制标志
        bool applyClahe = true;
        bool applyBrightness = false;
        float clipLimit = 0.1f;
        int tileGridX = 8, tileGridY = 8;
        float brightnessFactor = 1.5f;

        // 调用统一处理函数
        cudaError_t process_err = apply_image_processing(&cuArray_y, width, height, applyClahe, applyBrightness, clipLimit, tileGridX, tileGridY, brightnessFactor);

        if (process_err != cudaSuccess) {
            printf("Image processing failed for surface %d: %s\n", bs, cudaGetErrorString(process_err));
        }
        // --------------------------------------------------------------- CUDA end --------------------------------------------------------------------------------
        // 同步设备
        cudaDeviceSynchronize();

        // cuRes = cuGraphicsUnmapResources(1, &cuResource, 0);
        // if (cuRes != CUDA_SUCCESS) {
        //     printf("Unmap failed: %d\n", cuRes);
        // }
        
        // cuRes = cuGraphicsUnregisterResource(cuResource);
        // if (cuRes != CUDA_SUCCESS) {
        //     printf("cuGraphicsUnregisterResource failed: %d\n", cuRes);
        // }
        if (NvBufSurfaceUnMapEglImage(surf, bs) != 0) {
            printf("NvBufSurfaceUnMapEglImage failed for surface %d\n", bs);
        }
    }   
    gst_buffer_unmap(buffer, &map_info);
    
}

Could you share sample code to reproduce the problem, this code snippet I cannot compile it.

Here is the sample code of my project. Among them, apply_image_processing can be replaced by a simple brightness enhancement CUDA processing function. I have tested apply_image_processing and confirmed that this part is fine. Maybe you can change the input to a local video stream (now is RTSP) for testing?

main.cpp

#include <gst/gst.h>
#include <gst/rtsp-server/rtsp-server.h>
#include <gst/allocators/allocators.h>
#include <iostream>
#include <ctime>
#include <nvbufsurface.h>      
#include <cuda_runtime.h>       
#include "gstnvdsmeta.h"
#include <cuda_egl_interop.h>
#include <cuda.h>
#include <cudaEGL.h>


#define RTSP_PORT "8554"
#define RTSP_PATH "/b"
#define SOURCE_RTSP_URI "rtsp://192.168.1.100:8554/b"

// 全局上下文
static GstElement *identity = nullptr;
static guint frame_count = 0;
static gint64 last_print_time = 0;


extern "C" cudaError_t apply_image_processing(CUarray* array, int width, int height, 
                                     bool applyClahe, bool applyBrightness, 
                                     float clipLimit, int tileGridX, int tileGridY, 
                                     float brightnessFactor);


// handoff 回调
static void handoff_handler(GstElement* identity, GstBuffer* buffer, GstPad* pad, gpointer user_data) {
    // 确保 CUDA 设备已初始化
    static bool cuda_initialized = false;
    if (!cuda_initialized) {
        cudaSetDevice(0);
        // cudaFree(0); 
        cuda_initialized = true;
    }
    
    // // 打印内存信息
    // size_t free_memory, total_memory;
    // cudaMemGetInfo(&free_memory, &total_memory);
    // printf("GPU Memory: %zu MB free, %zu MB total\n", free_memory / (1024 * 1024), total_memory / (1024 * 1024));

    frame_count++;
    gint64 current_time = g_get_monotonic_time();
    
    // FPS计算
    if (current_time - last_print_time > G_USEC_PER_SEC) {
        gdouble fps = (gdouble)frame_count * G_USEC_PER_SEC / (current_time - last_print_time);
        printf("FPS: %.2f\n", fps);
        frame_count = 0;
        last_print_time = current_time;
    }

    // 从 GstBuffer 获取 NvBufSurface
    NvBufSurface* surf = nullptr;
    // 获取 NvBufSurface
    GstMapInfo map_info;
    if (!gst_buffer_map(buffer, &map_info, GST_MAP_READWRITE)) {
        printf("Failed to map buffer\n");
        return;
    }
    
    // 获取 NvBufSurface 指针
    surf = (NvBufSurface*)map_info.data;
    if (!surf || surf->numFilled <= 0 || surf->batchSize <= 0) {
        printf("Failed to get NvBufSurface\n");
        gst_buffer_unmap(buffer, &map_info);
        return;
    }  
    // 打印bufer信息
    int p;
    printf("identity->surf : \n");
    printf("  batchSize = %d\n", surf->batchSize);
    printf("  numFilled = %d\n", surf->numFilled);
    printf("  memType = %d\n", surf->memType);
    // 遍历整个batch
    for (int bs = 0; bs < surf->batchSize; bs++) { 
        NvBufSurfaceParams *sur = &(surf->surfaceList[bs]);
        if (sur == NULL)
            break;
        printf("  surfaceList[%d]:\n", bs);
        printf("    width = %d\n", sur->width);
        printf("    height = %d\n", sur->height);
        printf("    pitch = %d\n", sur->pitch);
        printf("    layout = %d\n", sur->layout);
        printf("    colorFormat = %d\n", sur->colorFormat);
        printf("    bufferDesc = %lu\n", sur->bufferDesc);
        printf("    dataSize = %d\n", sur->dataSize);
        printf("    dataPtr = %p\n", sur->dataPtr);
        if(sur->colorFormat == NVBUF_COLOR_FORMAT_NV12_ER)
            printf("it's NVBUF_COLOR_FORMAT_NV12_ER!\n");
        else
            printf("it's not NVBUF_COLOR_FORMAT_NV12_ER(%d)\n", NVBUF_COLOR_FORMAT_NV12_ER);
        NvBufSurfacePlaneParams *planeParams = &(sur->planeParams);
        printf("    NvBufSurfaceParams->planeParams:\n");
        printf("      num_planes = %d\n", planeParams->num_planes);
        for (p = 0; p < planeParams->num_planes; p++) {
            printf("      width[%d] = %u\n", p, planeParams->width[p]);
            printf("      height[%d] = %u\n", p, planeParams->height[p]);
            printf("      pitch[%d] = %u\n", p, planeParams->pitch[p]);
            printf("      offset[%d] = %u\n", p, planeParams->offset[p]);
            printf("      psize[%d] = %u\n", p, planeParams->psize[p]);
            printf("      bytesPerPix[%d] = %u\n", p, planeParams->bytesPerPix[p]);
        }

        NvBufSurfaceMappedAddr *mAddr = &(sur->mappedAddr);
        printf("    NvBufSurfaceParams->mappedAddr:\n");
        for (p = 0; p < NVBUF_MAX_PLANES; p++) {
            if (!mAddr->addr) {
            printf("      mappedAddr->addr[%d] is NULL\n", p);
            break;
            }
            printf("      mappedAddr->addr[%d] = %p\n", p, mAddr->addr[p]);
        }

        if (mAddr->eglImage == NULL)
            printf("      mappedAddr->eglImage is NULL\n");
        else
            printf("      mappedAddr->eglImage is %p\n", mAddr->eglImage);
        
        // ---------------------------------------------------------------------------- CUDA 版本 ---------------------------------------------------------------------------------
        // map EGLImage
        if (NvBufSurfaceMapEglImage(surf, bs) != 0) {
            printf("Failed to map EGLImage for surface %d\n", bs);
            gst_buffer_unmap(buffer, &map_info);
            continue;
        }
        
        // 从 surf 结构中获取Y平面 EGLImage
        EGLImageKHR egl_image_y = surf->surfaceList[bs].mappedAddr.eglImage;
        if (egl_image_y == EGL_NO_IMAGE_KHR) {
            printf("EGLImage is NULL after mapping for surface %d\n", bs);
            NvBufSurfaceUnMapEglImage(surf, bs);
            gst_buffer_unmap(buffer, &map_info);
            continue;
        }

        // 使用CUDA接口注册EGLImage
        CUgraphicsResource cuResource;
        CUresult cuRes = cuGraphicsEGLRegisterImage(&cuResource, egl_image_y, CU_GRAPHICS_MAP_RESOURCE_FLAGS_NONE);
        if (cuRes != CUDA_SUCCESS) {
            printf("cuGraphicsEGLRegisterImage failed for surface %d: %d\n", bs, cuRes);
            NvBufSurfaceUnMapEglImage(surf, bs);
            gst_buffer_unmap(buffer, &map_info);
            continue;
        }
        printf("CUDA EGL registration successful for surface %d\n", bs);
        
        // 映射CUDA资源
        CUeglFrame egl_frame_y;
        cuRes = cuGraphicsResourceGetMappedEglFrame(&egl_frame_y, cuResource, 0, 0);
        if (cuRes != CUDA_SUCCESS) {
            printf("cuGraphicsResourceGetMappedEglFrame failed for surface %d with error code %d\n", bs, cuRes);
            cuGraphicsUnmapResources(1,&cuResource,0);
            cuGraphicsUnregisterResource(cuResource);
            NvBufSurfaceUnMapEglImage(surf, bs);
            gst_buffer_unmap(buffer, &map_info);
            continue;
        }
        printf("cuGraphicsResourceGetMappedEglFrame successful for surface %d\n", bs);
        printf("  frame.width = %d\n", egl_frame_y.width);
        printf("  frame.height = %d\n", egl_frame_y.height);

        // 获取 cuArray
        CUarray cuArray_y = egl_frame_y.frame.pArray[0];
        int width = surf->surfaceList[0].width;
        int height = surf->surfaceList[0].height;
        // 打印调试信息
        printf("CUDA Array for surface %d: %p\n", bs, (void*)cuArray_y);
        printf("Image dimensions for surface %d: %d x %d\n", bs, width, height);
        // 控制标志
        bool applyClahe = true;
        bool applyBrightness = false;
        float clipLimit = 0.1f;
        int tileGridX = 8, tileGridY = 8;
        float brightnessFactor = 1.5f;

        // 调用统一处理函数
        cudaError_t process_err = apply_image_processing(&cuArray_y, width, height, applyClahe, applyBrightness, clipLimit, tileGridX, tileGridY, brightnessFactor);

        if (process_err != cudaSuccess) {
            printf("Image processing failed for surface %d: %s\n", bs, cudaGetErrorString(process_err));
        }
        // --------------------------------------------------------------- CUDA end --------------------------------------------------------------------------------
        // 同步设备
        cudaDeviceSynchronize();

        // cuRes = cuGraphicsUnmapResources(1, &cuResource, 0);
        // if (cuRes != CUDA_SUCCESS) {
        //     printf("Unmap failed: %d\n", cuRes);
        // }
        
        // cuRes = cuGraphicsUnregisterResource(cuResource);
        // if (cuRes != CUDA_SUCCESS) {
        //     printf("cuGraphicsUnregisterResource failed: %d\n", cuRes);
        // }
        if (NvBufSurfaceUnMapEglImage(surf, bs) != 0) {
            printf("NvBufSurfaceUnMapEglImage failed for surface %d\n", bs);
        }
    }   
    gst_buffer_unmap(buffer, &map_info);
    
}


// 媒体配置回调
static void media_configured(GstRTSPMediaFactory *factory, GstRTSPMedia *media, gpointer user_data) {
    GstElement *pipeline = gst_rtsp_media_get_element(media);
    identity = gst_bin_get_by_name(GST_BIN(pipeline), "stats_identity");

    if (identity) {
        g_object_set(identity, "signal-handoffs", TRUE, NULL);
        g_signal_connect(identity, "handoff", G_CALLBACK(handoff_handler), NULL);
        gst_object_unref(identity);
    }
    

    gst_object_unref(pipeline);
}

int main(int argc, char *argv[]) {
    gst_init(&argc, &argv);
    
    GMainLoop *loop = g_main_loop_new(NULL, FALSE);
    GstRTSPServer *server = gst_rtsp_server_new();
    
    // 绑定所有网络接口
    g_object_set(server, "service", RTSP_PORT, "address", "0.0.0.0", NULL);
    
    GstRTSPMountPoints *mounts = gst_rtsp_server_get_mount_points(server);
    GstRTSPMediaFactory *factory = gst_rtsp_media_factory_new();

    // 管道配置
    std::string launch_str =
        "( rtspsrc location=" + std::string(SOURCE_RTSP_URI) + " latency=0 ! "
        "application/x-rtp, media=video, payload=96, encoding-name=H265 ! "
        "rtph265depay ! h265parse ! "
        "nvv4l2decoder latency=10 ! "       // NVIDIA 硬件解码
        "nvvidconv name=format_conv format=NV12 ! "  // 显式格式转换
        "queue max-size-buffers=10 ! " // 在解码器后、编码器前添加队列
        "identity name=stats_identity ! "
        "queue max-size-buffers=10 ! "
        "nvv4l2h265enc insert-sps-pps=true bitrate=4000000 ! "
        "h265parse ! "
        "rtph265pay name=pay0 pt=96 config-interval=-1 )";

    gst_rtsp_media_factory_set_launch(factory, launch_str.c_str());
    gst_rtsp_media_factory_set_shared(factory, TRUE);
    g_signal_connect(factory, "media-configure", G_CALLBACK(media_configured), NULL);
    gst_rtsp_mount_points_add_factory(mounts, RTSP_PATH, factory);
    g_object_unref(mounts);

    if (gst_rtsp_server_attach(server, NULL) == 0) {
        g_printerr("Failed to attach server to main context\n");
        return 1;
    }
    
    g_print("RTSP server running at rtsp://0.0.0.0:%s%s\n", RTSP_PORT, RTSP_PATH);
    g_print("Pipeline: %s\n", launch_str.c_str());

    last_print_time = g_get_monotonic_time();
    g_main_loop_run(loop);
    
    g_main_loop_unref(loop);
    gst_object_unref(server);
    return 0;
}



std::string launch_str =
        "rtspsrc location=" + std::string(SOURCE_RTSP_URI) + " latency=0 ! "
        " application/x-rtp, media=video, encoding-name=H265 ! "
        "rtph265depay ! h265parse ! "
        "nvv4l2decoder ! "       // NVIDIA 硬件解码
        "nvvidconv bl-output=0 compute-hw=1 ! "  // 显式格式转换
        "video/x-raw(memory:NVMM),format=NV12 ! "
        "queue max-size-buffers=10 ! " // 在解码器后、编码器前添加队列
        "identity name=stats_identity ! "
        "queue max-size-buffers=10 ! "
        "nvv4l2h265enc insert-sps-pps=true bitrate=4000000 ! "
        "h265parse ! "
        "rtph265pay name=pay0 pt=96 config-interval=-1";

I modified the pipeline you provided and it works correctly, this is log
log.log (248.5 KB)

I thought the problem might be related to sur->layout, so I modified the property values ​​of nvvidconv. These are all Jetpack elements. Have you used deepstream elements such as nvinfer/nvstreammux?

I didn’t use deepstream elements. After I changed the sur->layout, the CUDA processing function failed to run.
bash output

apimagen@ubuntu:~/Desktop/gst_cpp_cuda$ ./build/gst_rtsp_cpp 
RTSP server running at rtsp://0.0.0.0:8554/b
Pipeline: ( rtspsrc location=rtsp://192.168.1.100:8554/b latency=0 ! application/x-rtp, media=video, payload=96, encoding-name=H265 ! rtph265depay ! h265parse ! nvv4l2decoder latency=10 ! nvvidconv bl-output=0 compute-hw=1 ! queue max-size-buffers=10 ! identity name=stats_identity ! queue max-size-buffers=10 ! nvv4l2h265enc insert-sps-pps=true bitrate=4000000 ! h265parse ! rtph265pay name=pay0 pt=96 config-interval=-1 )
Opening in BLOCKING MODE 
Opening in BLOCKING MODE 
NvMMLiteOpen : Block : BlockType = 279 
NvMMLiteBlockCreate : Block : BlockType = 279 
NvMMLiteOpen : Block : BlockType = 8 
===== NvVideo: NVENC =====
NvMMLiteBlockCreate : Block : BlockType = 8 
FPS: 0.15
identity->surf : 
  batchSize = 1
  numFilled = 1
  memType = 4
  surfaceList[0]:
    width = 5120
    height = 1440
    pitch = 5120
    layout = 0
    colorFormat = 7
    bufferDesc = 71
    dataSize = 11272192
    dataPtr = 0xffff38055fb0
it's NVBUF_COLOR_FORMAT_NV12_ER!
    NvBufSurfaceParams->planeParams:
      num_planes = 2
      width[0] = 5120
      height[0] = 1440
      pitch[0] = 5120
      offset[0] = 0
      psize[0] = 7471104
      bytesPerPix[0] = 1
      width[1] = 2560
      height[1] = 720
      pitch[1] = 5120
      offset[1] = 7471104
      psize[1] = 3801088
      bytesPerPix[1] = 2
    NvBufSurfaceParams->mappedAddr:
      mappedAddr->addr[0] = (nil)
      mappedAddr->addr[1] = (nil)
      mappedAddr->addr[2] = (nil)
      mappedAddr->addr[3] = (nil)
      mappedAddr->eglImage is NULL
CUDA EGL registration successful for surface 0
cuGraphicsResourceGetMappedEglFrame successful for surface 0
  frame.width = 5120
  frame.height = 1440
CUDA Array for surface 0: 0x2072e0000
Image dimensions for surface 0: 5120 x 1440

===== Starting Image Processing =====
Image size: 5120 x 1440
Apply CLAHE: YES
Apply Brightness: NO
CLAHE parameters:
  Clip limit: 0.10
  Tile grid: 8 x 8

[CLAHE] Starting processing for 5120x1440 image
[CLAHE] Tile configuration: 8x8 tiles
[CLAHE] Clip limit: 0.10
[CLAHE] Tile size: 640x180 pixels
[CLAHE] Total tiles: 64
[CUDA] Using CUDA array: 0x2072e0000
段错误 (核心已转储)

In fact, the pipeline works fine whether I add bl-output=0 compute-hw=1 or not. In your cuda code, is the CUarray modified and thus causing the crash?

You can refer to /usr/src/jetson_multimedia_api/samples/03_video_cuda_enc, this sample show how to map nvbufsurface to EGLImage and how to process EGLImage by CUDA.

if (nvbuf_surf->surfaceList[0].mappedAddr.eglImage == NULL)
    {
        if (NvBufSurfaceMapEglImage(nvbuf_surf, 0) != 0)
        {
            cerr << "Unable to map EGL Image" << endl;
            return -1;
        }
    }

    ctx->eglimg = nvbuf_surf->surfaceList[0].mappedAddr.eglImage;
    if (ctx->eglimg == NULL)
    {
        cerr << "Error while mapping dmabuf fd to EGLImage" << endl;
        return -1;
    }

    /* Map EGLImage to CUDA buffer, and call CUDA kernel to
       draw a 32x32 pixels black box on left-top of each frame */
    HandleEGLImage(&ctx->eglimg);

    /* Destroy EGLImage */
    if (NvBufSurfaceUnMapEglImage(nvbuf_surf, 0) != 0)
    {
        cerr << "Unable to unmap EGL Image" << endl;
        return -1;
    }
    ctx->eglimg = NULL;

Handle_EGLImage and CUDA code is located /usr/src/jetson_multimedia_api/samples/common/algorithm/cuda