.. zephyr:code-sample:: uvc
:name: USB Video webcam
:relevant-api: usbd_api usbd_uvc video_interface
Send video frames over USB.
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 :ref:`udc_api`.
Building and Running
********************
If a board does not have a camera supported, the :ref:`snippet-video-sw-generator` snippet can be
used to test without extra hardware than the USB interface, via a software-generated test pattern:
.. zephyr-app-commands::
:zephyr-app: samples/subsys/usb/uvc
:board: frdm_mcxn947/mcxn947/cpu0
:snippets: video-sw-generator
:goals: build flash
:compact:
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:
.. zephyr-app-commands::
:zephyr-app: samples/subsys/usb/uvc
:board: arduino_nicla_vision/stm32h747xx/m7
:goals: build flash
:compact:
The device is expected to be detected as a webcam device:
.. tabs::
.. group-tab:: Ubuntu
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.
.. group-tab:: MacOS
The ``dmesg`` logs are expected to mention a video device.
The ``ioreg -p IOUSB`` command list the USB devices including cameras.
The ``system_profiler SPCameraDataType`` command list video input devices.
.. group-tab:: Windows
The Device Manager or USBView utilities permit to list the USB devices.
The 3rd-party USB Tree View allows to review and debug the descriptors.
In addition, the `USB3CV `_ tool
from USB-IF can check that the device is compliant with the UVC standard.
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:
:menuselection:`Media --> Open Capture Device --> Capture Device --> Video device name`.
Or with Gstreamer and FFmpeg:
.. tabs::
.. group-tab:: Ubuntu
Assuming ``/dev/video0`` is your Zephyr device.
.. code-block:: console
ffplay -i /dev/video0
.. code-block:: console
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! autovideosink
.. group-tab:: MacOS
Assuming ``0:0`` is your Zephyr device.
.. code-block:: console
ffplay -f avfoundation -i 0:0
.. code-block:: console
gst-launch-1.0 avfvideosrc device-index=0 ! autovideosink
.. group-tab:: Windows
Assuming ``UVC sample`` is your Zephyr device.
.. code-block:: console
ffplay.exe -f dshow -i video="UVC sample"
.. code-block:: console
gst-launch-1.0.exe ksvideosrc device-name="UVC sample" ! 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.
.. tabs::
.. group-tab:: Ubuntu
Assuming ``/dev/video0`` is your Zephyr device.
.. code-block:: console
$ 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
.. group-tab:: MacOS
The `VLC `_ client and the system Webcam Settings panel
allows adjustment of the supported video controls.
.. group-tab:: Windows
The `VLC `_ client and `Pot Player `_
client permit to further access the video controls.
Software Processing
===================
Software processing tools can also use the video interface directly.
Here is an example with OpenCV (``pip install opencv-python``):
.. code-block:: 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()