RTP采样 p-Time Linux平台毫秒级别的延迟方法【原创】

本文探讨了VoIP通话中语音断续的原因及解决方案。通过对Wireshark捕获数据的分析发现,RTP包间时间间隔大于20ms是问题所在。文章介绍了使用select函数来精确控制发送延迟的方法,有效解决了语音断续问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    之前做voip的voice prompt功能时,两台话机建立通话后,其中一台话机给另一台话机播放语音提示, 类似呼叫中心的性质。但对方听到的语音给人的感觉断断续续,不如通过播放工具听起来圆润。 通过Wireshark 抓取数据然后直接播放,声音质量也是非常好,那问题到底出在哪里呢。

    通过Wireshark抓取的数据进行分析,每个rtp包之间的时间间隔大于20ms,这也就是我们所说的p-time。正常语音通话时p-time都是20ms,误差很小。

   说到这个p-time,就不的不说说RTP的数据采用,一般来说10ms 对应80bytes,20ms对应 160bytes,30ms对于240bytes,40ms对于320bytes,当然这是说的净荷,整个rtp包的话还要加上12bytes的header。

    以G711A编码的音频包如果以20ms打包,那么每个包有160个采样点(采样频率为8KHZ,那么每毫秒的采样个数为8个,因此20ms即为160个),这同样体现在时戳,如下图,两个包之间的时戳间隔为160。

    时间戳(timestamp):反映着个包第一个比特的采样时刻,且后面每个包时戳值呈线性增长,一个公式就是 timestamp = timestamp + (80 * (readDelay/10)); //readdelay为采样时间。

   

 

    言归正传:下面来说说如何解决这个p-time的问题。我们在应用层单独向far-end发送rtp的话,就需要精确这个延迟时间,对于之前使用的usleep(),通过实验是远远不行的,误差太大,20ms的延迟会多出来4ms这严重导致声音断续。下面就介绍一种更好的方法。

    select

    对就是这个万能的select。使用方法:

struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = readDelay*1000; //精确到的毫秒数
ret = select (0, NULL, NULL, NULL, &tv);
if (-1 == ret)
{
    printf("select error\n");

}

当ret返回0时,便表示超时时间到,那咱就可以将打包后的数据一股脑儿的发到far-end。

这时在使用Wireshark看看,p-time误差很小很小了,在听听声音质量,嗯,very good。

结束语:使用 select 来做延迟好处很多,不多说了。Linux下做毫秒级别的延迟用select非常好,其他平台还需测试。

附:参考网上一篇关于sleep,usleep,nanosleep,select的精度测试

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值