Close

UVC and UVA

A project log for Streamo Encodo Cheapo

Trying to make an inexpensive HDMI encoder with off the shelf stuff

wjcarpenterWJCarpenter 05/27/2024 at 19:280 Comments

I don't know whether to file this under "learn something new every day" or "teach an old dog new tricks", but I recently looked into a standard called USB video device class (UVC) published by the USB Implementers Forum. (There is a companion standard, UAC, for audio, but I haven't looked at that.) The dongles based on the MS2109 and MS2130 chips advertise UVC and UAC compatibility, but I didn't really know what that meant beyond "don't need to install custom drivers". The dongles also expose a USB HID device, and I had assumed that any configuration control of them would be via the USB HID. Not so.

UVC is one of those standards where any particular devices is likely to only implement some subset, and that is true of these dongles. UVC provides protocol elements for querying or changing lots of different configuration items. There are multiple open source utilities that can be used to interact with UVC devices. For example, yavta and v4l-utils. Here are some examples for my MS2130 dongle:

This reports the available video modes, resolutions, and frame rates (figures for frame rates are quotes as frame intervals, so 1/60 is 60fps):

$ sudo yavta --enum-formats /dev/video2
Device /dev/video2 opened.
Device `USB3 Video: USB3 Video' on `usb-0000:00:15.0-1' (driver 'uvcvideo') supports video, capture, without mplanes.
- Available formats:
    Format 0: YUYV (56595559)
    Type: Video capture (1)
    Name: YUYV 4:2:2
    Frame size: 1920x1080 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1600x1200 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1360x768 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1280x1024 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1280x960 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1280x720 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1024x768 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 800x600 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 720x576 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 720x480 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 640x480 (1/60, 1/50, 1/30, 1/20, 1/10)

    Format 1: MJPEG (47504a4d)
    Type: Video capture (1)
    Name: Motion-JPEG
    Frame size: 1920x1080 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1600x1200 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1360x768 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1280x1024 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1280x960 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1280x720 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1024x768 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 800x600 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 720x576 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 720x480 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 640x480 (1/60, 1/50, 1/30, 1/20, 1/10)

Video format: YUYV (56595559) 1920x1080 (stride 3840) field none buffer size 4147200$ sudo v4l2-ctl -d2 --set-fmt-video "pixelformat=MJPG

 This switches the video mode from YUYV to MJPG

$ sudo v4l2-ctl -d2 --get-fmt-video
Format Video Capture:
    Width/Height      : 1920/1080
    Pixel Format      : 'YUYV' (YUYV 4:2:2)
    Field             : None
    Bytes per Line    : 3840
    Size Image        : 4147200
    Colorspace        : sRGB
    Transfer Function : Rec. 709
    YCbCr/HSV Encoding: ITU-R 601
    Quantization      : Default (maps to Limited Range)
    Flags             : 

$ sudo v4l2-ctl -d2 --set-fmt-video "pixelformat=MJPG"

$ sudo v4l2-ctl -d2 --get-fmt-video
Format Video Capture:
    Width/Height      : 1920/1080
    Pixel Format      : 'MJPG' (Motion-JPEG)
    Field             : None
    Bytes per Line    : 0
    Size Image        : 4147200
    Colorspace        : sRGB
    Transfer Function : Rec. 709
    YCbCr/HSV Encoding: ITU-R 601
    Quantization      : Default (maps to Full Range)
    Flags             : 

These tools tend to think you already know what the various parameters mean, but they are quite handy once you get the hang of them. The settings seem to stick, at least for the specific dongle that I have. If I unplug it and replug it, it remembers what I last set. The bad news is that the video playing software that I have handy (vlc and ffplay) seem to want to tweak some of the UVC settings, probably to better suit how they handle things. That's inconvenient, but not a big deal for the overall goal.

I was able to capture some video via yavta and verify from the captured file that it had the settings expected. For example,

$ sudo yavta -f mjpeg --size 1920x1080 --capture=1000 --file=/tmp/vid.mjpeg /dev/video2

 With these same utilities, I was able to configure one of my MS2109 dongles to output MJPEG FHD@30fps. Here are its possibilities:

$ sudo yavta --enum-formats /dev/video2
Device /dev/video2 opened.
Device `USB3.0 HD VIDEO: USB3.0 HD VIDE' on `usb-0000:00:15.0-2' (driver 'uvcvideo') supports video, capture, without mplanes.
- Available formats:
    Format 0: MJPEG (47504a4d)
    Type: Video capture (1)
    Name: Motion-JPEG
    Frame size: 1920x1080 (1/30, 1/25, 1/20, 1/10, 1/5)
    Frame size: 1600x1200 (1/30, 1/25, 1/20, 1/10, 1/5)
    Frame size: 1360x768 (1/30, 1/25, 1/20, 1/10, 1/5)
    Frame size: 1280x1024 (1/30, 1/25, 1/20, 1/10, 1/5)
    Frame size: 1280x960 (1/50, 1/30, 1/20, 1/10, 1/5)
    Frame size: 1280x720 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 1024x768 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 800x600 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 720x576 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 720x480 (1/60, 1/50, 1/30, 1/20, 1/10)
    Frame size: 640x480 (1/60, 1/50, 1/30, 1/20, 1/10)

    Format 1: YUYV (56595559)
    Type: Video capture (1)
    Name: YUYV 4:2:2
    Frame size: 1920x1080 (1/5)
    Frame size: 1600x1200 (1/5)
    Frame size: 1360x768 (1/8)
    Frame size: 1280x1024 (1/8)
    Frame size: 1280x960 (1/8)
    Frame size: 1280x720 (1/10)
    Frame size: 1024x768 (1/10)
    Frame size: 800x600 (1/20, 1/10, 1/5)
    Frame size: 720x576 (1/25, 1/20, 1/10, 1/5)
    Frame size: 720x480 (1/30, 1/20, 1/10, 1/5)
    Frame size: 640x480 (1/30, 1/20, 1/10, 1/5)

Video format: MJPEG (47504a4d) 1920x1080 (stride 0) field none buffer size 4147200

All in all, good news for cheap dongles. Even the cheapest of the cheap with the MS2109 chip should be able to get FHD@30fps, which is maybe good enough for under ten US bucks. Of course, MJPEG is lossy compression. That will affect quality, but I don't yet have a bead on that. For MS2130 devices, you can get FHD@60fps with (lossless) YUYV, so there is no point to switching to MJPEG. For MS2109, the lossy MJPEG at 30fps is better than YUYV at 5fps when viewing entertainment video streams.

Discussions