WebRTC Pacer
Abstract |
WebRTC Pacer 发送节奏控制 |
Authors |
Walter Fan |
Status |
v1.0 |
Updated |
2026-08-17 |
概述
Pacer(发送节奏控制器)是 WebRTC 拥塞控制中的关键组件。 它的核心作用是**将突发的编码输出平滑为均匀的发送速率**,避免网络瞬时拥塞。
没有 Pacer 的话,编码器输出一个关键帧(可能 50KB+)会一次性将所有 RTP 包发送出去, 造成网络突发拥塞和丢包。Pacer 则将这些包排入队列,按照目标比特率匀速发送。
flowchart LR
subgraph Burst[编码器输出 突发]
B1[大关键帧突发]
B2[普通帧]
end
subgraph Smooth[Pacer 输出 平滑]
S1[匀速发包]
end
Burst --> Smooth
在 WebRTC 中的位置
flowchart LR
Enc[编码器] --> RTP[RTP 打包]
RTP --> PQ[Pacer 队列]
PQ --> SRTP[SRTP 加密]
SRTP --> ICE[ICE/UDP 发送]
GCC[GCC 带宽估计] -->|设定发送速率| PQ
核心类
PacingController
PacingController 实现了 Leaky Bucket(漏桶)算法,是 Pacer 的核心逻辑:
维护一个按优先级排序的包队列
按照设定的发送速率(pacing rate)释放包
处理不同类型包的优先级调度
关键方法:
class PacingController {
public:
// 将包加入发送队列
void EnqueuePacket(std::unique_ptr<RtpPacketToSend> packet);
// 处理定时器触发,发送到期的包
void ProcessPackets();
// 设置发送速率(由 GCC 算法决定)
void SetPacingRates(DataRate pacing_rate, DataRate padding_rate);
// 设置是否允许探测式发送
void SetProbingEnabled(bool enabled);
// 暂停/恢复发送
void Pause();
void Resume();
};
RtpPacketPacer
TaskQueuePacedSender (旧版中为 RtpPacketPacer) 是 Pacer 的外层封装,
负责定时器调度和实际的包发送:
主要调用链:
flowchart TD
A["TaskQueuePacedSender::EnqueuePackets()"] --> B["PacingController::EnqueuePacket()"]
C["TaskQueuePacedSender::MaybeProcessPackets()"] --> D["PacingController::ProcessPackets()"]
D --> E["PacketRouter::SendPacket()"]
E --> F["ModuleRtpRtcpImpl::TrySendPacket()"]
包类型与优先级
Pacer 按照包类型分配不同的发送优先级:
static constexpr size_t kNumMediaTypes = 5;
enum class RtpPacketMediaType : size_t {
kAudio, // 音频包 (最高优先级)
kVideo, // 视频包
kRetransmission, // 重传包 (响应 NACK)
kForwardErrorCorrection, // FEC 包
kPadding = kNumMediaTypes - 1, // 填充包 (最低优先级)
};
发送优先级从高到低:
优先级 |
类型 |
说明 |
|---|---|---|
1 |
Audio |
音频包始终最高优先级,确保语音流畅 |
2 |
Retransmission |
NACK 重传包需要快速发送以降低恢复延迟 |
3 |
Video |
正常视频包 |
4 |
FEC |
前向纠错冗余包 |
5 |
Padding |
填充包,用于维持带宽估计探测 |
发送速率控制
Pacer 的发送速率由 GCC(Google Congestion Control)算法决定:
flowchart TD
A[GCC 估计可用带宽] --> B["设定 pacing_rate = estimated_bitrate × multiplier"]
B --> C[Pacer 按 pacing_rate 匀速发送]
C --> D{队列为空且带宽有富余?}
D -->|是| E[发送 padding 包探测更高带宽]
关键参数:
Pacing rate:通常是目标比特率的 2.5 倍(允许突发恢复,同时不过度占用带宽)
Padding rate:当没有媒体数据时的填充发送速率,用于保持带宽估计准确
Max queue time:队列中包的最大等待时间(默认 2 秒),超过则丢弃
// 典型配置
pacer->SetPacingRates(
DataRate::KilobitsPerSec(2500), // pacing rate: 2.5 Mbps
DataRate::KilobitsPerSec(200)); // padding rate: 200 kbps
Probe 探测
Pacer 还负责带宽探测(Probing)。在连接初期或带宽变化时, GCC 会要求 Pacer 以特定速率发送探测包来估算可用带宽:
flowchart TD
A[连接建立] --> B["Probe Cluster 1: 以 900 kbps 发送 5 个包"]
B --> C["Probe Cluster 2: 以 1800 kbps 发送 5 个包"]
C --> D[根据 TWCC 反馈计算实际可用带宽]
D --> E[进入正常 GCC 速率控制]
探测包优先使用排队中的媒体包,只在媒体包不足时才补充 padding。
与 GCC 的协作
flowchart LR
Enc[Encoder] -->|输出 RTP 包| Pacer[Pacer 排队加调度]
Pacer -->|发送| Net[Network]
Net --> Recv[Receiver]
Recv -->|TWCC/REMB 反馈| GCC[GCC 估计可用带宽]
GCC -->|设定速率| Pacer
参考资料
WebRTC 源码:
modules/pacing/目录