剑痴乎

  • 首页
  • 文章分类
    • 音视频
    • WebRTC
    • 编程之美
    • Linux
    • Windows
    • 生活点滴
    • 校园生活
  • 参考
    • API参考
    • 实用工具
    • 测试音视频
    • 文档
  • 留言板
  • 关于
剑痴乎
代码为剑,如痴如醉
  1. 首页
  2. WebRTC
  3. 正文

WebRTC研究:统计参数之抖动

2021年3月14日 4277点热度 17人点赞 8条评论

当我们调试WebRTC web客户端时,经常会打开chrome://webrtc-internals/这个页面,在这里我们可以看到音视频流的各种统计。今天我们就来看下其中的一个统计参数:抖动(jitter)。

什么是抖动

在网络传输中,每个包从发送端到接收端的时延都是不相同的,而jitter就是用来衡量这种不同。一般在发送端,数据包发送时间间隔是相同的,也就是均匀发送数据,但是传输过程中由于各种情况,例如拥塞,丢包,网络错误等,接收端收到的数据包间隔就会不一样,可能一会大,一会小,导致时延发生变化,这个时延的变化程度就是所谓的抖动,接收端如果不做任何处理,就会影响用户体验。例如对于视频来说,会导致帧率变化,视频播放就不平滑,有卡顿感。如下图片是抖动的一个形象描述。
jitter
WebRTC内部通过NetEQ与JitterBuffer进行音视频的抖动处理,消除抖动造成的影响,这些会在我的后续文章介绍。

抖动计算

根据RFC3550,假设RTP包i,RTP报头记录的时间戳为Si(单位为采样率),到达接收端的时间为Ri(单位同样为采样率),对于包i,j,我们定义一个变量\(D\),描述两个包时间的差异,由接收时间差减去发送时间差:
\[D(i,j) = (Rj - Ri) - (Sj - Si) = (Rj - Sj) - (Ri - Si)\tag{1}\]
抖动\(J\)按如下公式定义:
\[J(i) = J(i-1) + (|D(i-1,i)| - J(i-1))/16\tag{2}\]
上述公式中i-1指的是前一个收到的包,不是按RTP序列号计数的。增益参数1/16是为了消除噪声影响,使抖动收敛在较合理范围内,避免突发数据的影响。

由公式可知,如果接受端收到的包间隔跟发送端发送间隔一样,那么抖动为0。

代码导读

WebRTC统计参数中的抖动计算代码位于StreamStatisticianImpl::UpdateJitter中,看下如何计算。
1)计算接收时间差,也就是\(Ri - R_{i-1}\):

1
2
3
4
5
  // 计算接收时间差
  int64_t receive_diff_ms = receive_time_ms - last_receive_time_ms_;
  // 接收时间差:ms时间单位转换为采样率描述的时间单位
  uint32_t receive_diff_rtp = static_cast<uint32_t>(
      (receive_diff_ms * packet.payload_type_frequency()) / 1000);

2)计算\(|D(i-1,i)|\),其中发送时间为RTP报头记录的时间戳:

1
2
3
4
5
  // D:接收时间差 - 发送时间差
  int32_t time_diff_samples =
      receive_diff_rtp - (packet.Timestamp() - last_received_timestamp_);
 
  time_diff_samples = std::abs(time_diff_samples);

3)由公式(2),使用jitter_diff表示\(|D(i-1,i)|-J(i-1)\):
\[jitter\_diff = time\_diff\_samples - J(i-1)\tag{3}\]
\[J(i) = J(i-1) + jitter\_diff/16\tag{4}\]
所以相关代码如下:

1
2
3
4
5
6
7
8
9
10
11
  // lib_jingle sometimes deliver crazy jumps in TS for the same stream.
  // If this happens, don't update jitter value. Use 5 secs video frequency
  // as the threshold.
  // 由于一般视频的时钟采样率为90kHz,5S用采样率单位表示刚好是450000
  if (time_diff_samples < 450000) {
    // 根据公式(3)计算jitter_diff:q4后缀表示左移4位,也就是乘以16
    // 两边同乘以16,也就是<<4,这样做是为了避免计算使用float表示
    int32_t jitter_diff_q4 = (time_diff_samples << 4) - jitter_q4_;
    // 根据公式(4)更新jitter_q4_:(jitter_diff_q4 + 8)是为了四舍五入
    jitter_q4_ += ((jitter_diff_q4 + 8) >> 4);
  }

至此我们得到了jitter_diff_q4,单位为采样率,如果需要转换为毫秒时间单位,需要如下计算:
1)由于jitter_diff_q4放大了16倍,首先需要还原回去:

1
jitter = jitter_q4_ >> 4;

2)转换为毫秒单位:

1
2
// 一般视频的时钟采样频率clockrate_hz为:90kHz
jitter_ms = jitter / (clockrate_hz / 1000);

这样我们就得到了以毫秒表示的抖动统计参数,chrome://webrtc-internals/中抖动的单位是秒。

参考

[1] Jitter.https://en.wikipedia.org/wiki/Jitter.
[2] RFC3550.https://tools.ietf.org/html/rfc3550.

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
标签: WebRTC
最后更新:2022年3月27日

Jeff

管理员——代码为剑,如痴如醉

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • MarkCao

    谢谢Jeff,讲解的很清晰,受教了。
    另外文中有一处笔误:“到达接收端的时间为Si(根据上下文应该是Ri)(单位同样为采样率)“。

    2021年6月11日
    回复
    • Jeff

      @MarkCao 已纠正

      2021年6月11日
      回复
  • MarkCao

    补充一点自己的理解:RTP包的时间戳timestamp虽然是用64位表示,但是webrtc中只用了32位表示,即整数和小数部分个16位,即4个字节。这也就是计算jitter_diff时使用Q4格式来避免浮点计算的原因。

    2021年6月11日
    回复
  • xman

    公式写错了吧,应该是J(i)=J(i−1)+( 16*|D(i−1,i)| −J(i−1) ) / 16

    2023年2月11日
    回复
  • hello123#

    // 两边同乘以16,也就是<<4,这样做是为了避免计算使用float表示
    int32_t jitter_diff_q4 = (time_diff_samples << 4) - jitter_q4_; 这个段代码,为什么 jitter_q4没有<<4呢

    2024年2月20日
    回复
    • hello123#

      @hello123# 理解了 不用回复了 谢谢

      2024年2月20日
      回复
      • mj

        @hello123# 能不能讲一下呢,我也没理解

        2024年6月27日
        回复
      • mj

        @hello123# 突然懂了

        2024年6月27日
        回复
  • razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
    回复 Jeff 取消回复

    这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

    版权声明

    为支持原创,创作更好的文章,未经许可,禁止任何形式的转载与抄袭,如需转载请邮件私信!本人保留所有法定权利。违者必究!

    文章目录
    • 什么是抖动
    • 抖动计算
    • 代码导读
    • 参考
    最近评论
    ztt 发布于 1 个月前(04月05日) 你好,想看里面的视频和图片为什么没有显示呢?需要下flash吗还是什么。
    huowa222 发布于 1 个月前(03月26日) 同问
    邱国禄 发布于 3 个月前(02月17日) Receive Delta以0.25ms为单位,reference time以64ms为单位,kDe...
    啊非 发布于 4 个月前(12月30日) 大神,请教一个问题: constexpr int kBaseScaleFactor = Tran...
    啊非 发布于 4 个月前(12月30日) reference time:3字节,表示参考时间,以64ms为单位,但是 代码里面是 Trans...
    相关文章
    • WebRTC资讯:H265支持进展
    • WebRTC研究:Audio level
    • Mac平台WebRTC编译
    • WebRTC研究:RTP时间戳的产生
    • WebRTC研究:统计参数之丢包率

    COPYRIGHT © 2024 jianchihu.net. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang