webrtc弱网-ReceiveSideCongestionController类源码分析及算法原理
ReceiveSideCongestionController是WebRTC接收端拥塞控制的核心枢纽,承担双模式带宽估计的关键职责。它通过智能算法切换机制,动态选择发送端BWE(基于TransportSequenceNumber的延迟反馈)或接收端BWE(基于AbsoluteSendTime/TOF的本地估计)模式。针对音频流强制使用发送端BWE确保低延迟,视频流则自适应选择最优路径。该组件集成RembThrottler进行码率限制,通过RemoteEstimatorProxy生成TransportFeedback,并采用精细的线程安全设计保护共享状态。最终通过REMB和TransportFeedback RTCP消息将网络状态反馈给发送端,实现端到端的拥塞控制闭环,确保实时通信的质量和稳定性。
一. 核心功能
接收端拥塞控制器是WebRTC中负责接收方带宽估计的关键组件,主要功能包括:
-
双模式带宽估计:支持发送端BWE和接收端BWE两种模式
-
反馈管理:通过TransportFeedback和REMB消息向发送端反馈网络状态
-
动态算法选择:根据RTP扩展头自动选择最优的带宽估计算法
-
码率控制:限制最大接收码率,避免网络拥塞
二. 核心算法原理
发送端BWE (Sender-side BWE)
详细见:https://blog.csdn.net/talkRTC/article/details/150635619?spm=1001.2014.3001.5501 // 基于TransportSequenceNumber的带宽估计 // 接收端记录包到达时间,通过TransportFeedback消息反馈给发送端 // 发送端基于这些信息进行带宽估计
接收端BWE (Receiver-side BWE)
// 两种估计算法: // 1. AbsoluteSendTime算法:基于绝对发送时间扩展头 // 2. SingleStream算法:基于传输时间偏移 // 算法根据数据包中的扩展头动态切换
算法原理图
1. 两种估计算法对比
特性 | AbsoluteSendTime算法 | SingleStream(TOF)算法 |
---|---|---|
时间基准 | 绝对发送时间戳 | 传输时间偏移 |
精度 | 高(24位, 约15μs) | 中等 |
同步要求 | 需要时钟同步 | 相对时间,不要求严格同步 |
适用场景 | 视频会议、实时通信 | 传统RTP流 |
2. 包分组处理
// 包组划分原则: // - 发送时间间隔 > 5ms 作为组边界 // - 每组包含多个连续包 // 计算组间延迟变化: 组间延迟梯度 = (到达时间差 - 发送时间差) / 发送时间差
3. 过载检测机制
基于Kalman滤波的延迟变化检测: 状态变量: [延迟梯度, 延迟变化率] 观测值: 实际测量的延迟梯度 检测逻辑:- 延迟梯度 > 阈值 + 方差: 过载- 延迟梯度 < -阈值: 欠载 - 其他: 正常
工作时序图
AST算法核心流程
// 1. 时间戳转换 absolute_send_time = 从RTP扩展头提取 send_time_24bits = (absolute_send_time * 1000) >> 18// 2. 包组检测 if (current_send_time - prev_send_time > 5ms) {// 新包组开始form_new_packet_group(); }// 3. 延迟计算 inter_arrival = current_arrival - prev_arrival inter_send = current_send - prev_send delay_gradient = inter_arrival - inter_send// 4. 状态判断 if (delay_gradient > threshold + noise_var) {state = OVERUSE; } else if (delay_gradient < -threshold) {state = UNDERUSE; } else {state = NORMAL; }
三. 关键数据结构
class ReceiveSideCongestionController { private:Clock& clock_; // 系统时钟RembThrottler remb_throttler_; // REMB码率限制器RemoteEstimatorProxy remote_estimator_proxy_; // 远程估计代理mutable Mutex mutex_; // 线程安全锁std::unique_ptr<RemoteBitrateEstimator> rbe_; // 远程带宽估计器bool using_absolute_send_time_; // 当前使用的算法标志uint32_t packets_since_absolute_send_time_; // AST算法包计数器 };
四. 核心方法详解
4.1 构造函数
ReceiveSideCongestionController::ReceiveSideCongestionController(Clock* clock,RemoteEstimatorProxy::TransportFeedbackSender feedback_sender,RembThrottler::RembSender remb_sender,NetworkStateEstimator* network_state_estimator): clock_(*clock),remb_throttler_(std::move(remb_sender), clock),remote_estimator_proxy_(std::move(feedback_sender), network_state_estimator),rbe_(new RemoteBitrateEstimatorSingleStream(&remb_throttler_, clock)),using_absolute_send_time_(false),packets_since_absolute_send_time_(0) {}
功能:初始化所有组件,默认使用SingleStream算法
4.2 包处理入口
void ReceiveSideCongestionController::OnReceivedPacket(const RtpPacketReceived& packet, MediaType media_type) {bool has_transport_sequence_number = packet.HasExtension<TransportSequenceNumber>() ||packet.HasExtension<TransportSequenceNumberV2>();if (media_type == MediaType::AUDIO && !has_transport_sequence_number) {// 音频流且无传输序列号,不支持接收端BWEreturn;}if (has_transport_sequence_number) {// 发送端BWE模式:转发包信息给远程估计代理remote_estimator_proxy_.IncomingPacket(packet);} else {// 接收端BWE模式:本地进行带宽估计MutexLock lock(&mutex_);PickEstimator(packet.HasExtension<AbsoluteSendTime>());rbe_->IncomingPacket(packet);} }
4.3 算法选择器
void ReceiveSideCongestionController::PickEstimator(bool has_absolute_send_time) {if (has_absolute_send_time) {// 发现AST扩展头,立即切换到AST算法if (!using_absolute_send_time_) {RTC_LOG(LS_INFO) << "切换到绝对发送时间RBE算法";using_absolute_send_time_ = true;rbe_ = std::make_unique<RemoteBitrateEstimatorAbsSendTime>(&remb_throttler_, &clock_);}packets_since_absolute_send_time_ = 0;} else {// 没有AST扩展头,等待一定包数后切回TOF算法if (using_absolute_send_time_) {++packets_since_absolute_send_time_;if (packets_since_absolute_send_time_ >= kTimeOffsetSwitchThreshold) {RTC_LOG(LS_INFO) << "切换到传输时间偏移RBE算法";using_absolute_send_time_ = false;rbe_ = std::make_unique<RemoteBitrateEstimatorSingleStream>(&remb_throttler_, &clock_);}}} }
4.4 周期处理
TimeDelta ReceiveSideCongestionController::MaybeProcess() {Timestamp now = clock_.CurrentTime();mutex_.Lock();TimeDelta time_until_rbe = rbe_->Process(); // 处理接收端BWEmutex_.Unlock();TimeDelta time_until_rep = remote_estimator_proxy_.Process(now); // 处理发送端BWE反馈TimeDelta time_until = std::min(time_until_rbe, time_until_rep);return std::max(time_until, TimeDelta::Zero()); // 返回下次处理时间 }
五. 设计亮点
5.1 智能算法切换
// 基于数据包特征自动选择最优算法 // AST算法优先,在没有AST时回退到TOF算法 // 切换阈值kTimeOffsetSwitchThreshold=30包,避免频繁切换
算法原理图:
5.2 双模式支持
// 统一处理发送端BWE和接收端BWE // 根据TransportSequenceNumber存在性自动路由 // 音频流特殊处理:仅支持发送端BWE
算法原理图
5.3 线程安全设计
// 使用Mutex保护共享状态 // RTC_GUARDED_BY(mutex_)注解明确线程约束 // 细粒度锁:仅保护接收端BWE相关状态
六. 典型工作流程
6.1 视频流处理(接收端BWE)
1. 收到视频RTP包 → 检查扩展头 2. 有AbsoluteSendTime → 选择AST算法 3. 调用rbe_->IncomingPacket()进行本地估计 4. 定期MaybeProcess()生成REMB反馈 5. 通过remb_throttler_发送码率限制
6.2 音频流处理
1. 收到音频RTP包 2. 必须有TransportSequenceNumber,否则跳过 3. 仅支持发送端BWE模式
这个设计体现了WebRTC拥塞控制的核心理念:灵活性和自适应性,能够根据网络条件和流类型自动选择最优的带宽估计策略。