七、FFmpeg把視頻流同步到音頻流

1、如何同步視頻

直到現在,我們的視頻播放器還幾乎無法正常工作,雖然它能播放視頻,也能播放聲音,但是聲音和視頻還沒同步。那麼現在我們要怎麼做呢?

 

2、PTS和DTS的作用

音頻流和視頻流信息裏面,都有一些信息用於表明應該以多快速度和什麼時間來播放它們。音頻流有采樣率,視頻流有幀率。但是如果只是簡單的通過數幀和乘以幀率的方式來同步視頻,那麼同步很可能會出問題。爲了可以實現同步,在流中的數據包中有解碼時間戳(DTS)和顯示時間戳(PTS)。要理解這兩個參數的作用,得先了解電影的存儲方式。像MPEG等格式,使用被稱爲B幀(B代表“bidrectional”)的方式。另外兩種幀被稱爲I幀和P幀(I表示"intra",P表示“predicted”)。I幀包含了一幀指定的完整圖像,P幀依賴於前面的I幀或者P幀,且使用比較或者差分的方式來編碼。B幀與P幀有點類似,但是它是依賴於前面和後面的幀的信息。這也就解釋了爲什麼在調用avcodec_decode_video的時候可能得不到一幀完整的圖像。

假設我們有個視頻,幀序列爲:I B B P,現在要在顯示B幀之前知道P幀中的信息。所以這個幀序列的存儲方式可能是這樣的:IPBB。從這裏就可以看出解碼時間戳和時間戳的作用了,解碼時間戳決定什麼時候解碼,顯示時間戳決定什麼時候需要顯示(因爲幀存儲序列的順序並不一定和它原始的順序一模一樣)。我們的流可能是這樣的:

DTS: 1 4 2 3

PTS: 1 2 3 4

Stream: I P B B

通常PTS和DTS只有在流中有B幀的時候不同。在調用av_read_frame()得到一個包的時候,包裏面會包含PTS和DTS的信息。但我們真正想要的是我們剛剛解碼出來的原始幀的PTS,這樣我們才知道什麼時候顯示它。幸運的是,ffmpeg給我們提供了一個"best effort"時間戳,可以通過av_frame_get_best_effort_timestamp()函數獲取到。

 

 

 

3、解決每一幀視頻應該在什麼時間顯示的問題

AVStream裏面有

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