NetEQ 是 WebRTC 音视频核心技术之一,对于提高 VoIP 质量有明显的效果,本文将从更为宏观的视角,用通俗白话介绍 WebRTC 中音频 NetEQ 的相关概念背景和框架原理,以及相关的优化实践。
作者| 良逸
审校| 泰一
为什么要 “白话” NetEQ?
丢包、抖动和优化的理解
NetEQ 及相关模块
InsertPacketInternal 输入到 NetEQ 的接收模块中。UpdateLastReceivedPacket 函数更新到 Nack 重传请求模块,Nack 模块会通过 RTP 收包或定时器触发两种模式,调用 GetNackList 函数来生成重传请求,以 NACK RTCP 包的格式发送给推流侧。GetAudioInternal接口从 NetEQ 里面取 10ms 长度的数据来播放。GetAudioInternal 的函数之后,第一步要决策如何应对当前数据请求,这个任务交给操作决策模块来完成,决策模块根据之前的和当前的数据和操作的状态,给出最终的操作类型判断。NetEQ 里面定义了几种操作类型:正常、加速、减速、融合、拉伸(丢包补偿)、静音,这几种操作的意义,后面再详细的说。有了决策的操作类型,再从输入部分的包缓存(packet buffer)里面取出一个 RTP 包,送给抽象的解码器,抽象的解码器通过 DecodeLoop 函数层层调用到真正的解码器进行解码,并把解码后的 PCM 音频数据放到 DecodedBuffer 里面去。然后就是开始执行不同的操作了,NetEQ 里面为每一种操作都实现了不同的音频数字信号处理算法(DSP),除了 “正常” 操作会直接使用 DecodedBuffer 里的解码数据,其它操作都会结合解码的数据进行二次 DSP 处理,处理结果会先被放到算法缓存(Algorithm Buffer)里面去,然后再插入到 Sync Buffer 里面。Sync Buffer 是一个循环 buffer,设计的比较巧妙,存放了已经播放过的数据、解码后未播放的数据,刚刚从算法缓存里插入的数据放在 Sync Buffer 的末尾,如上图所示。最后就是从 Sync Buffer 取出最早解码后的数据,送出去给外部的混音模块,混音之后再送到音频硬件来播放。SetMinimumPlayoutDelay 最终设置到 NetEQ 里面的最小目标水位,来控制 TargetLevel,实现音视频同步。NetEQ 内部模块
NetEQ 相关模块优化点
总结
END