ffmpeg是怎么處理rtp時(shí)間戳的

結(jié)構(gòu)體struct RTPDemuxContext中有若干時(shí)間戳相關(guān)的成員,含義如下

timestamp:上一個(gè)接收到的RTP時(shí)間戳
base_timestamp:第一個(gè)接收到的RTP時(shí)間戳
cur_timestamp:未知
unwrapped_timestamp:假如rtp時(shí)間沒有32位溢出的話,當(dāng)前的rtp時(shí)間應(yīng)該是多少
range_start_offset:RTSP Range頭部指定的開始時(shí)間

last_rtcp_ntp_time:上一次收到RTCP SR報(bào)告中的ntp時(shí)間
last_rtcp_timestamp:上一次收到RTCP SR報(bào)告中的rtp時(shí)間
first_rtcp_ntp_time:第一次收到的RTCP SR報(bào)告中的ntp時(shí)間
rtcp_ts_offset:第一次接收到RTCP SR報(bào)告中的RTP時(shí)間與第一個(gè)收到的RTP時(shí)間差

每一幀的時(shí)間戳是這樣計(jì)算的,在libavformat/rtpdec.c finalize_packet()

如果rtp只有一個(gè)音頻流或者一個(gè)視頻流,或者沒有RTCP的SR報(bào)告,則

    pkt->pts     = s->unwrapped_timestamp + s->range_start_offset -
                   s->base_timestamp;

表達(dá)式右邊的順序換一下,含義就清晰了 s->unwrapped_timestamp - s->base_timestamp 代表當(dāng)前自運(yùn)行以來的相對時(shí)間,然后再加上s->range_start_offset,變成一個(gè)絕對時(shí)間。

如果有音視頻兩個(gè)流,且收到了RTCP的SR報(bào)告,計(jì)算是這樣的

            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;

有點(diǎn)不好懂的是addend這個(gè)變量。根據(jù)rfc 3550,RTCP SR報(bào)告中的ntp時(shí)間定義為
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.

由于讀進(jìn)來的rtcp_ntp_time是32位的定點(diǎn)小數(shù),因此在做時(shí)間戳單位轉(zhuǎn)換的時(shí)候做了一個(gè)32位的左移。因此addend代表最后一個(gè)收到的ntp時(shí)間距離第一個(gè)收到的ntp時(shí)間相隔多久。

回到pkt->pts的計(jì)算,s->rtcp_ts_offset這部分代表第一次收到的RTCP SR包距離流開始時(shí)的時(shí)間差,addend代表最后一次收到RTCP SR包距離第一次收到的RTCP SR包的時(shí)間差,delta_timestamp代表當(dāng)前距離最后一次收到RTCP SR包的時(shí)間差,這三部分一求和就代表當(dāng)前距離流開始時(shí)的時(shí)間差。

ffmpeg這種計(jì)算方式用于音視頻流同步是有問題的,它會(huì)默認(rèn)音視頻流時(shí)間戳都從0開始。假如兩者的開始時(shí)間不一致,會(huì)導(dǎo)致音視頻不同步。而且顯然,它這種計(jì)算方式浪費(fèi)了RTCP SR報(bào)告中的ntp與rtp時(shí)間對應(yīng)關(guān)系

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容