首页 > 技术知识 > 正文

1. 前言

nvidia相机插件“nvv4l2camerasrc”目前只支持UYVY格式 然而使用的相机是GRAY8格式,需要扩展nvv4l2camerasrc格式

2. 参考12_camera_v4l2_cuda

尝试运行样例来捕获帧,并将其移植到nvv4l2camerasrc插件 sample如下: /usr/src/jetson_multimedia_api/samples/12_camera_v4l2_cuda

3. 丢帧问题

目前能够使用 v4l2src gstreamer插件捕获帧。 但是性能有些问题,导致帧丢失。 已经确定帧丢失发生在我的管道的开始,所以基本上是在源。

希望通过使用 nvv4l2camerasrc 插件,可以利用NVMM缓冲区有一些性能提高,也能够增加v4l2设备在插件中使用的队列缓冲区大小。

(1)在运行中检查是否能达到目标帧数:

gst-launch-1.0 v4l2src ! video/x-raw,format=GRAY8,width=_W_,height=_H_,framerate=_FR_ ! nvvidconv ! video/x-raw(memory:NVMM),format=I420 ! fpsdisplaysink text-overlay=0 video-sink=fakesink sync=0 -v

如果能在管道中获得足够的性能,可能不需要定制nvv4l2camerasrc。 自定义消除了一个从CPU缓冲区到NVMM缓冲区的内存副本。 如果想减少CPU负载,可以试一试。

(2)采集异常log

Setting pipeline to PAUSED … Pipeline is live and does not need PREROLL … /GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstFakeSink:fakesink0: sync = false Setting pipeline to PLAYING … New clock: GstSystemClock /GstPipeline:pipeline0/GstV4l2Src:v4l2src0.GstPad:src: caps = video/x-raw, format=(string)GRAY8, width=(int)4208, height=(int)3120, framerate=(fraction)26/1, colorimetry=(string)2:4:7:1, interlace-mode=(string)progressive /GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:src: caps = video/x-raw, format=(string)GRAY8, width=(int)4208, height=(int)3120, framerate=(fraction)26/1, colorimetry=(string)2:4:7:1, interlace-mode=(string)progressive /GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:src: caps = video/x-raw(memory:NVMM), width=(int)4208, height=(int)3120, framerate=(fraction)26/1, interlace-mode=(string)progressive, format=(string)NV12 /GstPipeline:pipeline0/GstCapsFilter:capsfilter1.GstPad:src: caps = video/x-raw(memory:NVMM), width=(int)4208, height=(int)3120, framerate=(fraction)26/1, interlace-mode=(string)progressive, format=(string)NV12 /GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0.GstGhostPad:sink.GstProxyPad:proxypad0: caps = video/x-raw(memory:NVMM), width=(int)4208, height=(int)3120, framerate=(fraction)26/1, interlace-mode=(string)progressive, format=(string)NV12 /GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0/GstFakeSink:fakesink0.GstPad:sink: caps = video/x-raw(memory:NVMM), width=(int)4208, height=(int)3120, framerate=(fraction)26/1, interlace-mode=(string)progressive, format=(string)NV12 /GstPipeline:pipeline0/GstFPSDisplaySink:fpsdisplaysink0.GstGhostPad:sink: caps = video/x-raw(memory:NVMM), width=(int)4208, height=(int)3120, framerate=(fraction)26/1, interlace-mode=(string)progressive, format=(string)NV12 /GstPipeline:pipeline0/GstCapsFilter:capsfilter1.GstPad:sink: caps = video/x-raw(memory:NVMM), width=(int)4208, height=(int)3120, framerate=(fraction)26/1, interlace-mode=(string)progressive, format=(string)NV12 /GstPipeline:pipeline0/Gstnvvconv:nvvconv0.GstPad:sink: caps = video/x-raw, format=(string)GRAY8, width=(int)4208, height=(int)3120, framerate=(fraction)26/1, colorimetry=(string)2:4:7:1, interlace-mode=(string)progressive /GstPipeline:pipeline0/GstCapsFilter:capsfilter0.GstPad:sink: caps = video/x-raw, format=(string)GRAY8, width=(int)4208, height=(int)3120, framerate=(fraction)26/1, colorimetry=(string)2:4:7:1, interlace-mode=(string)progressive gst_nvvconv_transform: NvBufferTransform not supported 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 error (-5) Execution ended after 0:00:00.141547135 Setting pipeline to PAUSED … Setting pipeline to READY … Setting pipeline to NULL … Freeing pipeline …
<

(3)更换视频格式 I420替换NV12。

用I420可以采集视频,但不是预期的26帧,而是21帧。 可能是从GRAY8到I420发生了格式转换导致的。

源代码是4208x312026fps。 由于分辨率高于4K,建议定制nvv4l2camerasrc插件。

4. 运行定制nvv4l2camerasrc

修改了插件以支持GRAY8格式。 然而,我遇到了一些奇怪的性能问题

gst-launch-1.0 v4l2src ! “video/x-raw, format=(string)GRAY8, width=(int)4208, height=(int)3120, framerate=(fraction)26/1” ! fpsdisplaysink video-sink=fakesink text-overlay=false -e -v

帧率是正常的26fps。

gst-launch-1.0 nvv4l2camerasrc bufapi-version=true ! “video/x-raw(memory:NVMM), format=(string)GRAY8, width=(int)4208, height=(int)3120, framerate=(fraction)26/1” ! fpsdisplaysink video-sink=fakesink text-overlay=false -e -v

只有2fps。

5. 运行12_camera_v4l2_cuda sample

试试12_camera_v4l2_cuda 看看运行示例时能否达到目标帧率

得到了下面的图像,帧率只有10fps。

nvidia xavier nx平台nvv4l2camerasrc支持GRAY8格式问题调试

6. 格式转换问题

根据文档nvvidconv插件应该支持从GRAY8(NVMM)到I420(NVMM)的转换。 然而,当我使用管道做这个转换,总是报以下问题

st_nvvconv_transform: NvBufferTransform not supported

12_camera_v4l2_cudaby GRAY8到I420的转换默认如下:

if (-1 == NvBufferTransform(ctx->g_buff[v4l2_buf.index].dmabuff_fd, ctx->render_dmabuf_fd, &transParams)) ERROR_RETURN(“Failed to convert the buffer”); if (ctx->cam_pixfmt == V4L2_PIX_FMT_GREY) { if(!nvbuff_do_clearchroma(ctx->render_dmabuf_fd)) ERROR_RETURN(“Failed to clear chroma”); }

调用NvBufferGetParams()来获取pitch,width,height。 看起来分辨率4208×3120,硬件缓冲区没有相同的间距和宽度, 所以帧没有捕获和放入缓冲区正确。

这是否意味着DMA不能用于此分辨率的v4l2相机?

if (ctx->cam_pixfmt == V4L2_PIX_FMT_GREY && params.pitch[0] != params.width[0]) ctx->capture_dmabuf = false;

对于我使用的分辨率,我得到 witdh = 4208 height = 3120 pitch = 4352 所以在我的例子中,它不使用DMA。为什么会这样呢? 通过手动修改宽度为4224在Raw2NvBuffer调用。所以显然宽度是64的倍数?为什么会这样呢? 无论如何,这是没有使用DMA,,因为这会导致过低的帧率。为什么会这样呢?

原因如下:

这是硬件DMA缓冲区的约束。 对于4208×3120,它的缓冲区在4352×3120中,有效数据在4208×3120中。

应该使用pitch=width分配DMA缓冲区。如果源程序只支持4208×3120,那么您将需要捕获到CPU缓冲区并调用Raw2NvBuffer。

7. 间距值设置

间距值对齐到256,所以320→512,640→768,4208→4352。

猜你喜欢