网易干货 | 浅析视频Jitter Buffer

1、 什么是JitterBuffer

Jitter Buffer也叫作抖动缓冲区,它是实时音视频里面的一个重要模块,它对数据包丢失、乱序、延迟到达等状况进行处理,平滑的向解码模块输出数据包/帧,抵抗各类弱网状况对播放/渲染形成的影响,下降卡顿,提升用户的观看体验。

2、JitterBuffer在音视频系统中的位置

JitterBuffer在实时音视频系统中的位置以下所示:

3、 视频JitterBuffer的工做原理

1. JitterBuffer的核心思想
Jitter buffer的核心思想是用时间换空间,以增大端到端的延迟为代价来换取视频通话的流畅性。当网络不稳定时(抖动发生),增长buffer的长度,多缓存一些数据,以应对未来可能发生的抖动;当网络稳定下来时,减少buffer的长度,少缓存一些数据,下降视频端到端的延迟,提升实时性。所以jitter buffer的运行过程是一个根据抖动来动态调整buffer长度的过程。好的jitter buffer可以在保证尽可能不卡的前提降低低端到端的延迟,即它可以在延迟和卡顿率之间取得较好的平衡。
2. 产生抖动的缘由
1) 网络传输路径改变。例如,当前的传输路径是A,可是下一刻路径A上的某个路由器出现了故障,这时候数据包的路径就会发生改变,致使端到端的传输时长发生变化。
2) 网络自身的抖动。不少状况下网络有噪声,产生抖动是很正常的。
3) 网络发生拥塞。拥塞发生的时候,数据包会在路由器上排队,致使端到端延迟变大。
4) 抗丢包手段带来的额外抖动。网络出现丢包的时候,咱们通常会使用nack/arq去重传数据,重传会带来额外的延迟。
3. 计算抖动的方法
数据包传输时长的变化就是抖动,假设相邻的两个数据包packet1和packet2,它们发送时间戳是send_timestamp1和send_ timestamp2,接收时间戳是recv_ timestamp1和recv_ timestamp2,那么它们之间的抖动能够按照下面的方法计算:
这是最简单的计算方法,要想准确计算出网络抖动还须要考虑不少因素,这里再也不赘述。
4. JitterBuffer的工做原理
1) 接收侧收到数据包,开始组帧,这一步是必须的,帧不完整会致使花屏。
2) 每一个帧组好以后,放进buffer里,而后按照帧序号进行排序。
3) 检查帧的参考关系。对于解码器来讲,若是一个帧的参考帧丢失了,那么这个帧将解码失败或者花屏,因此参考关系必需要知足以后才能把数据送进解码器里。
4) 根据每一帧的时间戳(采集时间戳或者发送时间戳)以及接收时间戳计算抖动。这里的难点在于如何精确计算抖动。
5) 根据抖动计算buffer的长度。
6) 根据抖动自适应的调整buffer长度。抖动越大,预留的buffer长度越大,这样能够利用增长延迟的方式来下降卡顿;抖动越小,预留的buffer长度越小,这样能够下降延迟。

4、浅析webrtc里的视频JitterBuffer

1.WebRTC里视频JitterBuffer的运行机制
Jitterbuffer被两个线程操做,写线程负责组帧完成以后把数据写入JitterBuffer里,读线程负责从JitterBuffer里读取数据而后解码。
写线程:
1) 判断当前视频帧是否有效,把帧插入buffer里,而后移除buffer里过时的、无效的帧;
2) 判断帧之间的参考关系是否已经知足;
3) 若是当前帧能够解码,那么激活解码线程(读线程)。
读线程:
1) 找到buffer中第一个能够解码的帧(假设它是frame):若是这个帧的渲染时间戳是无效的,那么根据当前的抖动(开始的时候抖动值是0,它在步骤3中被更新)计算每一个帧的渲染时间戳(render timestamp),并保存在帧信息中,而后根据这个帧的渲染时间戳和当前时间计算最大须要等待的时间(最大的等待时间不会超过200毫秒),而后休眠等待;
2) 若是在等待的时间内还有新的能够解码的帧到来,那么重复步骤2,直到超时;
3) 根据frame的时间信息以及帧大小计算新的抖动值,并用这个抖动更新当前的抖动。
2. 计算抖动延迟
抖动延迟由网络抖动延迟、解码延迟、渲染延迟构成。其中,解码延迟和渲染延迟比较稳定,网络抖动延迟是动态变化的。计算网络抖动是Jitterbuffer的核心之一。webrtc认为网络抖动由两个部分构成:
1) 网络噪声带来的抖动延迟,也叫作网络排队延迟
2) 传输大的视频帧(特别是关键帧)对网络形成冲击带来的抖动延迟
为了准确估算出抖动延迟,必需要估算出网络排队延迟和信道速率(经过信道速率能够计算大的视频帧对网络形成的冲击所带来的延迟) 。webrtc使用卡尔曼滤波估算网络排队延迟和信道速率。卡尔曼滤波是一种预测的算法,它以协方差为标准,根据上一时刻的系统状态估算当前时刻系统的状态,而后根据当前的测量值调整当前时刻系统的状态,最后获得当前最优的系统状态。它认为估算出来的值和测量出来值都是有误差的,所以要根据一个偏好因子(卡尔曼滤波增益系数)来判断咱们最后须要的值更加偏向于估计值仍是测量值。因为卡尔曼滤波比较复杂,这里并不打算深刻探讨,下面介绍一下使用卡尔曼滤波计算网络抖动延迟的大体流程:
1) 抖动的计算与信道速率、网络排队延迟有关,所以要计算抖动,就必须先计算信道速度和网络排队延迟
2) 把信道速率和网络排队延迟看成系统状态,算法的目标就是估算出最优的信道速度和网络排队延迟。假设系统是一个线性系统,若是网络很是好,那么很容易估算出当前系统的状态等于上一个时刻的系统状态,也就是说信道速度和网络排队延迟保持不变
3) 可是实际上网络是动态变化的,所以须要对估算出的这个系统状态(即信道速度和网络排队延迟)进行调整
4) 调整的具体方式:
a) 根据抖动延迟的观测值(两帧传输时长的变化值)和预测值(根据上一个系统状态推导出来),计算它们的残差;
b) 利用残差计算网络噪声;
c) 根据抖动延迟观测值、先后两帧大小差值、网络噪声、系统偏差协方差等计算卡尔曼增益系数
d) 利用卡尔曼增益系数更新系统状态(即信道速率和网络排队延迟)
5) 根据更新后的系统状态计算抖动延迟:
3. 根据抖动延迟计算视频帧的渲染时间
获得网络抖动延迟以后,计算总的抖动延迟:jitter_delay = net_jitter_delay + decode_delay + render_delay。而后根据抖动延迟和当前的时间,计算何时渲染当前的视频帧,而后根据渲染时间和当前时间肯定当前帧在解码以前须要等待的时间(wait_time),经过wait_time保证了各个视频之间是平滑的,减小了卡顿。另外在等待的时间内也能够缓存更多的视频帧,避免了下一次遇到弱网时再次卡顿。

5、视频JitterBuffer在云信NRTC中的应用

NRTC是网易云信自研的实时音视频通讯系统,NRTC的Jitterbuffer在计算网络抖动的基础上考虑了丢包带来的影响。通常的抗丢包手段有FEC和NACK,两种方法各有优劣,FEC延迟比较低,可是浪费带宽,NACK能够节省带宽,可是会带来延迟。NRTC使用FEC+NACK做为抗丢包手段,当遇到突发丢包时,使用NACK请求发送方重发丢失的包,若是丢包持续,那么使用FEC增长冗余防止丢包。根据前面的分析咱们知道,NACK做为抗丢包手段是会引入额外延迟的,这个延迟不是网络自身的抖动,若是Jitterbuffer不把NACK带来的延迟考虑进去,那么很容易致使卡顿,下降用户的主观体验,所以NRTC的Jitterbuffer把网络抖动和NACK带来的延迟综合考虑,经过实时监测网络变化,在低延迟和流畅性上取得了比较好的平衡。

6、参考

相关文章
相关标签/搜索