Skip to content

Commit 6235d5d

Browse files
committed
samples: usb: add new UVC sample
Following the addition of USB Video Class, this adds a sample that makes use of the &zephyr,camera chosen node of any board to stream the video source to the host. A fallback video-emul.overlay is provided for test and debugging purpose for devices without a camera. Signed-off-by: Josuah Demangeon <[email protected]>
1 parent eb58497 commit 6235d5d

13 files changed

+411
-1
lines changed

doc/connectivity/usb/device/usb_device.rst

+2
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ The following Product IDs are currently used:
551551
+----------------------------------------------------+--------+
552552
| :zephyr:code-sample:`uac2-implicit-feedback` | 0x000F |
553553
+----------------------------------------------------+--------+
554+
| :zephyr:code-sample:`uvc` | 0x0011 |
555+
+----------------------------------------------------+--------+
554556
| :zephyr:code-sample:`usb-dfu` (DFU Mode) | 0xFFFF |
555557
+----------------------------------------------------+--------+
556558

doc/connectivity/usb/device_next/usb_device.rst

+4
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ Samples
3232

3333
* :zephyr:code-sample:`uac2-implicit-feedback`
3434

35+
* :zephyr:code-sample:`uvc`
36+
3537
Samples ported to new USB device support
3638
----------------------------------------
3739

@@ -223,6 +225,8 @@ instance (``n``) and is used as an argument to the :c:func:`usbd_register_class`
223225
+-----------------------------------+-------------------------+-------------------------+
224226
| Bluetooth HCI USB transport layer | :ref:`bt_hci_raw` | :samp:`bt_hci_{n}` |
225227
+-----------------------------------+-------------------------+-------------------------+
228+
| USB Video Class (UVC) | Video device | :samp:`uvc_{n}` |
229+
+-----------------------------------+-------------------------+-------------------------+
226230

227231
CDC ACM UART
228232
============

samples/subsys/usb/common/sample_usbd_init.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ static void sample_fix_code_triple(struct usbd_context *uds_ctx,
8181
IS_ENABLED(CONFIG_USBD_CDC_ECM_CLASS) ||
8282
IS_ENABLED(CONFIG_USBD_CDC_NCM_CLASS) ||
8383
IS_ENABLED(CONFIG_USBD_MIDI2_CLASS) ||
84-
IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS)) {
84+
IS_ENABLED(CONFIG_USBD_AUDIO2_CLASS) ||
85+
IS_ENABLED(CONFIG_USBD_VIDEO_CLASS)) {
8586
/*
8687
* Class with multiple interfaces have an Interface
8788
* Association Descriptor available, use an appropriate triple

samples/subsys/usb/uvc/CMakeLists.txt

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# SPDX-License-Identifier: Apache-2.0
2+
3+
cmake_minimum_required(VERSION 3.20.0)
4+
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
5+
project(usb_video)
6+
7+
include(${ZEPHYR_BASE}/samples/subsys/usb/common/common.cmake)
8+
target_sources(app PRIVATE src/main.c)

samples/subsys/usb/uvc/Kconfig

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Copyright The Zephyr Project Contributors
2+
# SPDX-License-Identifier: Apache-2.0
3+
4+
# Source common USB sample options used to initialize new experimental USB
5+
# device stack. The scope of these options is limited to USB samples in project
6+
# tree, you cannot use them in your own application.
7+
source "samples/subsys/usb/common/Kconfig.sample_usbd"
8+
9+
source "Kconfig.zephyr"

samples/subsys/usb/uvc/README.rst

+176
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
.. zephyr:code-sample:: uvc
2+
:name: USB Video sample
3+
:relevant-api: usbd_api video_interface
4+
5+
Send video frames over USB.
6+
7+
Overview
8+
********
9+
10+
This sample demonstrates how to use a USB Video Class instance to
11+
send video data over USB.
12+
13+
Upon connection, a video device will show-up on the host,
14+
usable like a regular webcam device.
15+
16+
Any software on the host can then access the video stream as a local video source.
17+
18+
Requirements
19+
************
20+
21+
This sample uses the new USB device stack and requires the USB device
22+
controller ported to the :ref:`udc_api`.
23+
24+
Building and Running
25+
********************
26+
27+
If a board is equipped with a supported video sensor, and ``zephyr,camera``
28+
node is chosen for the board, it will be used as the video source.
29+
The sample can be built as follows:
30+
31+
.. zephyr-app-commands::
32+
:zephyr-app: samples/subsys/usb/uvc
33+
:board: arduino_nicla_vision/stm32h747xx/m7
34+
:goals: build flash
35+
:compact:
36+
37+
The device is expected to be detected as a webcam device:
38+
39+
.. tabs::
40+
41+
.. group-tab:: Ubuntu
42+
43+
The ``dmesg`` logs are expected to mention a ``generic UVC device``.
44+
45+
The ``lsusb`` is expected to show an entry for a Zephyr device.
46+
47+
Refers to `Ideas on board FAQ <https://www.ideasonboard.org/uvc/faq/>`_
48+
for how to get more debug information.
49+
50+
.. group-tab:: MacOS
51+
52+
The ``dmesg`` logs are expected to mention a video device.
53+
54+
The ``ioreg -p IOUSB`` command list the USB devices including cameras.
55+
56+
The ``system_profiler SPCameraDataType`` command list video input devices.
57+
58+
.. group-tab:: Windows
59+
60+
The Device Manager or USBView utilities permit to list the USB devices.
61+
62+
The 3rd-party USB Tree View allows to review and debug the descriptors.
63+
64+
In addition, the `USB3CV <https://www.usb.org/document-library/usb3cv>`_ tool
65+
from USB-IF can check that the device is compliant with the UVC standard.
66+
67+
Playing the Stream
68+
==================
69+
70+
The device is recognized by the system as a native webcam and can be used by any video application.
71+
72+
For instance with VLC:
73+
``Media`` > ``Open Capture Device`` > ``Capture Device`` > ``Video device name``.
74+
75+
Or with Gstreamer and FFmpeg:
76+
77+
.. tabs::
78+
79+
.. group-tab:: Ubuntu
80+
81+
Assuming ``/dev/video0`` is your Zephyr device.
82+
83+
.. code-block:: console
84+
85+
ffplay -i /dev/video0
86+
87+
.. code-block:: console
88+
89+
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! autovideosink
90+
91+
.. group-tab:: MacOS
92+
93+
Assuming ``0:0`` is your Zephyr device.
94+
95+
.. code-block:: console
96+
97+
ffplay -f avfoundation -i 0:0
98+
99+
.. code-block:: console
100+
101+
gst-launch-1.0 avfvideosrc device-index=0 ! autovideosink
102+
103+
.. group-tab:: Windows
104+
105+
Assuming ``UVC sample`` is your Zephyr device.
106+
107+
.. code-block:: console
108+
109+
ffplay.exe -f dshow -i video="UVC sample"
110+
111+
.. code-block:: console
112+
113+
gst-launch-1.0.exe ksvideosrc device-name="UVC sample" ! videoconvert ! autovideosink
114+
115+
The video device can also be used by web and video call applications systems.
116+
117+
Android and iPad (but not yet iOS) are also expected to work via dedicated applications.
118+
119+
Accessing the Video Controls
120+
============================
121+
122+
On the host system, the controls would be available as video source
123+
control through various applications, like any webcam.
124+
125+
.. tabs::
126+
127+
.. group-tab:: Ubuntu
128+
129+
Assuming ``/dev/video0`` is your Zephyr device.
130+
131+
.. code-block:: console
132+
133+
$ v4l2-ctl --device /dev/video0 --list-ctrls
134+
135+
Camera Controls
136+
137+
auto_exposure 0x009a0901 (menu) : min=0 max=3 default=1 value=1 (Manual Mode)
138+
exposure_dynamic_framerate 0x009a0903 (bool) : default=0 value=0
139+
exposure_time_absolute 0x009a0902 (int) : min=10 max=2047 step=1 default=384 value=384 flags=inactive
140+
141+
$ v4l2-ctl --device /dev/video0 --set-ctrl auto_exposure=1
142+
$ v4l2-ctl --device /dev/video0 --set-ctrl exposure_time_absolute=1500
143+
144+
.. group-tab:: Windows
145+
146+
The `VLC <https://www.videolan.org/vlc/>`_ client and `Pot Player <https://potplayer.tv/>`_
147+
client permit to further access the video controls.
148+
149+
.. group-tab:: MacOS
150+
151+
The `VLC <https://www.videolan.org/vlc/>`_ client and the system Webcam Settings panel
152+
allows adjustment of the supported video controls.
153+
154+
Software Processing
155+
===================
156+
157+
Software processing tools can also use the video interface directly.
158+
159+
Here is an example with OpenCV (``pip install opencv-python``):
160+
161+
.. code-block:: python
162+
163+
import cv2
164+
165+
# Number of the /dev/video# interface
166+
devnum = 2
167+
168+
cv2.namedWindow("preview")
169+
vc = cv2.VideoCapture(devnum)
170+
171+
while (val := vc.read())[0]:
172+
cv2.waitKey(20)
173+
cv2.imshow("preview", val[1])
174+
175+
cv2.destroyWindow("preview")
176+
vc.release()

samples/subsys/usb/uvc/app.overlay

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* Copyright (c) 2025 tinyVision.ai Inc.
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
/ {
8+
uvc: uvc {
9+
compatible = "zephyr,uvc-device";
10+
};
11+
};
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
# Enough two 320x240 YUYV frames
2+
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=163840
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=40000
2+
CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright (c) 2025 tinyVision.ai Inc
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include "../app.overlay"
8+
9+
/{
10+
chosen {
11+
zephyr,camera = &video_sdma;
12+
};
13+
};

samples/subsys/usb/uvc/prj.conf

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
CONFIG_LOG=y
2+
CONFIG_ASSERT=y
3+
CONFIG_POLL=y
4+
CONFIG_VIDEO=y
5+
CONFIG_VIDEO_LOG_LEVEL_WRN=y
6+
CONFIG_VIDEO_BUFFER_POOL_NUM_MAX=2
7+
CONFIG_VIDEO_BUFFER_POOL_SZ_MAX=24576
8+
CONFIG_USB_DEVICE_STACK_NEXT=y
9+
CONFIG_USBD_LOG_LEVEL_WRN=y
10+
CONFIG_USBD_VIDEO_CLASS=y
11+
CONFIG_USBD_VIDEO_LOG_LEVEL_WRN=y
12+
CONFIG_UDC_DRIVER_LOG_LEVEL_WRN=y
13+
CONFIG_SAMPLE_USBD_PID=0x0011
14+
CONFIG_SAMPLE_USBD_PRODUCT="UVC sample"

samples/subsys/usb/uvc/sample.yaml

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
sample:
2+
name: USB Video sample
3+
tests:
4+
sample.subsys.usb.uvc.camera:
5+
depends_on:
6+
- usbd
7+
tags: usb video
8+
filter: dt_chosen_enabled("zephyr,camera")
9+
integration_platforms:
10+
- arduino_nicla_vision/stm32h747xx/m7

0 commit comments

Comments
 (0)