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

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

1. 核心功能

DelayBasedBwe (Delay-Based Bandwidth Estimation) 是基于延迟的带宽估计器,是 WebRTC Google Congestion Control (GoogCC) 算法的核心组件之一。其主要功能是通过分析网络数据包的到达时间差(包间延迟)来检测网络拥塞状态,并据此估算出当前可用的网络带宽。

  • 输入: 带有发送时间和接收时间的时间戳反馈。

  • 输出: 估算出的可用带宽值 (target_bitrate) 和当前的网络状态(如 kBwNormalkBwOverusingkBwUnderusing)。

  • 目标: 在避免网络拥塞的前提下,尽可能高效地利用可用带宽。

2. 核心算法原理

DelayBasedBwe 的实现基于以下算法和理论:

  1. 包组(Packet Group)与延迟梯度(Delay Gradient)

    • 算法将连续到达的数据包分组(默认组长为 5ms)。不是处理单个包,而是处理包组之间的延迟变化,这能提高抗噪声能力。

    • 计算连续包组的发送时间差 (send_delta) 和接收时间差 (recv_delta)。

    • 延迟梯度 = recv_delta - send_delta。如果网络排队延迟增加,接收时间差会大于发送时间差,导致延迟梯度为正;反之则为负。

  2. 趋势线估计(Trendline Estimation)

    • TrendlineEstimator 是核心的延迟增长检测器。

    • 它收集一系列延迟梯度样本,并通过线性回归拟合出一条“趋势线”。

    • 趋势线的斜率代表了排队延迟的变化趋势:

      • 正斜率: 延迟在持续增加,表明网络正在排队,可能正在拥塞(kBwOverusing)。

      • 接近零的斜率: 延迟稳定,网络状态正常(kBwNormal)。

      • 负斜率: 延迟在减少,网络队列正在排空,可能处于轻载状态(kBwUnderusing)。

    • 通过与动态调整的阈值进行比较,最终判断出当前的网络状态 (BandwidthUsage)。

  3. AIMD 速率控制(AIMD Rate Control)

    • 一旦 TrendlineEstimator 检测到状态变化,AimdRateControl 类就会根据状态来调整带宽估计值。

    • 加法增大(Additive Increase, AI): 在 kBwNormal 状态下,线性增加带宽估计值,以探测更多可用带宽。

    • 乘性减小(Multiplicative Decrease, MD): 在 kBwOverusing 状态下,乘性减小带宽估计值(通常减半),以快速缓解拥塞。

    • 保持(Hold): 在 kBwUnderusing 状态下,通常保持当前带宽估计值不变。

3. 关键数据结构

  1. DelayBasedBwe::Result

    • 带宽估计的结果容器。

    • bool updated: 估计值是否在此次更新中发生了变化。

    • DataRate target_bitrate: 计算出的目标码率。

    • BandwidthUsage delay_detector_state: 延迟检测器判断出的当前网络状态。

  2. BweSeparateAudioPacketsSettings

    • 配置项,决定是否对音频和视频流使用独立的过载检测器。

    • bool enabled: 功能开关。

    • int packet_threshold & TimeDelta time_threshold: 触发切换到音频检测器的条件(例如,连续收到 10 个音频包且超过 1 秒没收到视频包)。

  3. 内部状态成员

    • std::unique_ptr<InterArrivalDelta> video_inter_arrival_delta_: 处理视频包组间隔计算的类。

    • std::unique_ptr<TrendlineEstimator> video_delay_detector_: 视频流的延迟趋势线估计器。

    • std::unique_ptr<InterArrivalDelta> audio_inter_arrival_delta_ 和 audio_delay_detector_: 音频流的对应组件(如果启用分离检测)。

    • DelayIncreaseDetectorInterface* active_delay_detector_: 指向当前活跃的检测器(视频或音频)。

    • AimdRateControl rate_control_: 执行 AIMD 算法的速率控制器。

    • DataRate prev_bitrate_ & BandwidthUsage prev_state_: 保存上一次的估计值和状态,用于判断是否需要触发日志等事件。

4. 核心方法详解

  1. IncomingPacketFeedbackVector

    • 功能: 主入口方法。接收一个包含多个数据包反馈信息的向量,并触发处理流程。

    • 流程

      • 对反馈包按接收时间排序。

      • 遍历每个包,调用 IncomingPacketFeedback 进行处理。

      • 遍历过程中跟踪状态变化(如是否从 kBwUnderusing 恢复)。

      • 最后调用 MaybeUpdateEstimate 来综合所有信息并可能更新带宽估计值。

  2. IncomingPacketFeedback

    • 功能: 处理单个数据包反馈。

    • 流程

      • 超时检查与重置: 如果距离上次收到包超过 kStreamTimeOut (2秒),重置所有内部状态(inter_arrival 和 delay_detector),防止陈旧数据影响新估计。

      • 分离音频处理

        • 如果启用 (separate_audio_.enabled),会根据包是音频还是视频,选择对应的 inter_arrival 和 delay_detector

        • 如果长时间未收到视频包且收到大量音频包,会将 active_delay_detector_ 切换到音频检测器。

      • 计算包组增量

        • 调用 InterArrivalDelta::ComputeDeltas。该方法判断当前包是否属于一个新的包组。如果是,则计算新组与上一组之间的发送时间差、接收时间差和大小差。

      • 更新延迟检测器

        • 将计算出的增量(send_deltarecv_delta)传递给 TrendlineEstimator::Update

        • TrendlineEstimator 利用这些数据点更新其内部趋势线模型和状态。

  3. MaybeUpdateEstimate

    • 功能: 根据延迟检测器的当前状态、确认码率、探测码率等信息,决定是否以及如何更新最终带宽估计。

    • 流程

      • kBwOverusing (过载)

        • 如果已有确认码率 (acked_bitrate),并且速率控制器判断需要进一步降速 (TimeToReduceFurther),则调用 UpdateEstimate 进行降速。

        • 如果还没有确认码率但已有有效估计,则执行保守的降速(每 200ms 减半)。

      • 其他状态 (kBwNormal 或 kBwUnderusing)

        • 如果存在探测码率 (probe_bitrate),则直接使用探测结果,快速提升估计。

        • 否则,调用 UpdateEstimate 进行常规的 AI 增加或保持。

      • 事件记录: 如果估计值或状态发生变化,通过 RtcEventLog 记录带宽更新事件,用于调试和分析。

  4. UpdateEstimate

    • 功能: 桥梁方法。将延迟检测器的状态和可选的确认码率封装成 RateControlInput,传递给 AimdRateControl::Update 方法执行具体的 AIMD 运算,并返回新的码率估计值。

5. 设计亮点

  1. 音频视频分离检测: 这是一个重要的优化。视频流通常量大且突发性强,而音频流量小且平稳。使用独立的检测器可以避免视频流的突发性掩盖音频流所经历的真实网络状态,从而在视频暂停(如语音通话时)也能做出更准确的带宽估计。

  2. 基于包组的处理: 处理包组而非单个包,有效平滑了网络抖动(Noise)带来的影响,提高了延迟趋势估计的鲁棒性。

  3. 模块化设计

    • InterArrivalDelta 负责包组划分和增量计算。

    • TrendlineEstimator 负责延迟趋势分析和状态判断。

    • AimdRateControl 负责基于状态的速率调整。

    • 这种设计使得算法各部件职责清晰,易于测试、维护和替换(例如,可以实现不同的 DelayIncreaseDetectorInterface)。

  4. 状态机管理: 清晰地维护了上一次的状态和码率,用于决策是否需要触发日志、更新等操作,保证了逻辑的严谨性。

  5. 外部参数化: 通过 FieldTrialsView 支持运行时配置(Field Trials),使得无需重新编译即可调整算法参数,便于大规模 A/B 测试和算法迭代。

6. 典型工作流程

  1. 接收反馈: 从网络接收带有发送和接收时间戳的 TransportPacketsFeedback

  2. 处理每个包: 对每个包反馈调用 IncomingPacketFeedback

    • 判断包所属的流(音/视频)并选择相应的检测器。

    • 与上一个包组比较,计算时间差。

    • 用时间差更新趋势线估计器。

  3. 状态判断: 趋势线估计器根据新的数据点更新其内部状态(正常、过载、欠载)。

  4. 更新带宽估计: 所有包处理完后,调用 MaybeUpdateEstimate

    • 速率控制器 (AimdRateControl) 根据当前网络状态、当前估计值、确认码率等,应用 AIMD 规则计算出新的带宽估计值。

  5. 返回结果: 将新的估计值、更新状态和网络状态封装在 Result 结构体中返回给上级调用者(如 GoogCcNetworkController)。

  6. 日志记录: 如果估计值或状态发生变化,记录事件以供后续分析。

7.流程图

整体流程图

  1. 接收数据包反馈信息

  2. 检查反馈是否有效

  3. 处理每个数据包,包括超时检查和音视频分离逻辑

  4. 计算包组时间差并更新延迟检测器

  5. 根据网络状态决定带宽调整策略

  6. 记录状态变化并返回最终结果

MaybeUpdateEstimate方法流程图

DelayBasedBwe(基于延迟的带宽估计)类是WebRTC拥塞控制的核心组件。它通过分析数据包到达延迟的变化趋势,检测网络拥塞状态(正常、过载或欠载),并基于AIMD(加法增大乘法减小)算法动态调整带宽估计值。该类支持音视频流分离检测,能够为实时通信提供准确的自适应码率控制,确保网络传输效率和质量。


文章转载自:

http://Tsx6tEZi.sqqds.cn
http://N2Wsk35D.sqqds.cn
http://loNaMxi9.sqqds.cn
http://HM5SGHiZ.sqqds.cn
http://hkZpDBPZ.sqqds.cn
http://at25ckOe.sqqds.cn
http://DOqnTRAF.sqqds.cn
http://5r6jgfC6.sqqds.cn
http://qdC5AL7I.sqqds.cn
http://jhfJQH3i.sqqds.cn
http://72BvZSEu.sqqds.cn
http://o5o0TZ0j.sqqds.cn
http://G29tdeOR.sqqds.cn
http://ZbtxHzyh.sqqds.cn
http://Y4mnHlWJ.sqqds.cn
http://bm1bzlzR.sqqds.cn
http://3NDWiZ9x.sqqds.cn
http://Kve66ZWw.sqqds.cn
http://psnwV51C.sqqds.cn
http://5G1hyvsd.sqqds.cn
http://tsEsmtQO.sqqds.cn
http://fwuxdSk4.sqqds.cn
http://JlgxAGKL.sqqds.cn
http://8SqDjHRa.sqqds.cn
http://O9tdje8Z.sqqds.cn
http://uKGU7JtB.sqqds.cn
http://BWHdG6Ld.sqqds.cn
http://sisoEQSF.sqqds.cn
http://LTySF8Dx.sqqds.cn
http://VuHz9sju.sqqds.cn
http://www.dtcms.com/a/376040.html

相关文章:

  • 【Floor报错注入】
  • Docker生产部署
  • 小型语言模型:智能体AI的未来?
  • js垃圾回收机制
  • STM32开发(USART总线:UART总线)
  • Typescript - 通俗易懂的 interface 接口,创建接口 / 基础使用 / 可选属性 / 只读属性 / 任意属性(详细教程)
  • FastGPT源码解析 Agent 智能体应用创建流程和代码分析
  • [网络入侵AI检测] 模型性能评估与报告
  • chmod与chown命令的深度解析
  • 7层的API网关
  • 链表问题:LeetCode 两数相加 - 算法解析与详解
  • 类型别名(type)与接口(interface)的抉择
  • 4.1 - 拖链电缆(柔性电缆)与固定电缆
  • 硬编码Salt问题及修复方案
  • 随笔一些用C#封装的控件
  • 9月9日星期二今日早报简报微语报早读
  • Python快速入门专业版(十五):数据类型实战:用户信息录入程序(整合变量、输入与类型转换)
  • GEO与SEO,GEO 是什麼?SEO + AI = GEO 生成式搜尋引擎優化 全解析
  • Asp .Net Core 系列:Asp .Net Core 集成 Hangfire+MySQL
  • 如果服务端有数据更新,浏览器缓存同时也没有过期,如何直接使用最新的数据
  • 使用java编写一个基础的彩票抽奖程序
  • 算法题 Day5---String类
  • 【靶场练习】--DVWA第二关Command Injection(命令执行)全难度分析
  • 什么是Adobe Analytics?数据驱动营销的关键工具​
  • 使用Docker搭建MaxKB智能体平台
  • 【链表】3.重排链表(medium)
  • 免费!离线!免安装!Windows文件夹隐藏工具
  • 联邦学习及其相关创新SCI辅导
  • 466章:Python Web爬虫入门:使用Requests和BeautifulSoup
  • ES8集群部署与使用-zookeeper集群部署与使用