USB Video webcam

Browse source code on GitHub

Overview

This sample demonstrates how to use a USB Video Class instance to send video data over USB.

Upon connection, a video device will show-up on the host, usable like a regular webcam device.

Any software on the host can then access the video stream as a local video source.

Requirements

This sample uses the new USB device stack and requires the USB device controller ported to the USB device controller (UDC) driver API.

Building and Running

If a board does not have a camera supported, the Video Software Generator Snippet (video-sw-generator) snippet can be used to test without extra hardware than the USB interface, via a software-generated test pattern:

west build -b frdm_mcxn947/mcxn947/cpu0 -S video-sw-generator samples/subsys/usb/uvc
west flash

If a board is equipped with a supported image sensor configured as the zephyr,camera chosen node, then it will be used as the video source. The sample can then be built as follows:

west build -b arduino_nicla_vision/stm32h747xx/m7 samples/subsys/usb/uvc
west flash

The device is expected to be detected as a webcam device:

The dmesg logs are expected to mention a generic UVC device.

The lsusb is expected to show an entry for a Zephyr device.

Refers to Ideas on board FAQ for how to get more debug information.

Playing the Stream

The device is recognized by the system as a native webcam and can be used by any video application.

For instance with VLC: Media ‣ Open Capture Device ‣ Capture Device ‣ Video device name.

Or with Gstreamer and FFmpeg:

Assuming /dev/video0 is your Zephyr device.

ffplay -i /dev/video0
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! autovideosink

The video device can also be used by web and video call applications systems.

Android and iPad (but not yet iOS) are also expected to work via dedicated applications.

Accessing the Video Controls

On the host system, the controls would be available as video source control through various applications, like any webcam.

Assuming /dev/video0 is your Zephyr device.

$ v4l2-ctl --device /dev/video0 --list-ctrls

Camera Controls

                  auto_exposure 0x009a0901 (menu)   : min=0 max=3 default=1 value=1 (Manual Mode)
     exposure_dynamic_framerate 0x009a0903 (bool)   : default=0 value=0
         exposure_time_absolute 0x009a0902 (int)    : min=10 max=2047 step=1 default=384 value=384 flags=inactive

$ v4l2-ctl --device /dev/video0 --set-ctrl auto_exposure=1
$ v4l2-ctl --device /dev/video0 --set-ctrl exposure_time_absolute=1500

Software Processing

Software processing tools can also use the video interface directly.

Here is an example with OpenCV (pip install opencv-python):

import cv2

# Number of the /dev/video# interface
devnum = 2

cv2.namedWindow("preview")
vc = cv2.VideoCapture(devnum)

while (val := vc.read())[0]:
    cv2.waitKey(20)
    cv2.imshow("preview", val[1])

cv2.destroyWindow("preview")
vc.release()

See also

USB device core API
USB Video Class (UVC) device API
Video Interface