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 是算法层,只负责纯粹的数学恢复计算。

相关推荐
开开心心就好31 分钟前
音频降噪剪辑工具,音量裁剪一键处理
运维·服务器·前端·spring·ocr·音视频·1024程序员节
AI视频工具指南4 小时前
AI视频的声音和画面怎么配合?先分清谁在传递信息
人工智能·aigc·音视频
辰辰观影6 小时前
无广告播放器推荐来啦
音视频
TrueDei6 小时前
GStreamer 使用 valve 分别控制音视频流的暂停与恢复
音视频
一条破秋裤7 小时前
基于 Hi3516CV610 的立定跳远视频测量系统调研与实施方案
arm开发·音视频
2601_966827458 小时前
视频里的特效字幕怎么翻译?外挂字幕与AI字幕一键处理教程
音视频
八月的雨季 最後的冰吻9 小时前
音视频面试--延迟优化
面试·职场和发展·音视频
智能直播10 小时前
MEDAI-W2_Tinyalsa音频_HDMI输出_CSDN文章
音视频·实时音视频·视频编解码
狗凯之家源码网1 天前
吃瓜主题 3.0 视频源码深度评测与实战指南
音视频
美狐美颜sdk1 天前
视频美颜SDK中的YUV与RGBA格式有什么区别?直播APP开发解析
人工智能·计算机视觉·音视频·美颜sdk·直播美颜sdk·视频美颜sdk