webrtc 音频模块FEC模块

FecControllerPlrBased 模块是 WebRTC 音频网络适配器(Audio Network Adaptor, ANA)中的一个控制模块。它的核心职责是根据网络丢包率(Packet Loss Rate, PLR)和上行带宽动态决定是否启用前向纠错(FEC)。

FEC 是一种通过发送冗余数据来对抗网络丢包的技术,但它会占用额外的带宽。因此,需要在"抗丢包能力"和"带宽消耗"之间取得平衡。这个类就是用来做这个权衡决策的。

该模块通过这种动态、滞后的策略,确保了在网络波动时音频质量的稳定性,同时避免了不必要的带宽浪费。

一、滞后阈值(Hysteresis)

为了防止 FEC 状态在"开启"和"关闭"之间频繁震荡(Flapping),该类使用了两条不同的阈值曲线,形成一种滞后机制:

1, fec_enabling_threshold (开启阈值):

• 当当前丢包率 高于 这条曲线时,决定开启 FEC。

• 这条曲线通常较高,意味着只有当网络状况较差(丢包多)且带宽允许时,才愿意付出带宽代价去开启 FEC。

2, fec_disabling_threshold (关闭阈值):

• 当当前丢包率 低于 这条曲线时,决定关闭 FEC。

• 这条曲线通常较低,意味着只有当网络状况明显好转(丢包很少)时,才关闭 FEC 以节省带宽。

3,说明

复制代码
packet-loss ^   |  |
            |   |  |   FEC ON (区域)
            |    \  \   
            | FEC \  \_______ fec_enabling_threshold (高阈值)
            | OFF  \_________ fec_disabling_threshold (低阈值)
            |-----------------> bandwidth

• 如果当前状态是 FEC OFF,必须等到丢包率超过上方的 enabling 曲线才会切换为 ON。

• 如果当前状态是 FEC ON,必须等到丢包率降到下方的 disabling 曲线以下才会切换为 OFF。

• 在两条曲线之间的区域,保持当前状态不变。

二、关键成员变量

2.1 config:

• 存储配置信息,包括初始状态、两条阈值曲线以及平滑滤波器的时间常数。

cpp 复制代码
struct Config {
  // |fec_enabling_threshold| defines a curve, above which FEC should be
  // enabled. |fec_disabling_threshold| defines a curve, under which FEC
  // should be disabled. See below
  //
  // packet-loss ^   |  |
  //             |   |  |   FEC
  //             |    \  \   ON
  //             | FEC \  \_______ fec_enabling_threshold
  //             | OFF  \_________ fec_disabling_threshold
  //             |-----------------> bandwidth
  Config(bool initial_fec_enabled,
         const ThresholdCurve& fec_enabling_threshold,
         const ThresholdCurve& fec_disabling_threshold,
         int time_constant_ms);
  bool initial_fec_enabled;
  ThresholdCurve fec_enabling_threshold;
  ThresholdCurve fec_disabling_threshold;
  int time_constant_ms;
};

2.2 fec_enabled_

• 当前 FEC 的状态标志(true/false)。

• 当前的估计上行带宽。阈值曲线是带宽的函数,因为带宽越高,我们越能承受 FEC 带来的额外开销。

2.4 packet_loss_smoother_ (SmoothingFilter)

• 平滑滤波器。网络报告的丢包率通常是瞬时且波动的。直接使用原始丢包率会导致决策不稳定。

• 这个滤波器对丢包率进行指数加权移动平均(EWMA),提供一个更平滑、更稳定的丢包率估值用于决策。

• time_constant_ms 决定了平滑的程度:时间常数越大,反应越慢但越稳定;时间常数越小,反应越快但易受噪声影响。

三, 主要方法

3.1 UpdateNetworkMetrics(const NetworkMetrics& network_metrics):

• 输入更新。从 ANA 的其他部分接收最新的网络统计数据。

• 提取上行带宽 (uplink_bandwidth_bps)。

• 提取原始丢包率,并通过 packet_loss_smoother_ 进行平滑处理,得到用于决策的有效丢包率。

3.2 MakeDecision(AudioEncoderRuntimeConfig* config):

• 核心决策逻辑。这是 Controller 接口的实现,每帧或定期被调用。

• 它会根据当前的平滑丢包率和带宽,查询两条阈值曲线。

• 调用 FecEnablingDecision 或 FecDisablingDecision 来判断是否应该改变 fec_enabled_ 的状态。

• 最终将决策结果写入 config->enable_fec,从而指导音频编码器是否生成 FEC 数据。

3.3 FecEnablingDecision / FecDisablingDecision:

• 私有辅助函数,分别执行具体的比较逻辑:

1, FecEnablingDecision: 如果 !fec_enabled_ 且 smoothed_packet_loss > GetThreshold(bandwidth, enabling_curve),则返回 true。

2, FecDisablingDecision: 如果 fec_enabled_ 且 smoothed_packet_loss < GetThreshold(bandwidth, disabling_curve),则返回 true。

四、工作流程

  1. 初始化: 创建实例,设定初始 FEC 状态和阈值曲线。

  2. 监控: 每次收到网络指标更新 (UpdateNetworkMetrics),更新带宽估计,并平滑最新的丢包率样本。

  3. 决策: 在 MakeDecision 中:

• 根据当前带宽,从 fec_enabling_threshold 曲线计算出"开启临界丢包率"。

• 根据当前带宽,从 fec_disabling_threshold 曲线计算出"关闭临界丢包率"。

• 如果当前 FEC 是关闭的,且平滑丢包率 > 开启临界值 -> 开启 FEC。

• 如果当前 FEC 是开启的,且平滑丢包率 < 关闭临界值 -> 关闭 FEC。

• 否则,保持现状。

  1. 执行: 将结果传递给音频编码器,编码器据此调整输出包的格式(是否包含冗余帧)。

五,为什么需要基于带宽的曲线?

FEC 会增加比特率。

• 低带宽时:即使丢包率稍高,也可能无法承受 FEC 带来的额外负载,否则会导致拥塞加剧。因此,低带宽下的开启阈值会设得很高(很难开启 FEC)。

• 高带宽时:有足够的余量容纳冗余数据,因此可以更早地开启 FEC 以保护音质。此时开启阈值会降低。

相关推荐
youngerwang2 小时前
【从搬运工到协处理器:网卡芯片架构、算法、验证与边缘演进深度剖析】
网络·算法·架构·芯片
qq_366566502 小时前
视频配音自动化Pipeline:TTS选型+音色克隆+批量处理(附完整代码)
自动化·新媒体运营·音视频·音频
智慧光迅AINOPOL4 小时前
校园在线巡课系统方案:督导全覆盖
网络·全光网解决方案·全光网·校园全光网·校园全光网解决方案
酉鬼女又兒4 小时前
零基础入门计算机网络:网络层核心任务、三大关键问题、两种服务类型与 TCP/IP 网际层协议体系全解析
服务器·网络·网络协议·tcp/ip·计算机网络·php·求职招聘
Urbano5 小时前
工装制作全流程科普:从面料到自动化生产
网络·人工智能
2401_868534785 小时前
网规笔记 | 真题解析:2018年11月软考网规-网络安全案例分析
网络
Gauss松鼠会5 小时前
【GaussDB】GaussDB重要通信参数汇总
服务器·网络·数据库·sql·性能优化·gaussdb·经验总结
超级无敌zhq6 小时前
后渗透痕迹清理:攻防对抗中的隐身术
网络·数据库·网络安全
“初生”6 小时前
Codex 桌面端新会话 5 次 Reconnecting 怎么办?HTTP/SSE 完美修复方案(2026最新)
网络·网络协议·http