4. UVC(USB Video Class)协议基础

UVC(USB Video Class)是 USB-IF 定义的标准化视频设备协议,使摄像头、视频采集卡等设备无需安装专用驱动即可在主机端即插即用。在 ARM 平台移植 UVC Gadget 驱动前,必须深入理解 UVC 标准规范、视频流格式以及描述符结构。本章将围绕这三个核心知识点展开,为后续驱动移植打下坚实的协议基础。

4.1 UVC 标准规范概述

UVC 规范定义了一套标准的 USB 描述符、请求和事件机制,用于枚举和控制视频设备。其核心设计思想是将视频设备抽象为 功能单元(Functional Units) 和 终端(Terminals) 的拓扑结构。

关键概念: UVC 设备在主机端被识别为“视频设备类”,而非“HID”或“大容量存储”。主机操作系统通过标准的 UVC 驱动(如 Linux 的 uvcvideo)加载,无需厂商自定义驱动。

4.1.1 UVC 版本与兼容性

UVC 版本 发布年份 主要特性 ARM 平台关注点
UVC 1.0 2003 基础视频流、静态图像捕获、MJPEG 格式 兼容性最广,Gadget 驱动首选
UVC 1.1 2005 增加 H.264 支持、改进流控 需注意 H.264 编码器硬件支持
UVC 1.5 2012 增加 H.265/HEVC、帧间隔控制 ARM 平台硬件编码器需支持 HEVC
实战建议: 在 ARM 平台移植 UVC Gadget 时,优先实现 UVC 1.0 兼容描述符,确保主机端(Windows/Linux/macOS)无需额外驱动即可识别。后续再根据硬件编码能力扩展 1.1/1.5 特性。

4.1.2 UVC 功能拓扑结构

UVC 设备内部由多个逻辑单元组成,主机通过 USB 控制传输(端点 0)与这些单元交互。典型的 UVC 摄像头拓扑包含以下单元:

  • 输入终端(IT): 代表物理摄像头传感器,负责采集原始图像数据。
  • 处理单元(PU): 负责图像处理,如亮度、对比度、饱和度调节。
  • 编码单元(EU): 负责将原始视频流编码为 MJPEG 或 H.264 格式。
  • 输出终端(OT): 代表 USB 接口,将编码后的视频流发送给主机。
UVC 摄像头功能拓扑结构 输入终端 (IT) 摄像头传感器 处理单元 (PU) 亮度/对比度/饱和度 编码单元 (EU) MJPEG / H.264 输出终端 (OT) USB 接口 主机 UVC 驱动 (uvcvideo) USB 控制/批量传输

4.2 视频流格式:MJPEG 与 H.264

UVC 规范支持多种视频编码格式,其中 MJPEG 和 H.264 是 ARM 平台最常用的两种格式。两者在带宽占用、编码复杂度、主机兼容性方面差异显著。

4.2.1 MJPEG(Motion JPEG)

MJPEG 将视频的每一帧独立压缩为 JPEG 图像。其特点是编码简单、帧内无依赖,适合嵌入式平台的低功耗场景。

  • 编码原理: 每帧独立 JPEG 压缩,帧间无预测。
  • 带宽需求: 较高,1080p@30fps 约需 30-50 Mbps。
  • 主机兼容性: 极佳,所有操作系统原生支持。
  • ARM 实现: 可使用硬件 JPEG 编码器或软件 libjpeg。

4.2.2 H.264(Advanced Video Coding)

H.264 利用帧间预测和变换编码,在相同画质下带宽仅为 MJPEG 的 1/5 到 1/10。但编码复杂度高,通常需要硬件编码器支持。

  • 编码原理: I/P/B 帧结构,帧间运动估计与补偿。
  • 带宽需求: 较低,1080p@30fps 约需 5-10 Mbps。
  • 主机兼容性: UVC 1.1+ 支持,Windows/macOS 需额外解码器。
  • ARM 实现: 必须依赖硬件 H.264 编码器(如 Rockchip MPP、Allwinner VENC)。
对比维度 MJPEG H.264
编码复杂度 低(适合 MCU/低功耗 ARM) 高(需硬件编码器)
带宽占用 高(30-50 Mbps @1080p) 低(5-10 Mbps @1080p)
帧内依赖 无(每帧独立) 有(I/P/B 帧依赖)
UVC 版本要求 UVC 1.0+ UVC 1.1+
主机解码 无需解码器 需 H.264 解码器
移植陷阱: 在 ARM 平台实现 H.264 UVC Gadget 时,必须确保硬件编码器输出的码流符合 H.264 字节流格式(Annex B),且包含 SPS/PPS 头信息。否则主机端解码器无法正确解析视频流。

4.3 UVC 描述符结构

UVC 描述符是设备向主机声明自身能力的数据结构,位于 USB 配置描述符中。主机通过解析这些描述符来识别视频流格式、分辨率、帧率以及控制能力。UVC 描述符分为 标准描述符 和 类特定描述符 两大类。

4.3.1 接口描述符(Interface Descriptor)

UVC 设备通常包含两个接口:控制接口(Interface 0) 和 流接口(Interface 1)。控制接口用于发送 UVC 请求(如设置亮度、启动/停止流),流接口用于传输视频数据。

  • 控制接口(VideoControl Interface):
    • 接口类:0x0E(Video Interface Class)
    • 接口子类:0x01(VideoControl Subclass)
    • 接口协议:0x00(未指定)
    • 包含:终端描述符、单元描述符
  • 流接口(VideoStreaming Interface):
    • 接口类:0x0E(Video Interface Class)
    • 接口子类:0x02(VideoStreaming Subclass)
    • 接口协议:0x00(未指定)
    • 包含:格式描述符、帧描述符、端点描述符

4.3.2 端点描述符(Endpoint Descriptor)

流接口必须包含一个 等时(Isochronous) 或 批量(Bulk) 端点,用于传输视频帧数据。UVC 1.0 标准推荐使用等时端点,但 UVC 1.5 开始支持批量端点以提升兼容性。

端点类型 传输方式 带宽保证 典型应用
等时端点 Isochronous 有(预留带宽) UVC 1.0 标准摄像头
批量端点 Bulk 无(尽力而为) UVC 1.5 高分辨率摄像头
ARM 平台选择: 在 USB Gadget 驱动中,推荐使用 批量端点 传输视频流。原因:批量传输不占用固定带宽,适合 USB 共享场景;且 ARM 平台的 USB 控制器对批量传输支持更稳定。

4.3.3 类特定描述符(Class-Specific Descriptors)

UVC 定义了一系列类特定描述符,用于描述视频格式、帧尺寸、帧率等参数。这些描述符位于流接口的接口描述符之后。

  • VS_INPUT_HEADER: 描述流接口的总体信息,包含支持的格式数量。
  • VS_FORMAT_MJPEG / VS_FORMAT_H264: 描述视频编码格式,如 MJPEG 或 H.264。
  • VS_FRAME_MJPEG / VS_FRAME_H264: 描述帧尺寸(宽度、高度)和帧率(帧间隔)。
  • VS_COLORFORMAT: 描述色彩空间(如 YUY2、NV12)。
UVC 描述符层级结构 配置描述符 (Configuration Descriptor) 接口 0: 视频控制 (VideoControl) 输入终端描述符 处理单元描述符 编码单元描述符 接口 1: 视频流 (VideoStreaming) VS_INPUT_HEADER VS_FORMAT_MJPEG VS_FRAME (1920x1080) VS_FRAME (1280x720) VS_FRAME (640x480) 端点描述符 (Bulk IN)

4.3.4 描述符代码示例(UVC Gadget 内核配置)

在 Linux 内核的 UVC Gadget 驱动中,描述符通过 uvc_function_info 结构体定义。以下是一个简化的 MJPEG 流接口描述符配置片段:

/* 流接口描述符定义 */
static struct usb_interface_descriptor uvc_streaming_intf_alt0 = {
    .bLength            = USB_DT_INTERFACE_SIZE,
    .bDescriptorType    = USB_DT_INTERFACE,
    .bInterfaceNumber   = 1,           /* 流接口编号 */
    .bAlternateSetting  = 0,           /* 备用设置 0:无带宽 */
    .bNumEndpoints      = 0,           /* 无端点 */
    .bInterfaceClass    = USB_CLASS_VIDEO,
    .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING,
    .bInterfaceProtocol = 0,
    .iInterface         = 0,
};

static struct usb_interface_descriptor uvc_streaming_intf_alt1 = {
    .bLength            = USB_DT_INTERFACE_SIZE,
    .bDescriptorType    = USB_DT_INTERFACE,
    .bInterfaceNumber   = 1,
    .bAlternateSetting  = 1,           /* 备用设置 1:启用流 */
    .bNumEndpoints      = 1,           /* 1 个批量端点 */
    .bInterfaceClass    = USB_CLASS_VIDEO,
    .bInterfaceSubClass = UVC_SC_VIDEOSTREAMING,
    .bInterfaceProtocol = 0,
    .iInterface         = 0,
};

/* 批量端点描述符 */
static struct usb_endpoint_descriptor uvc_fs_streaming_ep = {
    .bLength            = USB_DT_ENDPOINT_SIZE,
    .bDescriptorType    = USB_DT_ENDPOINT,
    .bEndpointAddress   = USB_DIR_IN | 1,  /* EP1 IN */
    .bmAttributes       = USB_ENDPOINT_XFER_BULK,
    .wMaxPacketSize     = cpu_to_le16(512), /* 全速批量最大包 */
    .bInterval          = 0,
};
关键点: 描述符中的 bAlternateSetting 用于切换带宽模式。备用设置 0 表示无数据传输(用于枚举),备用设置 1 及以上表示启用视频流。主机通过 SET_INTERFACE 请求切换备用设置。

4.4 本章小结

UVC 协议是 USB Gadget 摄像头驱动的核心通信语言。本章涵盖了:

  • UVC 标准规范: 版本演进、功能单元拓扑结构。
  • 视频流格式: MJPEG 与 H.264 的编码原理、带宽对比及 ARM 实现要点。
  • 描述符结构: 接口描述符、端点描述符、类特定描述符的层级关系与代码示例。