1. USB 的时间基准
USB Host 周期性发送 SOF(Start‑Of‑Frame),用于维持总线时间基准和调度。
-
Full Speed
- 1 Frame = 1 ms
- 每秒 1000 个 Frame
-
High Speed
- 一个 USB Frame 被细分成 8 个 Microframe:
- 1 Frame = 1 ms
- 1 Microframe = 125 μs
- 每秒 8000 个 Microframe
- 一个 USB Frame 被细分成 8 个 Microframe:
High‑Speed 等时视频和音频,主要按照 Microframe 进行调度。
例如 bInterval = 1:
- 2^(1‑1) = 1 个 Microframe
- 即每 125 μs 获得一次服务机会。
如果 bInterval = 2:
- 2^(2‑1) = 2 个 Microframe
- 即每 250 μs 一次。
通用公式:
- 服务周期 = 2^(bInterval‑1) × 125 μs
- 每秒服务次数 = 8000 ÷ 2^(bInterval‑1)
2. Host 如何分配一个 Microframe
简化理解:
一个 125 μs Microframe
├─ SOF
├─ Isochronous 传输
├─ Interrupt 传输
├─ Control 传输
└─ Bulk 传输
Host 通常优先安排周期性传输:
- Isochronous + Interrupt
剩余时间再用于:
- Control + Bulk
所以:
- 等时端点需要 Host 提前保留周期带宽。
- Bulk 使用剩余总线时间。
- 如果周期带宽不足,Host 可能拒绝启用某个 Alternate Setting。
- Linux 上可能表现为
-ENOSPC。 - Windows 可能无法启动摄像头或选择某个分辨率。
- Linux 上可能表现为
这里的 ENOSPC 不一定表示磁盘没空间,也可能表示 USB 调度中没有足够的周期带宽。
3. 等时端点容量公式
High‑Speed Isochronous Endpoint:
c
payload = wMaxPacketSize & 0x07FF;
encoded = (wMaxPacketSize >> 11) & 0x03;
transactions = encoded + 1;
每秒理论 Payload:
payload
× transactions
× 8000
÷ 2^(bInterval‑1)
4. bInterval 会直接降低容量
假设:
wMaxPacketSize = 0x1400- 每次服务最多:1024 × 3 = 3072 Byte
bInterval = 1
3072 × 8000 = 24.576 MB/s
bInterval = 2
每秒只有 4000 次服务:
3072 × 4000 = 12.288 MB/s
bInterval = 3
每秒只有 2000 次服务:
3072 × 2000 = 6.144 MB/s
因此分析等时端点时,必须同时看:
wMaxPacketSizebInterval
不能只看其中一个。
5. 为什么 480 Mbps 不等于 60 MB/s
纯数学换算:
480 Mbps ÷ 8 = 60 MB/s
但 60 MB/s 是物理线路比特率换算,不是视频数据可用带宽。
总线上还存在:
- Token Packet
- SOF
- CRC
- 包间隔
- 位填充
- USB 协议头
- UVC Payload Header
- 其他 Endpoint
- Hub 和 Host Controller 调度
- Control、Interrupt 及 Bulk 传输
- 错误和控制请求
此外,High‑Speed 等时端点单个 Microframe 最多 3 次、每次最多 1024 字节,因此单端点理论 Payload 上限为:
3072 × 8000 = 24.576 MB/s
远小于 60 MB/s。
6. 未压缩视频带宽
计算公式:
带宽 = 宽 × 高 × 每像素字节数 × 帧率
640×480 YUYV 30fps
YUYV 平均每像素 2 字节:
640 × 480 × 2 × 30 = 18,432,000 Byte/s = 18.432 MB/s
理论上需要:
0x1400→ 24.576 MB/s0x0C00只有 16.384 MB/s,不够。
1280×720 YUYV 30fps
1280 × 720 × 2 × 30 = 55.296 MB/s
超过单个 High‑Speed 等时端点的 24.576 MB/s 理论上限,因此无法直接这样设计。
1920×1080 YUYV 30fps
1920 × 1080 × 2 × 30 = 124.416 MB/s
USB 2.0 显然无法承载。
因此 USB 2.0 摄像头通常采用:
- 降低分辨率
- 降低帧率
- MJPEG 压缩
- H.264/H.265(但 Host 免驱兼容性需要另外考虑)
- 改用 USB 3.x Device 模式
7. MJPEG 带宽
MJPEG 每帧大小不固定,因此计算方式是:
平均带宽 = 平均 JPEG 帧大小 × 帧率
假设 720p MJPEG 平均一帧 120 KB:
120 KB × 30 ≈ 3.6 MB/s
即使加上 UVC Header 和 USB 开销,也明显低于 8.192 MB/s。
如果画面复杂时一帧涨到 300 KB:
300 KB × 30 ≈ 9 MB/s
此时 0x0400 对应的 8.192 MB/s 就可能无法及时发送,需要:
- 提高端点容量
- 降低 JPEG 质量
- 降低帧率
- 增加缓冲(但缓冲只能吸收短期抖动,不能解决长期平均带宽不足)
- 超时后丢弃旧帧
一个重要结论 :
Buffer 可以缓解瞬时峰值,但不能修复长期输入速率大于输出速率的问题。
如果编码器持续产生 10 MB/s,而 USB 只能发送 8 MB/s,队列一定会不断增长,最终耗尽内存。
8. UVC Payload Header 也占带宽
视频不是把纯 JPEG 数据直接塞进每个 USB Transaction。
每个 UVC Payload 通常包含:
UVC Payload Header
+ 一部分视频帧数据
Header 可能包含:
- Header 长度
- Frame Identifier(FID)
- End Of Frame(EOF)
- Presentation Time Stamp(PTS)
- Source Clock Reference(SCR)
- 错误标志
简化示例:
USB Payload
├─ UVC Header:2~若干字节
└─ JPEG Data:剩余空间
如果 Endpoint 一次最多承载 1024 字节,UVC Header 占 2 字节,那么真正用于图像数据的可能只有约 1022 字节。
因此,理论端点容量不是纯图像净带宽。
9. 音频带宽很小,但时序更严格
48 kHz、16‑bit、单声道:
48000 × 2 × 1 = 96000 Byte/s
每个 High‑Speed Microframe:
96000 ÷ 8000 = 12 Byte
也就是:
6 个采样 × 2 Byte = 12 Byte/Microframe
双声道:
12 × 2 = 24 Byte/Microframe
与视频相比,音频带宽很小。但音频非常在意:
- 每个周期应发送多少采样
- 设备采样时钟是否与 USB Host 时钟一致
- Buffer 是否欠载或溢出
- 长时间运行后是否积累时钟漂移
例如 44.1 kHz:
44100 ÷ 8000 = 5.5125 个采样/Microframe
不可能每个 Microframe 发送 5.5125 个采样,因此必须形成类似:
5、6、5、6、5、6......
的包大小变化,使长期平均采样率等于 44.1 kHz。
后续学习 UAC2 时会专门讲时钟域和反馈。
10. UVC + UAC 共享同一总线
假设:
- UVC 视频平均带宽:10 MB/s
- UAC 麦克风带宽:0.192 MB/s
不能只分别看它们是否能工作,还要计算总和:
10 + 0.192 = 10.192 MB/s
此外还有:
- USB 协议开销
- UVC Header
- UVC 状态 Interrupt Endpoint
- EP0 控制请求
- 同一 Host Controller 上的其他设备
- Host 与 UDC 的调度能力
如果视频 Endpoint 容量是 16.384 MB/s,平均看似足够,但项目中仍然不建议逼近理论上限。需要为复杂画面导致的 MJPEG 帧变大、调度抖动和用户态延迟留出余量。
11. 整条媒体链路都可能成为瓶颈
最终项目的数据链路是:
CSI 采集
↓
RGA 处理
↓
RKNN 推理
↓
MPP 编码
↓
用户态 UVC 程序
↓
UVC Gadget
↓
DWC3 UDC
↓
USB Host
实际帧率由最慢的一环决定。
假设各阶段最大处理速度:
| 阶段 | 最大处理速度 |
|---|---|
| CSI 采集 | 30 fps |
| RGA 处理 | 100 fps |
| RKNN 推理 | 25 fps |
| MPP 编码 | 60 fps |
| USB 输出 | 30 fps |
整条链路最多只能稳定在:
min(30, 100, 25, 60, 30) = 25 fps
增加 Buffer 只能降低短时抖动,不能让 25 fps 的 NPU 长期输出 30 fps。
Day 4 练习
练习 1:视频带宽
分别计算:
- 640×480 YUYV 15fps
- 1280×720 YUYV 15fps
- 1280×720 MJPEG 30fps,平均每帧 150 KB
- 1920×1080 MJPEG 30fps,平均每帧 300 KB
然后从下面选择理论上能够满足的最小端点容量:
0x0400→ 8.192 MB/s0x0C00→ 16.384 MB/s0x1400→ 24.576 MB/s- 无法满足
(暂时忽略协议开销。)
答:
640 × 480 × 2 × 15 = 9,216,000 Byte/s = 9.216 MB/s1280 × 720 × 2 × 15 = 27,648,000 Byte/s = 27.648 MB/s150 KB × 30 = 4.5 MB/s300 KB × 30 = 9 MB/s
练习 2:计算端点容量
给定:
wMaxPacketSize = 0x1200bInterval = 2
计算:
- 每次 Transaction 最大 Payload
- 每次服务包含几次 Transaction
- 每次服务最多多少字节
- 每秒服务多少次
- 每秒理论 Payload 是多少 MB/s
答:
0x1200的低 11 位:0x200 = 512字节- 每个 Microframe 包含 3 次 Transaction
- 单次服务最大字节数 =
512 字节 × 3 = 1536 字节 8000 ÷ 2 = 4000次512 × 3 × 4000 = 6.144 MB/s
练习 3:队列是否会增长
编码器持续输出:
- 平均 10 MB/s
USB 实际只能持续发送:
- 8 MB/s
回答:
- 每秒积压多少数据?
- 一个 20 MB 的 Buffer 最多多长时间会被填满?
- 增加到 100 MB Buffer 能不能从根本上解决问题?
- 对实时摄像头,队列快满时应该优先丢旧帧还是新帧?为什么?
答:
- 每秒积压数据 =
10 MB/s - 8 MB/s = 2 MB/s 20 MB ÷ 2 MB/s = 10 s- 不能,根本原因是输入速率大于输出速率,增加 100 MB 只能延缓时间
- 丢弃旧帧,用户关心的是"当前最新的画面"。旧帧数据即使发过去也已经过期失效,丢弃旧帧可以保证后续发送给用户的始终是最新帧。
练习 4:综合理解
- 为什么 480 Mbps 不能直接认为应用可以发送 60 MB/s?
- 为什么音频带宽很小,仍然容易出现爆音?
- 为什么 Buffer 能解决短期抖动,却不能解决长期速率不匹配?
- Host 为什么可能拒绝某个视频 Alternate Setting?
- 720p YUYV 30fps 为什么不适合 USB 2.0 High‑Speed UVC 等时传输?
答:
480 Mbps ÷ 8 = 60 MB/s,USB 数据传输包含大量的额外开销,如包头(PID)、地址与端点号、CRC 校验码、帧同步信号(SYNC)、SOF 包以及包间间隔(Inter‑packet Gap / EOP)。除去协议开销后,USB 2.0 High‑Speed 的实际有效数据吞吐量最高通常只有 35~45 MB/s 左右。- 极高的实时性要求,还有可能会出现时钟漂移。
- Buffer 的本质是一个平滑器/缓冲池。当数据输入或消费速率发生短暂的忽快忽慢(抖动)时,Buffer 可以通过暂存或补充数据来消除微小的时间差。无法解决长期速率不匹配:如果长期平均输入速率大于输出速率。
- USB 带宽预留限制(Bandwidth Reservation):USB 2.0 规范规定,等时传输(Isochronous)和中断传输(Interrupt)的总带宽占用不能超过单条总线可用带宽的 80%(针对 High‑Speed)。竞争与冲突:当设备请求选择某个 Alternate Setting 时,Host 的控制器驱动(HC Driver)会计算该 Setting 下端点所需的带宽(
wMaxPacketSize × 传输频率)。如果总线上已有其他高带宽设备(如 USB 音频、其他摄像头),导致剩余可用带宽不足,Host 就会拒绝该请求(返回错误码)。 - 720p YUYV 30fps 所需要的带宽(≈ 52.7 MB/s)远远超出了 USB 2.0 等时传输的极限能力(≈ 24.58 MB/s)。因此在 USB 2.0 下传输 720p 视频必须改用压缩格式(如 MJPEG 或 H.264)。