FEC 前向纠错 · 不用往返就能恢复
重传要等一个往返,高延迟场景来不及。FEC 换个思路:提前发冗余包,收端丢了包能就地算回来,无需往返。这一章讲清 FEC 的异或恢复原理、ULPFEC 与 FlexFEC 两种实现、音频的 RED,以及 FEC 与重传「费带宽 vs 费往返」的权衡。
FEC 前向纠错 · 不用往返就能恢复
重传(NACK/RTX)有个软肋:要等一个 RTT。高延迟或急需低延迟时,重传来不及。FEC(Forward Error Correction,前向纠错) 换了个思路:提前多发点冗余,让接收端丢了包能自己算回来,根本不用往返。 这一章讲它。
思路:多发冗余,就地恢复
FEC 的核心:发送端在媒体包之外,额外发一些「冗余包」;接收端一旦丢了个别媒体包,能用收到的媒体包 + 冗余包就地算出丢失的那个,无需请对端重传。 最简单的形式是异或(XOR):发送端把几个媒体包异或出一个冗余包一起发。接收端若丢了其中一个媒体包,用「其余媒体包 + 冗余包」再异或一次,就恢复出丢失的那个——就像「已知 A⊕B⊕C=P,丢了 B,用 A⊕C⊕P 就能把 B 算回来」。
和重传一比,FEC 的取舍很清楚:它不需要往返(丢包当下就能恢复,零延迟),但恒定地多花带宽(不管丢不丢,冗余包都得发)。所以:低 RTT 用重传更省(丢了才重发),高 RTT / 高丢包用 FEC 更值(免往返,虽然费带宽)。WebRTC 常两者结合,按网络状况动态调冗余量。
两种实现:ULPFEC 与 FlexFEC
WebRTC 视频的 FEC 有两代实现(modules/rtp_rtcp/source/ 及相关):
| ULPFEC | FlexFEC | |
|---|---|---|
| 全称 | Uneven Level Protection FEC | Flexible FEC |
| 冗余包放哪 | 常和媒体捆在一起(经 RED 封装) | 独立的 RTP 流(自己的 SSRC) |
| 灵活性 | 保护模式较固定 | 灵活:可跨包、按行 / 列保护,适配不同丢包模式 |
| 现状 | 较老 | 较新(默认放低 PT 范围) |
ULPFEC 提供「不均等保护」——对一个包里更重要的部分给更强保护。FlexFEC(flexfec-03)更灵活,能配置成「保护连续 N 个包」或「按二维行列保护」,适应不同的丢包分布(突发连丢 vs 零星散丢),且走独立流不干扰媒体流。
音频的冗余:RED
音频对丢包的对抗,常用另一个更简单的机制——RED(Redundant Encoding,冗余编码,RFC 2198):
音频 RED 的做法:每个包里,除了当前这一小段音频,再捎带上前几段音频的副本**。** 音频包很小、间隔很密(如每 20ms 一个),所以在一个包里塞进「当前 + 前一两段」代价不大。于是丢了一个包,它携带的那段音频,很可能在下一个包里还带着一份副本,直接就补上了——听感上几乎无损。这比给音频做复杂 FEC 简单得多,对语音这种「丢一小段就卡顿」的媒体特别有效。Opus 编解码器本身还内建了 in-band FEC(在下一个包里编码一份上一包的低码率版本),和 RED 异曲同工。音频靠这些「顺手捎带冗余」的手段,对丢包的韧性其实比视频还好。
谁决定发多少 FEC
FEC 的冗余量不是固定的——发太多浪费带宽、发太少防不住丢包。由 FecController(可在工厂替换的 fec_controller_factory)根据当前的丢包率和可用带宽动态决定:网络好、丢包少,就少发甚至不发 FEC,把带宽全给媒体;丢包一上来,就加大冗余保护。这是又一个实时系统「随网况自适应」的体现——一切参数都在跟着网络实时调整。
小结与下一章
FEC 前向纠错用冗余包让接收端就地恢复丢包,免往返(对比重传要一个 RTT),代价是恒定多花带宽——故低 RTT 靠重传、高 RTT / 高丢包靠 FEC,常结合。原理是异或恢复。视频有 ULPFEC(捆媒体)和 FlexFEC(独立流、灵活)两代;音频用 RED(包里捎带前几段副本)+ Opus in-band FEC。冗余量由 FecController 按丢包动态调。
重传和 FEC 都是「对抗丢包」。而更上游的问题是该发多快——发太快必堵、太慢浪费。这需要精确的带宽反馈,就是 Transport-CC。下一章讲这个连接第 4、第 5 部分的枢纽。👉 Transport-CC 反馈。
参考资料
- [1] libwebrtc 源码.
modules/rtp_rtcp/source/(ulpfec / flexfec 相关)、fec_controller接口。 - [2] IETF RFC 5109「ULPFEC」、RFC 8627「FlexFEC」、RFC 2198「RED」。
- [3] libwebrtc 源码.
g3doc/rtp.md(flexfec-03 的 PT 分配)。