TX2 Camera convert/encode using Multimedia API issue

Hi,
I’m a newbie for Jetson products.

Recently, I’m trying to capture/pixel-format-converting/encoding on frame units. (To meet the conditions for finally streaming)
First, the camera interface I use is PCIe. (V4L2 support)

So, I’m implementing code through samples(12, etc… ) and API documents.

  • Capture: using ioctl (MMAP)
  • Converting: ouput plane (MMAP), capture plane (MMAP)
  • Encoding: ouput plane (MMAP), capture plane (MMAP)

However, I am blocked in the part of encoding after converting.

How can I connect the “render_dmabuf_fd” obtained through NvBufferTransform() to “NvBuffer” that NVVideoEncoder() can handle?

I tried to find similar content in this forum, but I still have failed.
I uploaded the code I am implementing.
The part that encoding is required to be TODO on the 620 line.
camera_v4l2_cuda.cpp (22.3 KB)

Can anyone please help me resolve this issue?
Thank you.

Hi,
There is a patch for 12_camera_v4l2_cuda + NvVideoEncoder. Please take a look at
tegra multimedia samples not working properly - #11 by DaneLLL

Thanks for your answer.
I will try to implement it with the code and share the results with you.

Hi, @DaneLLL

I tried to implement the code by referring to patch file and original sample.12 of 32.2. (I’m using 32.5 version.)
Because of the current hardware specification, I must use MMAP in the capture plane. (Not available DMA)
Therefore, I wrote the code as a condition that does not use DMA. (request_camera_buff_mmap() in use)
And I used Raw2NVBuffer() instead of NvBufferMemSyncForDevice() in start_capture(). (Because it is MMAP)

First of all, if I use Raw2NVBuffer() and NvBufferMemSyncForDevice(), all the following events are generated, blocked, and backtrace information is as follows.

#0 0x0000007fb7f732a4 in futex_wait_cancelable (private=, expected=0, futex_word=0x555561e308) at …/sysdeps/unix/sysv/linux/futex-internal.h:88
#1 0x0000007fb7f732a4 in __pthread_cond_wait_common (abstime=0x0, mutex=0x555561e2b0, cond=0x555561e2e0) at pthread_cond_wait.c:502
#2 0x0000007fb7f732a4 in __pthread_cond_wait (cond=0x555561e2e0, mutex=0x555561e2b0)
at pthread_cond_wait.c:655
#3 0x0000007fb75b7fdc in () at /usr/lib/aarch64-linux-gnu/tegra/libnvos.so
#4 0x0000007fb4d24b54 in TegraV4L2_Poll_OPlane ()
at /usr/lib/aarch64-linux-gnu/tegra/libtegrav4l2.so
#5 0x0000007fb4d8a088 in plugin_ioctl ()
at /usr/lib/aarch64-linux-gnu/libv4l/plugins/nv/libv4l2_nvvideocodec.so
#6 0x0000007fb7e555c0 in v4l2_ioctl () at /usr/lib/aarch64-linux-gnu/libv4l2.so.0
#7 0x000000555558f3d8 in NvV4l2ElementPlane::dqBuffer(v4l2_buffer&, NvBuffer**, NvBuffer**, unsigned int) ()
#8 0x000000555555ccd8 in start_capture(context_t*) ()
#9 0x000000555555b0e0 in main ()

Also, if I use NvBufferMemSyncForDevice(), the following error is displayed.

NvMapMemCacheMaint:1075334668 failed [99]
Got EOS, exiting…
[Thread 0x7fa58211d0 (LWP 9665) exited]
NvMapMemCacheMaint:1075334668 failed [99]
NvMapMemCacheMaint:1075334668 failed [99]
NvMapMemCacheMaint:1075334668 failed [99]
NvMapMemCacheMaint:1075334668 failed [99]
NvMapMemCacheMaint:1075334668 failed [99]
NvMapMemCacheMaint:1075334668 failed [99]

Below is the code I modified.
camera_v4l2_cuda.cpp (24.8 KB)
If the use according to MMAP/DMA is wrong, please let me know.
Thank you.

Hi,
Should be something wrong in the app. Please check if you can capturing frames and encoding dummy NvBuffer separately. May do

  1. Capture frames through v4l2 but do not copy to NvBuffer
  2. Feed dummy NvBuffer(empty buffer; no valid data) to NvVideoEncoder.

If capturing frames and encoding dummy NvBuffer work, may try to call Raw2NVBuffer().

As comparison please also try gstreamer commands. Please try the command:

$ gst-launch-1.0 v4l2src ! video/x-raw,width=640,height=480,format=NV12,framerate=30/1 ! fakesink

If it works, please try

$ gst-launch-1.0 v4l2src ! video/x-raw,width=640,height=480,format=NV12,framerate=30/1 ! nvvidconv ! nvv4l2h264enc ! h264parse ! matroskamux ! filesink location=a.mkv
1 Like

Hi,
The first command returns errors… (Note, it works with capture and converting with MMAP without encoding to output to EGLDISPLAY. - with sample.12)

$ gst-launch-1.0 v4l2src ! video/x-raw,width=1280,height=720,format=NV12,framerate=30/1 ! fakesink
Setting pipeline to PAUSED ...
Pipeline is live and does not need PREROLL ...
ERROR: from element /GstPipeline:pipeline0/GstV4l2Src:v4l2src0: Internal data stream error.
Additional debug info:
gstbasesrc.c(3055): gst_base_src_loop (): /GstPipeline:pipeline0/GstV4l2Src:v4l2src0:
streaming stopped, reason not-negotiated (-4)
ERROR: pipeline doesn't want to preroll.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

Below is the current video format.

$ v4l2-ctl --get-fmt-video
Format Video Capture:
        Width/Height      : 1280/720
        Pixel Format      : 'NV12'
        Field             : None
        Bytes per Line    : 1280
        Size Image        : 921600
        Colorspace        : SMPTE 170M
        Transfer Function : Default (maps to Rec. 709)
        YCbCr/HSV Encoding: Default (maps to ITU-R 601)
        Quantization      : Default (maps to Limited Range)

In fact, I first tested Gstreamer, but it did not work. So I was implementing directly with Multimedia API.
Fortunately, like notes on the above, I confirmed that “Capture → Converting → EgLDisplay” through Sample.12 modifications, and were in implementing parts for encoding.

Note, below is the entire format of the capture card I use. (PCIe interface) .

> $ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
        Index       : 0
        Type        : Video Capture
        Pixel Format: 'MPEG' (compressed)
        Name        : H264 Encoded Stream
                Size: Discrete 640x480
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 720x480
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 720x576
                        Interval: Discrete 0.020s (50.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1024x768
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x800
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1360x768
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1440x900
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1680x1050
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)

        Index       : 1
        Type        : Video Capture
        Pixel Format: 'YV12'
        Name        : YVU 4:2:0 12bpp
                Size: Discrete 640x480
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 720x480
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 720x576
                        Interval: Discrete 0.020s (50.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1024x768
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x800
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1360x768
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1440x900
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1680x1050
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)

        Index       : 2
        Type        : Video Capture
        Pixel Format: 'YU12'
        Name        : YUV 4:2:0 12bpp
                Size: Discrete 640x480
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 720x480
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 720x576
                        Interval: Discrete 0.020s (50.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1024x768
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x800
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1360x768
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1440x900
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1680x1050
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)

        Index       : 3
        Type        : Video Capture
        Pixel Format: 'NV12'
        Name        : NV12 4:2:0 12bpp
                Size: Discrete 640x480
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 720x480
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 720x576
                        Interval: Discrete 0.020s (50.000 fps)
                Size: Discrete 800x600
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1024x768
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x720
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x800
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1280x1024
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1360x768
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1440x900
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1920x1080
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)
                Size: Discrete 1680x1050
                        Interval: Discrete 0.067s (15.000 fps)
                        Interval: Discrete 0.042s (24.000 fps)
                        Interval: Discrete 0.040s (25.000 fps)
                        Interval: Discrete 0.033s (30.000 fps)
                        Interval: Discrete 0.020s (50.000 fps)
                        Interval: Discrete 0.017s (60.000 fps)

And, as you advise me, I will more check for the following items.

  • v4l2 to NvBuffer
  • Dummy NvBuffer to NVVideoEncorder

Hi,
It supports 720p50 and 720p60. You may try:

$ gst-launch-1.0 v4l2src ! video/x-raw,width=1280,height=720,format=NV12,framerate=60/1 ! fakesink

And may try io-mode=mmap:

$ gst-launch-1.0 v4l2src io-mode=2 ! video/x-raw,width=1280,height=720,format=NV12,framerate=60/1 ! fakesink
1 Like

It supports 720p50 and 720p60.

Oh, thank you. It was my fault…

And, after added “io-mode = 2” option, it works well. Also, encoding works well :)

gst-launch-1.0 v4l2src io-mode=2 ! video/x-raw,width=1280,height=720,format=NV12,framerate=50/1 ! nvvidconv ! nvv4l2h264enc ! h264parse ! matroskamux ! filesink location=a.mkv

Implementing the same process as the GStreamer command above using the “Multimedia API”, it seems to be able to solve this issue.
As you say, I think I’m using Multimedia API incorrectly.
Could you recommend samples or documents related to this?

Thank you!

Please refer to Jetson Linux API Reference: Main Page (nvidia.com)

Thanks for the reply.
I was continually referencing the document.
Also, I’m looking for some other points compared to “GStreamer source code”.

Hi,
The reference sample is 12_camera_v4l2_cuda. Except YUV422, it also has implementation of MJPEG decoding. You may set source to MJPEG and give it a try.

Hi,

I changed the existing capture card to a capture card that supports YUV422 (YUYV, UYVY). (Also DMA buffer available)
So, I can now use 12_camera_v4l2_cuda example without modifying examples. (Previously, I modified this example due to the pixelformat of the existing capture card and the DMA Buffer non-support)

Also, I applied the patch you provided for Encode code to 12_camera_v4l2_cuda.
However, there is still a problem on Encode’s part. (Error content is the same as before)

Hi,
Please check if you can apply this patch and run successfully:

diff --git a/multimedia_api/ll_samples/samples/12_camera_v4l2_cuda/camera_v4l2_cuda.cpp b/multimedia_api/ll_samples/samples/12_camera_v4l2_cuda/camera_v4l2_cuda.cpp
index 0ec23a4..c63acca 100644
--- a/multimedia_api/ll_samples/samples/12_camera_v4l2_cuda/camera_v4l2_cuda.cpp
+++ b/multimedia_api/ll_samples/samples/12_camera_v4l2_cuda/camera_v4l2_cuda.cpp
@@ -46,6 +46,8 @@
 
 #define MJPEG_EOS_SEARCH_SIZE 4096
 
+#define OUTPLANE_BUFNUM 6
+static int outplane_fd[OUTPLANE_BUFNUM];
 static bool quit = false;
 
 using namespace std;
@@ -330,6 +332,48 @@ display_initialize(context_t * ctx)
     return true;
 }
 
+
+
+static bool
+encoder_initialize(context_t * ctx)
+{
+    ctx->enc = NvVideoEncoder::createVideoEncoder("enc0");
+    if (ctx->enc == NULL)
+        ERROR_RETURN("Failed to create video encoder");
+
+    if (ctx->enc->setCapturePlaneFormat(V4L2_PIX_FMT_H264, ctx->cam_w,
+                ctx->cam_h, 2 * 1024 * 1024) < 0)
+        ERROR_RETURN("Failed to set up ENC capture plane format");
+
+    if (ctx->enc->setOutputPlaneFormat(V4L2_PIX_FMT_YUV420M, ctx->cam_w,
+                ctx->cam_h) < 0)
+        ERROR_RETURN("Failed to set up ENC output plane format");
+
+    if (ctx->enc->setBitrate(4<<20) < 0)
+        ERROR_RETURN("Failed to set up ENC bitrate");
+
+    if (ctx->enc->setProfile(V4L2_MPEG_VIDEO_H264_PROFILE_HIGH) < 0)
+        ERROR_RETURN("Failed to set up ENC profile");
+
+    if (ctx->enc->setLevel(V4L2_MPEG_VIDEO_H264_LEVEL_5_0) < 0)
+        ERROR_RETURN("Failed to set up ENC level");
+
+    if (ctx->enc->setRateControlMode(V4L2_MPEG_VIDEO_BITRATE_MODE_VBR) < 0)
+        ERROR_RETURN("Failed to set up ENC rate control mode");
+
+    if (ctx->enc->output_plane.reqbufs(V4L2_MEMORY_DMABUF, OUTPLANE_BUFNUM))
+        ERROR_RETURN("Failed to set up ENC output plane");
+
+    if (ctx->enc->capture_plane.setupPlane(V4L2_MEMORY_MMAP, 6, true, false) < 0)
+        ERROR_RETURN("Failed to set up ENC capture plane");
+
+    ctx->enc->subscribeEvent(V4L2_EVENT_EOS,0,0);
+
+    return true;
+}
+
+
+
 static bool
 init_components(context_t * ctx)
 {
@@ -339,6 +383,9 @@ init_components(context_t * ctx)
     if (!display_initialize(ctx))
         ERROR_RETURN("Failed to initialize display");
 
+    if (!encoder_initialize(ctx))
+        ERROR_RETURN("Failed to initialize encoder");
+
     INFO("Initialize v4l2 components successfully");
     return true;
 }
@@ -539,12 +586,57 @@ start_stream(context_t * ctx)
         ERROR_RETURN("Failed to start streaming: %s (%d)",
                 strerror(errno), errno);
 
+    // Start ENC output plane
+    if (ctx->enc->output_plane.setStreamStatus(true) < 0)
+        ERROR_RETURN("Failed to start ENC output plane streaming");
+
+    // Start ENC capture plane
+    if (ctx->enc->capture_plane.setStreamStatus(true) < 0)
+        ERROR_RETURN("Failed to start ENC capture plane streaming");
+
     usleep(200);
 
     INFO("Camera video streaming on ...");
     return true;
 }
 
+static bool
+enc_capture_dqbuf_thread_callback(struct v4l2_buffer *v4l2_buf,
+                                   NvBuffer * buffer, NvBuffer * shared_buffer,
+                                   void *arg)
+{
+    context_t *ctx = (context_t *) arg;
+    if (v4l2_buf == NULL)
+    {
+        printf("Got nullptr \n");
+        return false;
+    }
+
+    if(v4l2_buf->flags & V4L2_BUF_FLAG_LAST)
+    {
+        struct v4l2_event ev;
+        int ret = 0;
+        memset(&ev,0,sizeof(struct v4l2_event));
+        ret = ctx->enc->dqEvent(ev,1000);
+        if (ret < 0)
+            printf("Error in dqEvent \n");;
+        if(ev.type == V4L2_EVENT_EOS)
+        {
+            printf("Got EOS, exiting...\n");
+            return false;
+        }
+    }
+
+    printf("encoded frame size %d \n", buffer->planes[0].bytesused);
+    if (ctx->enc->capture_plane.qBuffer(*v4l2_buf, NULL) < 0)
+    {
+        ctx->enc->abort();
+        ERROR_RETURN("Failed to queue buffer on ENC capture plane");
+    }
+
+    return true;
+}
+
 static void
 signal_handle(int signum)
 {
@@ -592,6 +684,25 @@ start_capture(context_t * ctx)
     if (ctx->cam_pixfmt == V4L2_PIX_FMT_MJPEG)
         ctx->jpegdec = NvJPEGDecoder::createJPEGDecoder("jpegdec");
 
+    ctx->enc->capture_plane.setDQThreadCallback(enc_capture_dqbuf_thread_callback);
+    ctx->enc->capture_plane.startDQThread(ctx);
+    // Enqueue all the empty capture plane buffers
+    for (uint32_t i = 0; i < ctx->enc->capture_plane.getNumBuffers(); i++)
+    {
+        struct v4l2_buffer v4l2_buf;
+        struct v4l2_plane planes[MAX_PLANES];
+
+        memset(&v4l2_buf, 0, sizeof(v4l2_buf));
+        memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
+
+        v4l2_buf.index = i;
+        v4l2_buf.m.planes = planes;
+
+        if (ctx->enc->capture_plane.qBuffer(v4l2_buf, NULL) < 0)
+            ERROR_RETURN("Failed to queue buffer on ENC capture plane");
+    }
+
+
     /* Init the NvBufferTransformParams */
     memset(&transParams, 0, sizeof(transParams));
     transParams.transform_flag = NVBUFFER_TRANSFORM_FILTER;
@@ -600,6 +711,15 @@ start_capture(context_t * ctx)
     /* Enable render profiling information */
     ctx->renderer->enableProfiling();
 
+    int bufferIndex = 0;
+    NvBufferCreateParams input_params = {0};
+    input_params.payloadType = NvBufferPayload_SurfArray;
+    input_params.width = ctx->cam_w;
+    input_params.height = ctx->cam_h;
+    input_params.layout = NvBufferLayout_Pitch;
+    input_params.colorFormat = get_nvbuff_color_fmt(V4L2_PIX_FMT_YUV420M);
+    input_params.nvbuf_tag = NvBufferTag_VIDEO_ENC;
+
     fds[0].fd = ctx->cam_fd;
     fds[0].events = POLLIN;
     /* Wait for camera event with timeout = 5000 ms */
@@ -625,6 +745,59 @@ start_capture(context_t * ctx)
             if (ctx->frame == ctx->save_n_frame)
                 save_frame_to_file(ctx, &v4l2_buf);
 
+
+#if 1
+            {
+                // Cache sync for VIC operation
+                NvBufferMemSyncForDevice(ctx->g_buff[v4l2_buf.index].dmabuff_fd, 0,
+                        (void**)&ctx->g_buff[v4l2_buf.index].start);
+
+                NvBuffer *buffer;
+                int fd = -1;
+
+                struct v4l2_buffer enc_buf;
+                struct v4l2_plane planes[MAX_PLANES];
+
+                memset(&enc_buf, 0, sizeof(enc_buf));
+                memset(planes, 0, MAX_PLANES * sizeof(struct v4l2_plane));
+
+                enc_buf.type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+                enc_buf.memory = V4L2_MEMORY_DMABUF;
+
+                enc_buf.m.planes = planes;
+
+                // Check if we need dqBuffer first
+                if (bufferIndex < OUTPLANE_BUFNUM &&
+                    ctx->enc->output_plane.getNumQueuedBuffers() <
+                    ctx->enc->output_plane.getNumBuffers())
+                {
+                    // The queue is not full, no need to dqBuffer
+                    // Prepare buffer index for the following qBuffer
+                    enc_buf.index = bufferIndex;
+                    // Create Render buffer
+                    if (-1 == NvBufferCreateEx(&fd, &input_params))
+                        ERROR_RETURN("Failed to create NvBuffer");
+                    outplane_fd[bufferIndex] = fd;
+                    bufferIndex++;;
+                }
+                else
+                {
+                    // Output plane full or max outstanding number reached
+                    ctx->enc->output_plane.dqBuffer(enc_buf, &buffer, NULL, 10);
+                    fd = enc_buf.m.planes[0].m.fd;
+                }
+
+                if (-1 == NvBufferTransform(ctx->g_buff[v4l2_buf.index].dmabuff_fd, fd,
+                            &transParams))
+                    ERROR_RETURN("Failed to convert the buffer");
+                // Push the frame into V4L2.
+                enc_buf.m.planes[0].m.fd = fd;
+                enc_buf.m.planes[0].bytesused = 1; // byteused must be non-zero
+                ctx->enc->output_plane.qBuffer(enc_buf, NULL);
+
+                ctx->renderer->render(fd);
+            }
+#else
             if (ctx->cam_pixfmt == V4L2_PIX_FMT_MJPEG) {
                 int fd = 0;
                 uint32_t width, height, pixfmt;
@@ -679,6 +852,7 @@ start_capture(context_t * ctx)
 
             /* Preview */
             ctx->renderer->render(ctx->render_dmabuf_fd);
+#endif
 
             /* Enqueue camera buffer back to driver */
             if (ioctl(ctx->cam_fd, VIDIOC_QBUF, &v4l2_buf))
@@ -707,6 +881,9 @@ stop_stream(context_t * ctx)
         ERROR_RETURN("Failed to stop streaming: %s (%d)",
                 strerror(errno), errno);
 
+    ctx->enc->setEncoderCommand(V4L2_ENC_CMD_STOP, 1);
+    ctx->enc->capture_plane.waitForDQThread(2000);
+
     INFO("Camera video streaming off ...");
     return true;
 }
@@ -715,7 +892,7 @@ int
 main(int argc, char *argv[])
 {
     context_t ctx;
-    int error = 0;
+    int error = 0, i;
 
     set_defaults(&ctx);
 
@@ -767,6 +944,12 @@ cleanup:
 
     NvBufferDestroy(ctx.render_dmabuf_fd);
 
+    for (i = 0; i < OUTPLANE_BUFNUM ; i++)
+        NvBufferDestroy(outplane_fd[i]);
+
+    if (ctx.enc != NULL)
+        delete ctx.enc;
+
     if (error)
         printf("App run failed\n");
     else
diff --git a/multimedia_api/ll_samples/samples/12_camera_v4l2_cuda/camera_v4l2_cuda.h b/multimedia_api/ll_samples/samples/12_camera_v4l2_cuda/camera_v4l2_cuda.h
index 4155cd2..d7a5047 100644
--- a/multimedia_api/ll_samples/samples/12_camera_v4l2_cuda/camera_v4l2_cuda.h
+++ b/multimedia_api/ll_samples/samples/12_camera_v4l2_cuda/camera_v4l2_cuda.h
@@ -28,6 +28,7 @@
 
 #include <queue>
 #include "NvJpegDecoder.h"
+#include "NvVideoEncoder.h"
 
 #define V4L2_BUFFERS_NUM    4
 
@@ -89,6 +90,7 @@ typedef struct
 
     /* MJPEG decoding */
     NvJPEGDecoder *jpegdec;
+    NvVideoEncoder *enc;
 
     /* Verbose option */
     bool enable_verbose;
diff --git a/multimedia_api/ll_samples/samples/unittest_samples/camera_unit_sample/camera_unit_sample.cpp b/multimedia_api/ll_samples/samples/unittest_samples/camera_unit_sample/camera_unit_sample.cpp
index c45c524..1a95091 100644
--- a/multimedia_api/ll_samples/samples/unittest_samples/camera_unit_sample/camera_unit_sample.cpp
+++ b/multimedia_api/ll_samples/samples/unittest_samples/camera_unit_sample/camera_unit_sample.cpp
@@ -991,6 +991,7 @@ int capture_proc (context_t &ctx, int argc, char const *argv[])
     struct sigaction sig_action;
     char camera_device[16];
     char renderer[16];
+    int fd;
 
     /* Register a shutdown handler to ensure
     ** a clean exit if <ctrl+c> is detected.
@@ -1068,6 +1069,11 @@ int capture_proc (context_t &ctx, int argc, char const *argv[])
     ctx.fd = v4l2_open(camera_device, flags | O_RDWR);
     CHECK_ERROR(ctx.fd == -1, "Error in opening camera device", cleanup);
 
+    fd = v4l2_open("/dev/video1", flags | O_RDWR);
+    CHECK_ERROR(fd == -1, "Error in opening camera device", cleanup);
+    cout << "open the second camera!!!" << endl;
+    v4l2_close(fd);
+
     /* The Querycap Ioctl call queries the video capabilities
     ** of the opened node and checks for
     ** V4L2_CAP_VIDEO_CAPTURE_MPLANE capability on the device.

We verify it on r32.5.1/r32.6.1 and it runs well.

1 Like

Thanks for the support :) @DaneLLL

Now, EOS and DQThread’s infinite cond_wait phenomenon have been resolved.
But, the following error occurs in NvBufferMemSyncForDevice.

NvMapMemCacheMaint:1075334668 failed [99]

What’s the meaning of that number 99?
Is there a document for errors?

Done!!

Note. I found a bug. please refer to comment below.
( version info: nvidia-l4t-jetson-multimedia-api // 32.5.0-20210115151051 )

static void
set_defaults(context_t *ctx)
{
  memset(ctx, 0, sizeof(context_t));

  ctx->cam_devname = "/dev/video0";
  ctx->cam_fd = -1;
  ctx->cam_pixfmt = V4L2_PIX_FMT_YUYV;
  ctx->cam_w = 640;
  ctx->cam_h = 480;
  ctx->frame = 0;
  ctx->save_n_frame = 0;

  ctx->g_buff = NULL;
  ctx->capture_dmabuf = false;  // <========================= It must be true
  ctx->renderer = NULL;
  ctx->fps = 30;

  ctx->enable_cuda = false;
  ctx->egl_image = NULL;
  ctx->egl_display = EGL_NO_DISPLAY;

  ctx->enable_verbose = false;
}

Anyway, thank you @DaneLLL

Hi,
The parameter capture_dmabuf should be true by default. A bit strange you see it be false. But you have resolved it, it should be fine now. Glad to know you work out a solution.

1 Like