Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

usb: device_next: new USB Video Class (UVC) implementation #76798

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

josuah
Copy link
Collaborator

@josuah josuah commented Aug 7, 2024

How to test:

From any branch you wish to test, get the UVC and sample commits:

git remote add tvai git@github.com:tinyvision-ai-inc/zephyr
git fetch tvai
git cherry-pick 9ea2df0a5a2 023076440c7

The method to test with any device_next board:

west build --board <board> samples/subsys/usb/uvc -- \
    -DEXTRA_DTC_OVERLAY_FILE=video-emul.overlay

The method to test with any device with a dcmi node:

west build --board <board> samples/subsys/usb/uvc -- \
    -DEXTRA_DTC_OVERLAY_FILE=video-dcmi.overlay
  1. Build the sample for the selected board like above and load it in the board
  2. Connect it to a host USB port and expect a video interface to show-up
  3. Play the feed using one of the method listed on the sample documentation

It will use a very small test pattern as video source, so no camera is required.
To connect a camera instead of a test pattern, connect a different video source through the devicetree.
The USB descriptors will be updated by querying the driver.

Dependencies:

This is a preview of an USB Video Class implementation for Zephyr that was only tested on custom devices insofar.

Proper Zephyr samples will be provided on upcoming commits. The API is simply to submit frames to the UVC device like to any Zephyr video device.

There is an unsolved challenge around the Video API: there is no set_format because the Zephyr application cannot decide what the host uses, only get_format for what the host does support. But there is a missing video API to allow the driver to warn the application about a forced format change requested by the host. I thought of maybe reusing set_signal() to also warn about format changes and not just buffer events.

	.get_format = uvc_get_format,
	.get_caps = uvc_get_caps,

I will now work on building examples for existing Zephyr devices, as this was built for a custom USB3 board.
Here is the devicetree configuration used insofar:

#include <zephyr/dt-bindings/usb/video.h>

&zephyr_udc0 {
	uvc: uvc {
		compatible = "zephyr,uvc-device";

		port {
			uvc_ep_in: endpoint {
				remote-endpoint-label = "mipi0_ep_out";
			};
		};
	};
};

The sizes and FPS are to be selected by the developer. The USB descriptors get configured as described above, and the host will request a particular format. Once that is done, the USB Video Class driver can let the application know which of these was selected through the video.h get_format() API.

This is still a draft PR, but I am grateful for comments and suggestions. I am willing to do the work of refactoring this as much as needed.

[EDIT: see this comment for latest description]

@josuah
Copy link
Collaborator Author

josuah commented Aug 7, 2024

I am grateful for the work on the USB and Video stacks of Zephyr, as well as the entire Zephyr tree, on the shoulder of which this is built.

@josuah josuah added priority: low Low impact/importance bug area: USB Universal Serial Bus area: Video Video subsystem area: Devicetree Binding PR modifies or adds a Device Tree binding labels Aug 7, 2024
@josuah
Copy link
Collaborator Author

josuah commented Aug 8, 2024

Force push:

  • fixes to make it compile with west build -b frdm_mcxn947/mcxn947/cpu0 (a board I happened to have, open to suggestions)
  • added another commit (with I hope proper attributions!) to introduce fragments, which UVC and this implementation support.

@josuah
Copy link
Collaborator Author

josuah commented Aug 8, 2024

Force-push:

  • Add a sample to illustrate the usage. It is not yet tested but compiles.

Comment on lines 920 to 961
.dwMinBitRate = sys_cpu_to_le32(15360000), \
.dwMaxBitRate = sys_cpu_to_le32(15360000), \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where are these values coming from?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are chosen arbitrarily, and I need to think about what should I do here: pick reasonable defaults? Deduce from other values? Let the user figure out by exposing a devicetree option?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In future work, it will be possible to ask the sensor for VIDEO_CID_PIXEL_RATE in combination with video_bits_per_pixel() to generate this field.

.bLength = sizeof(struct usb_ep_descriptor), \
.bDescriptorType = USB_DESC_ENDPOINT, \
.bEndpointAddress = 0x81, \
.bmAttributes = USB_EP_TYPE_BULK, \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe UVC can be BULK or ISO.... but I only see BULK supported here. Do you plan to have a way to select which type of EP?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I forgot to mention that only BULK is supported through this early version. I will need to spend more time investigating the device_next APIs for how ISO is implemented.

I cannot guarantee ETAs as I would do this feature on free time, but will add it to the roadmap: this will be needed at some point.

@josuah
Copy link
Collaborator Author

josuah commented Aug 8, 2024

Very grateful for your reviews @XenuIsWatching I will force-push with the changes as soon as I get a chance to do so.

@josuah
Copy link
Collaborator Author

josuah commented Aug 21, 2024

Force-push:

  • control a selected source = <&dev>; device from the UVC stack directly
  • wait that a format got selected before queuing video buffers to the USB
  • use "discrete" frame intervals (FPS) values, which seemed to help getting it to work under Windows
  • USB3CV compliant descriptors

@josuah josuah force-pushed the pr-usb-uvc branch 2 times, most recently from 182ac7c to cec26cc Compare August 21, 2024 11:43
@josuah josuah force-pushed the pr-usb-uvc branch 2 times, most recently from 02c1087 to 4bdc1ea Compare September 7, 2024 15:46
@josuah
Copy link
Collaborator Author

josuah commented Sep 7, 2024

force push: rebased on main

@josuah
Copy link
Collaborator Author

josuah commented Sep 7, 2024

force push: changed the way descriptors are declared and introduce video controls at the descriptor level (no support for controls commands yet)

@josuah josuah changed the title usb: device_next: new USB Video Class implementation usb: device_next: new USB Video Class (UVC) implementation Sep 12, 2024
@josuah
Copy link
Collaborator Author

josuah commented Sep 12, 2024

force push: implemented the UVC controls for the supported Video class controls.

I did not test this yet with the samples, but on the internal fork, we could get an IMX219 sensor with exposure and gain control from the host, format selection at startup (but not runtime, see [1]).

I believe that the last step for me is to test the sample on several boards that support device_next and fix the CI.

@josuah
Copy link
Collaborator Author

josuah commented Sep 12, 2024

Known limitations:

[1]: there is currently no <video.h> API to let the application know that a format change occurred. For now, the sample waits that the host makes an initial choice, and does not reconsider its format selection.
A trade-off between supported feature and sample complexity.

[2]: there is currently no <video.h> API to let the video device communicate their min/max/step, so 0 is always picked as min, INT32/16/8_MAX as max, and 1 as step. Maybe the solution is to define an unit for each of the controls and have every sensor map this to their local definition. For instance, 1 µs for exposure, 1/1000 for gain, etc, and have the max value implicit. DONE

[3]: The "default" value is an arbitrary value of 1 instead of querying the controls of each sensor. DONE

[4]: There is no device const struct uvc_conf and only struct uvc_data, which wastes precious memory. DONE.

[5]: There are missing implementations for selector unit, extensions unit, encoding unit. TODO.

[6]: UVC introduces dependencies between some controls, i.e. auto-expopsure needs to be off for exposure to be accepted. TODO.

[7]: UVC has "error" control type reporting the last error. DONE

[8]: Only a single endpoint and output/streaming interface is supported per UVC interface. Composite devices (multiple UVC classes per device) are used instead for supporting multiple video streams per device. DONE

[9]: No documentation outside the devicetree bindings. DONE (no documentation needed anymore as no configuration required).

[10]: Supports custom header size, but not passing custom header data yet.

[11]: Still image capture (capturing one frame at full resolution) not supported.

[12]: USB3CV compliance tests not all passing since last rebase. TODO.

[13]: Announcing different resolutions/FPS for different connection speed not supported.

[14]: Asynchronous controls (the host setting a control, and a notification interrupt alert of completion) not supported.

Supported features:

[A]: Class API and enumeration

[B]: Custom control chains descriptors built from the devicetree layout Not supported by Linux

[C]: Selection of which controls to expose to the host via devicetree toggles Now controlled by the drivers.

[D]: Per-control entity tuning Sending all the controls requests to the first driver of the pipeline.

[E]: Handling of control commands end-to-end from host to Zephyr video device

[F]: Zephyr native Video API that allows to enqueue/dequeue frames like any other Zephyr video device.

[G]: Supports fragmented frames as discussed in #66994 and #72827

[H]: Can configure pixel format and resolution on the devicetree Done automatically by asking the video drivers.

[I]: Supports querying the min/max/current values of every controls end-to-end from host to Zephyr video driver.

@josuah josuah force-pushed the pr-usb-uvc branch 3 times, most recently from c049412 to 8f2155e Compare March 1, 2025 16:09
@josuah
Copy link
Collaborator Author

josuah commented Mar 1, 2025

Force-push:

  • Only support a single stream. If not liking this, I can git reset --hard 1039a2b.

On Windows, multiple streams only give 1 camera device (unlike Linux) and for instance the default camera app does not support switching between the streams:

image1

Using "composite devices" with 2 UVC instances on devicetree allows to show multiple camera devices, much better supported in applications:

image

This also permits to simplify the implementation everywhere.

@josuah josuah force-pushed the pr-usb-uvc branch 3 times, most recently from 451bde6 to b50ad20 Compare March 5, 2025 23:56
@josuah
Copy link
Collaborator Author

josuah commented Mar 5, 2025

force-push:

  • Windows compatibility is back [1]
  • Descriptors and controls closer to compliance according to USB3CV
  • Rebase on latest main
  • Bugfix for dual-stream support (allow init to be called several times without crashing)

[1]: For getting an actual stream out on Wndows, there need any of these, to support the YUYV pixel format:

Comment on lines 164 to 166
NET_BUF_POOL_VAR_DEFINE(uvc_buf_pool, DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) * 16,
512 * DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) * 16,
sizeof(struct uvc_buf_info), NULL);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UDC_BUF_POOL_VAR_DEFINE(uvc_buf_pool, DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) * 16,
			512 * DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) * 16,
			sizeof(struct uvc_buf_info), NULL);

I was confused, but while working on #86920 I noticed that actually ud_size parameter can be passed to the macro.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is a drop-in replacement... 😯 Zero excuse for using NET_BUF_POOL_VAR_DEFINE() instead of UDC_BUF_POOL_VAR_DEFINE()!

Comment on lines +231 to +235
.size = 4,
.bit = 3,
.selector = UVC_CT_EXPOSURE_TIME_ABS_CONTROL,
.op = UVC_OP_VC_INT,
.param = VIDEO_CID_EXPOSURE
Copy link
Member

@XenuIsWatching XenuIsWatching Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

speaking of windows in your last comment... doesn't Windows also like to "not follow" the specification where it doesn't use 100us units for the exposure time absolute like Linux and Mac OS do, and sends it over in log2 value.

I know that in the past when I had to implement a 6 class USB composite device superspeed plus camera interface many years ago, and IIRC, Windows was kind of a nightmare to deal with 😠 (and I also ran in to the same issue you're having with V4L2 being 'better' and had to put a YUVU format desc in there for 'windows' peeps), and did a not fun workaround to get users happy and put an extension unit in there as a quick bandaid to make the 100us still work. While I don't think having an extenstion unit here just for special Windows users is the right solution.... I'm not quite sure what good solution here would be... but maybe it's something to think about...

Copy link
Collaborator Author

@josuah josuah Mar 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exposure being much more sensitive in the low values, I suppose they wanted to improve user experience of all the naive implementations exposing a linear exposure slider... Preventing to write correct software at the same time.

Currently, UVC does not really have a mapping between the controls and their integration. This is an arbitrary value passed to the sensor register directly, happily overflowing the max.

When #82158 is introduced, this would be the opportunitty to focus on how the UVC controls and Zephyr Video controls are mapped to each other, allowing some customization here.

Much grateful for this insight! This is the opportunity to put a long-term fix/workaround for these issues.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some proposal that could also help with such quirk and others:

@josuah josuah force-pushed the pr-usb-uvc branch 2 times, most recently from e7b5d11 to aa8b3f1 Compare March 11, 2025 14:53
@@ -0,0 +1,9 @@
# Copyright (c) 2023 Nordic Semiconductor ASA
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change it to # Copyright The Zephyr Project Contributors

Comment on lines 19 to 38
Requirements
************

The requirements for this sample is an USB driver using the latest
``device_next`` API.

If a ``zephyr,camera`` node is chosen for the board, it will be used as source.
If not, this sample can be built using this command to use an emulated video source:

.. code-block:: console

west build -b <board> -- -DEXTRA_DTC_OVERLAY_FILE=video-emul.overlay

The USB descriptors are generated from the video API, and the user does not need
to configure them.

Building and Running
********************

Build the sample application and flash the resulting binaries.

.. zephyr-app-commands::
:zephyr-app: samples/subsys/usb/uvc
:board: nrf52840dongle
:goals: build flash
:compact:

.. zephyr-app-commands::
:zephyr-app: samples/subsys/usb/uvc
:board: rpi_pico
:goals: build flash
:compact:

Upon reboot, the device is expected to be detected as a webcam device:

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems to be outdated and a bit unclear. What about

diff --git a/samples/subsys/usb/uvc/README.rst b/samples/subsys/usb/uvc/README.rst
index 6539692f137..e500375abbd 100644
--- a/samples/subsys/usb/uvc/README.rst
+++ b/samples/subsys/usb/uvc/README.rst
@@ -19,37 +19,34 @@ video streams.
 Requirements
 ************
 
-The requirements for this sample is an USB driver using the latest
-``device_next`` API.
-
-If a ``zephyr,camera`` node is chosen for the board, it will be used as source.
-If not, this sample can be built using this command to use an emulated video source:
-
-.. code-block:: console
-
-   west build -b <board> -- -DEXTRA_DTC_OVERLAY_FILE=video-emul.overlay
-
-The USB descriptors are generated from the video API, and the user does not need
-to configure them.
+This sample uses the new USB device stack and requires the USB device
+controller ported to the :ref:`udc_api`.
 
 Building and Running
 ********************
 
-Build the sample application and flash the resulting binaries.
+If a board is equipped with a supported video sensor, and ``zephyr,camera``
+node is chosen for the board, it will be used as the video source. Currently
+only Arduino Nicla Vision is supported. The sample can be built as follows:
 
 .. zephyr-app-commands::
    :zephyr-app: samples/subsys/usb/uvc
-   :board: nrf52840dongle
+   :board: arduino_nicla_vision/stm32h747xx/m7
    :goals: build flash
    :compact:
 
+If the video sensor is not present, the emulated video source can be used
+instead, and the sample can be built for any board with a supported USB device
+controller and sufficient RAM as follows:
+
 .. zephyr-app-commands::
    :zephyr-app: samples/subsys/usb/uvc
    :board: rpi_pico
    :goals: build flash
+   :gen-args: -DEXTRA_DTC_OVERLAY_FILE=video-emul.overlay
    :compact:
 
-Upon reboot, the device is expected to be detected as a webcam device:
+The device is expected to be detected as a webcam device:
 
 .. tabs::

?

Copy link
Collaborator Author

@josuah josuah Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed video-emul.overlay altogether to make it like the other video samples, which use VIDEO_SW_GENERATOR as a fallback.

Thank you for the clarifications!

Currently only Arduino Nicla Vision is supported

I just checked, and it enumerates, but fail to start. I'll solder UART pins and debug... and try on a couple more boards. This was tried most extensively on 3rd-party boards not yet on Zephyr.

How is it usually done?

Should there be a list of boards that were tested end-to-end on the README? If so no problem, I'll try to add PRs every time some extra device is known to work.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought you used Vision board for testing/development and want to include it in the sample. To make it easy and get this PR in ASAP, I suggest to make the sample very simple, it is UVC class implementation sample, there is no requirement to support real hardware, using emulated video data source is the preferred way since it just works. Ideally, the emulated video source should have build/runtime behavior close to the real hardware.

Comment on lines 122 to 129
LOG_INF("Dequeued %p from %s, enqueueing to %s",
vbuf, video_dev->name, uvc_dev->name);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change it to

Suggested change
LOG_INF("Dequeued %p from %s, enqueueing to %s",
vbuf, video_dev->name, uvc_dev->name);
LOG_DBG("Dequeued %p from %s, enqueueing to %s",
(void *)vbuf, video_dev->name, uvc_dev->name);

Comment on lines 133 to 140
LOG_INF("Dequeued %p from %s, enqueueing to %s",
vbuf, uvc_dev->name, video_dev->name);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change it to

Suggested change
LOG_INF("Dequeued %p from %s, enqueueing to %s",
vbuf, uvc_dev->name, video_dev->name);
LOG_DBG("Dequeued %p from %s, enqueueing to %s",
(void *)vbuf, uvc_dev->name, video_dev->name);

Comment on lines 8 to 11
chosen {
zephyr,camera = &rx0;
};

Copy link
Collaborator

@jfischer-no jfischer-no Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But then VIDEO_SW_GENERATOR generator cannot be enabled because

DT_CHOSEN_ZEPHYR_CAMERA := zephyr,camera
config VIDEO_SW_GENERATOR
bool "Video Software Generator"
depends on !$(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_CAMERA))

The concept behind VIDEO_SW_GENERATOR/imager/video-frame-rx-core is a bit confusing, I would expect there just VIDEO_SW_GENERATOR configured using devicetree.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The VIDEO_SW_GENERATOR is the main test pattern generator, but has no devicetree bindings, a Kconfig-enabled struct device.

The emulated imager/video-frame-rx is a stub implementation for CI purpose, and was abused for UVC before uvc_set_video_dev(uvc0_dev, video0_dev) support, allowing to use VIDEO_SW_GENERATOR.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open to suggestions on how to handle "hardware-less" devices for USB UVC or the Video area!

Copy link
Collaborator

@ngphibang ngphibang Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@josuah Can you explain more why uvc requires video_sw_generator as a device-tree based driver to be used by uvc ?
At first look at uvc_set_video_dev(uvc0_dev, video0_dev), maybe with the new video control framwork implementation, it can help as the video device is defined at compile time, so it can be retrieved easily at any moment ?

DEVICE_DEFINE(video_sw_generator, "VIDEO_SW_GENERATOR", &video_sw_generator_init, NULL,
	      &video_sw_generator_data_0, NULL, POST_KERNEL, CONFIG_VIDEO_INIT_PRIORITY,
	      &video_sw_generator_driver_api);

VIDEO_DEVICE_DEFINE(video_sw_generator, DEVICE_GET(video_sw_generator), NULL);

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, just ignore my unrelated comment ... I understand the issue now: we need to expose the video_sw_generator some how as the device-tree based hardware so that it can be "chosen" as "zephyr,camera"

Copy link
Collaborator Author

@josuah josuah Mar 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why uvc requires video_sw_generator as a device-tree based driver

It was in the past, but not anymore following @jfischer-no guidance.

maybe with the new video control framwork implementation, it can help as the video device is defined at compile time

This can avoid usability bugs such as "forgot to call uvc_set_video_dev() before enabling USB".

I did not know about DEVICE_GET(video_sw_generator)!

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why uvc requires video_sw_generator as a device-tree based driver

It was in the past, but not anymore following @jfischer-no guidance.

I am not sure we are talking about the same thing.
If video_sw_generator is a virtual video source device, using DT to configure and instantiate that device is the only correct way to make it behave like a real hardware video source. How the UVC implementation instantiates the class instances and binds them to the video source is another matter entirely.

Copy link
Collaborator

@jfischer-no jfischer-no Mar 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With video_sw_generator as the emulated video source, but configured the same way as a real video device, the sample code would be as follows:

/ {
	chosen {
		zephyr,camera = &sw_gen_foo1;
	};

	sw_gen_foo1: sw_gen_foo1 {
		compatible = "zephyr,video-sw-generator";

		port {
			...
		};
	};

};

&uvc {
	port {
		....
	};
};
	video_dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_camera));

	if (!device_is_ready(video_dev)) {
		LOG_ERR("video source %s is not ready or failed to initialize",
			video_dev == NULL ? "(nil)" : video_dev->name);
		return -ENODEV;
	}

	/* Must be done before initializing USB */
	uvc_set_video_dev(uvc_dev, video_dev);

Copy link
Collaborator

@ngphibang ngphibang Mar 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Open to suggestions on how to handle "hardware-less" devices for USB UVC or the Video area!

As in #82158, the video subsystem now keeps a list of registered video devices which can be exposed to user (by index), similar to the way Linux expose /dev/video0, /dev/video1, ... sysfs.

So, I think we don't need to predefine a single "zephyr,camera" chosen node anymore. Applications can work with the video device (HW or SW) of their choice and can change as they want:

0da5c4c

But then VIDEO_SW_GENERATOR generator cannot be enabled because

And then,

DT_CHOSEN_ZEPHYR_CAMERA := zephyr,camera
config VIDEO_SW_GENERATOR
bool "Video Software Generator"
depends on !$(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_CAMERA))
can be reverted.

69c4305

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The virtual video source selection got split out into this PR to facilitate review on this current PR in hope to make this current PR more manageable.

@josuah
Copy link
Collaborator Author

josuah commented Mar 30, 2025

Tested on FRDM-MCXN947 (64x64 test pattern):

10 (2) [-] none 10 8192 B 1265.812846 1265.812952 62.131 fps ts mono/SoE
11 (3) [-] none 11 8192 B 1265.828953 1265.829078 62.085 fps ts mono/SoE
12 (4) [-] none 12 8192 B 1265.845063 1265.845160 62.073 fps ts mono/SoE
13 (5) [-] none 13 8192 B 1265.861121 1265.861257 62.274 fps ts mono/SoE
14 (6) [-] none 14 8192 B 1265.877265 1265.877415 61.943 fps ts mono/SoE
15 (7) [-] none 15 8192 B 1265.893397 1265.893530 61.989 fps ts mono/SoE
16 (0) [-] none 16 8192 B 1265.909502 1265.909630 62.093 fps ts mono/SoE
17 (1) [-] none 17 8192 B 1265.925604 1265.925710 62.104 fps ts mono/SoE
18 (2) [-] none 18 8192 B 1265.941705 1265.941875 62.108 fps ts mono/SoE
19 (3) [-] none 19 8192 B 1265.957741 1265.957848 62.360 fps ts mono/SoE

frdm_mcxn947_test_pattern

Tested on Arducam Nicla Vision (320x240 image from the GC2145):

10 (2) [-] none 10 153600 B 1616.527349 1616.536039 17.575 fps ts mono/SoE
11 (3) [-] none 11 153600 B 1616.585332 1616.594024 17.246 fps ts mono/SoE
12 (4) [-] none 12 153600 B 1616.643287 1616.651874 17.255 fps ts mono/SoE
13 (5) [-] none 13 153600 B 1616.701219 1616.709955 17.262 fps ts mono/SoE
14 (6) [-] none 14 153600 B 1616.759261 1616.767988 17.229 fps ts mono/SoE
15 (7) [-] none 15 153600 B 1616.817353 1616.825967 17.214 fps ts mono/SoE
16 (0) [-] none 16 153600 B 1616.875228 1616.883880 17.279 fps ts mono/SoE
17 (1) [-] none 17 153600 B 1616.933229 1616.941945 17.241 fps ts mono/SoE
18 (2) [-] none 18 153600 B 1616.990988 1616.999615 17.313 fps ts mono/SoE
19 (3) [-] none 19 153600 B 1617.048931 1617.057769 17.258 fps ts mono/SoE

arduino_nicla_vision_zephyr_kite
arduino_nicla_vision_capturing_frmd_mcxn947_green_and_red_led

The colors are wrong with this board, probably because of an H-Flip: the LED in the middle is red.

@josuah josuah force-pushed the pr-usb-uvc branch 2 times, most recently from fddc96f to e844110 Compare March 30, 2025 15:55
@josuah
Copy link
Collaborator Author

josuah commented Mar 30, 2025

Force-push:

  • Let the application start the video device (required for DCMI, more flexible).
  • Update the devicetree documentation for UVC: port/endpoint/remote-endpoint-label not needed anymore
  • Applied suggested changes from the README without the "only Arducam Nicla Vision" which I am happy to test, but I hope many more would come next! :)

josuah added 2 commits March 30, 2025 16:04
Introduce a new USB Video Class (UVC) implementation from scratch.
It exposes a native Zephyr Video driver interface, allowing to call the
video_enqueue()/video_dequeue() interface. It will query the attached
video device to learn about the pipeline capabilities, and use this to
configure the USB descriptors. At runtime, this UVC implementation will
send this device all the control requests, which it can then dispatch to
the rest of the pipeline. The application can poll the format currently
selected by the host, but will not be alerted when the host configures
a new format, as there is no video.h API for it yet.

Signed-off-by: Josuah Demangeon <me@josuah.net>
The Arduino Nicla Vision board supports the new device_next USB stack
and can be used for testing USB Device features such as UVC.

Signed-off-by: Josuah Demangeon <me@josuah.net>
@josuah josuah force-pushed the pr-usb-uvc branch 2 times, most recently from fb8e6e8 to 1c6117c Compare March 30, 2025 17:33
@josuah
Copy link
Collaborator Author

josuah commented Mar 30, 2025

Force-push:

  • Removed configuration for VIDEO_SW_GENERATOR
  • Removed configuration for zephyr,video-emul-*

For now:

  • Only ability to use it with chosen { zephyr,camera = ... };
  • Editing src/main.c manually to use VIDEO_SW_GENERATOR will work out of the box as seen above.

In hope this makes review easier!

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 <me@josuah.net>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: Devicetree Binding PR modifies or adds a Device Tree binding area: Devicetree area: Samples Samples area: USB Universal Serial Bus area: Video Video subsystem Experimental Experimental features not enabled by default
Projects
None yet
Development

Successfully merging this pull request may close these issues.