深入理解pts,dts,time_base

原文鏈接:https://blog.csdn.net/bixinwei22/article/details/78770090

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

補充: 
next_pts-current_pts=current_duration,根據數學等差公式an=a1+(n-1)*d可得pts=n*d
--------------------- 
版權聲明:本文爲CSDN博主「bixinwei」的原創文章,遵循CC 4.0 by-sa版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/bixinwei22/article/details/78770090

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章