作者:付明旺。唐桥科技资深架构师。负责实时通信软件的技术创新与研发。曾就职于中兴通讯、诺基亚,在4G和IMS-webRTC等电信通信产品担任软件工程师、系统架构师等角色,具有丰富的无线/互联网通信、实时音视频通信产品技术经验。
唐桥科技,医疗云通信专家,是专业的智能视频PaaS及SaaS云服务提供商。致力于三网融合视频通讯平台的研发和在不同领域的应用,已经与医疗行业应用深度结合,推出了远程医疗、医学视频云会议、互动医教、医学线上峰会平台等一系列行业解决方案,为医疗行业提供专业音视频通讯服务。在此基础上,唐桥科技将多年积累的音视频技术以SDK/API的形式开放给企业及开发者,降低技术门槛,让企业跑得更快。
webRTC解决方案实现了P2P的音视频通信,其中有关timing的几个问题值得归纳总结。开始本文之前建议先行阅读https://xie.infoq.cn/article/738b8293dce86f7c8748e2629 了解视频传输的关键路径。webRTC是一个异步系统,通信的双方无需做时间同步。本文主要探讨webRTC是怎样解决下面两个跟时间有关的问题:1. 音视频同步 2. 基于延时的带宽评估。
音视频同步(Lip-sync)
发送端采集-编码-发送,接收端解码-渲染,音频流和视频流的处理和网络传输是互相独立的,而且各自的采样/播放频率也是不同的。如何在接收端还原采集端的真实场景,从来都不是一件容易的事情。好在人的听觉/视觉系统本来就有一定容忍能力,ITU(国际电信联盟)给了一个建议:音频之于视频在这个范围内[-125ms,45ms],也就是落后125ms或早于45ms,人类感觉上是可以接受的,我们认为这是音视频处于同步状态。
webRTC解决这个问题的原理也比较简单,发送端给音频流和视频流的数据包都打上时间戳,这些时间戳都可以跟同一个时间基准对齐,接收端利用时间戳和缓存就可以调整每个流上音频/视频帧渲染时间,最终达到同步的效果。我们可以进一步了解一下实现的细节,以视频流为例。下图为视频处理的流水线,每个矩形框是一个线程实例。
实现上有三种时间信息:
1.本地系统时间:从操作系统启动计时至当前的时间差值
2.NTP(Network Time Protocol)时间:全局时间信息,从1/1/1900-00:00h计时到当前的时间差值
3.RTP时间:帧时间戳,以视频采样90k频率为例,rtp_timestamp=ntp_timestamp*90
这三种时间坐标都是对时间的度量,只是描述时间的方式不同。比如当前绝对时间2020-08-05T06:08:52+00:00, 它们是这样表达的。
本地时间1919620051:表示开机计数起,过去1919620051ms了,大概22.2days。
NTP时间3805596543795:表示距离1/1/1900-00:00h,过去3805596543795ms了。
RTP时间:RTP时间由NTP时间计算而来,时间单位1/90000s,u32存储,计算过程会发送溢出,((u32)3805596543795)*90=1521922030。
发送端
一帧视频画面在caputer线程就记录下了,这一帧对应的三个时间信息,尤其重要的是RTP时间。这个rtp_timestamp在Packet pacer模块会加一个提前设定的偏移量,作为最终的rtp时间发出去。这个偏移量加在了整个rtp时间坐标系内,所有的对外的RTP时间都加了。
视频流按照自己的RTP时间对每一个包做了标记,音频流也类似的根据自己的RTP时间对每一个音频包做了标记,但这两条流里的时间都是按照自己的步调在走,是独立的。如果要求接收端使这两条流同步渲染,就要想办法让这些时间统一跟同一个时间基准对齐。如下图示,逻辑上举例描述了两条流如何同步,其中的时间数字只做参考,非真实数据。
RTCP SR(sender report)的作用之一就是做时间对齐的,将该流中的RTP时间于NTP时间对齐。所有的流都对齐发送端的NTP时间,这样接收端就有了统一时间基准。
RTCP SR format 如下:
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
header |V=2|P| RC | PT=SR=200 | length |
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
| SSRC of sender |
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
sender | NTP timestamp, most significant word |
info ±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
| NTP timestamp, least significant word |
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
| RTP timestamp |
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
| sender’s packet count |
±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±±+
| sender’s octet count |
+=+=+=