在前文中介绍了RTT计算原理及其应用。下面介绍网络抖动Jitter原理、计算方法以及在Webrtc中的应用。
什么是抖动?在网络传输中,每个包从发送端到接收端的时延都是不相同的,而Jitter就是用来衡量这种不同。一般在发送端,数据包发送时间间隔是相同的,也就是均匀发送数据,但是传输过程中由于各种情况,例如拥塞,丢包,网络错误等,接收端收到的数据包间隔就会不一样,可能一会大,一会小,导致时延发生变化,这个时延的变化程度就是所谓的抖动。网络中存在抖动会导致接收端收包不均匀、甚至乱序,如果按照收包顺序去播放,对于视频而言,会导致帧率变化,视频播放就不平滑,有卡顿感。对于音频而言,肯定会有时快时慢、来不及播放导致卡顿、错音等问题,在比较差的网络场景中语音基本是没法听。接收端如果不做任何处理,就会影响用户体验。
WebRTC针对网络抖动问题,根据音视频分为:.NETEQ与JitterBuffer2种,分别对音频、视频进行抖动处理,消除抖动造成的影响,这些会在我的后续文章介绍。
按照抖动的频率,也可以分为:
稳定抖动:这种抖动是网络和算法固有属性导致的,有一定的统计上的稳定性,在一段时间内呈现统计上的稳定性;
突发抖动:这些抖动是在稳定抖动基础上叠加上突发的抖动尖峰,突发通常没有太大规律,无法找到统计上的规律性。
一般的Jitter算法都是尽力去解决稳定抖动,对于突发抖动解决的并不是太好。
如下图片是抖动的一个形象描述。
图1 -Jitter
如何计算抖动?假设RTP中第i包中记录的时间戳为Si(单位为采样率),到达接收端的时间为Ri(单位同样为采样率),如果Si代表第i个包的发送时间戳,Ri代表第i个包的接收时间戳。Sj、Rj同理。
图2 - Jitter计算原理图
抖动(i, j) = |(Rj - Ri) - (Sj - Si)| = |(Rj - Sj) - (Ri - Si)| (1)
WebRTC为了统一抖动,并且为了很好地降噪、降低突发抖动的影响,把上面的抖动(i, j)定义为D(i, j),抖动J(i)定义为:
J(i) = J(i-1) + (|D(i-1, i)| - J(i - 1)) / 16 (2)
增益参数1/16是为了消除噪声影响,使抖动收敛在较合理范围内,避免突发数据的影响。从上一个公式中可以看到D(i-1, j)是唯一引起J(i)变化的因素。
WebRTC统计参数中的抖动计算代码位于
StreamStatisticianImpl::UpdateJitter中
图3 - 代码
time_diff_samples =|D(i−1,i)| (3)
J(i) = J(i-1) + (time_diff_samples - J(i - 1)) / 16 (4)
图4 - 代码
至此我们得到了jitter_diff_q4,单位为采样率,如果需要转换为毫秒时间单位。由于jitter_diff_q4放大了16倍,首先需要还原回去jitter = jitter_q4_ >> 4;转换为毫秒单位:jitter_ms = jitter / (clockrate_hz / 1000)(一般视频的时钟采样频率clockrate_hz为:90kHz)。jitter_ms就是得到的毫秒级别的抖动。