时间戳 (timestamp)
同步问题就是快慢的问题,就会牵扯到时间跟音视频流媒体的对应关系,就有了时间戳的概念。
时间戳用来定义媒体负载数据的采样时刻,从单调线性递增的时钟中获取 , 时钟的精度由 RTP 负载数据的采样频率决定。音频和视频的采样频率是不一样的,一般音频的采样频率有 16KHz、44.1KHz、48KHz 等,而视频反映在采样帧率上,一般帧率有 25fps、29.97fps、30fps 等。
习惯上音频的时间戳的增速就是其采样率,比如 16KHz 采样,每 10ms 采集一帧,则下一帧的时间戳,比上一帧的时间戳,从数值上多 16 x10=160,即音频时间戳增速为 16/ms。而视频的采样频率习惯上是按照 90KHz 来计算的,就是每秒 90K 个时钟 tick,之所以用 90K 是因为它正好是上面所说的视频帧率的倍数,所以就采用了 90K。所以视频帧的时间戳的增长速率就是 90/ms。
时间戳的生成
音频帧时间戳的生成
WebRTC 的音频帧的时间戳,从第一个包为 0,开始累加,每一帧增加 = 编码帧长 (ms) x 采样率 / 1000,如果采样率 16KHz,编码帧长 20ms,则每个音频帧的时间戳递增 20 x 16000/1000 = 320。这里只是说的未打包之前的音频帧的时间戳,而封装到 RTP 包里面的时候,会将这个音频帧的时间戳再累加上一个随机偏移量(构造函数里生成),然后作为此 RTP 包的时间戳,发送出去,如下面代码所示,注意,这个逻辑同样适用于视频包。
视频帧时间戳的生成
WebRTC 的视频帧,生成机制跟音频帧完全不同。视频帧的时间戳来源于系统时钟,采集完成后至编码之前的某个时刻(这个传递链路非常长,不同配置的视频帧,走不同的逻辑,会有不同的获取位置),获取当前系统的时间 timestamp_us_
,然后算出此系统时间对应的 ntp_time_ms_
,再根据此 ntp 时间算出原始视频帧的时间戳 timestamp