WebRTC Native 代码里面有很多值得学习的宝藏,其中一个就是 WebRTC 的 NetEQ 模块。根据 WebRTC 术语表 对 NetEQ 的解释:
A dynamic jitter buffer and error concealment algorithm used for concealing the negative effects of network jitter and packet loss. Keeps latency as low as possible while maintaining the highest voice quality.
一种动态抖动缓冲区和错误隐藏(丢包补偿)算法,用于去除网络抖动和数据包丢失的负面影响。在保持最高语音质量的同时,保持尽可能低的延迟。
NetEQ 其实就是音视频处理中的 Jitter Buffer 模块,在 WebRTC 的语音引擎中使用。这个模块很重要,会影响播放时的体验,同时也相当复杂。
本文源码参考 WebRTC Native M78 版本。
抖动消除
同码率下:抖动(J) = 平均到达间隔(接近发送间隔) - 单次到达间隔
- J > 0:正抖动,数据包提前到达,包堆积,接收端溢出
- J < 0 :负抖动,数据包延迟或丢包
由于网络包的到达有快有慢,导致间隔不一致,这样听感就不顺畅。而抖动消除就是使不统一的延迟变为统一的延迟,所有数据包在网络传输的延迟之和与抖动缓冲区处理后的延迟之和相等。
通过处理,A、B、C、D 的播放间隔一致,播放端就听感就会感受到延迟,但不会有卡顿。
常见的抖动缓冲控制算法有两种:
- 静态抖动缓冲控制算法:缓冲区大小固定,容易实现,网络抖动大时,丢包率高,抖动小时,延迟大。
- 自适应抖动缓冲控制算法:计算目前最大抖动,调整缓冲区大小,实现复杂,网络抖动大时,丢包率低,抖动小时,延迟小。
好的算法自然是追求低丢包率和低延迟。
丢包补偿
丢包补偿(PLC,Packet Loss Concealment)顾名思义,就是在丢包发生时,做的应对措施。主要分为发送端的接受端的丢包补偿。
发送端
- 主动重传:通过信令,让发送端重新补发。
- 被动通道编码:在组包时做一些特殊处理,丢包时可以作依据。
- 前向差错纠正(FEC,Forward error correction):根据丢包前面的包信息来进行处理。
- 媒体相关:双发,数据包中第二个包一般用较低码率和音质编码的包。
- 媒体无关:每 n 个数据包生成一个(多个)新的校验包,校验包能还原出这 n 个包的信息。
- 交织:对数据包分割重排,减少单次丢包的数据量大小。
- 前向差错纠正(FEC,Forward error correction):根据丢包前面的包信息来进行处理。
接收端
- 插入:用固定的包进行补偿
- 静音包
- 噪音包
- 重复包
- 插值:模式匹配及插值技术生成相似的包,算法不会理解数据包具体内容,而只是从数据特征上进行处理
- 重构:根据编码参数和压缩参数生成包,与插值不同,算法使用更多数据包的信息,效果更好
整体架构