UVC User Guide¶
REVISION HISTORY¶
| Revision No. | Description |
Date |
|---|---|---|
| 1.0 | 02/01/2024 |
1. Overview¶
This article will introduce the method of configuring UVC on the device side and the implementation method of related applications on the device side.
2. Introduction to Keywords¶
-
EP
EP stands for Endpoint, an important concept in the USB transmission protocol. In USB communication, data transmission is done through endpoints. A USB device can contain one or more endpoints, each with a unique endpoint address for data transmission between the device and the host. The transmission modes of the endpoint are mainly Control Transfer (Control), Bulk Transfer (Bulk), Interrupt Transfer (Interrupt), and Isochronous Transfer (Isochronous).
-
interval
In USB transmission, data transmission is carried out in frames. Interval, also known as frame interval, is a parameter used to describe the time interval between two consecutive data transmissions.
-
maxpacket
USB devices transmit data through endpoints, and when endpoints transmit data, they do so in packets. Maxpacket defines the maximum packet size of the corresponding endpoint in bytes.
-
burst
In USB communication, data transmission is divided into frames, each frame containing a specific number of packets. Burst is the process of sending or receiving multiple packets within a frame period by a USB host or device. Since the bandwidth of USB is limited, using Burst can improve the speed of data transmission and thus improve the performance of the device.
-
mult
Represents how many maxpackets can be sent in one transmission, depending on the hardware FIFO depth under its EP.
-
isoc
Isoc transmission is a time-based transmission method that provides a real-time transmission mechanism for transmitting real-time data such as audio and video. The characteristics of isoc transmission are fixed bandwidth and data transmission rate, but no processing is done for retransmission and loss of packets, so it is not suitable for transmitting data with high requirements for data transmission delay and data integrity.
-
bulk
Bulk transfer is a transfer-oriented transfer method that provides an efficient mechanism for transmitting large amounts of data. The characteristic of bulk transfer is that it does not guarantee the data transfer rate, but it has processed the retransmission and loss of packets, so it is suitable for transmitting data with low requirements for data transfer delay and data integrity.
-
PU
PU (Processing Unit) is a descriptor used to describe video processing units. It contains various attributes and control options of video processing units.
-
XU
XU (Extension Unit) is a descriptor used to describe extension units. It allows device manufacturers to define and support custom functions and control options to extend device functionality.
-
ConfigFs
ConfigFs (Configuration Filesystem) is a virtual filesystem implemented in the Linux kernel for configuring and managing runtime parameters of devices and drivers. By representing configuration parameters of devices and drivers as files and directories, users can configure and control device behavior by modifying these files and directories.
3. Hardware Endpoint Description¶
As the only entity in USB transmission, endpoints complete communication between devices and hosts. Different endpoint configurations will affect the transmission rate of devices. Therefore, this article will introduce how endpoint configuration affects transmission rate. In addition, when using UVC devices at the same time may compound other functions such as RNDIS and DFU because each hardware endpoint has limited resources if endpoint parameter configuration is unreasonable may cause EP endpoint allocation failure.
3.1 Bandwidth Speed Description¶
Explanation: 8000 represents the maximum number of times USB can transmit per second. The USB2.0 protocol defines frames and microframes. Each frame has a length of 1ms. In high-speed mode, each frame is divided into 8 microframes with a length of 125us each. Therefore theoretically USB can send up to 8000 times per second.
3.1.1 bulk mode¶
Interval: 1-16
maxpacketsize: The maximum value can be set to 512 in USB2.0 protocol and 1024 in USB3.0 protocol.
burst: 1-13 The maximum value changes depending on hardware conditions.
Since bulk's actual bandwidth will vary depending on factors such as video stream resolution, specific transmission rates will depend on actual Device-side endpoint configuration and Host-side idle bandwidth.
3.1.2 isoc mode¶
-
usb2.0
max_loadsize = 8000 / (2^(Interval-1)) * maxpacketsize * mult
-
usb3.0
max_loadsize = 8000 / (2^(Interval-1)) * maxpacketsize * mult * burst
-
Range
Interval: 1-16
maxpacketsize: Maximum set to 1024
mult: 1-3
burst: 1-13 Maximum value changes depending on hardware conditions.
Example: Interval=1, maxpacketsize=1024, mult=3, burst=5
The EP rate used under USB2.0 is: 23.4MB/s
The EP rate used under USB3.0 is: 117.1MB/s
3.2 EP Endpoint Allocation Description¶
3.2.1 Common Device EP Occupancy¶
| Direction of Use | EP Occupancy |
|---|---|
| RNDIS | INT-in+BULK-in+BULK-out |
| UVC | ISOC-in+INT-in OR BULK-in+INT-in |
| UAC | ISOC-in OR ISOC-out |
| CDC (serial) | INT-in+BULK-in+BULK-out |
| USB Mass Storage | BULK-in+BULK-out |
| Human Interface Device (HID) | INT-in+INT-out |
3.2.2 EP Endpoint Allocation Example¶
If the current USB2.0 hardware EP situation is as follows:
| EP.NO | Maxpacksize(Byte) |
|---|---|
| EP0 (fixed as CONTROL-mode, not assignable) | 512 |
| EP1 | 1024 |
| EP2 | 128 |
| EP3 | 512 |
| EP4 | 1024 |
| EP5 | 128 |
| EP6 | 512 |
If using UVC (IN) + UAC (IN) + RNDIS (bulk-IN + bulk-OUT + int-IN), it will occupy five EPs. If the set maxpacketsize is 512, there are only four EPs that can support maxpacketsize greater than or equal to 512, so it cannot meet the allocation situation.
4. Environment Setup¶
The UVC environment is built on top of the basic environment setup. Device attributes can be completed by loading drivers and configuring scripts (ConfigFS). Script configuration is convenient for debugging. Loading driver configuration can be fixed and compiled into the kernel.
Note: The difference between the two configuration methods is whether g_sstar_gadget is loaded. The script configuration method only does not need to load g_sstar_gadget, and other UVC dependent modules still need to be loaded.
4.1 Basic Environment Setup¶
4.1.1 Configuration under USB2.0¶
Device Drivers --->
<M> Multimedia support --->
Media device types --->
[*] Cameras and video grabbers
Media core support --->
<M> Video4linux core
[*] Media Controller API
[*] USB support --->
<M> USB Gadget Support --->
USB Peripheral Controller --->
<M> Sstar USB 2.0 Dvice Controller
USB Gadget precomposed configurations ->
<M> USB Sigmastar Gadget
[*] Include configuration with UVC (video)
The following ko files will be generated:
/**************/
USB basic driver
usb-common.ko
usbcore.ko
udc-core.ko
/**************/
UVC related dependent drivers
mc.ko
videodev.ko
videobuf2-common.ko
videobuf2-v4l2.ko
videobuf2-memops.ko v
videobuf2-vmalloc.ko
videobuf2-dma-sg.ko
/**************/
USB2.0 driver
udc-msb250x.ko
libcomposite.ko
/**************/
UVC driver
usb_f_uvc.ko
/**************/
UVC config driver
g_sstar_gadget.ko
4.1.2 Configuration under USB3.0(IFORD not supported)¶
Device Drivers --->
SStar SOC platform drivers
[*] SStar USB support
<M>Sigmastar USB3 PHY drivers
<M>Simple Glue Layer of SStar For DWC3
Device Drivers --->
<M> Multimedia support --->
Media device types --->
[*] Cameras and video grabbers
Media core support --->
<M> Video4linux core
[*] Media Controller API
[*] USB support --->
<M> Support for Host-side USB
<M> DesignWare USB3 DRD Core Support
DWC3 mode Selection (Gadget only mode)->
<M> USB Gadget Support --->
USB Peripheral Controller --->
<空> Sstar USB 2.0 Dvice Controller
USB Gadget precomposed configurations ->
<M> USB Sigmastar Gadget
[*] Include configuration with UVC (video)
The following ko files will be generated:
/**************/
USB basic driver
usb-common.ko
usbcore.ko
udc-core.ko
/**************/
UVC related dependent drivers
mc.ko
videodev.ko
videobuf2-common.ko
videobuf2-v4l2.ko
videobuf2-memops.ko
videobuf2-vmalloc.ko
videobuf2-dma-sg.ko
/**************/
USB3.0 driver
usbpll.ko
usb3-phy.ko
dwc3.ko
sstar-dwc3-of-simple.ko
libcomposite.ko
/**************/
UVC driver
usb_f_uvc.ko
4.1.3 Module Parameter Description¶
usb_f_uvc.ko
interrupt_ep_enable:
-
Parameter Description
Indicates whether to enable the interrupt endpoint (Interrupt Endpoint).
-
Configuration
insmod usb_f_uvc.ko interrupt_ep_enable=0Disable the interrupt EP endpoint.
4.2 UVC Device Attribute Configuration¶
4.2.1 Driver Configuration Description¶
To configure UVC through loading drivers, additional options need to be enabled in the kernel's menuconfig.
Device Drivers --->
[*] USB support --->
<M> USB Gadget Support --->
USB Gadget precomposed configurations ->
<M> USB Sigmastar Gadget
[*] Include configuration with UVC (video)
g_sstar_gadget.ko is generated.
g_sstar_gadget parameter description
bcdDevice:
-
Parameter Description
bcdDevice is a field in the USB device descriptor used to indicate the firmware version of the device. It is a 16-bit field, usually composed of three bytes, in BCD (Binary-Coded Decimal) format.
-
Configuration
insmod g_sstar_gadget.ko bcdDevice=0x0201If the value of bcdDevice is 0x0201, it means that the firmware version of the device is 2.01.
iSerialNumber:
-
Parameter Description
iSerialNumber is a field in the USB device descriptor used to indicate the serial number of the device. It is an index value that points to an entry in the String Descriptor Table that contains the serial number string of the device.
-
Configuration
insmod g_sstar_gadget.ko iSerialNumber=0The value of the iSerialNumber field is either zero or a non-zero index value. If it is zero, it means that the device does not provide serial number information.
streaming_maxburst:
-
Parameter Description
streaming_maxburst is a parameter in UVC used to specify the maximum continuous transmission burst packet count (burst) allowed when transmitting video data. It defines the maximum number of packets that can be sent continuously in one transmission.
-
Configuration Description
insmod g_sstar_gadget.ko streaming_maxburst=13,13 (two-way configuration)streaming_maxburst specifies the size of uvc transmission ep maxburst and supports multi-way configuration (separated by commas)
bulk_streaming_ep:
-
Parameter Description
bulk_streaming_ep refers to the bulk transfer (Bulk Transfer) endpoint used for transmitting video data in UVC devices.
-
Configuration Description
insmod g_sstar_gadget.ko bulk_streaming_ep=0bulk_streaming_ep = 0: use isoc mode
bulk_streaming_ep = 1: use bulk mode
idProduct:
-
Parameter Description
idProduct is a field in the USB device descriptor used to identify the product ID of the device. Each USB device has a unique product ID.
-
Configuration
insmod g_sstar_gadget.ko idProduct=0x3311Product ID (idProduct) is a 16-bit integer value used to represent the specific product model or version of a device. It is assigned by the manufacturer of the device and set during the manufacturing process of the device. The host system can identify and distinguish different USB devices by reading the product ID in the device descriptor.
iManufacturer:
-
Parameter Description
iManufacturer is a field in the USB device descriptor used to identify the manufacturer name of the device. It is an index pointing to a string descriptor that contains manufacturer name information for the device.
-
Configuration
insmod g_sstar_gadget.ko iManufacturer=0The manufacturer name string descriptor is a string containing the actual manufacturer name, usually provided by the manufacturer of the device and set during the manufacturing process of the device. The host system can obtain the manufacturer name of the device by reading the value of the
iManufacturerfield in the device descriptor and then looking up the corresponding string descriptor in the string descriptor list.
streaming_interval:
-
Parameter Description
A parameter in the UVC (USB Video Class) protocol used to represent the interval time for video stream transmission. In UVC, video streams are transmitted in frames, each frame containing a complete image. streaming_interval represents the time interval between two consecutive video frames, usually in milliseconds. It is used to determine the rate and stability of video frame transmission.
-
Configuration Description
insmod g_sstar_gadget.ko streaming_interval=1,1 (two-way configuration)streaming_interval range is 1-16.
streaming_name:
-
Parameter Description
It is used to identify the unique name or identifier of a video stream.
-
Configuration Description
insmod g_sstar_gadget.ko streaming_name=vide0,video1 (two-channel configuration)
uvc_function_enable:
-
Parameter Description
Used to configure multi-channels Functions. The number of channels can also be selected when configuring g_sstar_gadget in menuconfig.
Device Drivers [*]USB support <M> USB Gadget Support ---> USB Gadget precomposed configurations -> <M> USB Sigmastar Gadget [*] Include configuration with UVC (video) (1) Muti Stream Under One Function //This can be set to other values. If set to 2, one UVC will share one control interface. -
Configuration Description
insmod g_sstar_gadget.ko uvc_function_enable=2 (configure two-channel UVC)
rndis_function_enable:
-
Parameter Description
Used to configure uvc's composite device configuration and enable rndis at the same time.
Device Drivers [*]USB support <M> USB Gadget Support ---> USB Gadget precomposed configurations -> <M> USB Sigmastar Gadget [*] Include configuration with UVC (video) (1) Muti Stream Under One Function [*] Include configuration with RNDSI -
Configuration Description
insmod g_sstar_gadget.ko rndis_function_enable=1 -
Note
If you find that there is no rndis device after configuring the above composite configuration, it is because at this time the board side is a usb composite device. Only after the uvc application is running will the rndis device be recognized by the host side.
4.2.2 Script Configuration Description¶
4.2.2.1 Script Example¶
#!/bin/sh
USB_DEVICE_DIR=/sys/kernel/config/usb_gadget/s-star
USB_CONFIGS_DIR=/sys/kernel/config/usb_gadget/s-star/configs/default.1
USB_FUNCTIONS_DIR=/sys/kernel/config/usb_gadget/s-star/functions
FUNCTION_ENALBE=0
# stream number
UVC_FUNCTION_ENABLE=0
RNDIS_FUNCTION_ENABLE=0
#uvc
UVC_STREAM_INDEX=0
UVC_STREAMING_MAX_PACKET_ARRAY="3072,1024"
UVC_STREAMING_MAX_BURST_ARRAY="13,13"
UVC_STREAMING_INTERVAL_ARRAY="1,1,1,1,1,1"
UVC_STREAMING_NAME_ARRAY="UVC Camera 0,UVC Camera 1"
UVC_STREAMING_FORMAT_YUV_ENABLE=0
UVC_STREAMING_FORMAT_NV12_ENABLE=0
UVC_STREAMING_FORMAT_MJPEG_ENABLE=1
UVC_STREAMING_FORMAT_H264_ENABLE=1
UVC_STREAMING_FORMAT_H265_ENABLE=1
UVC_VERSION=0x0100 #uvc1.5: 0x0150 uvc1.0:0x0100
UVC_MODE=0x1 #0x0 :isoc mode o0x1:bulk mode
USB_DEVICE_PID=0x0102
USB_DEVICE_VID=0x1d6b
MANUFACTURER="Linux Foundation"
PRODUCT="USB GADGET"
SERIAL_NUM="0123"
CONFIGURATION="composite device"
###########################################UVC CONFIG######################################################
# bBitsPerPixel(uncompressed/framebase)/bDefaultFrameIndex/bmaControls/guidFormat(uncompressed/framebase)
config_uvc_format_yuyv()
{
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv
echo 0x10 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/bBitsPerPixel
echo 0x01 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/bDefaultFrameIndex
echo 0x00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/bmaControls
echo -ne \\x59\\x55\\x59\\x32\\x00\\x00\\x10\\x00\\x80\\x00\\x00\\xaa\\x00\\x38\\x9b\\x71 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/guidFormat
}
config_uvc_format_nv12()
{
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12
echo 0x0C > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/bBitsPerPixel
echo 0x01 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/bDefaultFrameIndex
echo 0x04 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/bmaControls
echo -ne \\x4e\\x56\\x31\\x32\\x00\\x00\\x10\\x00\\x80\\x00\\x00\\xaa\\x00\\x38\\x9b\\x71 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/guidFormat
}
config_uvc_format_mjpeg()
{
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default
echo 0x01 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/bDefaultFrameIndex
echo 0x04 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/bmaControls
}
config_uvc_format_h264()
{
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264
echo 0x10 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/bBitsPerPixel
echo 0x01 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/bDefaultFrameIndex
echo 0x04 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/bmaControls
echo -ne \\x48\\x32\\x36\\x34\\x00\\x00\\x10\\x00\\x80\\x00\\x00\\xaa\\x00\\x38\\x9b\\x71 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/guidFormat
}
config_uvc_format_h265()
{
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265
echo 0x10 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/bBitsPerPixel
echo 0x01 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/bDefaultFrameIndex
echo 0x00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/bmaControls
echo -ne \\x48\\x32\\x36\\x35\\x00\\x00\\x10\\x00\\x80\\x00\\x00\\xaa\\x00\\x38\\x9b\\x71 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/guidFormat
}
# bmCapabilities/dwDefaultFrameInterval/dwFrameInterval/dwMaxBitRate/dwMaxVideoFrameBufferSize(uncompressed/mjpeg)/dwMinBitRate/wHeight/wWidth
config_uvc_frame_yuyv()
{
UVC_FRAME_WIDTH=$1
UVC_FRAME_HEIGHT=$2
UVC_FRAME_INTERVAL=$3
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p
echo 0x00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p/bmCapabilities
echo $UVC_FRAME_INTERVAL > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p/dwDefaultFrameInterval
echo -e "333333\n666666\n1000000" > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p/dwFrameInterval
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*30)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p/dwMaxBitRate
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*2)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p/dwMaxVideoFrameBufferSize
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*10)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p/dwMinBitRate
echo $UVC_FRAME_HEIGHT > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p/wHeight
echo $UVC_FRAME_WIDTH > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv/${UVC_FRAME_HEIGHT}p/wWidth
}
config_uvc_frame_nv12()
{
UVC_FRAME_WIDTH=$1
UVC_FRAME_HEIGHT=$2
UVC_FRAME_INTERVAL=$3
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p
echo 0x00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p/bmCapabilities
echo $UVC_FRAME_INTERVAL > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p/dwDefaultFrameInterval
echo -e "333333\n666666\n1000000" > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p/dwFrameInterval
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*12*30)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p/dwMaxBitRate
echo | awk "{print $UVC_FRAME_WIDTH*$UVC_FRAME_HEIGHT*3/2}" > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p/dwMaxVideoFrameBufferSize
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*12*10)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p/dwMinBitRate
echo $UVC_FRAME_HEIGHT > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p/wHeight
echo $UVC_FRAME_WIDTH > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/${UVC_FRAME_HEIGHT}p/wWidth
}
config_uvc_frame_mjpeg()
{
UVC_FRAME_WIDTH=$1
UVC_FRAME_HEIGHT=$2
UVC_FRAME_INTERVAL=$3
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p
echo 0x00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p/bmCapabilities
echo $UVC_FRAME_INTERVAL > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p/dwDefaultFrameInterval
echo -e "333333\n666666\n1000000" > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p/dwFrameInterval
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*30)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p/dwMaxBitRate
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*2)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p/dwMaxVideoFrameBufferSize
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*10)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p/dwMinBitRate
echo $UVC_FRAME_HEIGHT > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p/wHeight
echo $UVC_FRAME_WIDTH > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default/${UVC_FRAME_HEIGHT}p/wWidth
}
config_uvc_frame_h264()
{
UVC_FRAME_WIDTH=$1
UVC_FRAME_HEIGHT=$2
UVC_FRAME_INTERVAL=$3
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p
echo 0x00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/bmCapabilities
echo $UVC_FRAME_INTERVAL > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwDefaultFrameInterval
echo -e "333333\n666666\n1000000" > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwFrameInterval
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*30)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwMaxBitRate
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*10)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwMinBitRate
echo $UVC_FRAME_HEIGHT > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/wHeight
echo $UVC_FRAME_WIDTH > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/wWidth
}
config_uvc_frame_h265()
{
UVC_FRAME_WIDTH=$1
UVC_FRAME_HEIGHT=$2
UVC_FRAME_INTERVAL=$3
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/${UVC_FRAME_HEIGHT}p
echo 0x00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/${UVC_FRAME_HEIGHT}p/bmCapabilities
echo $UVC_FRAME_INTERVAL > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/${UVC_FRAME_HEIGHT}p/dwDefaultFrameInterval
echo -e "333333\n666666\n1000000" > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/${UVC_FRAME_HEIGHT}p/dwFrameInterval
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*30)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/${UVC_FRAME_HEIGHT}p/dwMaxBitRate
echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*10)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/${UVC_FRAME_HEIGHT}p/dwMinBitRate
echo $UVC_FRAME_HEIGHT > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/${UVC_FRAME_HEIGHT}p/wHeight
echo $UVC_FRAME_WIDTH > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265/${UVC_FRAME_HEIGHT}p/wWidth
}
config_uvc_yuv()
{
config_uvc_format_yuyv
config_uvc_frame_yuyv 320 240 333333
config_uvc_frame_yuyv 640 480 333333
config_uvc_frame_yuyv 1280 720 333333
config_uvc_frame_yuyv 1920 1080 333333
config_uvc_frame_yuyv 2560 1440 333333
config_uvc_frame_yuyv 3840 2160 666666
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/yuyv ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default/yuyv
}
config_uvc_nv12()
{
config_uvc_format_nv12
config_uvc_frame_nv12 320 240 333333
config_uvc_frame_nv12 640 480 333333
config_uvc_frame_nv12 1280 720 333333
config_uvc_frame_nv12 1920 1080 333333
config_uvc_frame_nv12 2560 1440 333333
config_uvc_frame_nv12 3840 2160 666666
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12 ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default/nv12
}
config_uvc_mjpeg()
{
config_uvc_format_mjpeg
config_uvc_frame_mjpeg 320 240 333333
config_uvc_frame_mjpeg 640 480 333333
config_uvc_frame_mjpeg 1280 720 333333
config_uvc_frame_mjpeg 1920 1080 333333
config_uvc_frame_mjpeg 2560 1440 333333
config_uvc_frame_mjpeg 3840 2160 333333
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/mjpeg/default ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default/mjpeg
}
config_uvc_h264()
{
config_uvc_format_h264
config_uvc_frame_h264 320 240 333333
config_uvc_frame_h264 640 480 333333
config_uvc_frame_h264 1280 720 333333
config_uvc_frame_h264 1920 1080 333333
config_uvc_frame_h264 2560 1440 333333
config_uvc_frame_h264 3840 2160 333333
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264 ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default/h264
}
config_uvc_h265()
{
config_uvc_format_h265
config_uvc_frame_h265 320 240 333333
config_uvc_frame_h265 640 480 333333
config_uvc_frame_h265 1280 720 333333
config_uvc_frame_h265 1920 1080 333333
config_uvc_frame_h265 2560 1440 333333
config_uvc_frame_h265 3840 2160 333333
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h265 ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default/h265
}
config_uvc()
{
UVC_STREAMING_MAX_PACKET=`echo $UVC_STREAMING_MAX_PACKET_ARRAY | awk -F ',' '{print $'$((UVC_STREAM_INDEX+1))'}'`
UVC_STREAMING_MAX_BURST=`echo $UVC_STREAMING_MAX_BURST_ARRAY | awk -F ',' '{print $'$((UVC_STREAM_INDEX+1))'}'`
UVC_STREAMING_INTERVAL=`echo $UVC_STREAMING_INTERVAL_ARRAY | awk -F ',' '{print $'$((UVC_STREAM_INDEX+1))'}'`
UVC_STREAMING_NAME=`echo $UVC_STREAMING_NAME_ARRAY | awk -F ',' '{print $'$((UVC_STREAM_INDEX+1))'}'`
# Configure speed/name
# streaming_maxpacket/streaming_maxburst/streaming_interval/bulk_streaming_ep
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}
echo $UVC_STREAMING_MAX_PACKET > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming_maxpacket
echo $UVC_STREAMING_MAX_BURST > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming_maxburst
echo $UVC_STREAMING_INTERVAL > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming_interval
echo -n $UVC_STREAMING_NAME > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming_name
echo $UVC_MODE > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/bulk_streaming_ep
# Configure control
# bcdUVC/dwClockFrequency
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/control/header/default
echo $UVC_VERSION > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/control/header/default/bcdUVC
echo 0x02DC6C00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/control/header/default/dwClockFrequency
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/control/header/default ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/control/class/fs/default
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/control/header/default ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/control/class/ss/default
# Configure streaming
mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default
if [ $UVC_STREAMING_FORMAT_YUV_ENABLE -gt 0 ]; then
config_uvc_yuv
fi
if [ $UVC_STREAMING_FORMAT_NV12_ENABLE -gt 0 ]; then
config_uvc_nv12
fi
if [ $UVC_STREAMING_FORMAT_MJPEG_ENABLE -gt 0 ]; then
config_uvc_mjpeg
fi
if [ $UVC_STREAMING_FORMAT_H264_ENABLE -gt 0 ]; then
config_uvc_h264
fi
if [ $UVC_STREAMING_FORMAT_H265_ENABLE -gt 0 ]; then
config_uvc_h265
fi
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/class/fs/default
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/class/hs/default
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/class/ss/default
}
###########################################RNDIS CONFIG####################################################
config_rndis()
{
# dev_addr/host_addr/qmult/class/subclass/protocol
mkdir ${USB_FUNCTIONS_DIR}/rndis.instance0
}
config_clear()
{
if [ ! -d $USB_DEVICE_DIR ];then
return
fi
echo "" > ${USB_DEVICE_DIR}/UDC
for i in `ls ${USB_CONFIGS_DIR}/ | grep ".instance"`
do
rm ${USB_CONFIGS_DIR}/$i
done
if [ -d $USB_CONFIGS_DIR/strings/0x409 ]; then
rmdir $USB_CONFIGS_DIR/strings/0x409
fi
if [ -d $USB_CONFIGS_DIR ]; then
rmdir $USB_CONFIGS_DIR
fi
for i in `ls $USB_FUNCTIONS_DIR | grep .instance`; do
if [ -n `echo $i | grep uvc` ]; then
rm -f $USB_FUNCTIONS_DIR/$i/control/class/fs/default
rm -f $USB_FUNCTIONS_DIR/$i/control/class/ss/default
rm -f $USB_FUNCTIONS_DIR/$i/streaming/class/fs/default
rm -f $USB_FUNCTIONS_DIR/$i/streaming/class/hs/default
rm -f $USB_FUNCTIONS_DIR/$i/streaming/class/ss/default
rm -f $USB_FUNCTIONS_DIR/$i/streaming/header/default/yuyv
rm -f $USB_FUNCTIONS_DIR/$i/streaming/header/default/nv12
rm -f $USB_FUNCTIONS_DIR/$i/streaming/header/default/mjpeg
rm -f $USB_FUNCTIONS_DIR/$i/streaming/header/default/h264
rm -f $USB_FUNCTIONS_DIR/$i/streaming/header/default/h265
if [ -d $USB_FUNCTIONS_DIR/$i/streaming/uncompressed/yuyv ]; then
rmdir $USB_FUNCTIONS_DIR/$i/streaming/uncompressed/yuyv/*p
rmdir $USB_FUNCTIONS_DIR/$i/streaming/uncompressed/yuyv
fi
if [ -d $USB_FUNCTIONS_DIR/$i/streaming/uncompressed/nv12 ]; then
rmdir $USB_FUNCTIONS_DIR/$i/streaming/uncompressed/nv12/*p
rmdir $USB_FUNCTIONS_DIR/$i/streaming/uncompressed/nv12
fi
if [ -d $USB_FUNCTIONS_DIR/$i/streaming/mjpeg/default ]; then
rmdir $USB_FUNCTIONS_DIR/$i/streaming/mjpeg/default/*p
rmdir $USB_FUNCTIONS_DIR/$i/streaming/mjpeg/default
fi
if [ -d $USB_FUNCTIONS_DIR/$i/streaming/framebase/h264 ]; then
rmdir $USB_FUNCTIONS_DIR/$i/streaming/framebase/h264/*p
rmdir $USB_FUNCTIONS_DIR/$i/streaming/framebase/h264
fi
if [ -d $USB_FUNCTIONS_DIR/$i/streaming/framebase/h265 ]; then
rmdir $USB_FUNCTIONS_DIR/$i/streaming/framebase/h265/*p
rmdir $USB_FUNCTIONS_DIR/$i/streaming/framebase/h265
fi
if [ -d $USB_FUNCTIONS_DIR/$i/control/header/default ]; then
rmdir $USB_FUNCTIONS_DIR/$i/control/header/default
fi
if [ -d $USB_FUNCTIONS_DIR/$i/streaming/header/default ]; then
rmdir $USB_FUNCTIONS_DIR/$i/streaming/header/default
fi
fi
rmdir $USB_FUNCTIONS_DIR/$i
done
if [ -d $USB_DEVICE_DIR/strings/0x409 ]; then
rmdir $USB_DEVICE_DIR/strings/0x409
fi
rmdir $USB_DEVICE_DIR
}
usage()
{
echo -e "Usage:./gadget-configfs.sh -x NUM\n"
echo -e "\t -a UVC"
echo -e "\t -z NO CLASS"
echo -e "\t Examples: ./gadget-configfs.sh -a1 ---> one UVC device"
}
main()
{
while getopts ":a:b:c:d:e:f:g:h:i:j:z" opt
do
case $opt in
a)
UVC_FUNCTION_ENABLE=$OPTARG
;;
z)
config_clear
exit 0
;;
?)
usage
exit 1
;;
esac
done
if [ $UVC_FUNCTION_ENABLE -eq 0 ] ; then
usage
exit 1
fi
config_clear
echo "UVC:$UVC_FUNCTION_ENABLE"
if [ -d /sys/kernel/config/usb_gadget ]
then
umount /sys/kernel/config
fi
mount -t configfs none /sys/kernel/config
mkdir $USB_DEVICE_DIR
mkdir $USB_CONFIGS_DIR
mkdir ${USB_DEVICE_DIR}/strings/0x409
mkdir ${USB_CONFIGS_DIR}/strings/0x409
# Configure configs
# MaxPower/bmAttributes
echo 0x02 > ${USB_CONFIGS_DIR}/MaxPower
echo 0xC0 > ${USB_CONFIGS_DIR}/bmAttributes
# Configure strings
# manufacturer/product/serialnumber/configuration
echo "$MANUFACTURER" > ${USB_DEVICE_DIR}/strings/0x409/manufacturer
echo "$PRODUCT" > ${USB_DEVICE_DIR}/strings/0x409/product
echo "$SERIAL_NUM" > ${USB_DEVICE_DIR}/strings/0x409/serialnumber
echo "$CONFIGURATION" > ${USB_CONFIGS_DIR}/strings/0x409/configuration
# functions
if [ $RNDIS_FUNCTION_ENABLE -gt 0 ]; then
config_rndis
ln -s ${USB_FUNCTIONS_DIR}/rndis.instance0 ${USB_CONFIGS_DIR}/rndis.instance0
fi
# functions
while [ $UVC_STREAM_INDEX -lt $UVC_FUNCTION_ENABLE ]
do
config_uvc
ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX} ${USB_CONFIGS_DIR}/uvc.instance${UVC_STREAM_INDEX}
let UVC_STREAM_INDEX++
done
# Configure device
# UDC/bDeviceClass/bDeviceProtocol/bDeviceSubClass/bMaxPacketSize0/bcdDevice/bcdUSB/idProduct/idVendor
echo 0xef > ${USB_DEVICE_DIR}/bDeviceClass
echo 0x01 > ${USB_DEVICE_DIR}/bDeviceProtocol
echo 0x02 > ${USB_DEVICE_DIR}/bDeviceSubClass
echo 0x00 > ${USB_DEVICE_DIR}/bMaxPacketSize0
echo 0x0419 > ${USB_DEVICE_DIR}/bcdDevice
echo 0x0200 > ${USB_DEVICE_DIR}/bcdUSB
echo $USB_DEVICE_PID > ${USB_DEVICE_DIR}/idProduct
echo $USB_DEVICE_VID > ${USB_DEVICE_DIR}/idVendor
UDC=`ls /sys/class/udc/ | head -n 1`
echo $UDC > ${USB_DEVICE_DIR}/UDC
}
main $@
4.2.2.2 Script Execution¶
./xxxx.sh -a2
Enable two-channel uvc device nodes. After successful execution, there are video0 and video1 device nodes under /dev.
./xxxx.sh -z
Clear all current configuration items.
Note: Relying on configfs to configure uvc cannot load the g_sstar_gadget driver because they are all doing configuration actions.
4.2.2.3 Script Parameter Description¶
| Parameter | Description | Example |
|---|---|---|
| UVC_STREAMING_NAME_ARRAY | Configure the name of each UVC device | Configure the names of two uvc devices: UVC_STREAMING_NAME_ARRAY="UVC Camera 0,UVC Camera 1" |
| UVC_STREAMING_MAX_PACKET_ARRAY | Configure the maxpacket attribute value of each uvc device | Configure the maxpacket of two uvc devices to 3072 and 1024: UVC_STREAMING_MAX_PACKET_ARRAY="3072,1024" |
| UVC_STREAMING_MAX_BURST_ARRAY | Configure the burst attribute value of each uvc device | Configure the brust of two uvc devices to 13 and 13: UVC_STREAMING_MAX_BURST_ARRAY="13,13" |
| UVC_STREAMING_INTERVAL_ARRAY | Configure the interval attribute value of each uvc device | Configure the interval of two uvc devices to 1: UVC_STREAMING_INTERVAL_ARRAY="1,1" |
| UVC_MODE | Configure the transmission mode of the uvc device | UVC_MODE = 0x0: isoc mode UVC_MODE = 0x1: bulk mode |
| UVC_STREAMING_FORMAT_YUV_ENABLE | Whether to enable YUV data format | UVC_STREAMING_FORMAT_YUV_ENABLE =0:Disable UVC_STREAMING_FORMAT_YUV_ENABLE=1:Enable |
| UVC_STREAMING_FORMAT_NV12_ENABLE | Whether to enable NV12 data format | UVC_STREAMING_FORMAT_NV12_ENABLE =0:Disable UVC_STREAMING_FORMAT_NV12_ENABLE=1:Enable |
| UVC_STREAMING_FORMAT_MJPEG_ENABLE | Whether to enable Mjpeg data format | UVC_STREAMING_FORMAT_MJPEG_ENABLE =0:Disable UVC_STREAMING_FORMAT_MJPEG_ENABLE=1:Enable |
| UVC_STREAMING_FORMAT_H264_ENABLE | Whether to enable H264 data format | UVC_STREAMING_FORMAT_H264_ENABLE =0:Disable UVC_STREAMING_FORMAT_H264_ENABLE=1:Enable |
| UVC_STREAMING_FORMAT_H265_ENABLE | Whether to enable H265 data format | UVC_STREAMING_FORMAT_H265_ENABLE =0:Disable UVC_STREAMING_FORMAT_H265_ENABLE=1:Enable |
| UVC_VERSION=0x0100 | Choose uvc version | UVC_VERSION =0x0150:uvc1.5 version UVC_VERSION=0x0100:uvc1.0 version |
5. Programming Guide¶
5.1 V4L2 Related API¶
-
StreamingBuf related api
Control Code Description VIDIOC_QBUF Used to add a buffer frame to the buffer queue for processing or acquisition by the driver. It passes an idle buffer frame to the driver so that the driver can fill data into that buffer frame VIDIOC_DQBUF Used to retrieve a filled video frame from the video buffer queue VIDIOC_REQBUFS Used to request allocation of V4L2 driver's video buffers VIDIOC_QUERYBUF Used to query information about buffers in the driver, such as buffer size and offset address. Its main function is to be able to access and operate buffers in user space. VIDIOC_STREAMON Used to start transmission of video stream data. This command is usually used after device initialization to notify the device to start collecting and transmitting video data VIDIOC_STREAMOFF Used to stop transmission of video streams -
Event control related API
Control Code Description VIDIOC_G_FMT Used to obtain the current format information of the collected or output video, such as resolution, frame rate, pixel format, etc. VIDIOC_S_FMT Request to set the format of the video data (such as the width, height, pixel format of the image, etc.) VIDIOC_DQEVENT Get information about video device events, such as data overflow, video stream loss, etc. UVCIOC_SEND_RESPONSE Used to send a response to a UVC request. This command can be used for communication between the UVC controller and the USB device VIDIOC_QUERYCAP Used to query the capabilities and attributes of the device, such as device name, driver name, supported video formats, supported input/output formats, etc. VIDIOC_SUBSCRIBE_EVENT Subscribe V4L2 device events to user space. V4L2 devices may generate multiple events, such as hot-plug events for camera modules and frame rate change events For detailed introduction or explanation of other APIs, please refer to: https://www.kernel.org/doc/html/v4.11/media/uapi/v4l/
5.2 Adding PU Events¶
-
Description
Processing Unit (PU) usually refers to the processing unit in a video capture device used for processing and adjusting images to provide various video effects and enhancement functions. PU can control image attributes such as brightness, contrast, saturation and hue. It can also apply image enhancement algorithms such as sharpening, noise reduction and auto exposure. PU can also control device transmission frame rate, image format and resolution parameters.
-
PU recognition process
-
USBCAM side
Add control options that PU can support in kernel
-
UVC control side
If it is determined that the control option can be used, send a control command
-
USBCAM side
Listen for PU events under APP and actually handle command processing and data processing for added control options
-
5.2.1 Adding Image Control Attributes¶
Example: Add brightness adjustment instruction
5.2.1.1 KERNEL side¶
-
Description
The driver side mainly modifies bmControls under the PU descriptor structure. bmControls is a bitmap (Bitmap) used to represent different control options supported by UVC devices. Each bit corresponds to a specific control option and is used to indicate whether that option is available or supported.
The following are the control options supported by kernel:
bmControls D00 Brightness D01 Contrast D02 Hue D03 Saturation D04 Sharpness D05 Gamma D06 White Balance Temperature D07 White Balance Component D08 Backlight Compensation D09 Gain D10 Power Line Frequency D11 Hue, Auto D12 White Balance Temperature, Auto D13 White Balance Component, Auto D14 Digital Multiplier D15 Digital Multiplier LimitFor more configuration of PU options in UVC protocol, please refer to: https://www.usb.org/document-library/video-class-v15-document-set
-
Modification example: Brightness adjustment corresponds to UVC_PU_BACKLIGHT_COMPENSATION_CONTROL
kernel\drivers\sstar\usb\gadget\legacy\bind_uvc.c static struct uvc_processing_unit_descriptor uvc_processing = { #if (USB_VIDEO_CLASS_VERSION == 0x150) .bLength = UVC_DT_PROCESSING_UNIT_SIZE(3), .bControlSize = 3, #else .bLength = UVC_DT_PROCESSING_UNIT_SIZE(2), .bControlSize = 2, #endif .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VC_PROCESSING_UNIT, .bUnitID = UVC_PU_ID, .bSourceID = UVC_IT_ID, .wMaxMultiplier = cpu_to_le16(16 * 1024), ----- .bmControls[0] = 0, ----- +++++ .bmControls[0] = 0x01, +++++ .bmControls[1] = 0, #if (USB_VIDEO_CLASS_VERSION == 0x150) .bmControls[2] = 0, #endif .iProcessing = 0, };
5.2.1.2 APP side¶
-
Description
The demo side mainly completes command processing and data processing for the added PU instructions.
-
Modification example
Note: The v4l2_event structure is used in the AppDemo to receive PU instructions and data
Specific control description of PU instructions on the APP side, for example:
sdk/verify/common/ss_uvc/ss_uvc.c modify one: static int8_t _UVC_Events_Process_Control(ST_UVC_Device_t *pdev,uint8_t req,uint8_t cs,uint8_t entity_id,uint8_t len,struct uvc_request_data *resp) { switch (entity_id) { /* Camera terminal */ case UVC_VC_INPUT_TERMINAL_ID: break; add++++++++++++++++++++++++++++++++++++++++++++++ /* Processing unit */ case UVC_VC_PROCESSING_UNIT_ID: switch (cs) { case UVC_PU_BRIGHTNESS_CONTROL: switch (req) { case UVC_SET_CUR: resp->length = 2; pdev->request_error_code.data[0] = 0x00; pdev->request_error_code.length = 1; break; case UVC_GET_CUR: resp->length = 2; resp->data[0] = pu_brightness_data[0]; resp->data[1] = pu_brightness_data[1]; pdev->request_error_code.data[0] = 0x00; pdev->request_error_code.length = 1; break; case UVC_GET_MIN: resp->length = 2; resp->data[0] = 0x00; resp->data[1] = 0x00; pdev->request_error_code.data[0] = 0x00; pdev->request_error_code.length = 1; break; case UVC_GET_MAX: resp->length = 2; resp->data[0] = 0xFF; resp->data[1] = 0x00; pdev->request_error_code.data[0] = 0x00; pdev->request_error_code.length = 1; break; case UVC_GET_RES: resp->length = 2; resp->data[0] = 0x01; resp->data[1] = 0x00; pdev->request_error_code.data[0] = 0x00; pdev->request_error_code.length = 1; break; case UVC_GET_INFO: resp->length = 1; resp->data[0] = 0x03; pdev->request_error_code.data[0] = 0x00; pdev->request_error_code.length = 1; break; case UVC_GET_DEF: resp->length = 2; pu_brightness_data[0] = resp->data[0] = 0x00; pu_brightness_data[1] = resp->data[1] = 0x00; pdev->request_error_code.data[0] = 0x00; pdev->request_error_code.length = 1; break; /* not support GET_LEN cmd */ case UVC_GET_LEN: default: /* * We don't support this control, so STALL the * default control ep. */ resp->length = -EL2HLT; /* * For every unsupported control request * set the request error code to appropriate * code. */ pdev->request_error_code.data[0] = 0x07; pdev->request_error_code.length = 1; break; } break; add++++++++++++++++++++++++++++++++++++++++++++++ } modify two: static int8_t _UVC_Events_Process_Data(ST_UVC_Device_t * pdev, struct uvc_request_data *data) { if(UVC_CONTROL_INTERFACE == pdev->control.ctype) { add++++++++++++++++++++++++++++++++++++++++++++++ return usb_vc_out_data(pdev, pdev->control.entity, pdev->control.control, pdev->control.length, data); add++++++++++++++++++++++++++++++++++++++++++++++ } } add++++++++++++++++++++++++++++++++++++++++++++++ // process PU, CT, XU job. int8_t usb_vc_out_data(ST_UVC_Device_t *pdev, uint8_t entity, uint8_t cs, uint32_t len, struct uvc_request_data * data) { switch (entity) { case UVC_VC_PROCESSING_UNIT_ID: return usb_vc_pu_cs_out(pdev, entity, cs, len, data); break; } return ST_UVC_SUCCESS; } add++++++++++++++++++++++++++++++++++++++++++++++ modify three: add++++++++++++++++++++++++++++++++++++++++++++++ int8_t usb_vc_pu_cs_out(ST_UVC_Device_t *pdev, uint8_t entity_id, uint8_t cs, uint32_t len, struct uvc_request_data *data) { unsigned char pu_brightness_data[2]; switch (cs) { case UVC_PU_BRIGHTNESS_CONTROL: if(data->data[0] < 0x00 || data->data[0] > 0xFF || data->data[1] != 0x00) { pdev->request_error_code.data[0] = 0x04; pdev->request_error_code.length = 1; return -1; } if(2 == len) { pu_brightness_data[0] = data->data[0]; //Process the obtained data yourself pu_brightness_data[1] = data->data[1]; //Process the obtained data yourself } break; default: XU_Print(":: not support.\n"); break; } return ST_UVC_SUCCESS; } add++++++++++++++++++++++++++++++++++++++++++++++For UVC_SET_CUR, please refer to UVC protocol 4.2.2.3: https://www.usb.org/document-library/video-class-v15-document-set
5.3 Adding XU Events¶
-
Description
XU (Extension Unit) is a mechanism for extending functionality. It allows camera devices to provide custom control functions beyond the basic control functions defined by the UVC standard.
-
XU recognition process
-
USBCAM side
Add descriptor definition and supported control options for XU in kernel
Note: The specific control options of XU do not need to define each control option like PU in kernel, but bmControls still needs to enable the corresponding use bit.
-
UVC control side
If it is determined that the control option can be used, send a control command
-
USBCAM side
Listen for PU events under APP and actually handle command processing and data processing for added control options
-
5.3.1 Adding Additional Control Attributes¶
Example: Add custom control instruction with command code CUS_XU_SET_DOSAMETHING: 0x1
5.3.1.1 KERNEL side¶
-
Description
The driver side mainly modifies bmControls under the XU descriptor structure. bmControls is a bitmap (Bitmap) used to represent different control options supported by UVC devices. Each bit corresponds to a specific control option and is used to indicate whether that option is available or supported.
-
Note
The definition of additional control instructions for XU does not need to be defined in kernel, as long as USBCAM-APP and UVC control side are consistent.
-
Modification example
kernel\drivers\sstar\usb\gadget\legacy\bind_uvc.c static struct UVC_EXTENSION_UNIT_DESCRIPTOR(1, 2) uvc_extension_unit2 = { .bLength = UVC_DT_EXTENSION_UNIT_SIZE(1, 2), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VC_EXTENSION_UNIT, .bUnitID = UVC_EU2_ID, .guidExtensionCode = UVC_EU2_GUID, .bNumControls = 0x06, .bNrInPins = 0x01, .baSourceID[0] = UVC_EU1_ID, .bControlSize = 0x02, ----- .bmControls[0] = 0, ----- +++++ .bmControls[0] = 0x3F, //Enable Bit0-Bit5 function +++++ .bmControls[1] = 0x00, .iExtension = 0x00, };Note: Since XU is a custom attribute, each bit of bmControls is determined by the user.
5.3.1.2 APP side¶
-
Description
The demo side mainly completes command processing and data processing for the added XU instructions.
-
Modification example
Note: The v4l2_event structure is used in the AppDemo to receive XU instructions and their data.
Specific control description of XU instructions on the APP side, for example:
sdk/verify/common/ss_uvc/ss_uvc.c static int8_t _UVC_Events_Process_Control(ST_UVC_Device_t *pdev,uint8_t req,uint8_t cs,uint8_t entity_id,uint8_t len,struct uvc_request_data *resp) { switch (entity_id) { /* Camera terminal */ case UVC_VC_INPUT_TERMINAL_ID: break; add++++++++++++++++++++++++++++++++++++++++++++++ /* Extension unit for customer */ case UVC_VC_EXTENSION2_UNIT_ID: if (0 == usb_vc_eu2_cs(cs, req, resp)) //Control instruction processing function, process it yourself { resp->length = len; pdev->request_error_code.data[0] = 0x00; pdev->request_error_code.length = 1; } else { resp->length = -EL2HLT; pdev->request_error_code.data[0] = 0x06; pdev->request_error_code.length = 1; } break; add++++++++++++++++++++++++++++++++++++++++++++++ } static int8_t _UVC_Events_Process_Data(ST_UVC_Device_t * pdev, struct uvc_request_data *data) { if(UVC_CONTROL_INTERFACE == pdev->control.ctype) { add++++++++++++++++++++++++++++++++++++++++++++++ return usb_vc_out_data(pdev, pdev->control.entity, pdev->control.control, pdev->control.length, data); add++++++++++++++++++++++++++++++++++++++++++++++ } } add++++++++++++++++++++++++++++++++++++++++++++++ // process PU, CT, XU job. int8_t usb_vc_out_data(ST_UVC_Device_t *pdev, uint8_t entity, uint8_t cs, uint32_t len, struct uvc_request_data * data) { switch (entity) { case UVC_VC_EXTENSION2_UNIT_ID: usb_vc_eu2_cs_out(entity, cs, len, data); break; } return ST_UVC_SUCCESS; } add++++++++++++++++++++++++++++++++++++++++++++++ add++++++++++++++++++++++++++++++++++++++++++++++ // CUS XU #define UVC_XU_EU2_UNDEFINED (0x0) #define CUS_XU_SET_DOSAMETHING (0x1) //command number #define CUS_XU_GET_DOSAMETHING (0x2) //command number int8_t usb_vc_eu2_cs_out(uint8_t entity_id, uint8_t cs, uint32_t len, struct uvc_request_data *data) { unsigned char pu_brightness_data[2]; switch (cs) { case CUS_XU_SET_DOSAMETHING: //do samething break; case CUS_XU_GET_DOSAMETHING: //do samething break; default: XU_Print(":: not support.\n"); break; } return ST_UVC_SUCCESS; } add++++++++++++++++++++++++++++++++++++++++++++++Note:
The
unitandselectorparameters of theuvc_xu_control_queryparameter structure on the host side must correspond to the parameters on the device side.The
unitparameter represents the Unit ID of the extension unit. Each extension unit in a UVC device has a unique identifier to distinguish different extension units.The
selectorparameter represents the Control Selector. Each extension unit can support multiple controls and is distinguished by different selectors. The control selector defines control commands for specific functions or attributes.For UVC_SET_CUR, please refer to UVC protocol 4.2.2.5: https://www.usb.org/document-library/video-class-v15-document-set
6. Video Stream Related Change Examples¶
6.1 Description of Related Structures in the Driver¶
Some structure descriptions in /kernel/drivers/sstar/usb/gadget/legacy/bind_uvc.c
-
Definition structure of the entire list of supported video formats
*uvc_streaming_cls_std[MAX_STREAM_SUPPORT][MAX_FORMAT_COUNT] = { (struct uvc_descriptor_header *)&uvc_input_header[0], UVC_DESCRIPTOR_HEADERS_OF_H264_FRAME UVC_DESCRIPTOR_HEADERS_OF_NV12_FRAME UVC_DESCRIPTOR_HEADERS_OF_MJPG_FRAME UVC_DESCRIPTOR_HEADERS_OF_YUY2_FRAME UVC_DESCRIPTOR_HEADERS_OF_H265_FRAME NULL, },As shown above, H264, H265, MJPEG, NV12 and YUY2 video formats are supported.
-
Definition structure of fixed video format descriptor
The following is an explanation of the H264 encoding format:
static struct uvc_format_framebase uvc_format_h264 = { .bLength = UVC_DT_FORMAT_FRAMEBASE_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED, .bFormatIndex = 1, .bNumFrameDescriptors = 7, .guidFormat = { 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }, .bBitsPerPixel = 16, .bDefaultFrameIndex = 7, .bAspectRatioX = 0, .bAspectRatioY = 0, .bmInterfaceFlags = 0, .bCopyProtect = 0, .bVariableSize = 1 };bFormatIndex: The position of the H264 video encoding format in the entire video format
*uvc_streaming_cls_std[MAX_STREAM_SUPPORT][MAX_FORMAT_COUNT] = { { (struct uvc_descriptor_header *)&uvc_input_header[0], UVC_DESCRIPTOR_HEADERS_OF_H264_FRAME bFormatIndex = 1 UVC_DESCRIPTOR_HEADERS_OF_NV12_FRAME bFormatIndex = 2 UVC_DESCRIPTOR_HEADERS_OF_MJPG_FRAME bFormatIndex = 3 UVC_DESCRIPTOR_HEADERS_OF_YUY2_FRAME bFormatIndex = 4 UVC_DESCRIPTOR_HEADERS_OF_H265_FRAME bFormatIndex = 5 NULL, },bNumFrameDescriptors: How many resolution formats are there under the H264 video encoding format
bDefaultFrameIndex: Default resolution format selection under H264 video encoding format
// bNumFrameDescriptors = 7 #define UVC_DESCRIPTOR_HEADERS_OF_H264_FRAME (struct uvc_descriptor_header *)&uvc_format_h264, (struct uvc_descriptor_header *)&uvc_frame_h264_240p,// bDefaultFrameIndex = 1 (struct uvc_descriptor_header *)&uvc_frame_h264_480p,//bDefaultFrameIndex = 2 (struct uvc_descriptor_header *)&uvc_frame_h264_720p, //bDefaultFrameIndex = 3 (struct uvc_descriptor_header *)&uvc_frame_h264_1080p,//bDefaultFrameIndex = 4 (struct uvc_descriptor_header *)&uvc_frame_h264_2kp, //bDefaultFrameIndex = 5 (struct uvc_descriptor_header *)&uvc_frame_h264_4kp, //bDefaultFrameIndex = 6 (struct uvc_descriptor_header *)&uvc_frame_h264_360p, //bDefaultFrameIndex = 7 (struct uvc_descriptor_header *)&uvc_frame_h264_still_image, (struct uvc_descriptor_header *)&uvc_color_matching, #else -
Definition structure of fixed video format resolution descriptor
The following is an explanation of the definition of the H264 encoding format for the 4K resolution:
static struct UVC_FRAME_FRAMEBASE(3) uvc_frame_h264_4kp = { .bLength = UVC_DT_FRAME_MJPEG_SIZE(3), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, .bFrameIndex = 6, .bmCapabilities = 0, .wWidth = cpu_to_le16(3840), .wHeight = cpu_to_le16(2160), .dwMinBitRate = cpu_to_le32(3840 * 2160 * 2 * 8 * 10), .dwMaxBitRate = cpu_to_le32(3840 * 2160 * 2 * 8 * 10), .dwDefaultFrameInterval = cpu_to_le32(333333), .bFrameIntervalType = 3, .dwFrameInterval[0] = cpu_to_le32(333333), .dwFrameInterval[1] = cpu_to_le32(666666), .dwFrameInterval[2] = cpu_to_le32(1000000), };bFrameIndex: The order of the arrangement of the 4K resolution in the H264 video format
wWidth: The width size of the 4K resolution
wHeight: The height size of the 4K resolution
dwDefaultFrameInterval: The default frame rate of the 4K resolution (here it is 30fps)
bFrameIntervalType: How many frame rates are supported by the 4K resolution
dwFrameInterval[x]: Set each frame rate corresponding to the above
#define UVC_DESCRIPTOR_HEADERS_OF_H264_FRAME (struct uvc_descriptor_header *)&uvc_format_h264, (struct uvc_descriptor_header *)&uvc_frame_h264_240p, bFrameIndex = 1 (struct uvc_descriptor_header *)&uvc_frame_h264_480p, bFrameIndex = 2 (struct uvc_descriptor_header *)&uvc_frame_h264_720p, bFrameIndex = 3 (struct uvc_descriptor_header *)&uvc_frame_h264_1080p, bFrameIndex = 4 (struct uvc_descriptor_header *)&uvc_frame_h264_2kp, bFrameIndex = 5 (struct uvc_descriptor_header *)&uvc_frame_h264_4kp, bFrameIndex = 6 (struct uvc_descriptor_header *)&uvc_frame_h264_still_image, (struct uvc_descriptor_header *)&uvc_color_matching, #else
6.2 Video Format Modification Example¶
6.2.1 Add NV12 as a video stream format¶
-
kernel driver side
kernel/drivers/sstar/usb/gadget/legacy/bind_uvc.c static struct uvc_descriptor_header *uvc_streaming_cls_std[MAX_STREAM_SUPPORT][MAX_FORMAT_COUNT] = { { (struct uvc_descriptor_header *)&uvc_input_header[0], UVC_DESCRIPTOR_HEADERS_OF_YUY2_FRAME add+++++++++++++++++++++++++++++ UVC_DESCRIPTOR_HEADERS_OF_NV12_FRAME add+++++++++++++++++++++++++++++ UVC_DESCRIPTOR_HEADERS_OF_MJPG_FRAME UVC_DESCRIPTOR_HEADERS_OF_H264_FRAME UVC_DESCRIPTOR_HEADERS_OF_H265_FRAME NULL, }, { (struct uvc_descriptor_header *)&uvc_input_header[1], #ifdef CONFIG_WINDOWS_HELLO_SUPPORT UVC_DESCRIPTOR_HEADERS_OF_IR_FRAME #else UVC_DESCRIPTOR_HEADERS_OF_YUY2_FRAME add+++++++++++++++++++++++++++++ UVC_DESCRIPTOR_HEADERS_OF_NV12_FRAME add+++++++++++++++++++++++++++++ UVC_DESCRIPTOR_HEADERS_OF_MJPG_FRAME UVC_DESCRIPTOR_HEADERS_OF_H264_FRAME UVC_DESCRIPTOR_HEADERS_OF_H265_FRAME #endif NULL, }, { (struct uvc_descriptor_header *)&uvc_input_header[2], UVC_DESCRIPTOR_HEADERS_OF_YUY2_FRAME add+++++++++++++++++++++++++++++ UVC_DESCRIPTOR_HEADERS_OF_NV12_FRAME add+++++++++++++++++++++++++++++ UVC_DESCRIPTOR_HEADERS_OF_MJPG_FRAME UVC_DESCRIPTOR_HEADERS_OF_H264_FRAME UVC_DESCRIPTOR_HEADERS_OF_H265_FRAME NULL, }, The following modifications are configured in the same way. add+++++++++++++++++++++++++++++ #define UVC_DESCRIPTOR_HEADERS_OF_YUY2_FRAME #endif #ifdef SUPPORT_NV12 static struct uvc_format_uncompressed uvc_format_nv12 = { .bLength = UVC_DT_FORMAT_UNCOMPRESSED_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VS_FORMAT_UNCOMPRESSED, .bFormatIndex = 2, .bNumFrameDescriptors = 6, .guidFormat = { 'N', 'V', '1', '2', 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }, .bBitsPerPixel = 12, .bDefaultFrameIndex = 1, .bAspectRatioX = 0, .bAspectRatioY = 0, .bmInterfaceFlags = 0, .bCopyProtect = 0, }; add+++++++++++++++++++++++++++++ add+++++++++++++++++++++++++++++ #define UVC_DESCRIPTOR_HEADERS_OF_NV12_FRAME \ (struct uvc_descriptor_header *)&uvc_format_nv12, \ (struct uvc_descriptor_header *)&uvc_frame_nv12_240p, \ (struct uvc_descriptor_header *)&uvc_frame_nv12_480p, \ (struct uvc_descriptor_header *)&uvc_frame_nv12_720p, \ (struct uvc_descriptor_header *)&uvc_frame_nv12_1080p, \ (struct uvc_descriptor_header *)&uvc_frame_nv12_2kp, \ (struct uvc_descriptor_header *)&uvc_frame_nv12_4kp, \ (struct uvc_descriptor_header *)&uvc_frame_nv12_still_image, \ (struct uvc_descriptor_header *)&uvc_color_matching, #else add+++++++++++++++++++++++++++++ -
APP side
sdk/verify/common/ss_uvc/ss_uvc_datatype.h static const struct uvc_format_info uvc_formats[] = { { V4L2_PIX_FMT_YUYV, uvc_frames_yuyv }, add+++++++++++++++++++++++++++++ { V4L2_PIX_FMT_NV12, uvc_frames_nv12 }, add+++++++++++++++++++++++++++++ { V4L2_PIX_FMT_MJPEG, uvc_frames_mjpg }, { V4L2_PIX_FMT_H264, uvc_frames_h264 }, { V4L2_PIX_FMT_H265, uvc_frames_h265 }, }; static const struct uvc_format_info uvc_still_formats[] = { { V4L2_PIX_FMT_YUYV, uvc_still_frames_yuyv }, add+++++++++++++++++++++++++++++ { V4L2_PIX_FMT_NV12, uvc_still_frames_nv12 }, add+++++++++++++++++++++++++++++ { V4L2_PIX_FMT_MJPEG, uvc_still_frames_mjpg }, { V4L2_PIX_FMT_H264, uvc_still_frames_h264 }, { V4L2_PIX_FMT_H265, uvc_still_frames_h265 }, }; add+++++++++++++++++++++++++++++ static const struct uvc_frame_info uvc_frames_nv12[] = { { 320, 240, { 333333, 666666, 1000000, 0 }, }, { 640, 480, { 333333, 666666, 1000000, 0 }, }, { 1280, 720, { 333333, 666666, 1000000, 0 }, }, { 1920, 1080,{ 333333, 666666, 1000000, 0 }, }, { 2560, 1440,{ 333333, 666666, 1000000, 0 }, }, { 3840, 2160,{ 333333, 666666, 1000000, 0 }, }, { 0, 0, { 0, }, }, }; add+++++++++++++++++++++++++++++ -
Script side
UVC_STREAMING_FORMAT_NV12_ENABLE=1 add+++++++++++++++++++++++++++++ config_uvc_nv12() { config_uvc_format_nv12 config_uvc_frame_nv12 320 240 333333 config_uvc_frame_nv12 640 480 333333 config_uvc_frame_nv12 1280 720 333333 config_uvc_frame_nv12 1920 1080 333333 config_uvc_frame_nv12 2560 1440 333333 config_uvc_frame_nv12 3840 2160 666666 ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12 ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default/nv12 } add+++++++++++++++++++++++++++++ add+++++++++++++++++++++++++++++ config_uvc_format_nv12() { mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12 echo 0x0C > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/bBitsPerPixel echo 0x01 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/bDefaultFrameIndex echo 0x04 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/bmaControls echo -ne \\x4e\\x56\\x31\\x32\\x00\\x00\\x10\\x00\\x80\\x00\\x00\\xaa\\x00\\x38\\x9b\\x71 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/uncompressed/nv12/guidFormat } add+++++++++++++++++++++++++++++
6.3 Video Resolution Modification Example¶
6.3.1 Add a set of H264 stream resolutions of 640x360¶
-
kernel driver side
kernel/drivers/sstar/usb/gadget/legacy/bind_uvc.c add+++++++++++++++++++++++++++++ static struct UVC_FRAME_FRAMEBASE(3) uvc_frame_h264_360p = { .bLength = UVC_DT_FRAME_MJPEG_SIZE(3), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, .bFrameIndex = 7, //Please note that the index must correspond to the position below. .bmCapabilities = 0, .wWidth = cpu_to_le16(640), .wHeight = cpu_to_le16(360), .dwMinBitRate = cpu_to_le32(640 * 360 * 2 * 8 * 10), .dwMaxBitRate = cpu_to_le32(640 * 360 * 2 * 8 * 30), .dwDefaultFrameInterval = cpu_to_le32(333333), .bFrameIntervalType = 3, .dwFrameInterval[0] = cpu_to_le32(333333), .dwFrameInterval[1] = cpu_to_le32(666666), .dwFrameInterval[2] = cpu_to_le32(1000000), }; add+++++++++++++++++++++++++++++ #define UVC_DESCRIPTOR_HEADERS_OF_H264_FRAME (struct uvc_descriptor_header *)&uvc_format_h264, (struct uvc_descriptor_header *)&uvc_frame_h264_240p, (struct uvc_descriptor_header *)&uvc_frame_h264_480p, (struct uvc_descriptor_header *)&uvc_frame_h264_720p, (struct uvc_descriptor_header *)&uvc_frame_h264_1080p, (struct uvc_descriptor_header *)&uvc_frame_h264_2kp, (struct uvc_descriptor_header *)&uvc_frame_h264_4kp, add+++++++++++++++++++++++++++++ (struct uvc_descriptor_header *)&uvc_frame_h264_360p, add+++++++++++++++++++++++++++++ (struct uvc_descriptor_header *)&uvc_frame_h264_still_image, (struct uvc_descriptor_header *)&uvc_color_matching, #else -
APP side
sdk/verify/common/ss_uvc/ss_uvc_datatype.h static const struct uvc_frame_info uvc_frames_h264[] = { { 320, 240, { 333333, 666666, 1000000, 0 }, }, { 640, 480, { 333333, 666666, 1000000, 0 }, }, { 1280, 720, { 333333, 666666, 1000000, 0 }, }, { 1920,1080, { 333333, 666666, 1000000, 0 }, }, { 2560,1440, { 333333, 666666, 1000000, 0 }, }, { 3840,2160, { 333333, 666666, 1000000, 0 }, }, add+++++++++++++++++++++++++++++++++ { 640, 360, { 333333, 666666, 1000000, 0 }, }, ++++++++++++++++++++++++++++++++++++ { 0, 0, { 0, }, }, }; -
Script side
UVC_STREAMING_FORMAT_H264_ENABLE=1 //Make sure that H264 stream is enabled config_uvc_h264() { config_uvc_format_h264 config_uvc_frame_h264 320 240 333333 config_uvc_frame_h264 640 480 333333 config_uvc_frame_h264 1280 720 333333 config_uvc_frame_h264 1920 1080 333333 config_uvc_frame_h264 2560 1440 333333 config_uvc_frame_h264 3840 2160 333333 add+++++++++++++++++++++++++++++++++ config_uvc_frame_h264 640 360 333333 ++++++++++++++++++++++++++++++++++++ ln -s ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264 ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/header/default/h264 }
6.4. Video Frame Rate Modification Example¶
6.4.1. Adding 25FPS under H264 stream with 1920X1080 resolution¶
-
Kernel driver side
kernel/drivers/sstar/usb/gadget/legacy/bind_uvc.c static struct UVC_FRAME_FRAMEBASE(3) uvc_frame_h265_1080p = { .bLength = UVC_DT_FRAME_MJPEG_SIZE(3), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubType = UVC_VS_FRAME_FRAME_BASED, .bFrameIndex = 4, .bmCapabilities = 0, .wWidth = cpu_to_le16(1920), .wHeight = cpu_to_le16(1080), .dwMinBitRate = cpu_to_le32(1920 * 1080 * 2 * 8 * 10), .dwMaxBitRate = cpu_to_le32(1920 * 1080 * 2 * 8 * 30), .dwDefaultFrameInterval = cpu_to_le32(333333), .bFrameIntervalType = 3, .dwFrameInterval[0] = cpu_to_le32(333333), add+++++++++++++++++++++++++++++++++ .dwFrameInterval[1] = cpu_to_le32(400000), add+++++++++++++++++++++++++++++++++ .dwFrameInterval[2] = cpu_to_le32(1000000), }; -
App side
sdk/verify/common/ss_uvc/ss_uvc_datatype.h static const struct uvc_frame_info uvc_frames_h264[] = { { 320, 240, { 333333, 666666, 1000000, 0 }, }, { 640, 480, { 333333, 666666, 1000000, 0 }, }, { 1280, 720, { 333333, 666666, 1000000, 0 }, }, ----- { 1920,1080, { 333333, 666666, 1000000, 0 }, }, ----- +++++ { 1920,1080, { 333333, 400000, 1000000, 0 }, }, +++++ { 2560,1440, { 333333, 666666, 1000000, 0 }, }, { 3840,2160, { 333333, 666666, 1000000, 0 }, }, { 5472,3078, { 333333, 666666, 1000000, 0 }, }, { 0, 0, { 0, }, }, }; -
Script side
config_uvc_frame_h264() { UVC_FRAME_WIDTH=$1 UVC_FRAME_HEIGHT=$2 UVC_FRAME_INTERVAL=$3 UVC_FRAME_INDEX=$4 mkdir ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p if [ $UVC_NEED_CONFIG_FRAME_INDEX == 1 ]; then echo $UVC_FRAME_INDEX > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/bFrameIndex fi echo 0x00 > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/bmCapabilities echo $UVC_FRAME_INTERVAL > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwDefaultFrameInterval ----- echo -e "333333\n666666\n1000000" > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwFrameInterval ----- +++++ echo -e "333333\n400000\n1000000" > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwFrameInterval +++++ echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*30)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwMaxBitRate echo $((UVC_FRAME_WIDTH*UVC_FRAME_HEIGHT*16*10)) > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/dwMinBitRate echo $UVC_FRAME_HEIGHT > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/wHeight echo $UVC_FRAME_WIDTH > ${USB_FUNCTIONS_DIR}/uvc.instance${UVC_STREAM_INDEX}/streaming/framebase/h264/${UVC_FRAME_HEIGHT}p/wWidth }