SendSideBandwidthEstimation 是 WebRTC 中用于发送端带宽估计的核心类,它负责根据网络反馈(如丢包、延迟、接收端限制等)动态调整发送码率。以下是从六个维度对该类的源码和算法原理的详细分析:
一、核心功能
SendSideBandwidthEstimation 主要用于:
- 
带宽估计:根据网络反馈信息(如丢包率、延迟、接收端REMB等)动态估计可用带宽。 
- 
码率控制:设置发送码率的上限和下限,避免网络拥塞并充分利用带宽。 
- 
多算法融合:支持多种带宽估计算法(如基于延迟、基于丢包V1/V2、RTT退避等)。 
- 
状态跟踪:记录历史码率、丢包率、RTT等信息,用于后续估计。 
- 
事件日志:记录带宽更新事件,用于调试和监控。 
二、核心算法原理
- 基于丢包的带宽估计(Loss-Based)
- 
使用丢包率(fraction_loss)调整带宽: - 
低丢包(<2%):增加带宽(乘以1.08) 
- 
中丢包(2%~10%):保持当前带宽 
- 
高丢包(>10%):降低带宽(乘以 (512 - loss) / 512) 
 
- 
- 基于延迟的带宽估计(Delay-Based)
- 通过 delay_based_limit_接收来自 GCC 延迟控制模块的带宽建议。
- RTT退避机制(RttBasedBackoff)
- 当RTT超过设定阈值时,主动降低发送码率,避免网络拥塞。
- 链路容量跟踪(LinkCapacityTracker)
- 根据确认的速率和延迟估计值,动态更新对链路容量的估计。
- 多估计器融合
- 支持 V1 和 V2 两个版本的丢包带宽估计器,可根据实验配置选择使用哪一个。
三、关键数据结构
- LinkCapacityTracker
double capacity_estimate_bps_;
Timestamp last_link_capacity_update_;
DataRate last_delay_based_estimate_;- 用于跟踪链路容量,结合延迟估计和确认速率进行更新。
- RttBasedBackoff
TimeDelta rtt_limit_;
Timestamp last_propagation_rtt_update_;
TimeDelta last_propagation_rtt_;
Timestamp last_packet_sent_;- 用于在RTT过高时触发退避机制,降低发送码率。
- min_bitrate_history_
std::deque<std::pair<Timestamp, DataRate>> min_bitrate_history_;- 保存历史最小码率记录,用于平滑码率增长。
- loss_based_bandwidth_estimator_v1_ / v2
- 两个版本的丢包带宽估计器,V2 是更先进的实验版本。
四、核心方法详解
- UpdateEstimate(Timestamp at_time)
- 
核心更新方法,根据当前状态(丢包、延迟、RTT等)更新目标码率。 
- 
会调用各子估计器(丢包、延迟、RTT退避)并综合得出最终码率。 
- UpdatePacketsLost(int64_t packets_lost, int64_t number_of_packets, Timestamp at_time)
- 更新丢包统计信息,计算丢包率,并触发带宽更新。
- UpdateDelayBasedEstimate(Timestamp at_time, DataRate bitrate)
- 更新来自延迟控制模块的带宽建议。
- UpdateReceiverEstimate(Timestamp at_time, DataRate bandwidth)
- 更新接收端通过 REMB 或 TMMBR 通知的带宽限制。
- SetAcknowledgedRate(absl::optional<DataRate> acknowledged_rate, Timestamp at_time)
- 设置当前确认的传输速率,用于链路容量估计。
- UpdateTargetBitrate(DataRate new_bitrate, Timestamp at_time)
- 最终设置目标码率,并应用上下限限制。
五、设计亮点
- 多算法融合
- 支持延迟、丢包、接收端限制、RTT退避等多种信号进行带宽估计,鲁棒性强。
- 状态机管理
- 使用 uma_update_state_和uma_rtt_state_等状态变量管理不同阶段的统计日志。
- 历史窗口机制
- 使用 min_bitrate_history_保存最近一段时间的最小码率,用于平滑码率增长。
- 实验性功能支持
- 通过 FieldTrial支持动态配置不同算法(如V2丢包估计器、RTT退避参数等)。
- 链路容量自适应
- LinkCapacityTracker能根据实际确认速率和延迟估计动态调整对链路容量的估计。
六、典型工作流程
时序图

- 初始化阶段
- 
发送端调用 SetBitrates设置初始码率、最小码率和最大码率
- 
带宽估计模块初始化内部状态变量 
- 
返回初始目标码率给发送端 
- 数据发送与反馈循环
- 
发送端持续发送数据包,并通知带宽估计模块每个包的发送时间 
- 
接收端通过RTCP发送各种反馈信息(REMB、丢包报告、RTT等) 
- 
发送端收到反馈后调用相应的更新方法 
- 反馈处理
- 
REMB/TMMBR处理:更新接收端限制,应用目标限制 
- 
丢包报告处理:计算丢包率,触发带宽估计更新 
- 
RTT报告处理:更新RTT值,用于后续估计 
- 延迟估计更新
- 
延迟估计模块定期提供基于延迟的带宽估计 
- 
更新延迟限制和链路容量估计 
- 
应用目标限制 
- 确认速率更新
- 
发送端提供已确认的传输速率 
- 
更新内部确认速率变量 
- 
更新V1/V2估计器的确认速率信息 
- 定期带宽估计
- 
发送端定期调用 UpdateEstimate进行带宽估计
- 
根据当前状态选择不同的估计算法: - 
RTT退避(当RTT超过限制时) 
- 
启动阶段策略(前2秒且无丢包时) 
- 
V1估计器(如果就绪) 
- 
V2估计器(如果就绪) 
- 
传统丢包算法(作为后备) 
 
- 
- 
应用上下限限制,记录日志事件 
- 
返回更新后的目标码率给发送端 
- 路由变化处理
- 
当检测到路由变化时,重置所有状态变量 
- 
重新初始化V2估计器(如果需要) 
注释精要
// 更新目标码率,并应用上下限限制
void SendSideBandwidthEstimation::UpdateTargetBitrate(DataRate new_bitrate,
                                                      Timestamp at_time) {
  // 不超过上限(延迟限制、接收端限制、配置最大码率的最小值)
  new_bitrate = std::min(new_bitrate, GetUpperLimit());
  
  // 如果低于最小码率,记录警告并设置为最小码率
  if (new_bitrate < min_bitrate_configured_) {
    MaybeLogLowBitrateWarning(new_bitrate, at_time);
    new_bitrate = min_bitrate_configured_;
  }
  
  current_target_ = new_bitrate;
  MaybeLogLossBasedEvent(at_time); // 记录事件日志
  link_capacity_.OnRateUpdate(acknowledged_rate_, current_target_, at_time);
}
// 判断是否处于启动阶段(前2秒)
bool SendSideBandwidthEstimation::IsInStartPhase(Timestamp at_time) const {
  return first_report_time_.IsInfinite() ||
         at_time - first_report_time_ < kStartPhase;
}SendSideBandwidthEstimation是WebRTC中负责发送端带宽估计的核心组件。它通过综合处理接收端反馈(REMB、丢包率、RTT)、延迟估计和确认速率等多源信息,动态调整发送码率。采用多种算法(V1/V2丢包估计、RTT退避等)适应不同网络状态,在保证网络不拥塞的同时最大化带宽利用率,确保实时音视频传输的质量和流畅性。