I am using ffmpeg
4.2.2 on an Ubuntu 20.04 machine to clone the video stream of a USB webcam so that multiple applications can use the same feed. To achieve this, I simply clone to a v4l2
loop back device:
ffmpeg -f v4l2 -i /dev/video0 -codec copy -f v4l2 /dev/video1
So far, this works reasonably well. I am able to successfully access /dev/video1
which presents the same feed as /dev/video0
.
Note: To make this work you need to ensure that the v4l2loopback
device kernel module is enabled:
modprobe v4l2loopback devices=1
Next I'd like to convert the pixel format of the dummy device as the application that is accessing the dummy device can only handle yuv422p
or RGB
whereas my source device /dev/video0
provides yuv420p
. I thought that this would be a simple task that can easily be handled by presenting ffmpeg
with an additional -pix_fmt
argument on the output device like so:
ffmpeg -f v4l2 -i /dev/video0 -codec copy -f v4l2 -pix_fmt yuv422p /dev/video1
While ffmpeg
starts cloning the stream without any warnings or errors, it is still outputting in yuv420p
instead:
joel@joel-ubuntu:~$ ffmpeg -f v4l2 -i /dev/video0 -codec copy -f v4l2 -pix_fmt yuv422p /dev/video1
ffmpeg version 4.2.2-1ubuntu1 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 9 (Ubuntu 9.3.0-3ubuntu1)
configuration: --prefix=/usr --extra-version=1ubuntu1 --toolchain=hardened --libdir=/usr/lib/x86_64-linux-gnu --incdir=/usr/include/x86_64-linux-gnu --arch=amd64 --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-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-nvenc --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
[video4linux2,v4l2 @ 0x55ca407b9700] Time per frame unknown
Input #0, video4linux2,v4l2, from '/dev/video0':
Duration: N/A, start: 6726.737520, bitrate: N/A
Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 640x480, 29.25 tbr, 1000k tbn, 1000k tbc
Output #0, video4linux2,v4l2, to '/dev/video1':
Metadata:
encoder : Lavf58.29.100
Stream #0:0: Video: rawvideo (I420 / 0x30323449), yuv420p, 640x480, q=2-31, 29.25 tbr, 1000k tbn, 1000k tbc
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press [q] to stop, [?] for help
frame= 76 fps= 34 q=-1.0 Lsize=N/A time=00:00:02.52 bitrate=N/A speed=1.14x
No matter what -pix_fmt
I pass, I always end up with yuv420p
on the output.
I did several tests with both proper USB UVC webcams as well as DroidCam. The output pixel format never changes as expected. This is also not specific to requesting yuv422p
as a pixel format. Also other formats are being ignored. Why is this happening? What am I missing?
Note: I have verified that ffmpeg
is capable of the yuv422p
pixel format (it is being listed when executing ffmpeg -pix_fmts
).