Optimizing Camera Pipeline on Jetson Xavier NX to Reduce Lag Without Maxing VIC

I’m working with example 12 to read from a camera and display it using nvdrmvideosink. When I run the following pipeline:

gst-launch-1.0 nvv4l2camerasrc device=/dev/video0 ! 'video/x-raw(memory:NVMM),width=3840,height=2160,format=UYVY,framerate=30/1' \
! nvvidconv ! 'video/x-raw(memory:NVMM),format=NV12,width=1920,height=1080' ! nvdrmvideosink

the video output is smooth with no lag. However, when I use the attached code below, the output becomes jittery and lags unless I enable the maximum VIC (Video Image Compositor) clock frequency.

Is there a way to optimize this pipeline to achieve smooth playback without maxing out the VIC, possibly by utilizing NVIDIA’s hardware engines more effectively? I’m using the Jetson Xavier NX with Jetpack 5.1.4.

12_v4l2_camera_cuda.zip (7.6 KB)

hello user34150,

may I know your actual use-case?
it may due to format conversion performance (YUV to RGB) if you would like to send the buffers to GPU.

I’m trying this approach, but after a while, my video starts to lag and slow down. Is there something incorrect in my handling?

static void
notify_to_destroy (gpointer user_data)
{
    uint64_t dmabuf_fd;
    NvBufSurface *surface;
    
    dmabuf_fd = *(uint64_t *)user_data;
    GST_INFO ("NvBufSurfaceDestroy %lu", dmabuf_fd);
    NvBufSurfaceFromFd(dmabuf_fd, (void**)(&surface));
    // if (NvBufSurfaceFromFd(dmabuf_fd, (void**)(&surface)) == 0) {
    //     NvBufSurfaceDestroy(surface);
    // }
    g_free(user_data);
}

static gboolean feed_function(GstElement *appsrc, NvBufSurface *pSurf) {
    GstBuffer *buffer;
    GstFlowReturn ret;
    GstMapInfo map = {0};
    gpointer user_data = NULL;
    GstMemoryFlags flags = (GstMemoryFlags)0;

    if (!pSurf) {
        g_printerr("No NvBufSurface available\n");
        return G_SOURCE_REMOVE;
    }

    // Thiết lập user_data cho buffer (để hủy khi hoàn thành)
    user_data = g_malloc(sizeof(uint64_t));
    GST_INFO("Using NvBufSurface with bufferDesc: %lu", pSurf->surfaceList[0].bufferDesc);
    *(uint64_t *)user_data = pSurf->surfaceList[0].bufferDesc;

    // Tạo GstBuffer và bọc quanh NvBufSurface
    buffer = gst_buffer_new_wrapped_full(flags,
                                         pSurf,
                                         sizeof(NvBufSurface),
                                         0,
                                         sizeof(NvBufSurface),
                                         user_data,
                                         notify_to_destroy);

    if (!buffer) {
        g_printerr("Failed to create GstBuffer\n");
        return G_SOURCE_REMOVE;
    }

    buffer->pts = timestamp;

    gst_buffer_map (buffer, &map, GST_MAP_WRITE);
    memcpy(map.data, pSurf , sizeof(NvBufSurface));
    gst_buffer_unmap(buffer, &map);

    // Đẩy buffer vào appsrc
    g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);
    gst_buffer_unref(buffer);

    timestamp += 33333333;  // Tăng timestamp cho khung hình tiếp theo

    return G_SOURCE_CONTINUE;
}

static bool
start_capture(context_t * ctx, GstElement *appsrc)
{
    struct sigaction sig_action;
    struct pollfd fds[1];
    // NvBufSurf::NvCommonTransformParams transform_params = {0};

    /* Register a shuwdown handler to ensure a clean shutdown if user types <ctrl+c> */
    sig_action.sa_handler = signal_handle;
    sigemptyset(&sig_action.sa_mask);
    sig_action.sa_flags = 0;
    sigaction(SIGINT, &sig_action, NULL);

    fds[0].fd = ctx->cam_fd;
    fds[0].events = POLLIN;
    
    bool use_dmabuf = ctx->capture_dmabuf;
    enum v4l2_memory memory_type = use_dmabuf ? V4L2_MEMORY_DMABUF : V4L2_MEMORY_MMAP;

    /* Wait for camera event with timeout = 5000 ms */
    while (poll(fds, 1, 5000) > 0 && !quit)
    {
        if (fds[0].revents & POLLIN) {
            struct v4l2_buffer v4l2_buf;

            /* Dequeue a camera buff */
            memset(&v4l2_buf, 0, sizeof(v4l2_buf));
            v4l2_buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
            v4l2_buf.memory = memory_type;

            if (ioctl(ctx->cam_fd, VIDIOC_DQBUF, &v4l2_buf) < 0)
                ERROR_RETURN("Failed to dequeue camera buff: %s (%d)",
                        strerror(errno), errno);

            ctx->frame++;
            printf("Current frame: %d\n", ctx->frame);

            NvBufSurface *pSurf = NULL;
            
            if (NvBufSurfaceFromFd(ctx->g_buff[v4l2_buf.index].dmabuff_fd, (void**)(&pSurf)) < 0)
                ERROR_RETURN("Cannot get NvBufSurface from fd");
            
            NvBufSurfaceSyncForDevice(pSurf, 0, 0);

            if (!feed_function(appsrc, pSurf)) {
                g_printerr("Failed to feed buffer to appsrc\n");
                break;
            }

            /* Enqueue camera buffer back to driver */
            if (ioctl(ctx->cam_fd, VIDIOC_QBUF, &v4l2_buf))
                ERROR_RETURN("Failed to queue camera buffers: %s (%d)",
                        strerror(errno), errno);
        }
    }

    return true;
}

hello user34150,

do you have any logs for reference?

The log show is:

WARN: request_camera_buff(): (line:276) Camera v4l2 buf length is not expected
WARN: request_camera_buff(): (line:276) Camera v4l2 buf length is not expected
WARN: request_camera_buff(): (line:276) Camera v4l2 buf length is not expected
WARN: request_camera_buff(): (line:276) Camera v4l2 buf length is not expected
Current frame: 1
Current frame: 2
Current frame: 3
Current frame: 4
Current frame: 5
nvbuf_utils: dmabuf_fd 25 mapped entry NOT found
ERROR: start_capture(): (line:536) Cannot get NvBufSurface from fd
ERROR: main(): (line:654) Failed to start capturing
nvbuf_utils: dmabuf_fd 25 mapped entry NOT found
nvbuf_utils: dmabuf_fd 26 mapped entry NOT found
nvbuf_utils: dmabuf_fd 27 mapped entry NOT found
nvbuf_utils: dmabuf_fd 28 mapped entry NOT found
App run failed

hello jadonjett031,

please initial a new topic since your issue doesn’t looks related to this discussion thread.

1 Like

hello user34150,

did you have camera on/off testing continuously? it cannot allocate capture buffers which might due to camera init has failed.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.