當前位置: 妍妍網 > 碼農

理解 FFmpeg 中的 pts,dts,time_base

2024-02-28碼農
首先介紹下概念:

PTS :Presentation Time Stamp。PTS主要用於度量解碼後的視訊幀什麽時候被顯示出來。

DTS :Decode Time Stamp。DTS主要是標識讀入記憶體中的bit流在什麽時候開始送入解碼器中進行解碼。

也就是pts反映幀什麽時候開始顯示,dts反映數據流什麽時候開始解碼。

怎麽理解這裏的「什麽時候」呢?如果有某一幀,假設它是第10秒開始顯示。那麽它的pts是多少呢。是10?還是10s?還是兩者都不是。

為了回答這個問題,先引入FFmpeg中時間基的概念,也就是 time_base 。它也是用來度量時間的。


如果把1秒分為25等份,你可以理解就是一把尺,那麽每一格表示的就是1/25秒。此時的time_base={1,25}。


如果你是把1秒分成90000份,每一個刻度就是1/90000秒,此時的time_base={1,90000}。

所謂時間基表示的就是每個刻度是多少秒

pts的值就是 占多 少個時間刻度(占多少個格子)。 它的單位不是秒,而是時間刻度。 只有pts加上time_base兩者同時在一起,才能表達出時間是多少。

好比我只告訴你,某物體的長度占某一把尺上的20個刻度。但是我不告訴你,這把尺總共是多少厘米的,你就沒辦法計算每個刻度是多少厘米,你也就無法知道物體的長度。


pts=20個刻度
time_base={1,10} 每一個刻度是1/10厘米
所以物體的長度=pts * time_base=20 *1/10 厘米

在ffmpeg中,av_q2d(time_base)=每個刻度是多少秒。


此時你應該不難理解 pts*av_q2d(time_base)才是幀的顯示時間戳。

下面理解時間基的轉換,為什麽要有時間基轉換。

首先, 不同 的封裝格式,timebase是不一樣的 另外,整個轉碼過程,不同的數據狀態對應的時間基也不一致。

拿mpegts封裝格式25fps來說(只說視訊,音訊大致一樣,但也略有不同)。

非壓縮時候的數據(即YUV或者其它),在ffmpeg中對應的結構體為AVFrame,它的時間基為AVCodecContext 的time_base ,AVRational{1,25}。

壓縮後的數據(對應的結構體為AVPacket)對應的時間基為AVStream的time_base,AVRational{1,90000}。


因為數據狀態不同,時間基不一樣,所以我們必須轉換,在1/25時間刻度下占10格,在1/90000下是占多少格。這就是pts的轉換。

根據pts來計算一楨在整個視訊中的時間位置:
timestamp(秒) = pts * av_q2d(st->time_base)

duration和pts單位一樣,duration表示當前幀的持續時間占多少格。或者理解是兩幀的間隔時間是占多少格,一定要理解單位。


pts:格子數
av_q2d(st->time_base): 秒/格

計算視訊長度:
time(秒) = st->duration * av_q2d(st->time_base)

ffmpeg內部的時間與標準的時間轉換方法:
ffmpeg內部的時間戳 = AV_TIME_BASE * time(秒)
AV_TIME_BASE_Q=1/AV_TIME_BASE

av_rescale_q(int64_t a, AVRational bq, AVRational cq)函式


這個函式的作用是計算a*bq / cq來把時間戳從一個時間基調整到另外一個時間基。

在進行時間基轉換的時候,應該首先這個函式,因為它可以避免溢位的情況發生。

函式表示在bq下的占a個格子,在cq下是多少。

關於音訊pts的計算:

音訊sample_rate:samples per second,即取樣率,表示每秒采集多少采樣點。
比如44100HZ,就是一秒采集44100個sample。


即每個sample的時間是1/44100秒。

一個音訊幀的 AVFrame 有 nb_samples 個 sample,所以一個AVFrame耗時是nb_samples乘以(1/44100)秒。


即標準時間下duration_s=nb_samples乘以(1/44100)秒。


轉換成 AVStream 時間基下
duration=duration_s / av_q2d(st->time_base)。


基於st->time_base 的 num 值一般等於取樣率, 所以 duration=nb_samples。

pts=n* duration=n *nb_samples。

-- END --

進技術交流群, 掃碼添加我的微信:Byte-Flow

獲取相關資料和源碼

推薦: