webrtc video jitter详解(二)

1,kalman滤波原理

https://www.zhihu.com/question/23971601

假设你有两个传感器,测的是同一个信号。可是它们每次的读数都不太一样,怎么办?
取平均。
再假设你知道其中贵的那个传感器应该准一些,便宜的那个应该差一些。那有比取平均更好的办法吗?
加权平均。
怎么加权?假设两个传感器的误差都符合正态分布,假设你知道这两个正态分布的方差,用这两个方差值,(此处省略若干数学公式),你可以得到一个“最优”的权重。
接下来,重点来了:假设你只有一个传感器,但是你还有一个数学模型。模型可以帮你算出一个值,但也不是那么准。怎么办?
把模型算出来的值,和传感器测出的值,(就像两个传感器那样),取加权平均。
OK,最后一点说明:你的模型其实只是一个步长的,也就是说,知道x(k),我可以求x(k+1)。问题是x(k)是多少呢?答案:x(k)就是你上一步卡尔曼滤波得到的、所谓加权平均之后的那个、对x在k时刻的最佳估计值。

我的理解是分别计算模型值和测量值的方差,方差越小,说明置信度越高,计算加权平均时权重越大。

2,webrtc中jitterdelay计算

  • 观测值:frameDelay = t(i) – t(i-1) – (T(i) – T(i-1))
    其中t(i)表示当前帧本地接收时刻,t(i-1)表示上一帧本地接收时刻;T(i)表示当前帧的时间戳,T(i-1)表示上一帧的时间戳。frameDelay表示相邻两帧的相对延迟
  • 模型值:frameDelay= (frameSize – prevFrameSize )*theta[0] + theta[1]
    其中theta[0]表示信道传输速率的倒数,theta[1]表示网络排队时延
    通过kalman滤波计算出theta[0]和theta[1](参阅这篇文章https://www.jianshu.com/p/bb34995c549a),然后计算jitterdelay。

JitterDelay由两部分延迟造成:传输大帧引起的延迟和网络噪声引起的延迟。其计算公式如下
JitterDelay = theta[0] * (MaxFS – AvgFS) + [noiseStdDevs * sqrt(varNoise) – noiseStdDevOffset]

其中theta[0]是信道传输速率的倒数,MaxFS是自会话开始以来所收到的最大帧大小,AvgFS表示平均帧大小。
noiseStdDevs表示噪声系数2.33,varNoise表示噪声方差(观测值frameDelay与模型值差值的方差),noiseStdDevOffset是噪声扣除常数30

3,webrtc中延时应用

在VCMTiming中计算延时
用current_delay_ms_表示前一帧总的延时(jitterdelay+ decodedelay + renderdelay)

VCMReceiver::FrameForDecoding(max_wait_time_ms)
   =>VCMJitterBuffer::NextCompleteFrame //返回decodable_frames_.Front()
   =>VCMTiming::SetJitterDelay  //根据kalman滤波算出的网络抖动延时,更新到timing里
   =>VCMTiming::UpdateCurrentDelay  
      =>计算总的延时target_delay_ms=jitterdelay+ decodedelay + renderdelay,
      =>计算与当前延时抖动,delay_diff_ms=target_delay_ms-current_delay_ms_
      =>控制delay_diff_ms在(-100/fps, 100/fps)范围内,即前后两帧的延时抖动不能超过100ms/fps
      =>更新current_delay_ms_+=delay_diff_ms
   =>VCMTiming::RenderTimeMs  //计算该帧显示的绝对时间
      =>(当前帧的时间戳-第一帧的时间戳)/90+第一帧绝对时间,得到当前帧的绝对时间
      =>控制current_delay_ms_在(min_playout_delay_ms_,max_playout_delay_ms_)范围内,得到actual_delay 
      //其中min_playout_delay_ms_与音视频同步相关
      =>返回当前帧绝对时间+actual_delay,即该帧显示的绝对时间render_time_ms
   =>根据render_time_ms-当前时间-decodedelay-renderdelay得到还富余的时间wait_time_ms
   =>在wait_time_ms满足最大获取时间max_wait_time_ms的前提下,线程等待(wait_time_ms)。
      否则函数结束,返回null;即当前缓冲区内没有满足时间要求应该显示的帧
   =>VCMJitterBuffer::ExtractAndSetDecode //此时真正从decodable_frames_删除frame,更新decode_state

在该帧实际解码前,还会根据实际时间更新timing中current_delay_ms_,如果程序运行中实际耗时超过预期等待时间,在current_delay_ms_不超过target_delay_ms的前提下,将current_delay_ms_更新到实际的延时。

优化点:1. 如果想要降低缓冲延时,减小max_playout_delay_ms_;如果想提高视频平滑度,增加min_playout_delay_ms_
2. NACK作为抗丢包方法会引入额外延迟,这个延迟不是网络自身的抖动,如果Jitterbuffer不把NACK带来的延迟考虑进去,那么很容易导致卡顿,jitterdelay需要根据nack请求数量提前加上rtt延时,不要等到重发包到达再增加延时

你可能感兴趣的:(音视频传输,webrtc)