webrtc QOS方法二.3(flexfec rfc8627简介)

本文详细介绍了WebRTC中两种冗余编码技术——UlpFEC和FlexFEC的工作原理、区别及优缺点。FlexFEC在1D行、列、2D数组异或模式下提供保护,而UlpFEC存在与媒体报文混淆导致带宽浪费的问题。目前,WebRTC更倾向于使用FlexFEC,但其源码设计仍有待优化以支持更多报文的冗余保护。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、背景介绍

WebRTC实现的冗余方式有三种:UlpFEC(rfc5109)、FlexFEC(rfc8627)、inbandFEC(opus音频使用)。

UlpFEC和FlexFEC实现的原理都是,将一组M个报文进行异或,生成N(N就是FEC的冗余度)个FEC报文,打包出去。这组报文任意丢其中的N个,都可以通过这组(M-N)个报文+FEC冗余包恢复回来,增大FEC冗余报文的保护范围。例如下面示意图:D为媒体包,R为冗余包,该图所示的冗余度为2。

1、发送端打包示意图

 2、网络丢包示意图

 3、报文恢复示意图

二、FlexFec VS UlpFEC

媒体包打包格式FEC SSRCFEC Sequence
UlpFECrfc2198+rfc5109同媒体报文SSRC与媒体报文共享Sequence
FlexFECrfc8627单独SSRC使用独立的Sequence

1、WebRTC H264在封装上只有一层Sequence,依靠Sequence连续来完判断是否是完整视频帧,没有更多信息的封装,导致如果FEC报文数据在一帧的包中间,这样的判断逻辑就会有问题。而VPX,除了Sequence,还有PictureId等比较多的边界信息和类型信息,可以很好的解码FEC包。所以WebRTC默认只有在VPX时才启用UlpFEC。

MaybeCreateFecGenerator
->ShouldDisableRedAndUlpfec
->PayloadTypeSupportsSkippingFecPackets

默认只有VPX支持UlpFEC冗余编码。 

bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name,
                                           const WebRtcKeyValueConfig& trials) {
  const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
  if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
    return true;
  }
  if (codecType == kVideoCodecGeneric &&
      absl::StartsWith(trials.Lookup("WebRTC-GenericPictureId"), "Enabled")) {
    return true;
  }
  return false;
}

 2、实际上UlpFEC的SSRC同媒体报文的SSRC,且Sequence和媒体报文是共享的,这样会导致在开启UlpFEC时,无法区分媒体报文还是FEC报文,在开启NACK时使FEC冗余包也会NACK重传,会导致一定程度上的带宽浪费。

所以目前大家都比较优选FlexFEC冗余编码,比较少使用UlpFEC冗余编码。

三、FlexFEC原理

1、冗余模式

按照rfc8627协议建议,FlexFEC可以在1D行、列、2D数组异或,三种编码模式。

1)1D行异或模式

 2)1D列异或模式

 3)2D数组异或模式

但是Webrtc源码仅实现了MaskRandom、MaskBursty或1D列异或冗余模式。

具体细节可参考PacketMaskTable::LookUp函数实现 

2、RTP包协议

1)完整RTP报文格式

2)FEC Header定义

webrtc并没有完全遵循RFC协议,而是自己自定义一套协议。该格式在flexfec_header_reader_writer.h头文件定义。

 mask掩码长度说明

// Size (in bytes) of packet masks, given number of K bits set.
constexpr size_t kFlexfecPacketMaskSizes[] = {2, 6, 14};

掩码用来标识改FEC冗余报文保护报文的列表。保护序列号列表的计算公式为:

SN base_i + mask对应为1的bit位置序号。 参见ForwardErrorCorrection::InsertFecPacket函数计算FEC冗余报文的保护队列序列号:

3、SDP协商

上面的示例可以看到,媒体视频rtp报文的pt值是100,flexfec冗余报文的PT值时110,媒体视频RTP报文的ssrc是1234,flexfec冗余报文的ssrc是2345。 

对应webrtc的实现代码如下:

1、PT值确定GetPayloadTypesAndDefaultCodecs

2、ssrc的确认 AddFecFrSsrc

四、代码实现

1、FlexFEC编码实现

1)FlexFEC生成和push pacer队列调用栈

2)FlexFEC报文生成流程

 

 

UlpfecGenerator::AddPacketAndGenerateFec函数走读说明:

目前webrtc限制,仅支持48bit的掩码(因为Kbit需要占位,48个报文打冗余的话,maskhead就是14字节),代码里面有一处不足,就是单帧视频报文数大于48的话,后续报文不会push到media_packets_队列,也就不会参与冗余。

WebRTC这样设计是考虑到UlpFEC不允许在一帧的包中间发送FEC报文,否则会影响接收端对帧的完整性判断。但是目前FlexFEC使用单独的SSRC和Sequence参数,这个问题可以天然解决。但是WebRTC源码没有同步更新设计。导致会出现概率情况下一帧报文中的部分报文不能进行FEC保护。

2、FlexFEC解码实现

<think>我们正在讨论WebRTC中的RED(Redundancy)机制。RED是一种用于音频的抗丢包技术,通过发送冗余编码来应对网络丢包。虽然用户的问题是关于视频传输的,但需要澄清:在WebRTC中,RED通常用于音频,而视频则使用其他机制(如FEC、NACK、PLI/FIR)。然而,根据引用[3]提到“音频RED”,我们可以推断用户可能混淆了音频和视频。但为了全面性,我们将解释音频RED的原理,并说明视频传输中类似的技术。 根据引用[3]: > 对抗丢包,WebRTCQos策略有,音频RED、NACK,FEC,PLI,FIR 这里明确提到“音频RED”,因此RED主要用于音频。但是,如果用户坚持要了解视频RED(尽管标准WebRTC视频传输不使用RED),我们可以讨论冗余思想在视频中的应用(例如通过FEC或重传)。 因此,回答将分为两部分: 1. 音频RED的原理和实现(标准用法) 2. 视频传输中类似的冗余机制(非RED,但思想类似) 注意:WebRTC视频传输通常不使用RED,而是使用FEC(前向纠错)、NACK(重传请求)和关键帧请求(PLI/FIR)等。 --- ### 一、音频RED(Redundant Audio Data)原理 RED是RTP音频负载的一种冗余编码方案(RFC 2198)。其核心思想是在当前音频包中携带之前一个或多个音频包的冗余副本。当网络发生丢包时,接收端可以使用冗余数据恢复丢失的包。 #### 1. RED封包格式 一个RTP包中可以包含多个冗余块,每个块可以是主编码数据或冗余数据。格式如下: - **RTP头部**:标准RTP头部,PT(Payload Type)字段设置为RED的负载类型(动态值,通过SDP协商)。 - **RED头部**:包含一个块头列表和可选的辅助信息。 - 块头列表:每个冗余块的头(1~3字节),描述块的类型、长度和时间戳偏移。 - 主数据块:当前时间戳的音频数据(主编码)。 - 冗余数据块:之前时间戳的音频数据(冗余编码,通常使用更低比特率的编码)。 **RED头部结构**(简化): ``` 0 1 2 3 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |F| block PT | timestamp offset | block length | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |F| block PT | ... (更多块头) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 主数据块(当前包) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 冗余数据块(前一个包) | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ``` - `F`:1位,指示是否还有后续块头(0表示还有,1表示最后一个块头)。 - `block PT`:7位,该块的负载类型(如OPUS、PCMA等)。 - `timestamp offset`:14位,相对于RTP头部时间戳的偏移量(以采样点为单位)。 - `block length`:10位,该块的长度(字节数)。 #### 2. RED工作流程 - **发送端**: 1. 对当前音频帧进行主编码(高质量)。 2. 将前一个音频帧进行冗余编码(低质量,如更低比特率)。 3. 将主编码数据(当前帧)和冗余编码数据(前一帧)打包到同一个RTP包中。 4. 设置RTP头部的PT为RED类型,并构造RED头部。 - **接收端**: 1. 收到RTP包后,根据PT判断为RED包。 2. 解析RED头部,提取主数据块和冗余数据块。 3. 若下一个包丢失(即当前包的主数据块对应的下一个包丢失),则使用当前包中的冗余数据块(它是前一个包的副本)来填补丢失的包。 4. 解码时优先使用主数据块,若主数据块对应的包丢失,则使用其他包中的冗余块恢复。 #### 3. 冗余策略 - **冗余层级**:可配置携带多级冗余(如最近1~3个包)。 - **编码选择**:冗余块通常使用低复杂度编码(如CELT、低比特率OPUS)以节省带宽。 - **带宽开销**:冗余数据增加带宽占用(例如,50%冗余意味着带宽增加50%)。 #### 4. WebRTC中的实现 - **启用条件**:通过SDP协商RED负载类型。例如: ```sdp a=rtpmap:111 red/8000/1 // 定义RED负载类型为111 a=fmtp:111 96/97 // 96为主编码类型(如OPUS),97为冗余编码类型 ``` - **配置参数**:在WebRTC中可通过`PeerConnection`配置编码器参数,设置冗余包数量。 - **源码位置**:WebRTC中RED编码/解码实现在`modules/audio_coding/neteq`和`modules/rtp_rtcp/source/rtp_format_red.[h/cc]`。 --- ### 、视频传输中的冗余机制(非RED) 视频数据量远大于音频,直接使用RED携带完整冗余帧会导致带宽剧增。因此,WebRTC视频采用以下冗余机制: #### 1. 前向纠错(FEC) - **原理**:发送原始数据包的同时发送冗余校验包(如XOR、Reed-Solomon编码)。当原始包丢失时,可通过校验包恢复。 - **实现**:WebRTC使用UlpFEC(Uneven Level Protection FEC)和FlexFECRFC 8627)。FlexFEC独立于RTP流发送,支持恢复连续丢包。 - **开销**:固定比例冗余(如10%~20%)。 #### 2. NACK重传 - **原理**:接收端检测到丢包后发送NACK报文请求重传。 - **适用场景**:低延迟、带宽充足且丢包率较低时(引用[3]提到“NACK:延时低,带宽够,少量随机的丢包”[^3])。 #### 3. 关键帧请求(PLI/FIR) - **原理**: - PLI(Picture Loss Indication):接收端通知发送端“画面不完整”,请求重发关键帧(I帧)[^3]。 - FIR(Full Intra Request):强制发送端生成关键帧(如新参与者加入时)[^3]。 - **适用场景**:大量丢包或解码失败时。 #### 4. 参考帧选择(RPS)与SVC - **RPS**:编码时选择参考帧,减少丢包传播。 - **SVC(可伸缩视频编码)**:将视频分为多层(基础层+增强层)。基础层丢失时可通过FEC保护,增强层可丢弃。 --- ### 三、视频传输中类似RED的冗余方案 尽管视频通常不使用RED,但某些场景下可采用: - **重传包(RTX)**:WebRTC定义RTX负载类型(RFC 4588),用于重传原始包。与RED不同,RTX是独立的重传流。 - **带内FEC**:将FEC数据与原始数据打包在同一包中(类似RED思想),但WebRTC未采用。 --- ### 四、RED的优缺点 | 优点 | 缺点 | |------|------| | 抗随机丢包(无需反馈) | 带宽开销大(冗余数据始终发送) | | 恢复延迟低(接收端即时恢复) | 不适用于突发丢包(冗余数据可能同时丢失) | | 实现简单 | 视频场景不适用(数据量大) | --- ### 五、相关问题 §§相关问题§§ 1. WebRTC中音频RED如何配置? 2. WebRTC视频传输如何选择FEC和NACK策略? 3. 如何评估RED对音频质量的影响? 4. WebRTCFlexFEC的实现原理是什么?</think>### WebRTC视频传输中RED机制的原理与实现 RED(Redundant Coding,冗余编码)是WebRTC中用于对抗网络丢包的关键技术,尤其在音频传输中广泛应用(引用[3]明确提到“音频RED”作为QoS策略之一[^3])。虽然RED主要面向音频,但其核心思想在视频传输中也有类似应用(如FEC冗余)。下面详细解析RED机制的原理和实现方式: --- ### 一、RED的核心原理 RED通过**发送冗余数据包**来提升抗丢包能力,其工作流程如下: 1. **冗余生成**: 发送端将当前数据包($P_n$)与之前的数据包($P_{n-1}$, $P_{n-2}$等)按特定算法组合,生成冗余包($R_n$)。 $$ R_n = f(P_n, P_{n-1}, ..., P_{n-k}) $$ 其中$k$为冗余层级(通常$k=1$或$2$)。 2. **并行传输**: 原始数据包和冗余包通过**不同网络路径**或**不同RTP包**发送(避免同时丢失)。 3. **丢包恢复**: 接收端检测到原始包丢失时,利用冗余包中的信息重建丢失数据: - 若$P_n$丢失,但$R_n$包含$P_n$的信息 → 直接恢复 - 若$P_n$丢失,但$R_{n+1}$包含$P_n$的信息 → 间接恢复 4. **带宽权衡**: 冗余数据增加带宽开销(典型冗余率$20\%-50\%$),但显著降低丢包影响(引用[3]指出需“冗余带宽够”时使用[^3])。 --- ### 、RED在WebRTC中的实现方式 #### 1. 音频RED实现(标准方案) 音频RED遵循**RFC 2198**标准,在RTP包中封装冗余数据: ```plaintext | RTP头部 | RED头部 | 主数据块 | 冗余数据块1 | 冗余数据块2 | ... ``` - **RED头部结构**: - 块PT(7位):冗余块的负载类型(如OPUS) - 时间戳偏移(14位):相对于主块的时间偏移 - 块长度(10位):冗余块字节数 **WebRTC源码关键位置**: - 编码器配置:`modules/audio_coding/audio_network_adaptor/` - RED封包逻辑:`modules/rtp_rtcp/source/rtp_sender_audio.cc` #### 2. 视频传输中的类RED机制 虽然视频不直接使用RED格式,但采用类似冗余思想: - **FEC(前向纠错)**: 生成奇偶校验包(类似RED冗余包),通过异或运算恢复丢失包: ```c // 伪代码:生成FEC冗余包 fec_packet = original_packet1 XOR original_packet2 ``` - **参考帧冗余**: 关键帧(I帧)复制到多个RTP包发送(类似RED的多级冗余),避免帧丢失导致解码中断(引用[3]的FIR/PLI策略与此相关[^3])。 **视频冗余源码位置**: - FEC生成:`modules/rtp_rtcp/source/flexfec_sender.cc` - 抗丢包策略:`modules/video_coding/utility/framerate_controller.cc` --- ### 三、RED的性能优化策略 1. **动态冗余调整**: 根据网络QoS动态改变冗余层级$k$: - 低丢包率:$k=0$(关闭冗余) - 高丢包率:$k=2$(双重冗余) ```mermaid graph LR A[网络监测] -->|丢包率<5%| B[k=0] A -->|丢包率5%-15%| C[k=1] A -->|丢包率>15%| D[k=2] ``` 2. **分层冗余**: 对关键数据(如音频SILK层、视频I帧)采用更高冗余级别。 3. **带宽自适应**: 冗余率$r$与可用带宽$B$的关系: $$ r = \min\left(0.5, \ \frac{B - B_{\text{min}}}{B_{\text{max}} - B_{\text{min}}}\right) $$ 当$B$接近$B_{\text{min}}$时关闭冗余(优先保流畅性)。 --- ### 四、RED的适用场景与限制 | **场景** | **效果** | **限制** | |-------------------------|------------------------------|------------------------------| | 随机单包丢失(<15%) | 恢复率>90% | 突发丢包时失效 | | 低延迟通信(<200ms) | 比NACK重传更快恢复 | 带宽开销增加20%-50% | | 移动网络(4G/5G) | 对抗信号波动 | 需终端支持RED解码 | > 注:引用[3]强调RED在“带宽够”时效果显著,高丢包场景需结合FEC/NACK[^3]。 --- ### 五、调试与验证 1. **Wireshark分析**: 过滤RTP包查看RED头结构:`rtp.payload_type == RED_PT` 2. **WebRTC日志**: 启用`rtc_event_log`查看冗余包统计: ```bash peerconnection.setOptions({rtcEventLog: true}); ``` ---
评论 15
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值