十: FFMPEG時間概念的講解

一. 本章節(jié)介紹:

本章節(jié)主要介紹FFMPEG的時間概念,包括時間基、時間戳、時間轉(zhuǎn)換、時間比較等知識點。這些知識點對于我們了解推流至關(guān)重要,因為音視頻合成本質(zhì)上是各種時間轉(zhuǎn)換的過程。

二. FFMPEG 時間基、 時間戳的講解:

2.1. 時間基(time_base):時間基也稱之為時間基準(zhǔn),它代表的是每個刻度是多少秒。比方說:視頻幀率是30FPS,那它的時間刻度是{1,30}。相當(dāng)于1s內(nèi)劃分出30個等分,也就是每隔1/30秒后顯示一幀視頻數(shù)據(jù)。具體的如下圖所示:


image.png

在FFMPEG中時間基準(zhǔn)都是用AVRational結(jié)構(gòu)體來表示:

image.png

num:它是numerator的縮小,代表的是分子
den:它是denominator的縮小,代表的是分母

在視頻時間基都是以幀率為單位,比方說50幀。FFMPEG就以AVRational video_timebase = {1, 50}來表示。

在音頻時間基都是以采樣率為單位,比方說音頻采樣率是48000HZ。FFMPEG就以AVRational audio_timebase = {1, 48000}來表示。

對于封裝格式來說:flv 封裝格式的 time_base 為{1,1000},ts 封裝格式的 time_base 為{1,90000}


image.png

從上圖ffplay的信息我們可以看到有很多關(guān)于時間基的信息:

tbr:表示幀率,該幀率是一個基準(zhǔn),通常來說tbr和fps是一致的
tbn:表示視頻流timebase(時間基),比方說:TS格式的數(shù)據(jù)timebase是90000,flv格式的視頻流timebase為1000
tbc:表示視頻流codec timebase,這個值一般為幀率的兩倍。比方說:幀率是30fps,則tbc是60

2.2. 時間戳(PTS、DTS):


image.png

首先時間戳它指的是在時間軸里面占了多少個格子,時間戳的單位不是具體的秒數(shù),而是時間刻度。只有當(dāng)時間基和時間戳結(jié)合在一起的時候,才能夠真正表達(dá)出來時間是多少。

比方說:
有一把尺子pts = 30個刻度,time_base = {1,30} 每一個刻度是1/30厘米
所以這把尺子的長度 = pts * time_base = 30 * 1/30 = 1厘米

PTS:全稱是Presentation Time Stamp(顯示時間戳),它主要的作用是度量解碼后的視頻幀什么時候顯示出來。

視頻PTS計算:n為第n幀視頻幀,timebase是{1,framerate},fps是framerate
pts = n *(( 1 / timebase) / fps):
pts = pts++;
舉例子:n = 1, pts = 1
n = 2, pts = 2
n =3, pts = 3

音頻PTS計算:n為第n幀音頻幀,nb_samples指的是采樣個數(shù)(AAC默認(rèn)1024),timebase是{1,samplerate},samplerate是采樣率

num_pkt = samplerate/nb_samples
pts = n * ( ( 1/ timebase) / num_pkt)
pts = pts+1024
舉例子:n = 1, pts = 1024
n = 2, pts = 2048
n = 3, pts = 3072

2.3. DTS:表示的是壓縮解碼的時間戳,在沒有B幀的情況下PTS 等于 DTS。假設(shè)編碼的里面引入了B幀,則還要計算B幀的時間。

沒有B幀:dts = pts
存在B幀:dts = pts + b_time

三. 時間轉(zhuǎn)換的原理:

在FFMPEG中由于不同的復(fù)合流,時間基是不同的,比方說:ts的時間基time_base= {1,90000},假設(shè)一個視頻time_base = {1,30},我們需要合成mpegts文件,它就需要把time_base = {1,30}占的格子轉(zhuǎn)換成time_base = {1,90000}占的格子。

image.png

在FFMPEG中用以下的API進(jìn)行時間基轉(zhuǎn)換:


image.png

void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);

第一個參數(shù):AVPacket結(jié)構(gòu)體指針
第二個參數(shù):源時間基
第三個參數(shù):目的時間基

上面這個api的用法是,把AVPacket的時間基tb_src轉(zhuǎn)換成時間基tb_dst。下面我們用H264和AAC時間基TS轉(zhuǎn)換的例子來說明這個轉(zhuǎn)換時間基的用法:

視頻H264時間基轉(zhuǎn)換成MPEGTS時間基: av_packet_rescale_ts
*DST_VIDEO_PTS = VIDEO_PTS * VIDEO_TIME_BASE / DST_TIME_BASE
例src_pts=1:dst_pts=1
(1/30)/(1/90000)=3000
H264 {1,30} MPEGTS {1,90000}
pts = 1 pts = 3000
pts = 2 pts = 6000
pts = 3 pts = 9000
pts = 4 pts = 12000

音頻AAC時間基轉(zhuǎn)換成MPEGTS時間基:av_packet_rescale_ts
DST_AUDIO_PTS = AUDIO_PTS * AUDIO_TIME_BASE / DST_TIME_BASE
例src_pts=1024:dst_pts=1024
(1/48000)
(1/90000)
AAC {1,48000} MPEGTS {1,90000}
pts =1024 pts = 1920
pts =2048 pts = 3840
pts =3072 pts = 5760
pts =4096 pts = 7680

從上述推導(dǎo)的結(jié)果可以看出來,如果使用av_packet_rescale_ts的API對視頻時間基進(jìn)行轉(zhuǎn)換,實際上是使用DST_VIDEO_PTS = VIDEO_PTS * VIDEO_TIME_BASE / DST_TIME_BASE去計算推流的視頻時間戳。

同理用av_packet_rescale_ts對音頻時間基進(jìn)行轉(zhuǎn)換,實際上是使用DST_AUDIO_PTS = AUDIO_PTS * AUDIO_TIME_BASE / DST_TIME_BASE去計算我們真實推流的音頻時間戳。

四. FFMPEG時間戳的比較:

image.png

int av_compare_ts(int64_t ts_a, AVRational tb_a, int64_t ts_b, AVRational tb_b)
第一個參數(shù):ts_a它指的是當(dāng)前相對tb_a的時間戳
第二個參數(shù):ts_a相對應(yīng)的時間基
第三個參數(shù):ts_b它指的是當(dāng)前相對tb_a的時間戳
第四個參數(shù):ts_b相對應(yīng)的時間基
返回值判斷:
當(dāng)ret == -1, ts_a的時間戳快過ts_b時間戳。
當(dāng)ret == 1, ts_a的時間戳慢過ts_b時間戳。
當(dāng)ret == 0, ts_a的時間戳等于ts_b時間戳

av_compare_ts它的主要作用是進(jìn)行時間戳進(jìn)行實時比較,它能夠?qū)崟r保證當(dāng)前的時間戳是準(zhǔn)確無誤的。它不會出現(xiàn)時間戳混亂的情況,所謂混亂的情況就相當(dāng)于:視頻時間戳當(dāng)成音頻時間戳處理,音頻時間戳當(dāng)成視頻時間戳處理。

下面這張圖是編碼視頻、音頻然后進(jìn)行時間戳比較然后合成復(fù)合流的流程:


image.png

視頻時間戳參考視頻幀率進(jìn)行比較、音頻時間戳進(jìn)行比較(這里我們默認(rèn)tb_a時間基是視頻時間基、tb_b時間基是音頻時間基)。所以當(dāng)比較的結(jié)果ret <= 0的時候,則要取出視頻數(shù)據(jù),否則就取出音頻數(shù)據(jù)。取出視頻數(shù)據(jù)后則利用av_packet_rescale_ts進(jìn)行時間轉(zhuǎn)換、同樣取出音頻數(shù)據(jù)后也要對其進(jìn)行時間轉(zhuǎn)換。音視頻數(shù)據(jù)進(jìn)行時間轉(zhuǎn)換后,則用av_interleaved_write_frame對復(fù)合流進(jìn)行寫入操作。

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

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

  • FFMpeg 實現(xiàn)視頻編碼、解碼、封裝、解封裝、轉(zhuǎn)碼、縮放[http://lazybing.github.io/b...
    上官宏竹閱讀 942評論 0 0
  • pts反映幀什么時候開始顯示,dts反映數(shù)據(jù)流什么時候開始解碼 怎么理解這里的“什么時候”呢?如果有某一幀,假設(shè)它...
    凌煙醉臥閱讀 780評論 0 0
  • PTS/DTS(時間戳)要想解決時間同步問題就必須要了解ffmpeg中的PTS和DTS到底是什么 PTS: PTS...
    FANDX閱讀 2,799評論 0 0
  • 視頻的播放過程可以簡單理解為一幀一幀的畫面按照時間順序呈現(xiàn)出來的過程,就像在一個本子的每一頁畫上畫,然后快速翻動的...
    zghbhdxw閱讀 1,750評論 0 1
  • FFmpeg 介紹 FFmpeg是一套可以用來記錄、轉(zhuǎn)換數(shù)字音頻、視頻,并能將其轉(zhuǎn)化為流的開源計算機(jī)程序。采用LG...
    Y了個J閱讀 11,595評論 0 28

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