UVC摄像头技术笔记
+ -

再谈USB摄像头UVC视频流接口控制请求dwMaxVideoFrameSize和dwMaxPayloadTransferSize

2021-09-15 706 0

刚开始的时候,我们做一件事是认真,一丝不苟。对于各个数据的考量力求做到精度,其实这个追求可能并不是因为我们因为项目上的要求,而是我们为了弄清一个事实,有了这个事实我们就可以随处吹牛逼,也成了我们在做新的类似的项目上的优势之资。

言归正转,以前在windows下通过USB总线驱动虚拟的UVC摄像头都只支持一个分辨率,由于项目上的实际应用,也并未曾想过支持多个分辨率,甚至是多个多种数据格式。

当然,市面上基于UVC规范的USB摄像头,我们通过视频播放软件或usbtreeview分析其描述符,一般是支持大量的分辨率和数据格式的。当然这里的数据格式并不是UVC规范中的负载数据头,而是真实的视频数据格式,上层是需要通过解码显示的,例如常见的MJPG格式,NV12格式,H264数据格式。这些数据格式都是通过负载数据头进行打包在USB总线传输的。

在打开一个基于UVC规范的USB摄像头时,我们在应用层一般都是选择,确认即可,但对于UVC摄像头的固件来说,可真是忙的一踏糊涂,基主要功能是数据通读的协商。

如本人打开电脑中的摄像头,其抓包过程如下:

    CTL    a1 81 00 01  01 00 1a 00                                                               GET CUR      
26  IN     00 00 01 01  15 16 05 00  00 00 00 00  00 00 1e 00  00 00 4d 22  1c 00 00 0c  00 00    .............
    CTL    21 01 00 01  01 00 1a 00                                                               SET CUR      
26  OUT    00 00 01 01  15 16 05 00  00 00 00 00  00 00 1e 00  00 00 4d 22  1c 00 00 00  00 00    .............
    CTL    a1 81 00 01  01 00 1a 00                                                               GET CUR      
26  IN     00 00 01 01  15 16 05 00  00 00 00 00  00 00 1e 00  00 00 4d 22  1c 00 00 0c  00 00    .............
    CTL    a1 83 00 01  01 00 1a 00                                                               GET MAX      
26  IN     00 00 01 01  15 16 05 00  00 00 00 00  00 00 00 00  00 00 4d 22  1c 00 00 0c  00 00    .............
    CTL    a1 82 00 01  01 00 1a 00                                                               GET MIN      
26  IN     00 00 01 01  15 16 05 00  00 00 00 00  00 00 00 00  00 00 4d 22  1c 00 00 0c  00 00    .............
    CTL    21 01 00 01  01 00 1a 00                                                               SET CUR      
26  OUT    00 00 01 01  15 16 05 00  00 00 00 00  00 00 1e 00  00 00 4d 22  1c 00 00 00  00 00    .............
    CTL    a1 81 00 01  01 00 1a 00                                                               GET CUR      
26  IN     00 00 01 01  15 16 05 00  00 00 00 00  00 00 1e 00  00 00 4d 22  1c 00 00 0c  00 00    .............
    CTL    21 01 00 02  01 00 1a 00                                                               SET CUR      
26  OUT    00 00 01 01  15 16 05 00  00 00 00 00  00 00 1e 00  00 00 4d 22  1c 00 00 0c  00 00    .............
    CTL    01 0b 06 00  01 00 00 00                                                               SET INTERFACE

可以看到,对于视频流接口VS前其进行大量的特定类请求,如GET_CUR,SET_CUR,GET_MIN,GET_MAX,选择子使用的是VS_PROBE_CONTROL。

bLength                  : 0x09 (9 bytes)
bDescriptorType          : 0x04 (Interface Descriptor)
bInterfaceNumber         : 0x01
bAlternateSetting        : 0x00
bNumEndpoints            : 0x00 (Default Control Pipe only)
bInterfaceClass          : 0x0E (Video)
bInterfaceSubClass       : 0x02 (Video Streaming)
bInterfaceProtocol       : 0x00
iInterface               : 0x00 (No String Descriptor)
Data (HexDump)           : 09 04 01 00 00 0E 02 00 00

而到最后一个SET_CUR时,这时换一个选择子VS_COMMIT_CONTROL,进行提交选择,这这个结构体中定义了协商好了的数据格式。这个格式是由视频控制结构体即VS_COMMIT_CONTROL对应的数据结构决定的。
这个结构体是26字节,是一个典型的UVC1.0版本。在其类特定视频控制接口头描述符中也可以看到:

        ------- Video Control Interface Header Descriptor -----
bLength                  : 0x0D (13 bytes)
bDescriptorType          : 0x24 (Video Control Interface)
bDescriptorSubtype       : 0x01 (Video Control Header)
bcdUVC                   : 0x0100 (UVC Version 1.00)
wTotalLength             : 0x0067 (103 bytes)
dwClockFreq              : 0x00E4E1C0 (15 MHz)
bInCollection            : 0x01 (1 VideoStreaming interface)
baInterfaceNr[1]         : 0x01
Data (HexDump)           : 0D 24 01 00 01 67 00 C0 E1 E4 00 01 01            .$...g.......

对于这个结构体,其结构体定义如下:

typedef struct  _VideoControl
{
#pragam pack(1)
   UINT16 bmHint;                      
   UINT8  bFormatIndex;                
   UINT8  bFrameIndex;                 
   UINT32 dwFrameInterval;             
   UINT16 wKeyFrameRate;               
   UINT16 wPFrameRate;                 
   UINT16 wCompQuality;                
   UINT16 wCompWindowSize;             
   UINT16 wDelay;                      
   UINT32 dwMaxVideoFrameSize;         
   UINT32 dwMaxPayloadTransferSize;    //UVC1.0 分隔符
#pragma pack()
} VideoControl;

完整的支持各版本的结构体可见:

这里有一个dwMaxVideoFrameSize字段比较有意思。是最大的视频单帧大小。其实在一般的摄像头固件中这个值是很少变化的,如从1920x1080分辨率换到1280x720或从MJPG换到H264,这个值很少变或者不变。其实这个值是只要大于单帧数据流的大小即可。而dwMaxPayloadTransferSize是指这一帧分多少包或者说多少次传输,这个包的最大值。所以前几小包的大小可以是dwMaxPayloadTransferSize,但最后一包一般小于dwMaxPayloadTransferSize这个值 。
所以类推到dwMaxVideoFrameSize上,这个字段表示一帧的最大值,一般的帧的最大小都是小于这个值,也可能永远不会出出现和这个值设定的值一样的帧,最大不一定存在。

这让我又不得想起一个电视剧中的台词:都一样,都一样。只要在合理的范围,都一样,都一样。都可以的….

HID人机交互QQ群:564808376    UAC音频QQ群:218581009    UVC相机QQ群:331552032    BOT&UASP大容量存储QQ群:258159197    STC-USB单片机QQ群:315457461    USB技术交流QQ群2:580684376    USB技术交流QQ群:952873936   

0 篇笔记 写笔记

UVC等时传输中的dwMaxPayloadTransferSize
UVC的视频流接口控制请求的数据大小可为26字节,34字节和48字节,其分别对应的是UVC的1.0,1,1和UVC1.5版本。在其整个视频流控制接口参数偏移地址22处的字段为一4字节的dwMaxPayloadTransferSize,根据其字段解释为“指定设备在单个有效负载传输中可以传输或接收的最大......
UVC等时传输中的dwMaxVideoFrameSizedwMaxPayloadTransferSize关系
在其整个视频流控制接口参数偏移地址18处的字段为一4字节的dwMaxVideoFrameSize,代表的是如果选择当前数据帧格式,其一帧图像的最大数据量大小,以字节为单位。关于dwMaxVideoFrameSize的计算可以参考 YUV2摄像头相关数据大小计算。这里我们主要说一下dwMaxVideo......
UVC批量传输中的dwMaxVideoFrameSizedwMaxPayloadTransferSize关系
上一节看了UVC等时/同步传输的关系,这里我们介绍一相批量传输。批量传输在这里相对于同步传输要简单的多。uvc_video_start_transfer中的代码如下: else { /* Bulk endpoint, proceed to URB initialization. */ ......
再谈USB摄像头UVC视频流接口控制请求dwMaxVideoFrameSizedwMaxPayloadTransferSize
刚开始的时候,我们做一件事是认真,一丝不苟。对于各个数据的考量力求做到精度,其实这个追求可能并不是因为我们因为项目上的要求,而是我们为了弄清一个事实,有了这个事实我们就可以随处吹牛逼,也成了我们在做新的类似的项目上的优势之资。言归正转,以前在windows下通过USB总线驱动虚拟的UVC摄像头都只......
UVC摄像头dwMaxPayloadTransferSize批量传输与USB端点描述符wMaxPacketSize的关系说明
这个问题是老生常谈了,其实结合以前的文章我们应该能说明白,可详见:USB数据长度为0的DATA/IN事务 https://www.usbzh.com/article/detail-624.htmlUSB2.0 事务 https://www.usbzh.com/article/detail-691......
关注公众号
取消
感谢您的支持,我会继续努力的!
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦

您的支持,是我们前进的动力!