V4L2 issues

Hello,

I’m working on modifying FFmpeg’s v4l2_m2m code to support Jetson nano H264/HEVC.

There are problems with your v4l2 drivers that don’t allow the encoder to be added.

  1. Issue with POLLIN flag
    ffmpeg uses poll() to decide whether to deque the capture buffers. poll() is called with an infinite timeout so that it acts as a throttle from the hardware device. The issue is that even when the POLLIN flag is raised in revents (indicating that capture buffers can be dequeued without blocking), the ioctl call returns -1 with EAGAIN quite a lot of the time. This is incorrect behaviour and means there is no throttling.

  2. Segfault when no sleep at exit
    A lot of the time I see a segfault if there is no sleep after the v4l2 device is closed and ffmpeg is exiting. This seems related to the race condition in this post.
    https://devtalk.nvidia.com/default/topic/1037743/jetson-tx2/vidioc_dqbuf-blocks/2
    Maybe solving 1) will solve this issue.

  3. Your v4l2 drivers need nvbuf_utils.h. At the moment this doesn’t have an open source license. Please release under something that’s LGPL compatible. Also, please provide pkg-config.pc file for nvbuf_utils that exists on your boards and lives in /usr/share/pkgconfig. This will make linking to nvbuf_utils a lot easier.

Thanks,
Andriy

Hi,
ffmpeg with hardware acceleration is the feature we are evaluating to support in future release. Before NVIDIA delivers official package, you may refer to the community contribution:

That’s good to hear, are you planning to support via v4l2_m2m or have nvenc for aarch64?

Also, I’ve read that you already support hardware encoding on gstreamer via v4l2_m2m. Are your contributions available online?

Thanks,
Andriy

Hi,
We have samples based on v4l2 in

/usr/src/tegra_multimedia_api/

You may refer to it and adapt to your usecase.

I was asking about your gstreamer implementation

Also there seems to be an issue when setting the frame rate:

For example in samples/01_video_encode:

./video_encode ~/ffmpeg_sources/ffmpeg/out.yuv 1280 720 H264 out.h264 -br 20000 -fps 20 1

the framerate always remains at 25fps no matter what fps is set to.

Hi,
Please try

./video_encode ~/ffmpeg_sources/ffmpeg/out.yuv 1280 720 H264 out.h264 -br 20000 -fps 20 1 <b>--insert-vui</b>

We have gstreamer user guide. The plugins are nvv4l2h264enc, nvv4l2h265enc, nvv4l2decoder.
https://developer.nvidia.com/embedded/dlc/l4t-accelerated-gstreamer-guide-32-2

I just tried this, but does not seem to work, the resolution is not used (not even with v4l2-ctl --set-fmt-video=width=1920,height=1080 and the output is all green frames (and hangs). I’m using raspberry V2 camera:

jetson@jetson:~$ ffmpeg -f v4l2 -input_format yuyv422 -video_size 1920x1080 -framerate 30 -i /dev/video0 -c:v h264_nvmpi test.mp4
ffmpeg version n4.2.2 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 7 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04)
  configuration: --prefix=/usr/local --extra-cflags=-I/usr/local/include --extra-ldflags=-L/usr/local/lib --arch=arm64 --enable-gpl --disable-stripping --enable-nvmpi --enable-libx264 --enable-libvpx --enable-libopus
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
[video4linux2,v4l2 @ 0x55a0845fe0] The V4L2 driver changed the video from 1920x1080 to 3264x2464
[video4linux2,v4l2 @ 0x55a0845fe0] ioctl(VIDIOC_G_PARM): Inappropriate ioctl for device
[video4linux2,v4l2 @ 0x55a0845fe0] Time per frame unknown
[video4linux2,v4l2 @ 0x55a0845fe0] Stream #0: not enough frames to estimate rate; consider increasing probesize
Input #0, video4linux2,v4l2, from '/dev/video0':
  Duration: N/A, start: 79563.524033, bitrate: N/A
    Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 3264x2464, 1000k tbr, 1000k tbn, 1000k tbc
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (h264_nvmpi))
Press [q] to stop, [?] for help
[mp4 @ 0x55a08487b0] Frame rate very high for a muxer not efficiently supporting it.
Please consider specifying a lower framerate, a different muxer or -vsync 2
Opening in BLOCKING MODE
NvMMLiteOpen : Block : BlockType = 4
===== NVMEDIA: NVENC =====
NvMMLiteBlockCreate : Block : BlockType = 4
875967048
842091865
H264: Profile = 77, Level = 51
Opening in BLOCKING MODE
NvMMLiteOpen : Block : BlockType = 4
===== NVMEDIA: NVENC =====
NvMMLiteBlockCreate : Block : BlockType = 4
875967048
842091865
H264: Profile = 77, Level = 51
Output #0, mp4, to 'test.mp4':
  Metadata:
    encoder         : Lavf58.29.100
    Stream #0:0: Video: h264 (h264_nvmpi) (avc1 / 0x31637661), yuv420p, 3264x2464, q=-1--1, 2000 kb/s, 1000k fps, 1000k tbn, 1000k tbc
    Metadata:
      encoder         : Lavc58.54.100 h264_nvmpi
More than 1000 frames duplicated
^C
jetson@jetson:~$

Hi,
YUV422 is not supported by hardware encoder. You may convert it to YUV420 and try again.

I’m not sure this is true, because it works with another v4l2 camera, but not with IMX219:

jetson@jetson:~$ ffmpeg -f v4l2 -input_format yuyv422 -video_size 640x480 -framerate 30 -i /dev/video3 -c:v h264_nvmpi test.mp4
ffmpeg version 4.2.2-1ubuntu1~18.04.york0 Copyright (c) 2000-2019 the FFmpeg developers
  built with gcc 7 (Ubuntu/Linaro 7.5.0-3ubuntu1~18.04)
  configuration: --prefix=/usr --extra-version='1ubuntu1~18.04.york0' --toolchain=hardened --libdir=/usr/lib/aarch64-linux-gnu --incdir=/usr/include/aarch64-linux-gnu --arch=arm64 --enable-gpl --disable-stripping --enable-avresample --disable-filter=resample --enable-avisynth --enable-gnutls --enable-ladspa --enable-libaom --enable-libass --enable-libbluray --enable-libbs2b --enable-libcaca --enable-libcdio --enable-libcodec2 --enable-libflite --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-libgme --enable-libgsm --enable-libjack --enable-libmp3lame --enable-libmysofa --enable-libopenjpeg --enable-libopenmpt --enable-libopus --enable-libpulse --enable-librsvg --enable-librubberband --enable-libshine --enable-libsnappy --enable-libsoxr --enable-libspeex --enable-libssh --enable-libtheora --enable-libtwolame --enable-libvidstab --enable-libvorbis --enable-libvpx --enable-libwavpack --enable-libwebp --enable-libx265 --enable-nvmpi --enable-libxml2 --enable-libxvid --enable-libzmq --enable-libzvbi --enable-lv2 --enable-omx --enable-openal --enable-opencl --enable-opengl --enable-sdl2 --enable-libdc1394 --enable-libdrm --enable-libiec61883 --enable-chromaprint --enable-frei0r --enable-libx264 --enable-shared
  libavutil      56. 31.100 / 56. 31.100
  libavcodec     58. 54.100 / 58. 54.100
  libavformat    58. 29.100 / 58. 29.100
  libavdevice    58.  8.100 / 58.  8.100
  libavfilter     7. 57.100 /  7. 57.100
  libavresample   4.  0.  0 /  4.  0.  0
  libswscale      5.  5.100 /  5.  5.100
  libswresample   3.  5.100 /  3.  5.100
  libpostproc    55.  5.100 / 55.  5.100
Input #0, video4linux2,v4l2, from '/dev/video3':
  Duration: N/A, start: 141965.860878, bitrate: 147456 kb/s
    Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 640x480, 147456 kb/s, 30 fps, 30 tbr, 1000k tbn, 1000k tbc
File 'test.mp4' already exists. Overwrite ? [y/N] y
Stream mapping:
  Stream #0:0 -> #0:0 (rawvideo (native) -> h264 (h264_nvmpi))
Press [q] to stop, [?] for help
Opening in BLOCKING MODE
NvMMLiteOpen : Block : BlockType = 4
===== NVMEDIA: NVENC =====
NvMMLiteBlockCreate : Block : BlockType = 4
875967048
842091865
H264: Profile = 77, Level = 51
Opening in BLOCKING MODE
NvMMLiteOpen : Block : BlockType = 4
===== NVMEDIA: NVENC =====
NvMMLiteBlockCreate : Block : BlockType = 4
875967048
842091865
H264: Profile = 77, Level = 51
Output #0, mp4, to 'test.mp4':
  Metadata:
    encoder         : Lavf58.29.100
    Stream #0:0: Video: h264 (h264_nvmpi) (avc1 / 0x31637661), yuv420p, 640x480, q=-1--1, 2000 kb/s, 30 fps, 15360 tbn, 30 tbc
    Metadata:
      encoder         : Lavc58.54.100 h264_nvmpi
frame=  650 fps= 33 q=-0.0 Lsize=    5086kB time=00:00:21.63 bitrate=1925.8kbits/s dup=55 drop=0 speed=1.09x
video:5082kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.067524%
Exiting normally, received signal 2.
jetson@jetson:~$

Are you talking about input pixel format or output pixel format?

Hi,
Input pixel format has to be YUV420(I420 or NV12). Please check development guide

And how can we get that from imx219 raspberry V2 camera?

$ ffmpeg -f v4l2 -list_formats all -i /dev/video0
...
[video4linux2,v4l2 @ 0x5594287130] Raw       : Unsupported : 10-bit Bayer RGRG/GBGB : 3264x2464 3264x1848 1920x1080 1280x720 1280x720
$ v4l2-ctl --list-formats-ext
ioctl: VIDIOC_ENUM_FMT
	Index       : 0
	Type        : Video Capture
	Pixel Format: 'RG10'
	Name        : 10-bit Bayer RGRG/GBGB
		Size: Discrete 3264x2464
			Interval: Discrete 0.048s (21.000 fps)
		Size: Discrete 3264x1848
			Interval: Discrete 0.036s (28.000 fps)
		Size: Discrete 1920x1080
			Interval: Discrete 0.033s (30.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.017s (60.000 fps)
		Size: Discrete 1280x720
			Interval: Discrete 0.017s (60.000 fps)

Hi,
Raspberry Pi V2 is a Bayer sensor. It goes through Argus to utilize hardware ISP engine for de-bayering. Suggest you use gstreamer or jetson_multimedia_api. You can run

$ gst-launch-1.0 nvarguscamerasrc num-buffers=100 ! nvv4l2h264enc ! h264parse ! qtmux ! filesink location=a.mp4

Please check gstreamer user guide or jetson_multimedia_api guide