UVC(USB Video Class)协议讲解

UVC协议学习2--UVC请求格式分析 前言    大致了解一下UVC请求格式,贴出来已做备忘。一、UVC请求格式1、设置请求格式2、获取请求格式二、字段释义1、bmRequestType字段(1字节)1)D7,下一步数据的出传输方向0 = 主机到设备(SET请求)1 = 设备到主机(GET请求)2)D6-D5,命令的类型00 = 标准请求命令01 = 类请求命令(UVC规范中的请求属于类请求命令)10 = 用户定义的请求命令11 = ... 阅读详情
AI摘要

本文深入解析UVC设备的工作原理及组成结构,包括UVC设备的多接口特性、IAD描述符的作用、VC与VS接口的功能及其实现方式,并探讨了UVC设备内部的实体结构及其在视频传输中的应用。

1. UVC功能概述

UVC设备都是多Interface设备,这点同普通的u盘不同。UVC设备最起码有两个Interface,VideoControl(VC)Interface和VideoStream(VS) Interface; 这也是最常见的UVC设备。 Spec明确要求一个具有可用的,具有实际UVC功能的设备要有一个VC Interface,一个或多个VS Interface。

VCInterface用于进行配置,操控,设置UVC设备进入不同的功能状态,而VSInterface则负责视频数据流的传输;完整的UVC功能需依赖VS,VC Interfaces的配合才能实现。

2.IAD以及Interfaces

UVC功能需要使用一个VC Interface和一个或多个VS Interface的配合。Spec明确要求UVC设备必须使用一个Interface Association Descriptor(IAD)来描述这个包含了VC和VS的Interfaces集合。

此外USB协议中并没有专门朝设备索取IAD的命令,IAD需作为Configuration描述符的一部分发送给Host端。在该Configuration描述符的排列顺序中,IAD要放在它所包含的VC,VS描述符之前,且同一个IAD中所有的VC,VS Interface的Interface number必须连贯。

===>Device Descriptor<===
...

===>Configuration Descriptor<===
...

===>IAD Descriptor<=== 
bLength: 0x08 
bDescriptorType: 0x0B 
bFirstInterface: 0x00 
bInterfaceCount: 0x02 
bFunctionClass: 0x0E -> Video Interface Class 
bFunctionSubClass: 0x03 -> Video Interface Collection 
bFunctionProtocol: 0x00 -> PC_PROTOCOL_UNDEFINED protocol 
iFunction: 0x00 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x00 
bAlternateSetting: 0x00 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x01 -> Video Control Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00
...

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x00 
bNumEndpoints: 0x00 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00
...

===>IAD Descriptor<=== 
bLength: 0x08 
bDescriptorType: 0x0B 
bFirstInterface: 0x02 
bInterfaceCount: 0x02 
bFunctionClass: 0x01 -> Audio Interface Class 
bFunctionSubClass: 0x01 -> Audio Control Interface SubClass 
bFunctionProtocol: 0x00 
iFunction: 0x04 
English (United States) "USB2.0 MIC" 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x02 
bAlternateSetting: 0x00 
bNumEndpoints: 0x00 
bInterfaceClass: 0x01 -> Audio Interface Class 
bInterfaceSubClass: 0x01 -> Audio Control Interface SubClass 
bInterfaceProtocol: 0x00 
CAUTION: This may be an invalid bInterfaceProtocol 
iInterface: 0x04 
English (United States) "USB2.0 MIC"
...

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x03 
bAlternateSetting: 0x00 
bNumEndpoints: 0x00 
bInterfaceClass: 0x01 -> Audio Interface Class 
bInterfaceSubClass: 0x02 -> Audio Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
CAUTION: This may be an invalid bInterfaceProtocol 
iInterface: 0x04 
English (United States) "USB2.0 MIC"
...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78

可以看到我所使用的uvc设备包含两个IAD,第一个IAD是视频输入设备,也就是摄像头。第二个IAD是音频输入设备,也就是麦克风,暂时忽略这个IAD。重点分析第一个IAD,它包含了两个Interface,一个VC Interface和一个VS Interface

3.VC Interface

VC主要用于控制UVC功能中的Units和Terminals,通过对不同的Units和Terminals发下不同的指令,从而影响UVC设备的当前工作状态;Host端发下的所有对UVC设备的操纵控制命令都是经由此Interface完成的

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x00 
bAlternateSetting: 0x00 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x01 -> Video Control Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Class-Specific Video Control Interface Header Descriptor<=== 
bLength: 0x0D 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x01 
bcdVDC: 0x0100 
wTotalLength: 0x0033 -> Validated 
dwClockFreq: 0x02DC6C00 = (48000000) Hz 
bInCollection: 0x01 
baInterfaceNr[1]: 0x01 
USB Video Class device: spec version 1.0

===>Video Control Input Terminal Descriptor<===
...

===>Video Control Processing Unit Descriptor<===
...

===>Video Control Output Terminal Descriptor<===
...

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x81 -> Direction: IN - EndpointID: 1 
bmAttributes: 0x03 -> Interrupt Transfer Type 
wMaxPacketSize: 0x0010 = 1 transactions per microframe, 0x10 max bytes 
bInterval: 0x0A 

===>Class-specific VC Interrupt Endpoint Descriptor<=== 
bLength: 0x05 
bDescriptorType: 0x25 
bDescriptorSubtype: 0x03 
wMaxTransferSize: 0x0010 = (16) Bytes
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

这个设备包含了一个Processing Unit、一个Input Terminal和Output Terminal,VC Interface需要对它们下发不同的命令,为此VC Interface需要包含一个控制端点(强制性要求),它使用的就是每个USB设备中默认的端点0。

另外一个Interrupt端点则是可选的,用来返回或通知Host端当前的UVC设备内部状态有变化。大部分情况下,一个UVC设备的VC Interface不需一定要实现此端点,但一旦UVC设备需要实现某些特定feature时,Spec会强制性要求实现该interrupt端点。

4. UVC设备内的各种Entity

UVC的Spec在制定时考虑到了诸多不同UVC设备可能存在的特性,为保证Spec具有最大范围的适用性和兼容性,将UVC设备内可能存在的每个功能模块划分为逻辑意义上的功能单元(Entity),并要求具体UVC设备的开发者必须为每个Entity指定ID号,且该ID号能唯一标识某一指定的功能单元,以便Host端的UVC驱动能依此对设备内不同的功能单元进行操作和配置。

Entity粗略可划分为Unit,Terminal两种。这都是逻辑意义上的划分,它们对应UVC设备内的某个功能单元。

4.1 Unit

Unit可以理解为构建出UVC设备功能的各功能单元,多个Unit按照一定的规则连接后就是一个完整的UVC功能设备。Spec规定Unit有一个或多个入口,一个出口;也就是说可以有多个Unit或Terminal作为一个Unit的输入源头,而数据在流经Unit后仅能作为其他Unit或Terminal的一个输入源头。

Spec中定义了三种Unit:Selector Unit (SU),Processing Unit (PU),Extension Unit (EU)。

===>Video Control Processing Unit Descriptor<=== 
bLength: 0x0B 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x05 
bUnitID: 0x02 
bSourceID: 0x01 
wMaxMultiplier: 0x0000 
bControlSize: 0x02 
bmControls : 0x3F 0x06 
D00 = 1 yes - Brightness 
D01 = 1 yes - Contrast 
D02 = 1 yes - Hue 
D03 = 1 yes - Saturation 
D04 = 1 yes - Sharpness 
D05 = 1 yes - Gamma 
D06 = 0 no - White Balance Temperature 
D07 = 0 no - White Balance Component 
D08 = 0 no - Backlight Compensation 
D09 = 1 yes - Gain 
D10 = 1 yes - Power Line Frequency 
D11 = 0 no - Hue, Auto 
D12 = 0 no - White Balance Temperature, Auto 
D13 = 0 no - White Balance Component, Auto 
D14 = 0 no - Digital Multiplier 
D15 = 0 no - Digital Multiplier Limit 
iProcessing : 0x00
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26

Processing Unit则代表了对采集的数据进行处理的单元,负责对采集到的图像特性进行调整设置,当Host端要求设定这些Processing Unit负责范围内的功能特性时,Processing Unit作为指定的命令响应者就需要对之进行响应和调整。

Spec定义中要求PU单元负责响应Host端对如下图像特性方面的设置调整要求(在该UVC设备确实支持这些特性可变,可供设置的前提下)
Usr 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

4.2 Terminal

Terminal是指整个UVC功能的入口和出口,逻辑意义上讲Terminal只有一个出口或者入口,它要么代表整个UVC功能的数据输入点,要么代表数据在流经UVC功能内部的各Unit功能单元后的最终流入点。

Spec中定义了两种Terminal:Input Terminal,Output Terminal。

===>Video Control Input Terminal Descriptor<=== 
bLength: 0x12 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x02 
bTerminalID: 0x01 
wTerminalType: 0x0201 = (ITT_CAMERA) 
bAssocTerminal: 0x00 
iTerminal: 0x00 
===>Camera Input Terminal Data 
wObjectiveFocalLengthMin: 0x0000 
wObjectiveFocalLengthMax: 0x0000 
wOcularFocalLength: 0x0000 
bControlSize: 0x03 
bmControls : 0x00 0x00 0x00 
D00 = 0 no - Scanning Mode 
D01 = 0 no - Auto-Exposure Mode 
D02 = 0 no - Auto-Exposure Priority 
D03 = 0 no - Exposure Time (Absolute) 
D04 = 0 no - Exposure Time (Relative) 
D05 = 0 no - Focus (Absolute) 
D06 = 0 no - Focus (Relative) 
D07 = 0 no - Iris (Absolute) 
D08 = 0 no - Iris (Relative) 
D09 = 0 no - Zoom (Absolute) 
D10 = 0 no - Zoom (Relative) 
D11 = 0 no - Pan (Absolute) 
D12 = 0 no - Pan (Relative) 
D13 = 0 no - Roll (Absolute) 
D14 = 0 no - Roll (Relative) 
D15 = 0 no - Tilt (Absolute) 
D16 = 0 no - Tilt (Relative) 
D17 = 0 no - Focus Auto 
D18 = 0 no - Reserved 
D19 = 0 no - Reserved 
D20 = 0 no - Reserved 
D21 = 0 no - Reserved 
D22 = 0 no - Reserved 
D23 = 0 no – Reserved 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

Input Terminal可以理解为整个UVC功能的数据源头,它仅有一个outPin,可以连接到其他Unit的Input Pin作为该Unit的输入源。

===>Video Control Output Terminal Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x03 
bTerminalID: 0x03 
wTerminalType: 0x0101 = (TT_STREAMING) 
bAssocTerminal: 0x00 
bSourceID: 0x02 
iTerminal: 0x00 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

Output Terminal则可以理解为当图像数据流程UVC设备内部的整个处理流程后的输出点,它仅有一个Input Pin, 整个UVC处理流程上的最后一个Unit会将它的Output Pin与Output Terminal的Input Pin连接在一起。

UVC Entity

通过如上描述符所获得的信息,我们可以看出该USB Camera大致有三个逻辑功能意义上的Entity:CT(代表硬件上的图像数据采集源,Sensor),PU(代表Sensor中可对采集所得图像数据进行加工的功能单元),OT(代表实际中USB模块的的ISO In端点),并无SU单元来控制图像数据采集源的切换和选择(只有一个输入源),此外也没有对采集所得的数据进行个性化处理的功能,故也没有EU单元的存在(无EU描述符)。

5. VS Interface

VS Interface则专注与负责传输UVC设备的Video数据到Host端。若一UVC设备支持n种格式的Video数据,则它需要实现n个VS Interface,每个Interface对应一种专门的数据格式;而每个VSInterface则必须包含一个ISO或bulk端点来传输Video数据,一个可选的bulk端点专门用于传输静态图片数据(在实现了第三种静态图片拍摄机制的前提下)。

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x00 
bNumEndpoints: 0x00 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Video Class-Specific VS Video Input Header Descriptor<=== 
bLength: 0x0E 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x01 
bNumFormats: 0x01 
wTotalLength: 0x010F -> Validated 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmInfo: 0x00 -> Dynamic Format Change not Supported 
bTerminalLink: 0x03 
bStillCaptureMethod: 0x02 -> Still Capture Method 2 
bTriggerSupport: 0x01 -> Hardware Triggering Support 
bTriggerUsage: 0x00 -> Host will initiate still image capture 
bControlSize: 0x01 
Video Payload Format 1 0x00 
D00 = 0 no - Key Frame Rate 
D01 = 0 no - P Frame Rate 
D02 = 0 no - Compression Quality 
D03 = 0 no - Compression Window Size 
D04 = 0 no - Generate Key Frame 
D05 = 0 no - Update Frame Segment 
D06 = 0 no - Reserved 
D07 = 0 no - Reserved 

===>Video Streaming MJPEG Format Type Descriptor<=== 
bLength: 0x0B 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x06 
bFormatIndex: 0x01 
bNumFrameDescriptors: 0x05 
bmFlags: 0x01 -> Sample Size is Fixed 
bDefaultFrameIndex: 0x01 
bAspectRatioX: 0x00 
bAspectRatioY: 0x00 
bmInterlaceFlags: 0x00 
D00 = 0 non-Interlaced stream or variable 
D01 = 0 2 fields per frame 
D02 = 0 Field 1 not first 
D03 = 0 Reserved 
D4..5 = 0 Field patterns -> Field 1 only 
D6..7 = 0 Display Mode -> Bob only 
bCopyProtect: 0x00 -> Duplication Unrestricted 

===>Video Streaming MJPEG Frame Type Descriptor<=== 
--->This is the Default (optimum) Frame index 
bLength: 0x2A 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x07 
bFrameIndex: 0x01 
bmCapabilities: 0x00 
wWidth: 0x0280 
wHeight: 0x01E0 
dwMinBitRate: 0x0001F400 
dwMaxBitRate: 0x00A8C000 
dwMaxVideoFrameBufferSize: 0x00096000 
dwDefaultFrameInterval: 0x00051615 
bFrameIntervalType: 0x04 
===>Additional Discrete Frame TypeData 
dwFrameInterval[1]: 0x00028B0A 
dwFrameInterval[2]: 0x00051615 
dwFrameInterval[3]: 0x000A2C2A 
dwFrameInterval[4]: 0x001E8480 

===>Video Streaming MJPEG Frame Type Descriptor<=== 
bLength: 0x2A 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x07 
bFrameIndex: 0x02 
bmCapabilities: 0x00 
wWidth: 0x00A0 
wHeight: 0x0078 
dwMinBitRate: 0x0001F400 
dwMaxBitRate: 0x00A8C000 
dwMaxVideoFrameBufferSize: 0x00009600 
dwDefaultFrameInterval: 0x00051615 
bFrameIntervalType: 0x04 
===>Additional Discrete Frame TypeData 
dwFrameInterval[1]: 0x00028B0A 
dwFrameInterval[2]: 0x00051615 
dwFrameInterval[3]: 0x000A2C2A 
dwFrameInterval[4]: 0x001E8480 

===>Video Streaming MJPEG Frame Type Descriptor<=== 
bLength: 0x2A 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x07 
bFrameIndex: 0x03 
bmCapabilities: 0x00 
wWidth: 0x00B0 
wHeight: 0x0090 
dwMinBitRate: 0x0001F400 
dwMaxBitRate: 0x00A8C000 
dwMaxVideoFrameBufferSize: 0x0000C600 
dwDefaultFrameInterval: 0x00051615 
bFrameIntervalType: 0x04 
===>Additional Discrete Frame TypeData 
dwFrameInterval[1]: 0x00028B0A 
dwFrameInterval[2]: 0x00051615 
dwFrameInterval[3]: 0x000A2C2A 
dwFrameInterval[4]: 0x001E8480 

===>Video Streaming MJPEG Frame Type Descriptor<=== 
bLength: 0x2A 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x07 
bFrameIndex: 0x04 
bmCapabilities: 0x00 
wWidth: 0x0140 
wHeight: 0x00F0 
dwMinBitRate: 0x0001F400 
dwMaxBitRate: 0x00A8C000 
dwMaxVideoFrameBufferSize: 0x00025800 
dwDefaultFrameInterval: 0x00051615 
bFrameIntervalType: 0x04 
===>Additional Discrete Frame TypeData 
dwFrameInterval[1]: 0x00028B0A 
dwFrameInterval[2]: 0x00051615 
dwFrameInterval[3]: 0x000A2C2A 
dwFrameInterval[4]: 0x001E8480 

===>Video Streaming MJPEG Frame Type Descriptor<=== 
bLength: 0x2A 
bDescriptorType: 0x24 
bDescriptorSubtype: 0x07 
bFrameIndex: 0x05 
bmCapabilities: 0x00 
wWidth: 0x0160 
wHeight: 0x0120 
dwMinBitRate: 0x0001F400 
dwMaxBitRate: 0x00A8C000 
dwMaxVideoFrameBufferSize: 0x00031800 
dwDefaultFrameInterval: 0x00051615 
bFrameIntervalType: 0x04 
===>Additional Discrete Frame TypeData 
dwFrameInterval[1]: 0x00028B0A 
dwFrameInterval[2]: 0x00051615 
dwFrameInterval[3]: 0x000A2C2A 
dwFrameInterval[4]: 0x001E8480 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148

可以看出这个设备只支持一种视频格式”MJPEG”,所以它只有一个VS Interface,而同一种视频格式下有很多参数可以调整,比如说图像分辨率,每秒的帧速率等。其参数组合信息就是紧跟在Format Type Descriptor之后的Frame Type Descriptor。

在采用不同的参数组合时,UVC设备进行数据传输时,所需占用的USB数据带宽显然有很大的不同;因此一个VS Interface下需要有多个setting,每个settnig对应一个固定的Video参数设置组合,也就对应了一个固定参数值的Video数据,该setting下每秒要传输的帧数(帧速率),图像分辨率等均固定,进而对USB的带宽要求也固定。

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x01 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x00C0 = 1 transactions per microframe, 0xC0 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x02 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x0180 = 1 transactions per microframe, 0x180 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x03 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x0200 = 1 transactions per microframe, 0x200 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x04 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x0280 = 1 transactions per microframe, 0x280 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x05 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x0320 = 1 transactions per microframe, 0x320 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x06 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x03C0 = 1 transactions per microframe, 0x3C0 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x07 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x0A80 = 2 transactions per microframe, 0x280 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x08 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x0B20 = 2 transactions per microframe, 0x320 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x09 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x0BE0 = 2 transactions per microframe, 0x3E0 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x0A 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x1380 = 3 transactions per microframe, 0x380 max bytes 
bInterval: 0x01 

===>Interface Descriptor<=== 
bLength: 0x09 
bDescriptorType: 0x04 
bInterfaceNumber: 0x01 
bAlternateSetting: 0x0B 
bNumEndpoints: 0x01 
bInterfaceClass: 0x0E -> Video Interface Class 
bInterfaceSubClass: 0x02 -> Video Streaming Interface SubClass 
bInterfaceProtocol: 0x00 
iInterface: 0x00 

===>Endpoint Descriptor<=== 
bLength: 0x07 
bDescriptorType: 0x05 
bEndpointAddress: 0x83 -> Direction: IN - EndpointID: 3 
bmAttributes: 0x05 -> Isochronous Transfer Type 
Synchronization Type = Asynchronous 
Bulk Transfer Type 
wMaxPacketSize: 0x13E8 = 3 transactions per microframe, 0x3E8 max bytes 
bInterval: 0x01 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230

此外,对于每个VS Interface来讲,必须实现setting0,且setting0不代表任何实际的Video流和参数组合,当指定setting0时就是要求UVC设备暂停数据传输,放弃对USB带宽的占用。

6. 总结

UVC同MSC一样,系USB框架下的功能类协议,但却与MSC有着较大差异。MSC功能采用Control+Bulk传输完成,其枚举流程,描述符配置较为清晰,控制传输阶段简单,定义的类功能控制命令较少。而BULK传输阶段则较为复杂繁琐,出错机制,续传机制等要求较为严格。

而UVC则刚好相反,它采用Control+ISO传输机制实现(BULK和INTR机制为可选特性),其枚举流程,描述符配置较为复杂,繁琐,定义了诸多的类控制命令,Entity等;而具体的数据传输阶段即ISO传输较为简单。

uvc协议介绍 以及windows和linux上简单demo uvc usb windows linux 阅读详情

相关推荐

USB Video Class设备端开发全面讲解

深入解析USB Video Class(uvc)协议架构与设备端实现流程,涵盖uvc控制请求、视频流格式配置及驱动适配关键点,帮助开发者快速构建兼容性强的uvc设备。

weixin_28746213的博客 972

USB 的UVC协议分析

本文介绍了UVC(USB Video Class)协议在STM32和GD32上的驱动实现。主要内容包括:1)USB枚举过程,详细解析了设备描述符获取、地址分配等关键步骤;2)UVC枚举分析,通过抓包数据解读标准请求格式和特定类请求;3)摄像头开关机制,说明通过SET_INTERFACE命令实现状态切换;4)通讯接口实现,包括命令接收、解析、驱动和回复流程。文章结合具体案例和流程图,系统阐述了UVC设备从枚举到数据传输的完整工作流程。

m0_37202877的博客 9519

流媒体 - UVC 协议

uvc 是传输协议,没有 ota 升级内容,升级通过 RNDIS 升级 uvc解决方案带宽限制在 6M/s,按20fps计算分辨率小于30W,不能使用yuyv,需h264编码传输 UVC功能的设备:一个 VC Interface,一个或多个 VS Interface。 (1)VCInterface 用于进行配置,操控,设置UVC设备进入不同的功能状态 (2)VSInterface则负责视频数据流的传输 规范明确要求UVC设备必须使用一个Interface Association Descrip.

qq_25439881的博客 1万+

UVC1.5协议 2

UVC协议 UVC1.5

m0_56922987的博客 3704

UVC协议学习前奏

    根据一些资料对UVC规范进行了一些了解,加上进一步接触UVC协议才发现有一些新的东西,将新的理解记录下来,以免忘记。1、关于UVC协议所需要知道的。    UVC,全称为:USB  video(device) class。    UVC是微软与另外几家设备厂商联合推出的为USB视频捕获设备定义的协议标准,目前已成为USB org标准之一。    USB协议中,除了通用的软硬件电气接口规范等...

go_str的博客 4969

UVC介绍及日志查看

在使用完摄像头后,还需要使用FT_UVC_Close()函数关闭UVC引擎,并使用FT_Close()函数关闭USB连接。UVC(USB Video Class)是一种基于USB协议的视频设备标准,可以让USB外接摄像头能够在不同的操作系统和平台上进行兼容,无需安装额外的驱动程序。UVC协议规定了USB摄像头与主机之间的通信协议,定义了摄像头在主机上的功能和特性,可视为一种简化版的USB HID协议。在单片机应用中,使用UVC协议可以方便地实现USB摄像头与单片机之间的数据传输,为开发者提供了很大的便利。

loop_class349的博客 1702

USB协议-UVC描述符篇(三)

USB协议-UVC描述符篇(三)1.概述2.UVC描述符布局3.设备描述符4.配置描述符5.接口关联描述符 - IAD6.视频控制接口描述符6.1 视频标准接口描述符6.2 类特定视频控制接口header描述符6.2.1 输入端点描述符6.2.2 输出端点描述符6.2.3 相机端点描述符6.2.4 SU选择器单元描述符7.视频控制端点描述符7.1VC控制端点描述符7.1.1 标准VC控制端点描述符7.1.2 类特定的VC控制端点描述符7.2 VC中断端点描述符7.2.1 标准VC中断端点描述符7.2.2 类

sevenjoin的博客 7822

Day 5:UVC 协议基础

今天的目标是回答:PC 打开摄像头时,如何选择 MJPEG、720p 和 30fps?一帧图像又如何拆成多个 USB Payload?

莫浅子的博客 59

usb uvc协议 1

USB描述符 设备描述符 PID VID 子类协议 usb协议版本 配置的数量 配置描述符 供电模式 电流值 接口数量 接口描述符 接口类型 接口子类型 接口协议 字符串的索引值 端点描述符 端点地址 传输属性 轮询间隔 数据包大小 USB传输方式 usb的传输模式USB 令牌包-数据包-/握手包 的传输机制,在令牌包中指定数据包去向或者来源的设备地址和端点,从而保证了只有一个设备对数据包/令牌包作出响应。握手包表示了传输的成功与否,等时传输没有握手包 令牌包总是由主机发送,...

m0_56922987的博客 1699

Linux内核中的UVC(USB Video Class)驱动

V4L2(Video for Linux 2)是Linux内核中的视频设备驱动框架,而UVC(USB Video Class)是一种使用USB接口的摄像头设备通信协议。在Linux内核中,V4L2和UVC之间存在以下关系:1. V4L2支持多种视频设备:V4L2是一个通用的视频设备驱动框架,它旨在支持各种类型的视频设备,包括USB摄像头、摄像头传感器、摄像头接口等。这样,V4L2可以在内核中集成不同类型的摄像头驱动程序。

新时代农民工 3345

UVC协议:统一视频设备接口的全面解析

在当今的数字时代,USB Video Class(UVC)协议已成为许多计算机视觉和视频捕获设备中不可或缺的一部分。本章将为大家提供UVC协议的基本概念、起源、以及它试图解决的问题。UVC,即USB Video Class,是一种定义了USB(通用串行总线)设备接口的协议。它允许设备在无需特定于操作系统的驱动程序的情况下,实现跨平台的视频输入和输出功能。UVC协议主要关注于如何通过USB接口传输视频数据,而不关心视频数据的压缩或处理方式。

weixin_35019679的博客 6024

【音视频开发】Linux UVC (USB Video Class) 驱动框架深度解析

本文深入解析Linux UVC(USB视频类)驱动框架,主要内容包括: UVC协议架构解析 详细阐述协议栈分层结构,包括视频控制接口和视频流接口 分析描述符体系,特别是视频流接口输入头描述符 讲解控制请求时序中的Probe和Commit协商机制 Linux内核实现剖析 展示驱动模块架构图,说明用户空间与内核空间的交互 介绍关键数据结构如uvc_device和uvc_streaming 分析数据流管道的工作原理 V4L2集成开发指南 讲解设备注册流程和IOCTL调用序列 说明帧格式协商过程 开发实战内容 包含

love131452098的博客 1639

Linux UVC视频子系统深度解析:从协议到排障

UVC(USB Video Class)是Linux中基于标准协议的免驱视频框架,其本质并非独立驱动模块,而是内核集成的v4l2视频子系统与USB协议栈协同工作的结果。它依托USB描述符解析、urb队列调度、DMA内存映射及v4l2设备注册等核心机制,实现即插即用的视频采集能力。技术价值在于消除平台依赖、统一用户空间接口,并支持MJPEG/H264等压缩格式以适配嵌入式带宽约束。典型应用场景包括工业相机接入、树莓派视觉开发、RK3399等ARM平台USB摄像头调优。本文聚焦uvcvideo内核模块与v4l2

weixin_29168675的博客 313

UVC协议与USB抓包实战:从协议解析到兼容性问题定位

USB视频类(UVC)协议是USB设备类规范中用于视频流传输的核心标准,其免驱特性依赖描述符体系的严格实现。通过USB抓包技术,可捕获总线上的原始数据包,对照UVC规范逐层解析设备描述符、类特定请求及等时传输数据,从而定位枚举失败、出图花屏、带宽协商异常等兼容性问题。该技术广泛应用于视频会议终端、嵌入式视觉设备及工业相机等场景,为USB摄像头开发与调试提供从协议理解到问题定位的完整方法论。

weixin_34023982的博客 290

UVC驱动Linux编译调试与嵌入式集成指南

USB摄像头因免驱特性被广泛应用于视频采集,其背后的UVC协议在Linux内核中由uvcvideo模块承载。理解驱动工作原理是排查设备无画面、出流失败等问题的前提。从USB枚举、格式协商到URB数据搬运,UVC驱动在内核中构成完整出流链路;本文结合v4l2-ctl工具,提供可复现的参数验证与带宽测试方法。针对嵌入式Linux场景,重点讲解在petalinux和buildroot中配置UVC驱动、应用补丁、检查设备树的关键步骤。同时梳理超时、花屏、掉帧、热插拔失效等典型故障,并逐一分析现象、根因与解法,帮助开

weixin_29169505的博客 116

Android Uvc 摄像头驱动

AndroidUSBCamera是基于[saki4510t/UVCCamera](https://github.com/saki4510t/UVCCamera)开发的,USB Camera(UVC设备)项目和视频数据采集的使用高度封装,可以帮助开发者通过一些简单的 API 轻松使用 USB 相机设备。使用AndroidUSBCamera,您可以简单的检测并连接USB Camera,还可以实现拍照、录制mp4、切换分辨率、获取h.264/aac/src.yuv(nv21)码流和设置相机对比度或亮度,支持480P、720P、1080P及更高等。支持覆盖和录制设备的麦克风。 支持安卓5.0,6.0,7.0,8.0,9.0,10.0

webcam.c和f_uvc.c驱动分析(一)

static int __init webcam_init(void) { return usb_composite_probe(&webcam_driver, webcam_bind); } static void __exit webcam_cleanup(void) { usb_composite_unregister(&webcam_driver); } 通过usb_composite_probe()函数将usb_composite_driver结构体和webcam_bin.

m0_56354240的博客 1612

Proteus仿真AT89C51驱动DHT11:温湿度数据采集与LCD1602显示的5个调试坑点总结

本文总结了在Proteus仿真环境下使用AT89C51驱动DHT11温湿度传感器并通过LCD1602显示的5个常见调试坑点,包括DHT11时序问题、LCD1602初始化错误、数据校验失败、仿真特有差异及系统稳定性问题,提供了详细的解决方案和优化代码示例,帮助开发者高效完成温湿度采集项目。

weixin_30335575的博客 355

USB协议 - UVC标准协议规范(二)

USB协议-UVC标准协议规范(二)1.概述2.UVC功能特征2.1 Video Interface Class2.2 Video Interface subclass and Protocol2.3 UVC功能拓扑2.3.1 Unit单元2.3.1.1 SU(选择器单元)2.3.1.2 PU(处理单元)2.3.1.3 EU(编码单元)2.3.1.4 XU(扩展单元)2.3.2 Teminals端点2.3.2.1 IT(Input Terminal)2.3.2.2 OT(Output Terminal)2.

sevenjoin的博客 1万+

Python+Vue计算机毕业设计风电场监控系统的设计与实现7bd6i(程序+LW+源码+部署)

Python3.7.7+Django+Mysql5.7+pip list+HBuilderX(Vscode也行)+Vue+Pychram社区版。2. 前端:vue+css+javascript+jQuery+easyUI+highcharts。2.IDE环境:Python和Python 社区版都可以。Django + Vue +Python+Mysql 等等组成,B/S模式等等。该项目含有源码、文档、程序、数据库、配套开发软件、软件安装教程。1. 后端:Python、Vue、Django、Mysql。

华信计算机毕设源码程序 341

camera 知识速查

本文总结了Camera开发中的常见问题排查方法和关键技术点。主要内容包括:I2C/MIPI不通的排查步骤、时序问题分析方法、Sensor/AF/Flash/PDAF的Bring Up流程、OTP调试方法、PDAF原理及调试、CTS/ITS问题解决思路、AE震荡解决方案、Systrace性能分析方法、Flicker产生原理、Tombstone问题定位等。还涉及V4L2框架解析、问题定位分层方法、Sensor Setting注意事项、时钟信号概念、第三方应用卡顿排查、大光圈概念、Monkey测试方法。

qq_41665131的博客 783
上一篇: i2c协议
下一篇: i2s总线规范
LinuxWorking
博客等级 码龄10年 24粉丝 32原创
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值