webrtc 视频传输Flexfec模块

FlexfecReceiver 和FlexfecSender 是webrtc用于处理视频FEC的接收和发送模块:

FlexfecReceiver 是 WebRTC 中用于处理 FlexFEC (Flexible Forward Error Correction) 接收逻辑的类。它的主要职责是接收包含媒体数据或 FlexFEC 冗余数据的 RTP 包,利用纠删码(Erasure Code)算法从冗余包中恢复丢失的媒体包,并将恢复后的包传递给上层模块进行解码和播放。

FlexfecSender 是 WebRTC 中用于生成 FlexFEC (Flexible Forward Error Correction) 冗余包的发送端类。它实现了 VideoFecGenerator 接口,负责接收原始的媒体 RTP 包,根据配置的保护参数(如 FEC 率、保护帧数),计算并生成对应的 FlexFEC 包,以增强视频流在网络丢包环境下的鲁棒性。

一、主要职责

1.1 接收端- FlexfecReceiver

1, FlexFEC 接收端:它是 RFC 8627 (FlexFEC) 标准在 WebRTC 中的实现部分。与传统的 ULPFEC 不同,FlexFEC 更灵活,支持保护多个媒体流、不同的保护等级以及更高效的编码方案。

2, 包恢复引擎:它内部维护一个缓冲区,收集到达的媒体包和 FEC 包。当收集到足够的数据时,它会尝试解码以恢复丢失的媒体包。

1.2 发送端- FlexfecSender

1, FEC 生成:作为视频发送流的一部分,它拦截发出的媒体包,缓冲它们,并在满足条件时生成纠错码(FEC)包。

2, FlexFEC 特定逻辑:与旧的 ULPFEC 不同,FlexFEC 支持更灵活的拓扑结构(例如一个 FEC 流保护多个媒体流,尽管当前实现主要关注单流保护),并使用不同的 RTP 头部扩展和 payload 格式。

3, 状态管理:维护 FlexFEC 流的 SSRC、序列号、时间戳偏移等状态,确保生成的 FEC 包符合 RTP 规范。

二、关键成员

2.1 接收端- FlexfecReceiver

cpp 复制代码
 private:
  // Config.
  const uint32_t ssrc_;
  const uint32_t protected_media_ssrc_;

  // Erasure code interfacing and callback.
  std::unique_ptr<ForwardErrorCorrection> erasure_code_
      RTC_GUARDED_BY(sequence_checker_);
  ForwardErrorCorrection::RecoveredPacketList recovered_packets_
      RTC_GUARDED_BY(sequence_checker_);
  RecoveredPacketReceiver* const recovered_packet_receiver_;

  // Logging and stats.
  Clock* const clock_;
  int64_t last_recovered_packet_ms_ RTC_GUARDED_BY(sequence_checker_);
  FecPacketCounter packet_counter_ RTC_GUARDED_BY(sequence_checker_);

  SequenceChecker sequence_checker_;

2.1.1 ssrc:

FlexFEC 流自身的 SSRC。用于识别哪些 RTP 包属于这个 FEC 流。

2.1.2 protected_media_ssrc_:

被保护的媒体流的 SSRC。FlexFEC 包是为了保护这个特定的媒体流而生成的。

2.1.3 erasure_code_ (std::unique_ptr<ForwardErrorCorrection>):

核心的纠删码算法实现对象。它负责执行具体的数学运算(如异或操作、矩阵运算等)来从冗余数据中重建原始数据。

2.1.4 recovered_packets_:

一个列表,用于暂存成功恢复出来的媒体包。

2.1.5 recovered_packet_receiver_:

回调接口指针。当有包被成功恢复后,FlexfecReceiver 会通过这个接口将包"发送"给上层(通常是 RtpVideoStreamReceiver 或类似的模块),以便将其插入抖动缓冲区或直接解码。

2.1.6 packet_counter_:

统计计数器,记录接收到的包数量、恢复的包数量等,用于生成 RTCP 报告或内部监控。

2.1.7 sequence_checker_:

线程安全检查器,确保该类的所有方法都在同一个线程序列上被调用,防止竞态条件。

2.1.8 统计信息 (GetPacketCounter)

返回 FecPacketCounter 结构体,包含:

  1. 接收到的媒体包数。

2 . 接收到的 FEC 包数。

  1. 恢复的媒体包数。

4 . 丢弃的包数(无法恢复或重复的)。

2.2 发送端- FlexfecSender

cpp 复制代码
 private:
  // Utility.
  Clock* const clock_;
  Random random_;
  int64_t last_generated_packet_ms_;

  // Config.
  const int payload_type_;
  const uint32_t timestamp_offset_;
  const uint32_t ssrc_;
  const uint32_t protected_media_ssrc_;
  // MID value to send in the MID header extension.
  const std::string mid_;
  // Sequence number of next packet to generate.
  uint16_t seq_num_;

  // Implementation.
  UlpfecGenerator ulpfec_generator_;
  const RtpHeaderExtensionMap rtp_header_extension_map_;
  const size_t header_extensions_size_;

  rtc::CriticalSection crit_;
  RateStatistics fec_bitrate_ RTC_GUARDED_BY(crit_);

2.2.1 配置与标识

• payload_type: FlexFEC 包使用的 RTP Payload Type。

• ssrc: FlexFEC 流自身的 SSRC。注意,FEC 流通常有独立的 SSRC,与被保护的媒体流不同。

• protected_media_ssrc_: 被保护的媒体流的 SSRC。在 FlexFEC 头中会引用这个 SSRC,告诉接收端这些冗余数据是给哪个流用的。

• mid: Media ID。用于 BUNDLE 策略下区分不同的媒体流。FlexFEC 包需要携带与媒体包相同的 MID 扩展。

• seq_num: FlexFEC 包的序列号计数器,独立于媒体流递增。

2.2.2 内部实现

• ulpfec_generator_ (UlpfecGenerator):

• 关键点:尽管类名是 FlexfecSender,但它内部复用了 UlpfecGenerator 的核心算法逻辑。

• FlexFEC 和 ULPFEC 在底层的纠删码数学运算(XOR 等)上是相似的。FlexfecSender 主要负责构建符合 FlexFEC 标准(RFC 8627)的 RTP 头部和 Payload 结构,而具体的"哪些包参与计算"、"如何生成冗余块"的逻辑委托给了 ulpfec_generator_。

• rtp_header_extension_map_ & header_extensions_size_:

• 用于正确构建 FlexFEC 包的 RTP 头部扩展。FlexFEC 包必须包含与媒体包一致的扩展(如 MID, Transmission Time Offset 等),以便接收端能正确关联和处理。

2.2.3 统计与工具

• fec_bitrate_ (RateStatistics): 统计当前 FEC 生成的比特率,用于监控带宽开销。

• random: 用于生成初始序列号或时间戳偏移的随机数,避免冲突。

• clock: 用于获取当前时间,计算比特率统计。

三,工作流程

3.1 接收端- FlexfecReceiver

3.1.1. 接收包 (OnRtpPacket)

这是入口函数,每当网络层收到一个 RTP 包(无论是媒体包还是 FlexFEC 包)时都会调用。

  1. 分类:判断包是属于媒体流还是 FlexFEC 流。

  2. 缓冲:调用 AddReceivedPacket 将包转换为内部格式并存储起来。

  3. 处理:调用 ProcessReceivedPacket。

• 如果是媒体包:检查是否之前因为丢失而被"占位",如果现在恢复了,则标记。

• 如果是 FEC 包:检查是否已经收集了足够的包(媒体+冗余)来进行一次解码操作。

3.1.2. 恢复逻辑 (ProcessReceivedPacket -> erasure_code_)

  1. ForwardErrorCorrection 模块会检查当前的包集合。

  2. 如果满足解码条件(例如,收到了 N 个包,其中包含 K 个媒体包和 M 个 FEC 包,且 K+M >= 原始媒体包总数),它就会执行恢复算法。

  3. 恢复出的新包会被放入 recovered_packets_ 列表。

3.1.3. 回调上层

  1. 一旦有包被恢复,FlexfecReceiver 会遍历 recovered_packets_。

  2. 对于每个恢复的包,调用 recovered_packet_receiver_->OnRecoveredPacket(...)。

  3. 上层模块拿到恢复的包后,会像处理正常接收到的包一样处理它(排序、去重、解码)。

3.2 发送端- FlexfecSender

3.2.1. 初始化:

  1. 构造函数中设置 FlexFEC 流的 SSRC、Payload Type、MID 等。

  2. 初始化内部的 ulpfec_generator_。

3.2.2. 设置保护参数 (SetProtectionParameters):

  1. 接收来自带宽估计模块或配置的策略。

  2. delta_params: 针对 P 帧/B 帧(差值帧)的保护参数(如 FEC 率 0.2 表示增加 20% 冗余)。

  3. key_params: 针对 I 帧(关键帧)的保护参数(通常关键帧更重要,保护率更高)。

  4. 这些参数会被传递给内部的 ulpfec_generator_。

3.2.3. 添加媒体包并生成 FEC (AddPacketAndGenerateFec):

  1. 当视频编码器产生一个 RTP 包时,调用此方法。

  2. 缓冲:将媒体包的信息(序列号、时间戳、大小等)添加到内部的 FEC 缓冲区。

  3. 触发判断:检查是否达到了生成 FEC 的条件(例如,累积了 N 个媒体包,或者时间窗口到期)。

  4. 生成:如果条件满足,调用内部生成器计算冗余数据。

  5. 存储:生成的 FlexFEC 包被存储在内部队列中,等待被取出发送。

3.2.4. 获取 FEC 包 (GetFecPackets):

  1. 发送线程调用此方法,获取所有已生成但尚未发送的 FlexFEC 包。

  2. 返回的包是完整的 RtpPacketToSend 对象,包含正确的 RTP 头、FlexFEC 头和冗余 Payload。

这些包随后会被送入网络发送队列。

3.2.5. 开销计算 (MaxPacketOverhead):

返回每个 FlexFEC 包的额外头部开销(字节数)。这有助于带宽控制器精确计算可用带宽,因为 FEC 包占用带宽但不携带新视频内容。

四,与ULPFEC 的区别的关系

4.1 接收端- FlexfecReceiver

webrc也实现了ULPFEC,UlpfecReceiver, 两者的区别为:

  1. UlpfecReceiver 处理旧的 ULPFEC (RFC 5109),通常只保护单个媒体流,且 FEC 头结构简单。

  2. FlexfecReceiver 处理新的 FlexFEC,支持更复杂的拓扑结构(如一个 FEC 流保护多个媒体流),效率更高,但实现也更复杂。

4.2 发送端- FlexfecSender

主要使用 UlpfecGenerator实现发生,当前模块复用了 UlpfecGenerator,但 FlexfecSender 在以下方面不同:

  1. RTP 头部: FlexFEC 使用特定的 Payload Type 和可能的头部扩展。

  2. SSRC: FlexFEC 有独立的 SSRC,而 ULPFEC 通常与媒体流共享 SSRC(通过 Marker Bit 或 Payload Type 区分,但在 WebRTC 旧实现中 ULPFEC 也有独立 SSRC,不过 FlexFEC 标准化了这一行为并增强了多流保护能力)。

  3. Payload 格式: FlexFEC 的冗余载荷格式遵循 RFC 8627,比 RFC 5109 (ULPFEC) 更灵活,支持更长的掩码和更复杂的保护结构。

五,与 ForwardErrorCorrection 的关系

主要是FlexfecReceiver接收端与 ForwardErrorCorrection的差别

  1. FlexfecReceiver 是管理层,负责包的收集、状态维护和回调。

  2. ForwardErrorCorrection 是算法层,只负责纯粹的数学恢复计算。

相关推荐
Kang.lee1 小时前
2026.6.4【MIPI C-PHY】C-PHY v2.1协议阅读后问题总结
音视频·soc·asic
AndyHuang19761 小时前
实战记录:如何在 Release 模式下成功调试 WebRTC 源码(解决断点失效问题)
webrtc
dualven_in_csdn4 小时前
h265视频的播放问题
音视频
企业老板ai培训6 小时前
2026中小企业AI应用落地白皮书:从AI短视频矩阵到数字人获客的破局增长趋势
人工智能·矩阵·音视频
换个昵称都难6 小时前
webrtc视频Ulpfec介绍
音视频·webrtc
MegaSig美格信6 小时前
非处方气导助听器音频测试解决方案
音视频·音频·健康医疗
CoderIsArt6 小时前
声纹识别与音频AI领域
人工智能·音视频
tedcloud1236 小时前
HyperFrames部署教程:用HTML生成MP4视频
前端·数据库·人工智能·html·音视频
美狐美颜SDK开放平台7 小时前
直播APP开发实战:第三方美颜sdk接入步骤与注意事项
人工智能·音视频·美颜sdk·第三方美颜sdk·短视频美颜sdk