WebRTC Packet Buffer
Abstract |
WebRTC Packet Buffer |
Authors |
Walter Fan |
Status |
v1.0 |
Updated |
2026-08-17 |
概述
从网络上收到的 RTP 包可能会丢失、乱序或延迟到达。 为了在不稳定的网络条件下保证音视频播放的流畅性,接收端需要缓冲区(Jitter Buffer)来:
重新排序乱序的 RTP 包
等待延迟到达的包(在一定时间窗口内)
组装完整的视频帧(从多个 RTP 包中)
为丢包恢复(NACK/FEC)提供时间
flowchart LR
Net["网络 乱序/丢包"] --> PB["Packet Buffer<br/>排序/组帧/等待"]
PB --> Dec["解码器 完整帧"]
P1["RTP: 3,1,5,2,4"] --> Sort["排序: 1,2,3,4,5"]
Sort --> F1["Frame 1: pkt 1,2,3"]
Sort --> F2["Frame 2: pkt 4,5"]
视频 Packet Buffer
视频帧通常由多个 RTP 包组成(一个 1080p 关键帧可能拆分为几十个 RTP 包)。 视频 Packet Buffer 需要将这些包重新组装为完整的帧。
关键类
类 |
说明 |
|---|---|
|
通用视频包缓冲区,负责收集 RTP 包并按序号排列,检测帧边界后组装为完整帧 |
|
H.264 专用扩展,处理 H.264 特有的分片(FU-A)和聚合(STAP-A)NAL 单元 |
|
建立帧间参考关系(I/P/B 帧依赖),确定帧的解码顺序 |
PacketBuffer 工作流程
flowchart TD
A[RTP 包到达] --> B[按序号插入环形缓冲区]
B --> C["检测帧边界 RTP Marker bit = 1"]
C --> D[向前搜索帧的第一个包]
D --> E{完整?}
E -->|是| F[组装帧输出]
E -->|否| G[等待/请求 NACK]
核心代码逻辑:
// 简化的 PacketBuffer 插入逻辑
InsertResult PacketBuffer::InsertPacket(std::unique_ptr<Packet> packet) {
uint16_t seq_num = packet->seq_num;
size_t index = seq_num % buffer_size_;
buffer_[index] = std::move(packet);
// 如果 Marker bit 为 1,尝试向前找到帧的起始包
if (buffer_[index]->marker_bit) {
return FindFrames(seq_num);
}
return InsertResult();
}
音频 Jitter Buffer
音频的 Jitter Buffer 通常独立于视频,因为音频帧较小(一个 Opus 帧通常只有一个 RTP 包) 且对延迟更敏感。
WebRTC 中音频 Jitter Buffer 的核心实现是 NetEQ,它不仅负责缓冲, 还集成了丢包隐藏(PLC)、加速播放、减速播放等功能。
详细内容参见 Jitter Buffer 和 WebRTC NetEQ 深度解析。
关键参数
参数 |
说明 |
|---|---|
Buffer 大小 |
环形缓冲区槽位数,默认 2048。过小会导致帧不完整,过大会增加内存占用 |
最大等待时间 |
等待缺失包的最长时间。超时后放弃等待,触发 NACK 或 PLC |
解码顺序 |
视频帧需要按解码顺序(DTS)输出,而非按到达顺序(PTS 可能不同) |