Skip to content

Commit 57abb72

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 f1c0806 commit 57abb72

File tree

12 files changed

+421
-1
lines changed

12 files changed

+421
-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

+186
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
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 image 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+
If not, it is possible to test with a test pattern generator by using the
38+
``video-sw-generator`` snippet with any board:
39+
40+
.. zephyr-app-commands::
41+
:zephyr-app: samples/subsys/usb/uvc
42+
:board: frdm_mcxn947/mcxn947/cpu0
43+
:snippet: video-sw-generator
44+
:goals: build flash
45+
:compact:
46+
47+
The device is expected to be detected as a webcam device:
48+
49+
.. tabs::
50+
51+
.. group-tab:: Ubuntu
52+
53+
The ``dmesg`` logs are expected to mention a ``generic UVC device``.
54+
55+
The ``lsusb`` is expected to show an entry for a Zephyr device.
56+
57+
Refers to `Ideas on board FAQ <https://www.ideasonboard.org/uvc/faq/>`_
58+
for how to get more debug information.
59+
60+
.. group-tab:: MacOS
61+
62+
The ``dmesg`` logs are expected to mention a video device.
63+
64+
The ``ioreg -p IOUSB`` command list the USB devices including cameras.
65+
66+
The ``system_profiler SPCameraDataType`` command list video input devices.
67+
68+
.. group-tab:: Windows
69+
70+
The Device Manager or USBView utilities permit to list the USB devices.
71+
72+
The 3rd-party USB Tree View allows to review and debug the descriptors.
73+
74+
In addition, the `USB3CV <https://www.usb.org/document-library/usb3cv>`_ tool
75+
from USB-IF can check that the device is compliant with the UVC standard.
76+
77+
Playing the Stream
78+
==================
79+
80+
The device is recognized by the system as a native webcam and can be used by any video application.
81+
82+
For instance with VLC:
83+
``Media`` > ``Open Capture Device`` > ``Capture Device`` > ``Video device name``.
84+
85+
Or with Gstreamer and FFmpeg:
86+
87+
.. tabs::
88+
89+
.. group-tab:: Ubuntu
90+
91+
Assuming ``/dev/video0`` is your Zephyr device.
92+
93+
.. code-block:: console
94+
95+
ffplay -i /dev/video0
96+
97+
.. code-block:: console
98+
99+
gst-launch-1.0 v4l2src device=/dev/video0 ! videoconvert ! autovideosink
100+
101+
.. group-tab:: MacOS
102+
103+
Assuming ``0:0`` is your Zephyr device.
104+
105+
.. code-block:: console
106+
107+
ffplay -f avfoundation -i 0:0
108+
109+
.. code-block:: console
110+
111+
gst-launch-1.0 avfvideosrc device-index=0 ! autovideosink
112+
113+
.. group-tab:: Windows
114+
115+
Assuming ``UVC sample`` is your Zephyr device.
116+
117+
.. code-block:: console
118+
119+
ffplay.exe -f dshow -i video="UVC sample"
120+
121+
.. code-block:: console
122+
123+
gst-launch-1.0.exe ksvideosrc device-name="UVC sample" ! videoconvert ! autovideosink
124+
125+
The video device can also be used by web and video call applications systems.
126+
127+
Android and iPad (but not yet iOS) are also expected to work via dedicated applications.
128+
129+
Accessing the Video Controls
130+
============================
131+
132+
On the host system, the controls would be available as video source
133+
control through various applications, like any webcam.
134+
135+
.. tabs::
136+
137+
.. group-tab:: Ubuntu
138+
139+
Assuming ``/dev/video0`` is your Zephyr device.
140+
141+
.. code-block:: console
142+
143+
$ v4l2-ctl --device /dev/video0 --list-ctrls
144+
145+
Camera Controls
146+
147+
auto_exposure 0x009a0901 (menu) : min=0 max=3 default=1 value=1 (Manual Mode)
148+
exposure_dynamic_framerate 0x009a0903 (bool) : default=0 value=0
149+
exposure_time_absolute 0x009a0902 (int) : min=10 max=2047 step=1 default=384 value=384 flags=inactive
150+
151+
$ v4l2-ctl --device /dev/video0 --set-ctrl auto_exposure=1
152+
$ v4l2-ctl --device /dev/video0 --set-ctrl exposure_time_absolute=1500
153+
154+
.. group-tab:: Windows
155+
156+
The `VLC <https://www.videolan.org/vlc/>`_ client and `Pot Player <https://potplayer.tv/>`_
157+
client permit to further access the video controls.
158+
159+
.. group-tab:: MacOS
160+
161+
The `VLC <https://www.videolan.org/vlc/>`_ client and the system Webcam Settings panel
162+
allows adjustment of the supported video controls.
163+
164+
Software Processing
165+
===================
166+
167+
Software processing tools can also use the video interface directly.
168+
169+
Here is an example with OpenCV (``pip install opencv-python``):
170+
171+
.. code-block:: python
172+
173+
import cv2
174+
175+
# Number of the /dev/video# interface
176+
devnum = 2
177+
178+
cv2.namedWindow("preview")
179+
vc = cv2.VideoCapture(devnum)
180+
181+
while (val := vc.read())[0]:
182+
cv2.waitKey(20)
183+
cv2.imshow("preview", val[1])
184+
185+
cv2.destroyWindow("preview")
186+
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

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

+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
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+
- nrf52840dk/nrf52840
11+
- nrf54h20dk/nrf54h20/cpuapp
12+
- frdm_k64f
13+
- stm32f723e_disco
14+
- nucleo_f413zh
15+
- mimxrt685_evk/mimxrt685s/cm33
16+
- mimxrt1060_evk/mimxrt1062/qspi
17+
sample.subsys.usb.uvc.camera:
18+
depends_on:
19+
- usbd
20+
tags: usb video
21+
filter: dt_chosen_enabled("zephyr,camera")
22+
integration_platforms:
23+
- arduino_nicla_vision/stm32h747xx/m7

0 commit comments

Comments
 (0)