RembThrottler在WebRTC中承担REMB消息的智能节流控制角色。它通过双重节流机制(200ms时间窗口+3%变化阈值)来平衡带宽估计的准确性和控制信令的开销。当接收端带宽变化较小时抑制不必要的REMB发送,避免网络拥塞;当带宽显著下降或超过时间间隔时及时通知发送端调整码率。这种设计既确保了拥塞控制的实时性,又避免了因频繁发送控制消息而加重网络负担,在维持视频质量稳定性和网络效率间取得了重要平衡。
一. 核心功能
RembThrottler 是一个REMB消息节流器,主要用于:
-
控制RTCP REMB(Receiver Estimated Maximum Bitrate)消息的发送频率
-
防止因带宽估计频繁变化导致的过多REMB消息
-
在带宽显著变化时及时通知发送端调整码率
二. 核心算法原理
采用时间窗口+变化阈值的双重节流机制:
-
时间窗口:确保REMB消息发送间隔至少200ms
-
变化阈值:只有带宽变化超过3%时才立即发送,避免微小波动
三. 关键数据结构
class RembThrottler : public RemoteBitrateObserver {
private:
const RembSender remb_sender_; // REMB发送回调函数
Clock* const clock_; // 时间时钟
mutable Mutex mutex_; // 线程安全锁
Timestamp last_remb_time_; // 上次发送REMB的时间
DataRate last_send_remb_bitrate_; // 上次发送的REMB码率值
DataRate max_remb_bitrate_; // 最大允许的REMB码率
};
四. 核心方法详解
4.1 构造函数
RembThrottler::RembThrottler(RembSender remb_sender, Clock* clock)
: remb_sender_(std::move(remb_sender)), // 保存REMB发送器
clock_(clock),
last_remb_time_(Timestamp::MinusInfinity()), // 初始化为最小值
last_send_remb_bitrate_(DataRate::PlusInfinity()), // 初始化为最大值
max_remb_bitrate_(DataRate::PlusInfinity()) {} // 初始化为最大值
4.2 接收码率变化处理
void RembThrottler::OnReceiveBitrateChanged(const std::vector<uint32_t>& ssrcs,
uint32_t bitrate_bps) {
DataRate receive_bitrate = DataRate::BitsPerSec(bitrate_bps);
Timestamp now = clock_->CurrentTime();
{
MutexLock lock(&mutex_);
// 节流条件:如果码率增长不超过3%且在200ms时间窗口内,则抑制发送
const int64_t kSendThresholdPercent = 103;
if (receive_bitrate * kSendThresholdPercent / 100 >
last_send_remb_bitrate_ &&
now < last_remb_time_ + kRembSendInterval) {
return; // 满足节流条件,不发送REMB
}
// 更新发送时间和码率
last_remb_time_ = now;
last_send_remb_bitrate_ = receive_bitrate;
// 确保发送码率不超过最大限制
receive_bitrate = std::min(last_send_remb_bitrate_, max_remb_bitrate_);
}
// 实际发送REMB消息
remb_sender_(receive_bitrate.bps(), ssrcs);
}
4.3 设置最大期望接收码率
void RembThrottler::SetMaxDesiredReceiveBitrate(DataRate bitrate) {
Timestamp now = clock_->CurrentTime();
{
MutexLock lock(&mutex_);
max_remb_bitrate_ = bitrate; // 更新最大码率限制
// 节流检查:如果在时间窗口内且上次发送码率已满足要求,则抑制发送
if (now - last_remb_time_ < kRembSendInterval &&
!last_send_remb_bitrate_.IsZero() &&
last_send_remb_bitrate_ <= max_remb_bitrate_) {
return;
}
}
// 发送新的REMB消息(空SSRC列表表示应用到所有流)
remb_sender_(bitrate.bps(), /*ssrcs=*/{});
}
五. 设计亮点
-
双重节流机制:结合时间窗口和变化阈值,平衡了响应速度和网络负载
-
线程安全:使用互斥锁保护共享状态,确保多线程环境下的安全性
-
回调模式 :通过
RembSender
函数对象实现松耦合,便于测试和扩展 -
资源优化:避免频繁的小幅度码率调整,减少不必要的网络开销
-
边界处理:合理处理初始状态和极端值情况
六. 典型工作流程
1. 接收端带宽估计模块检测到可用带宽变化
2. 调用OnReceiveBitrateChanged()传入新的带宽估计值
3. 节流器检查:
- 如果距离上次发送<200ms且变化<3%,抑制发送
- 否则,更新内部状态并发送REMB消息
4. 应用层可能通过SetMaxDesiredReceiveBitrate()设置最大限制
5. 节流器确保发送的REMB码率不超过应用层限制
6. 通过回调函数实际发送RTCP REMB包到发送端
这个设计在WebRTC中起到了重要的流量控制作用,既保证了带宽变化的及时反馈,又避免了因频繁发送控制消息而产生的额外网络负担。