当前位置: 首页 > java >正文

webrtc弱网-SendSideBandwidthEstimation类源码分析与算法原理

SendSideBandwidthEstimation 是 WebRTC 中用于发送端带宽估计的核心类,它负责根据网络反馈(如丢包、延迟、接收端限制等)动态调整发送码率。以下是从六个维度对该类的源码和算法原理的详细分析:

一、核心功能

SendSideBandwidthEstimation 主要用于:

  1. 带宽估计:根据网络反馈信息(如丢包率、延迟、接收端REMB等)动态估计可用带宽。

  2. 码率控制:设置发送码率的上限和下限,避免网络拥塞并充分利用带宽。

  3. 多算法融合:支持多种带宽估计算法(如基于延迟、基于丢包V1/V2、RTT退避等)。

  4. 状态跟踪:记录历史码率、丢包率、RTT等信息,用于后续估计。

  5. 事件日志:记录带宽更新事件,用于调试和监控。


二、核心算法原理

1. 基于丢包的带宽估计(Loss-Based)

  • 使用丢包率(fraction_loss)调整带宽:

    • 低丢包(<2%):增加带宽(乘以1.08)

    • 中丢包(2%~10%):保持当前带宽

    • 高丢包(>10%):降低带宽(乘以 (512 - loss) / 512)

2. 基于延迟的带宽估计(Delay-Based)

  • 通过 delay_based_limit_ 接收来自 GCC 延迟控制模块的带宽建议。

3. RTT退避机制(RttBasedBackoff)

  • 当RTT超过设定阈值时,主动降低发送码率,避免网络拥塞。

4. 链路容量跟踪(LinkCapacityTracker)

  • 根据确认的速率和延迟估计值,动态更新对链路容量的估计。

5. 多估计器融合

  • 支持 V1 和 V2 两个版本的丢包带宽估计器,可根据实验配置选择使用哪一个。


三、关键数据结构

1. LinkCapacityTracker

double capacity_estimate_bps_;
Timestamp last_link_capacity_update_;
DataRate last_delay_based_estimate_;
  • 用于跟踪链路容量,结合延迟估计和确认速率进行更新。

2. RttBasedBackoff

TimeDelta rtt_limit_;
Timestamp last_propagation_rtt_update_;
TimeDelta last_propagation_rtt_;
Timestamp last_packet_sent_;
  • 用于在RTT过高时触发退避机制,降低发送码率。

3. min_bitrate_history_

std::deque<std::pair<Timestamp, DataRate>> min_bitrate_history_;
  • 保存历史最小码率记录,用于平滑码率增长。

4. loss_based_bandwidth_estimator_v1_ / v2

  • 两个版本的丢包带宽估计器,V2 是更先进的实验版本。


四、核心方法详解

1. UpdateEstimate(Timestamp at_time)

  • 核心更新方法,根据当前状态(丢包、延迟、RTT等)更新目标码率。

  • 会调用各子估计器(丢包、延迟、RTT退避)并综合得出最终码率。

2. UpdatePacketsLost(int64_t packets_lost, int64_t number_of_packets, Timestamp at_time)

  • 更新丢包统计信息,计算丢包率,并触发带宽更新。

3. UpdateDelayBasedEstimate(Timestamp at_time, DataRate bitrate)

  • 更新来自延迟控制模块的带宽建议。

4. UpdateReceiverEstimate(Timestamp at_time, DataRate bandwidth)

  • 更新接收端通过 REMB 或 TMMBR 通知的带宽限制。

5. SetAcknowledgedRate(absl::optional<DataRate> acknowledged_rate, Timestamp at_time)

  • 设置当前确认的传输速率,用于链路容量估计。

6. UpdateTargetBitrate(DataRate new_bitrate, Timestamp at_time)

  • 最终设置目标码率,并应用上下限限制。


五、设计亮点

1. 多算法融合

  • 支持延迟、丢包、接收端限制、RTT退避等多种信号进行带宽估计,鲁棒性强。

2. 状态机管理

  • 使用 uma_update_state_ 和 uma_rtt_state_ 等状态变量管理不同阶段的统计日志。

3. 历史窗口机制

  • 使用 min_bitrate_history_ 保存最近一段时间的最小码率,用于平滑码率增长。

4. 实验性功能支持

  • 通过 FieldTrial 支持动态配置不同算法(如V2丢包估计器、RTT退避参数等)。

5. 链路容量自适应

  • LinkCapacityTracker 能根据实际确认速率和延迟估计动态调整对链路容量的估计。


六、典型工作流程

时序图

1. 初始化阶段

  • 发送端调用 SetBitrates 设置初始码率、最小码率和最大码率

  • 带宽估计模块初始化内部状态变量

  • 返回初始目标码率给发送端

2. 数据发送与反馈循环

  • 发送端持续发送数据包,并通知带宽估计模块每个包的发送时间

  • 接收端通过RTCP发送各种反馈信息(REMB、丢包报告、RTT等)

  • 发送端收到反馈后调用相应的更新方法

3. 反馈处理

  • REMB/TMMBR处理:更新接收端限制,应用目标限制

  • 丢包报告处理:计算丢包率,触发带宽估计更新

  • RTT报告处理:更新RTT值,用于后续估计

4. 延迟估计更新

  • 延迟估计模块定期提供基于延迟的带宽估计

  • 更新延迟限制和链路容量估计

  • 应用目标限制

5. 确认速率更新

  • 发送端提供已确认的传输速率

  • 更新内部确认速率变量

  • 更新V1/V2估计器的确认速率信息

6. 定期带宽估计

  • 发送端定期调用 UpdateEstimate 进行带宽估计

  • 根据当前状态选择不同的估计算法:

    • RTT退避(当RTT超过限制时)

    • 启动阶段策略(前2秒且无丢包时)

    • V1估计器(如果就绪)

    • V2估计器(如果就绪)

    • 传统丢包算法(作为后备)

  • 应用上下限限制,记录日志事件

  • 返回更新后的目标码率给发送端

7. 路由变化处理

  • 当检测到路由变化时,重置所有状态变量

  • 重新初始化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退避等)适应不同网络状态,在保证网络不拥塞的同时最大化带宽利用率,确保实时音视频传输的质量和流畅性。

http://www.xdnf.cn/news/18563.html

相关文章:

  • 手机横屏适配方案
  • 20250823给荣品RD-RK3588开发板刷Rockchip原厂的Buildroot【linux-5.10】时调通AP6275P的WIFI【源码部分】
  • ArkTS 语言全方位解析:鸿蒙生态开发新选择
  • 【AI基础:神经网络】17、神经网络基石:从MP神经元到感知器全解析 - 原理、代码、异或困境与突破
  • 线程间Bug检测工具Canary
  • uniapp 页面跳转及字符串转义
  • Redis学习笔记 ----- 缓存
  • rust语言 (1.88) egui (0.32.1) 学习笔记(逐行注释)(八)按键事件
  • 大语言模型应用开发——利用OpenAI函数与LangChain结合从文本构建知识图谱搭建RAG应用全流程
  • 【KO】前端面试七
  • 20250823给荣品RD-RK3588开发板刷Rockchip原厂的Android14【EVB7的V10】时调通AP6275P的WIFI
  • react相关知识
  • GitLab CI:Auto DevOps 全解析,告别繁琐配置,拥抱自动化未来
  • 运行npm run命令报错“error:0308010C:digital envelope routines::unsupported”
  • 二叉树的经典算法与应用
  • 【网安干货】--操作系统基础(上)
  • USRP采集的WiFi信号绘制星座图为方形
  • 新手向:异步编程入门asyncio最佳实践
  • K8s 实战:Pod 版本更新回滚 + 生命周期管控
  • 嵌入式学习日记(33)TCP
  • 【UnityAS】Unity Android Studio 联合开发快速入门:环境配置、AAR 集成与双向调用教程
  • CMake link_directories()详细介绍与使用指南
  • STM32F1 GPIO介绍及应用
  • C/C++三方库移植到HarmonyOS平台详细教程(补充版so库和头文件形式)
  • 凌霄飞控开发日志兼新手教程——基础篇:认识基本的文件内容和相关函数作用(25电赛备赛版)
  • 【序列晋升】12 Spring Boot 约定优于配置
  • Spring发布订阅模式详解
  • Python 调用 sora_image模型 API 实现图片生成与垫图
  • 【论文】Zotero文献管理
  • 为什么应用会突然耗尽所有数据库连接