FFMPEG 關於對時間戳轉換的理解

首先介紹轉換函數:av_rescale_q_rnd(int64_t a, int64_t b, int64_t c, enum  AVRounding rnd)

此函數主要用於對於不同時間戳的轉換。具體來說是將以 "時鐘基c" 表示的 數值a 轉換成以 "時鐘基b" 來表示。


FFMPEG的很多結構中有AVRationaltime_base;這樣的一個成員,它是AVRational結構的

typedef struct AVRational{

   int num; ///< numerator

   int den; ///< denominator

} AVRational;

AVRational這個結構標識一個分數,num爲分數,den爲分母。

 

實際上time_base的意思就是時間的刻度:

如(1,25),那麼時間刻度就是1/25

(1,9000),那麼時間刻度就是1/90000

那麼,在刻度爲1/25的體系下的time=5,轉換成在刻度爲1/90000體系下的時間time爲(5*1/25)/(1/90000)= 3600*5=18000

ffmpeg中做pts計算時,存在大量這種轉換

 

在以下結構中都有

AVCodecContext:編解碼上下文。

AVStream:文件或其它容器中的某一條流。

 

如果由某個解碼器產生固定幀率的碼流

AVCodecContext中的AVRational根據幀率來設定,如25幀,那麼num = 1,den=25

AVStream中的time_base一般根據其採樣頻率設定,如(1,90000)

 

在某些場景下涉及到PTS的計算時,就涉及到兩個Time的轉換,以及到底取哪裏的time_base進行轉換:

場景1:編碼器產生的幀,直接存入某個容器的AVStream中,那麼此時packet的Time要從AVCodecContext的time轉換成目標AVStream的time

 

場景2:從一種容器中demux出來的源AVStream的frame,存入另一個容器中某個目的AVStream。

           此時的時間刻度應該從源AVStream的time,轉換成目的AVStream timebase下的時間。

 

其實,問題的關鍵還是要理解,不同的場景下取到的數據幀的time是相對哪個時間體系的。

demux出來的幀的time:是相對於源AVStream的timebase

編碼器出來的幀的time:是相對於源AVCodecContext的timebase

mux存入文件等容器的time:是相對於目的AVStream的timebase

這裏的time指pts。


轉碼時:

在解碼之前需要進行如下轉換:

packet.pts = av_rescale_q_rnd(packet.pts,
					ic->streams[videoindex]->time_base,
					ic->streams[videoindex]->codec->time_base,
					(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));

在編碼後寫到file之前需要進行如下轉換:

pkt.pts = av_rescale_q_rnd(pkt.pts,
							oc->streams[videoindex]->codec->time_base,
							oc->streams[videoindex]->time_base,
							(AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));




 


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