1.抖动的定义和消除原理
抖动是指由于网络原因,到达接收端的数据在不同时间段,表现出的不均衡;或者说接收端接收数据包的时间间隔有大有小。
WebRTC 通过包到达时间间隔的变化来评估抖动,公式如下:
Ji 定义为时刻 i 时测量的抖动,E(T) 表示包到达时间的间隔均值,Ti 表示时刻 i 收到的包距上一次收包的时间间隔。
Ji > 0 说明数据包提前到了,这样抖动缓存区数据将会出现堆积,容易造成缓冲区数据溢出,导致端到端时间延迟增大;Ji < 0 说明数据包晚到或丢失,会增大延时;不管早到还是晚到,都可能造成丢包,增加时延。
NetEQ 通过测量包达到时间间隔,来预测包在网络中的传输时间延时;根据收到的包但还未播放的缓冲语音数据的大小来评估抖动的大小。
原则上通过对网络延时的测量,以其最大延时来设置抖动缓冲区的大小,然后使每个包在网络中的延时加上该包在抖动缓冲区的延时之和保持相等,这样可以消除抖动,就可以控制语音包从抖动缓冲区以一个相对平稳的速度播放音频数据。
下图[1]说明了抖动消除的核心思想:
(抖动消除的核心思路)
A、B、C、D 包在发送端分别以 30ms 间隔发送,即分别在 30ms、60ms、90ms、120ms 处发送;接收端接收到这些包对应的时间为 40ms、90ms、100ms、130ms;这样它们在网络中的延时分别是 10ms、30ms、10ms、10ms;包到达的间隔分别为 50ms、10ms、30ms,即抖动。
因此可以使包 A、C、D 在抖动缓存中的延时 20ms 再播放,即 A、B、C、D 的播放时间为 60ms、90ms、120ms、150ms,这样可以保持一个平稳的间隔进行播放。
NetEQ 通过估算网络传输延时,根据网络传输延时 95% 分位来调整抖动缓冲区;这使得 NetEQ 在消除抖动缓冲影响时,兼顾最小延时。
下图[2]是官方对 NetEQ 和其它技术在消除抖动带来的延时对比,可以看出 NetEQ 在消除抖动时,可以保持很低的时间延时。
(NetEQ 与其它技术消除抖动延时对比)
2.NetEQ 及其相关模块
下图[1]概要描述了 WebRTC 的语音引擎架构。红色区域为 NetEQ 部分,可以看出 NetEQ 位于接收端,包含了 jitter buffer 和解码器、PLC 等相关模块。接收端从网络收到语音包后,语音包将先进入 NetEQ 模块进行抖动消除、丢包隐藏、解码等操作,最后将音频数据输出到声卡播放。
(WebRTC 的语音引擎架构图)
NetEQ 包含的模块见下图[1]:
(NetEQ 模块)
NetEQ 核心模块有 MCU 模块和 DSP 模块,MCU 模块负责往 jitter buffer 缓存中插入数据和取数据,以及给 DSP 的操作;DSP 模块负责语音信息号的处理,包括解码、加速、减速、融合、PLC 等。
同时 MCU 模块从 jitter buffer 中取包受到 DSP 模块相关反馈影响。
MCU 模块包括音频包进入到 buffer,音频包从 buffer 中取出,通过语音包到达间隔评估网络传输时间延时,以及对 DSP 模块执行何种操作(加速、减速、PLC、merge)等。
DSP 模块包括解码,对解码后的语音 PCM 数据进行相关操作,评估网络抖动 level,向 play buffer 传递可播放的数据等等。
下面详细分析 MCU 和 DSP 各相关模块。
2.1MCU
将收到的包插入 packet_buffer_
从网络收到音频包后,将其插入到抖动缓存 packet_buffer_中,最多缓存 200 个包;当缓存满了,会刷新缓存中所有的包,同时该缓存最多缓存近 5 秒的音频数据,太早的会被定时清除。
若收到的包是 red 包,会将 red 包中的每个独⽴包解析出来存入到缓存队列中,包在缓存队列中按照 timestamp 的升序进行存储,即最近的音频包存储在队列后面,老的包存储在队列前面。
收到音频包后,还会更新 NackTracker 模块,该模块主要是通过包的序列号来判断是否存在丢包,若存在丢包且重传请求开启,需要向发送端发起 nack 请求,请求发送端重发丢失音频包。
估算网络传输延时
在将包插入到抖动缓存中时,根据包到达时间间隔对网络延时进行估算。这里将 WebRTC 中根据包到达时间间隔来计算网络延时,WebRTC 计算音频网络延时,主要考虑如下几点:
统计音频包到达时间间隔,取其 95% 分为作为网络时延估计。
以上公式通过计算当前包和上一个包的时间差,以及 seqnum 的差值,来计算每个 seq 包占有的时间戳范围,即 packet_per_time,然后通过当前包和上一个包收包间隔 iat_ms,来计算收包时间间隔延时,用包的个数来度量。
当正常包到达时 iat = 1,iat = 0 表示提前到了,iat = 2,表示延时一个包, 最终用包个数来衡量延迟时间。
每算出一个 iat 后,会将其插入到对应的直方图,直方图记录 0-64 个包,即记录 0-64 个包的延迟概率分布情况。所有延迟概率和为 1。
计算出当前包的到达间隔 iat,将其插入到直方图&