结构体struct RTPDemuxContext中有若干时间戳相关的成员,含义如下
timestamp:上一个接收到的RTP时间戳
base_timestamp:第一个接收到的RTP时间戳
cur_timestamp:未知
unwrapped_timestamp:假如rtp时间没有32位溢出的话,当前的rtp时间应该是多少
range_start_offset:RTSP Range头部指定的开始时间
last_rtcp_ntp_time:上一次收到RTCP SR报告中的ntp时间
last_rtcp_timestamp:上一次收到RTCP SR报告中的rtp时间
first_rtcp_ntp_time:第一次收到的RTCP SR报告中的ntp时间
rtcp_ts_offset:第一次接收到RTCP SR报告中的RTP时间与第一个收到的RTP时间差
每一帧的时间戳是这样计算的,在libavformat/rtpdec.c finalize_packet()
如果rtp只有一个音频流或者一个视频流,或者没有RTCP的SR报告,则
pkt->pts = s->unwrapped_timestamp + s->range_start_offset -
s->base_timestamp;
表达式右边的顺序换一下,含义就清晰了 s->unwrapped_timestamp - s->base_timestamp 代表当前自运行以来的相对时间,然后再加上s->range_start_offset,变成一个绝对时间。
如果有音视频两个流,且收到了RTCP的SR报告,计算是这样的
if (s->first_rtcp_ntp_time == AV_NOPTS_VALUE) { s->first_rtcp_ntp_time = s->last_rtcp_ntp_time; if (!s->base_timestamp) s->base_timestamp = s->last_rtcp_timestamp; s->rtcp_ts_offset = (int32_t)(s->last_rtcp_timestamp - s->base_timestamp); } /* compute pts from timestamp with received ntp_time */ delta_timestamp = timestamp - s->last_rtcp_timestamp; /* convert to the PTS timebase */ addend = av_rescale(s->last_rtcp_ntp_time - s->first_rtcp_ntp_time, s->st->time_base.den, (uint64_t) s->st->time_base.num << 32); pkt->pts = s->range_start_offset + s->rtcp_ts_offset + addend + delta_timestamp;
有点不好懂的是addend这个变量。根据rfc 3550,RTCP SR报告中的ntp时间定义为
http://www.ietf.org/rfc/rfc3550.txt
Wallclock time (absolute date and time) is represented using the timestamp format of the Network Time Protocol (NTP), which is in seconds relative to 0h UTC on 1 January 1900 [4]. The full resolution NTP timestamp is a 64-bit unsigned fixed-point number with the integer part in the first 32 bits and the fractional part in the last 32 bits.
由于读进来的rtcp_ntp_time是32位的定点小数,因此在做时间戳单位转换的时候做了一个32位的左移。因此addend代表最后一个收到的ntp时间距离第一个收到的ntp时间相隔多久。
回到pkt->pts的计算,s->rtcp_ts_offset这部分代表第一次收到的RTCP SR包距离流开始时的时间差,addend代表最后一次收到RTCP SR包距离第一次收到的RTCP SR包的时间差,delta_timestamp代表当前距离最后一次收到RTCP SR包的时间差,这三部分一求和就代表当前距离流开始时的时间差。
ffmpeg这种计算方式用于音视频流同步是有问题的,它会默认音视频流时间戳都从0开始。假如两者的开始时间不一致,会导致音视频不同步。而且显然,它这种计算方式浪费了RTCP SR报告中的ntp与rtp时间对应关系
作者:叶迎宪
链接:https://www.jianshu.com/p/67d3e6a1d72e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。