Some context first.
I have a UVC USB camera board from ELP, ref. ELP-USBFHD06H-L37. It has a 1/2.9" Sony IMX 322 sensor and outputs several streams: MJPEG, YUYV and H.264, up to 1920×1080 pixels @ 30 fps:

I plug this camera in a Raspberry Pi 3 Model B (OS version Stretch).
Here are results from various commands entered at prompt:
Code: Select all
$ lsusb
Bus 001 Device 004: ID 05a3:9422 ARC International
Code: Select all
$ v4l2-ctl --list-devices
H264 USB Camera: USB Camera (usb-3f980000.usb-1.4):
/dev/video0
/dev/video1
/dev/video2
/dev/video3
The camera also creates these four specific entries "by id":
Code: Select all
/dev/v4l/by-id/usb-Sonix_Technology_Co.__Ltd._H264_USB_Camera_SN0001-video-index0
/dev/v4l/by-id/usb-Sonix_Technology_Co.__Ltd._H264_USB_Camera_SN0001-video-index1
/dev/v4l/by-id/usb-Sonix_Technology_Co.__Ltd._H264_USB_Camera_SN0001-video-index2
/dev/v4l/by-id/usb-Sonix_Technology_Co.__Ltd._H264_USB_Camera_SN0001-video-index3
and these four entries "by path":
Code: Select all
/dev/v4l/by-path/platform-3f980000.usb-usb-0:1.4:1.0-video-index0
/dev/v4l/by-path/platform-3f980000.usb-usb-0:1.4:1.0-video-index1
/dev/v4l/by-path/platform-3f980000.usb-usb-0:1.4:1.0-video-index2
/dev/v4l/by-path/platform-3f980000.usb-usb-0:1.4:1.0-video-index3
I made a few probe tests with ffmpeg:
Code: Select all
$ ffmpeg -f v4l2 -list_formats all -i /dev/video0
[video4linux2,v4l2 @ 0x11ccc50] Compressed: mjpeg : Motion-JPEG : 1920x1080 1280x720 800x600 640x480 640x360 352x288 320x240 1920x1080
[video4linux2,v4l2 @ 0x11ccc50] Raw : yuyv422 : YUYV 4:2:2 : 640x480 800x600 640x360 352x288 320x240 640x480
Code: Select all
$ ffmpeg -f v4l2 -list_formats all -i /dev/video1
[video4linux2,v4l2 @ 0xce4c50] ioctl(VIDIOC_G_INPUT): Inappropriate ioctl for device
Code: Select all
$ ffmpeg -f v4l2 -list_formats all -i /dev/video2
[video4linux2,v4l2 @ 0x201c50] Compressed: h264 : H.264 : 1920x1080 1280x720 800x600 640x480 640x360 352x288 320x240 1920x1080
Code: Select all
$ ffmpeg -f v4l2 -list_formats all -i /dev/video3
[video4linux2,v4l2 @ 0x1684c50] ioctl(VIDIOC_G_INPUT): Inappropriate ioctl for device
So it appears that
/dev/video0 corresponds to both the MJPEG HD stream and the YUYV SD stream.
/dev/video2 corresponds to the H.264 HD stream.
When I output a video file (using a Matroska container to be independent of the codec) with ffmpeg from direct copy of input /dev/video0:
Code: Select all
ffmpeg -i /dev/video0 -vcodec copy ~/output-dev-video0.mkv
I get a playable 800×600 2YUY MKV:
Native bitrate in this case is as might be expected insanely high: over 115 Mbps.Stream #0:0: Video: rawvideo (YUY2 / 0x32595559), yuyv422, 800x600, q=2-31, 115200 kb/s, 15 fps, 15 tbr, 1000k tbn, 1000k tbc
BTW I do not know ho to tap into the MJPEG HD stream of same /dev/video0 input. Anyone? But this is a side question, so let's move on.
I do the same with:
Code: Select all
ffmpeg -i /dev/video2 -vcodec copy ~/output-dev-video2.mkv
Code: Select all
Stream #0:0: Video: h264 (Main) (H264 / 0x34363248), yuv420p(progressive), 1920x1080, q=2-31, 30 fps, 30 tbr, 1k tbn, 1000k tbc
Code: Select all
ffmpeg -i /dev/video2 -vcodec h264_omx -b:v 2M ~/output-dev-video2-omx.mkv
Now, in order to stream and display the video in web browsers, at first I tested motion/motionEye, alas with terrible results. Especially because motion is based on MJPEG and not H.264, so it only outputs a laggy 800x600 stream. It managed to catch the 1920×1080 MJPEG stream of the camer once, but systematically failed with a grey screen afterward.
So I decided to give UV4L a shot: https://www.linux-projects.org/uv4l/
This stream server with HTTP/HTTPS GUI has very good records regarding stability, HD stream quality, and low-latency (200-500 ms only).
Like ffmpeg it uses v4l2 (video4linux2). The software comes with uv4l-uvc driver for USB cameras, in addition to uv4l-raspicam (which is more intended to OV-based CSI pi camera boards, those with the ribbon cable).
Raspicam driver is advertised as being compatible with "any video format available from the GPU (yuv420, nv21, yvu420, rgb565, rgb565x, rgb24, bgr24, rgba, bgra, jpeg Still, mjpeg Video, h264)".
No mention of such extended support for the UVC driver though (?)
Whatever, the real issue here is that as soon as I fire UV4L, it first complains that /dev/video0, /dev/video1, /dev/video2 and /dev/video3 already exist (sure, as the camera is plugged in…) then it creates /dev/video4 to pick the camera stream from there instead, and worse it disables (deletes) the first four /dev/video* !!! It also deletes all camera entries in /dev/by-id/ and /dev/by-path
Code: Select all
$ uv4l --device-id 05a3:9422 --config-file=/etc/uv4l/uv4l-uvc.conf
<notice> [core] Trying to loading driver 'uvc' from built-in drivers...
<notice> [core] Loading driver 'uvc' from external plug-in's...
<notice> [driver] Video functionality 'USB Camera' recognized at 05a3:9422
<notice> [core] Device detected!
<warning> [core] Cannot create /dev/video0 because file already exists
<warning> [core] Cannot create /dev/video1 because file already exists
<warning> [core] Cannot create /dev/video2 because file already exists
<warning> [core] Cannot create /dev/video3 because file already exists
<notice> [core] Registering device node /dev/video4
WTF is that?! This means that when UV4L is running, I can no longer access the other streams with ffmpeg at all, or any other software for that matter. Even worse, from /dev/video4 UV4L decides to point to the 1920×1080 MJPEG stream of the camera* and not its H.264 stream! And I didn't find anywhere how to:
- either tell UV4L to keep original /dev/video2 and tap into it to pick the H.264 stream of the camera
- or keep this peculiar way of doing things with new /dev/video4, but point the H.264 stream of the camera instead of the MJPEG stream the software arbitrarily chooses (as it comes first in the list I think).
Is there any solution for one of these two possibilities?
[hr]
* I wrote "1920×1080" but this was yesterday. Now it picks the 800×600 MJPEG stream, always. And there is no width, height nor framerate options in the /etc/uv4l/uv4L-uvc.conf!