音视频探索(8):UVC1.5协议规范概述

UVC,全称为:USB video(device) class,是USB规范协议中设备类规范的其中一种,是用作USB接口的视频设备的一个统一的数据交换规范。在UVC规范中明确要求,具有实际UVC功能的视频设备只要需要两种接口:一种为VC Interface(视频控制接口)VS Interface(视频流接口)。其中VC接口用于对UVC设备进行配置操控 ,而VS接口则用于负责传输视频数据流,两者相互配合完成UVC设备功能。

1. UVC设备拓扑结构

从拓扑图结构来看,在UVC的VC接口部分,从摄像头传感器(Sensor)和和另一个复合视频设备得到的数据流由IT和CT输入,经过选择单元(SU)选择送到处理单元(PU)处理,再由OT绑定到指定的USB端点,最后由USB端点与主机交互数据发送到(主机)host,而这部分将由VS接口部分完成。

UVC设备拓扑结构如下:

UVC规范描述了以下类型的标准单元和终端:

  • 输入端子(ST)

作为数据流入video function的接收器,功能是作为已经被提取出来的数据的数据源,说白了就是UVC功能的数据源头。UVC输入端点由输入端点描述符来描述。

  • 输出端子(OT)

作为Video Function视频信息流出的出口,功能是作为输出数据的接收器。OT只有一个输入pin,处理流程最后一个单元会将它的out pin与OT的in pin连接在一起。

  • 选择器单元(SU)

SU单元用来控制图像数据采集源的切换和选择。例如上面相机拓扑图有两个数据输入源,这时需要SU来进行切换和选择。

  • 处理单元(PU)

PU代表对采集所得图像数据进行加工的单元,负责对采集到的图像特性进行调整设置.,主要有以下一些特性:

markdown 复制代码
**用户控制 User Controls**

-   Brightness(背光)
-   Contrast(对比度)
-   Hue(色度)
-   Saturatio(饱和度)
-   Sharpness(锐度)
-   Gamma(伽马)
-   Digital Multiplier (Zoom)(数字放大)

**自动控制 Auto Controls**

-   White Balance Temperature(白平衡色温)
-   White Balance Component(白平衡组件)
-   Blcklight Compensation(背光补偿)

**其它 Other**

-   Gain(增益)
-   Power Line Frequency(电源线平率)
-   Analog Video Standard(模拟视频标准)
-   Analog Video Lock Status(模拟视频死锁状态)
  • 编码单元(EU)

EU用于对采集所得的数据进行个性化处理的功能。

  • 扩展单元(XU)

XU是为了特定供应商添加规范而提供的单元。

此外,还有一些特殊的终端扩展了基本输入和输出终端的功能。

  • 媒体传输终端(在视频媒体传输终端规范的USB设备类定义中定义)
  • 摄像机终端(CT)

CT代表硬件上的数据采集源(sensor),用于控制视频流传输中的设备特性的。

它规定支持以下特性控制:

python 复制代码
@ 扫描模式(逐行扫描或隔行扫描)
@ 自动曝光模式
@ 自动曝光优先级
@ 曝光时间
@ 聚焦
@ 自动聚焦
@ 可变光圈
@ 缩放/变焦
@ 移动镜头
@ 滚动
@ 倾斜
@ 数字窗口
@ 感兴趣区域

2. UVC描述符

UVC设备使用通用的USB设备描述符来描述设备信息,一个USB设备描述符包含一个或多个配置描述符,一个配置描述符包含一个或多个端口描述符,一个端口描述符包含0个或多个端点描述符。 USB设备、配置、接口、端点之间的关系为:

设备 (Device) :就是一个实实在在的USB设备,比如USB鼠标,U盘。
配置 (Configuration):一个USB设备可以有多种配置。比如4G上网卡就有2种配置:U盘、上网卡。第1次把4G上网卡插入电脑时,它是一个U盘,可以安装里面的程序。装好程序后,把它再次插入电脑,它就是一个上网卡。驱动程序可以选择让它工作于哪种配置,同一时间只能有一种配置有效。大多数的USB设备只有一种配置。
接口 (Interface) :每个配置下可以有多个接口,这个接口不是硬件上的接口,可以把这个接口理解为功能,一个接口就代表该设备当前支持的一种功能。
端点 (Endpoint) :每个接口可以有多个端点。USB主机和设备就是通过端点进行数据交互的。每个端点地址对应一个方向,例如端点2-IN,端点2-OUT,这两个含义完全不同。一个具体的端点只能属于四种传输模式中的一种,通常把工作在什么模式下的端点就叫做什么端点,比如控制端点,批量端点等。每个USB设备必须要有一个端点0,它一上电就存在并且可用,其作用是对设备枚举和对设备进行一些基本的控制功能,端点0也被称为控制端点。只有端点0是双向的(设备-主机双向通信),其他端点都是单向。

2.1 设备描述符

一个USB设备只有一个设备描述符,设备描述符为主机提供了许多信息,如设备满足的USB规范,设备支持的协议,供应商标识、产品标识等等。根据UVC设备是否包含视频流接口,UVC设备的设备描述符分为两类:

(1)只包含一个视频控制接口的设备;

(2)包含一个视频控制接口一个或多个视频流接口集合的设备;

UVC(USB)设备描述符结构体如下:

c 复制代码
struct _DEVICE_DESCRIPTOR_STRUCT 
{
    ...
    bcdUSB;                  //USB规范版本,如USB 2.0=0x0200
    BYTE bDeviceClass;       //设备类别
    BYTE bDeviceSubClass;    //设备子类别
    BYTE bDeviceProtocl;     //设备协议
    BYTE bMaxPacketSize0;    //端点0得最大数据包大小
    BYTE idVendor;           //供应商ID(VID,由USB协会分配)
    BYTE idProduct;          //产品ID(PID, 由制造商分配)
    ...
}DEVICE_DESCRIPTOR_STRUCT ;

2.2 配置描述符

UVC的配置描述符和通用USB设备配置描述符一致,大部分USB设备只有一种配置,每种配置都有一个配置描述符,该描述符会提供特定设备配置的信息,如接口数量、 设备由总线供电还是自供电、 设备能否启动一个远程唤醒以及设备功耗。 配置描述数据中不仅包括配置描述符本身,也包括其下的接口控制描述符、视频流接口描述符以及其内部的各个端点描述符和其它UVC自定义的相关描述符。

配置描述符结构体如下:

c 复制代码
// Table 9-10. Standard Configuration Descriptor
typedef struct _usb_deviceConfigurationDescriptor_t
{
    unsigned char  bLength;
    unsigned char  bDescriptorType; // 表示描述符的类型,配置描述符的类型编码为 0x02
    unsigned short wTotalLength; // 整个配置描述符集合的总长度
    unsigned char  bNumInterfaces; // 在该指定配置中接口总数,如鼠标(1个),音频设备(多个)
    unsigned char  bConfigurationValue;
    unsigned char  iConfiguration;
    unsigned char  bmAttributes; //定义了 USB 设备的一些特性,如供电方式
    unsigned char  bMaxPower; // 表示设备需要从总线获取的最大电流量,以 2 mA 为单位
} usb_deviceConfigurationDescriptor_t;

UVC摄像头的配置描述符内存布局实例:

  • USB_CONFIGURATION_DESCRIPTOR(配置描述符)
  • USB_INTERFACE_ASSOCIATION_DESCRIPTOR(接口关联描述符)
    • USB_VC_HEADER(UVC控制接口头描述符)
      • Video Control Input Terminal Descriptor
      • Video Control Processing Unit Descriptor
      • Video Control Extension Unit Descriptor
      • Video Control Output Terminal Descriptor
      • Endpoint Descriptor
    • Class-specific VC Interrupt Endpoint Descriptor
      • VC-Specific VS Video Input Header Descriptor(视频流接口描述符)
      • VS Frame Based Payload Format Type Descriptor
      • VS Frame Based Payload Frame Type Descriptor
      • Endpoint Descriptor

在该配置描述符的排列顺序中,IAD要放在它所包含的VC,VS描述符之前,且同一个IAD中所有的VC,VS 接的的接口号必须连贯。

2.3 接口描述符

接口描述符(Interface Descriptor)描述了配置中一个特定的接口。配置提供了一个或多个接口,每个接口都含有类(Class),子类(SubClass)和协议(Protocol)的信息,以及接口所使用的端点(Endpoint)数目。一个配置可含有多个同时活跃的接口,这些接口可能联合于某个功能,也可能并不相关。

2.3.1 接口关联描述符IAD

设备必须使用接口关联描述符来描述需要视频控制接口和一个或多个视频流接口的每个设备功能的视频接口集合。接口关联描述符IAD定义如下:

c 复制代码
typedef struct _USB_INTERFACE_ASSOCIATION_DESCRIPTOR {
    UCHAR   bLength;            //接口关联描述符的长度,固定长度为8
    UCHAR   bDescriptorType;    //USB_INTERFACE_ASSOCIATION_DESCRIPTOR_TYPE,值为0x0b
    UCHAR   bFirstInterface;    //第一个接口编号.关联描述符中的接口号必须连续。
    UCHAR   bInterfaceCount;    //接口总数量(包括视频控制接口和所有视频流接口)
    UCHAR   bFunctionClass;        //视频接口类代码CC_VIDEO,值0x0E
    UCHAR   bFunctionSubClass;    //视频子类接口代码 SC_VIDEO_INTERFACE_COLLECTION,值为0x03
    UCHAR   bFunctionProtocol;     //未用,必须为PC_PROTOCOL_UNDEFINED,值为0x00
    UCHAR   iFunction;            //字符串描述符索引
} USB_INTERFACE_ASSOCIATION_DESCRIPTOR, *PUSB_INTERFACE_ASSOCIATION_DESCRIPTOR;
C_ASSERT(sizeof(USB_INTERFACE_ASSOCIATION_DESCRIPTOR) == 8);

2.3.2 视频控制接口描述符VCD

视频控制接口描述符由标准视频控制接口描述符以及各控制相关描述符组成。标准视频控制接口描述符使用通用USB设备接口描述符数据结构,且标准视频控制接口描述符后还有类特定视频控制接口头描述符,它是是控制单元和端点的描述符头,其总长度由控制接口类单元和端点和决定。

c 复制代码
struct _INTERFACE_DESCRIPTOR_STRUCT; 
{ 
    BYTE bLength;           //设备描述符的字节数大小,为0x09
    BYTE bDescriptorType;   //描述符类型编号,为0x01 
    BYTE bInterfaceNunber; //接口的编号 
    BYTE bAlternateSetting;//备用的接口描述符编号 
    BYTE bNumEndpoints;     //该接口使用端点数,不包括端点0 
    BYTE bInterfaceClass;   //接口类型 
    BYTE bInterfaceSubClass;//接口子类型 
    BYTE bInterfaceProtocol;//接口所遵循的协议 
    BYTE iInterface;         //描述该接口的字符串索引值 
}INTERFACE_DESCRIPTOR_STRUCT;
  • bInterfaceClass

bInterfaceClass类码(Class code),这个类码(Class code)由USB-IF分配。除了用于由接口规定的设备外,其他与设备描述符(Device Descriptor)中bDeviceClass 字段相同。值0x00为保留值,从0x01 -- 0xFE的值保留给USB定义的类,0xFF作为厂商定义的类。

Class Code Description
0x00 保留(Reserved)
0x01 音频(Audio)
0x02 通讯设备:通讯接口(Communications device: communication interface)
0x03 人机接口设备(Human interface device)
0x06 图像(Image) bInterfaceSubclass = 0x01 bInterfaceProtocol = 0x01: Imaging device
0x07 打印机(Printer)
0x08 大容量存储(Mass storage)
0x0E 视频(Video)
0x10 Audio/Video (AV):bInterfaceSubclass = 0x01 bInterfaceProtocol = 0x00: AVControl Interface bInterfaceSubclass = 0x02 bInterfaceProtocol = 0x00: AVData Video Streaming Interface bInterfaceSubclass = 0x03 bInterfaceProtocol = 0x00: AVData Audio Streaming Interface
... ...
  • 类特定视频控制接口头描述符
c 复制代码
typedef struct _USB_VC_HEADER
{
   UINT8  bLength; // 结构体自身长度13+bInCollection-1
   UINT8  bDescriptorType; // 描述符类型:CS_INTERFACE,值为0x24
   UINT8  bDescriptorSubType; // 描述符子类型VC_HEADER,值为0x01
   UINT16 bcdUVC; // uvc版本号。 UVC15: 0x0150;UVC10: 0x0100
   UINT16 wTotalLength; // 自身长度和后续控制单元和终端的描述符的数据长度。12+n
   UINT32 dwClockFrequency; // 时钟频率,以HZ为单位。
   UINT8  bInCollection; // 视频流接口个数。
   UINT8  baInterfaceNr[1]; //数量由bInCollection决定。
} USB_VC_HEADER;

视频控制接口包含了处理单元、相机终端、选择器单元等,它们都有各自得描述符,下面我们着重介绍下处理单元描述符和相机终端描述符。

(1)处理单元描述符

UVC处理单元描述符用于描述摄像头颜色亮度对比度控制,它使用bUnitID字段标识,同一视频功能内的任何其他单元或终端不得具有相同的功能ID。

c 复制代码
UINT8  bLength;   // 描述符的长度,13字节
UINT8  bDescriptorType; // 描述符类型,CS_INTERFACE,值为0x24.
UINT8  bDescriptorSubtype; // 描述符子类型。 VC_PROCESSING_UNIT ,值为0x05
UINT8  bUnitID; // 描述符唯一标识ID,非零值
UINT8  bSourceID;// 连接到此单元的单元ID或实体ID.
UINT16 wMaxMultiplier;
UINT8 bControlSize;  // bmControls的字节大小,为3字节=24位
UINT8 bmControls[3]; // 摄像头参数控制位,为1表示摄像头支持调整
UINT8 iProcessing;
UINT8 bmVideoStandards;

bmControls摄像头参数控制位分布如下:

  • D0:亮度
  • D1:对比度
  • D2:色调
  • D3:饱和
  • D4:锐度
  • D5:伽马射线
  • D6:白平衡温度
  • D7:白平衡分量
  • D8:背光补偿
  • D9:增益
  • D10:电源线频率
  • D11:色调,自动
  • D12:白平衡温度,自动
  • D13:白平衡组件,自动
  • D14:数字乘法器
  • D15:数字乘法器限制
  • D16:模拟视频标准
  • D17:模拟视频锁定状态
  • D18:对比度,自动
  • D19--D23:保留。设为零

(2)相机终端描述符

UVC终端描述符用于描述摄像头硬件特性,比如设定扫描模式、自动曝光等,它使用bTerminalID来标识其惟一的ID,所有的请求必须使用此ID。

c 复制代码
typedef struct _CAMERA_TERMINAL_DESCRIPTOR
   UINT8  bLength;  // 数据长度。固定为18.
   UINT8  bDescriptorType; // 描述符类型,CS_INTERFACE,值为0x24.
   UINT8  bDescriptorSubtype; // 描述符子类型。VC_INPUT_TERMINAL ,值为0x02。
   UINT8  bTerminalID; // 终端ID,唯一标识符,非零值
   UINT16 wTerminalType; // 终端类型,ITT_CAMERA值为0x201
   UINT8  bAssocTerminal; // 与输入端点关联的输出端点ID
   UINT8  iTerminal; // 描述此端点的字符串描述符索引
   UINT16 wObjectiveFocalLengthMin; // 光学变焦的最小值,如不支持为0
   UIN16 wObjectiveFocalLengthMax;  // 光学变焦的最大值,如不支持为0
   UIN16 wOcularFocalLength; // 光学缩放值,如不支持为0
   UINT8 bControlSize; // bmControls的字节大小, 3字节=24位
   UINT8  bmControls[3]; // 使用位图来表示支持的视频流
 }CAMERA_TERMINAL_DESCRIPTOR;

bmControls参数分布如下:

  • D0:扫描模式 //扫描模式(逐行扫描或隔行扫描)
  • D1:自动曝光模式
  • D2:自动曝光优先级
  • D3:曝光时间(绝对值)
  • D4:曝光时间(相对)
  • D5:焦点(绝对)
  • D6:焦点(相对)
  • D7:虹膜光圈(绝对)
  • D8:虹膜光圈(相对)
  • D9:缩放(绝对)
  • D10:缩放(相对)
  • D11:PanTilt(绝对) PT是左右和上下移动
  • D12:PanTilt(相对)
  • D13:滚动(绝对)
  • D14:滚动(相对)
  • D15:预留
  • D16:预留
  • D17:自动对焦
  • D18:隐私
  • D19:专注,简单
  • D20:窗口
  • D21:关注区域,感兴趣区域
  • D22--D23:保留,设置为零

2.3.3 视频流接口描述符VSD

视频流接口描述符由标准视频控制接口描述符以及各控制相关描述符组成,它包含了所有完整的视频流接口信息。标准视频流接口描述符使用通用USB设备接口描述符数据结构。

c 复制代码
struct _INTERFACE_DESCRIPTOR_STRUCT; 
{ 
    BYTE bLength;           //设备描述符的字节数大小,为0x09
    BYTE bDescriptorType;   //描述符类型编号,为0x01 
    BYTE bInterfaceNunber; //接口的编号 
    BYTE bAlternateSetting;//备用的接口描述符编号 
    BYTE bNumEndpoints;     //该接口使用端点数,不包括端点0 
    BYTE bInterfaceClass;   //接口类型(由USB-IF分配) 
    BYTE bInterfaceSubClass;//接口子类型 
    BYTE bInterfaceProtocol;//接口所遵循的协议 
    BYTE iInterface;         //描述该接口的字符串索引值 
}INTERFACE_DESCRIPTOR_STRUCT;

2.4 端点描述符

视频控制接口(VC)的端点描述符可以存在,也可以不存。

如果存在,必须是中断类型的,且必须为输入端点。

  • bLength : 描述符大小.固定为0x07.
  • bDescriptorType : 接口描述符类型.固定为0x05.
  • bEndpointType : USB设备的端点地址.Bit7为方向位,必须为1,用于标识为输入端点;BIT4-6为0,BIT0-3表示端点ID。
  • bmAttributes : 端点属性.BIT0-1必须为11,标识为中断端点;BIT2-3对于同步/等时传输有效,这里必须为00
  • wMaxPacketSize:本端点接收或发送的最大信息包大小.
  • bInterval : 时间间隔,对于全速为1ms为单位;对于高速为2的N次方。详见端点描述符中的解释

视频流接口(VS)中的端点描述符用于传输视频数据。

参考文献

相关推荐
Leyla3 分钟前
【代码重构】好的重构与坏的重构
前端
影子落人间6 分钟前
已解决npm ERR! request to https://registry.npm.taobao.org/@vant%2farea-data failed
前端·npm·node.js
世俗ˊ30 分钟前
CSS入门笔记
前端·css·笔记
子非鱼92131 分钟前
【前端】ES6:Set与Map
前端·javascript·es6
6230_35 分钟前
git使用“保姆级”教程1——简介及配置项设置
前端·git·学习·html·web3·学习方法·改行学it
想退休的搬砖人44 分钟前
vue选项式写法项目案例(购物车)
前端·javascript·vue.js
加勒比海涛1 小时前
HTML 揭秘:HTML 编码快速入门
前端·html
啥子花道1 小时前
Vue3.4 中 v-model 双向数据绑定新玩法详解
前端·javascript·vue.js
麒麟而非淇淋1 小时前
AJAX 入门 day3
前端·javascript·ajax
茶茶只知道学习1 小时前
通过鼠标移动来调整两个盒子的宽度(响应式)
前端·javascript·css