FFmpeg音視頻同步的問題

音視頻流裏都包含了播放速率的信息,音頻使用採樣率來表示,而視頻則採用f/s來表示,但是我們卻不能簡單地用這兩個數據來對音視頻進行同步,我們需要使用DTS(解碼時間戳)和PTS(播放時間戳)這兩個數據;我們知道影視數據在存儲時,會存在多種幀形式,例如MPEG中就採用了IBP,由於B幀的存在使得PTSDTS存在不同(原因見附錄),如圖1所示爲一個簡單的例子;當然真正影響我們音視頻同步的是PTS

       我們可以從影視文件中獲得包的PTS,但是我們無法直接獲得幀(我們真正關心的)的PTS,解決辦法是用一幀的第一個包的PTS作爲這一幀的PTS,這是可行的,因爲當一個包開始一幀時,avcodec_decode_video()會調用爲幀申請存儲空間的函數,我們可以重寫這個函數,在其中加入獲取包DTS的方法(這是很容易的),因爲ffmpeg會重新給包進行排序,因此被avcodec_decode_video()處理過的包的DTS和返回的幀的PTS是相同的,這樣就可以得到幀的PTS了。當然有時我們可能沒法得到這個PTS,那樣我們使用內部video_clock(記錄視頻已經過去的時間);

這樣我們就可以使用PTS來重新隊列化我們的幀(queue_picture);



然後,我們可以去獲得音頻的播放時間PTS

get_audio_clock():

audio_clock作爲音頻的pts,但是在audio_decode_frame()計算的audio_clock的是假定緩衝滿的情況,而實際上可能緩衝是不滿的,我們需要減去空閒的部分的時間:pts -= (double)hw_buf_size / bytes_per_sec;

audio_decode_frame():音頻解碼

讀取包時,獲取其pts,放入audio_clock中;

播放時根據緩衝大小和播放速率計算播放時間;

獲得這兩個pts後,我們有三個選擇:視頻同步音頻(計算音視頻PTS只差,來決定視頻是否有延遲)、音頻同步視頻(根據音視頻PTS差值調整音頻取的樣值,即改變音頻緩衝區的大小)和音頻視頻同步外部時鐘(同前一個)。


附錄:

I frame :幀內編碼幀 又稱intra picture幀通常是每個 GOPMPEG 所使用的一種視頻壓縮技術)的第一個幀,經過適度地壓縮,做爲隨機訪問的參考點,可以當成圖象。I幀可以看成是一個圖像經過壓縮後的產物。

P frame: 前向預測編碼幀 又稱predictive-frame,通過充分將低於圖像序列中前面已編碼幀的時間冗餘信息來壓縮傳輸數據量的編碼圖像,也叫預測幀;

B frame: 雙向預測內插編碼幀 又稱bi-directional interpolated prediction frame,既考慮與源圖像序列前面已編碼幀,也顧及源圖像序列後面已編碼幀之間的時間冗餘信息來壓縮傳輸數據量的編碼圖像,也叫雙向預測幀;

I frame:  自身可以通過視頻解壓算法解壓成一張單獨的完整的圖片。

P frame:需要參考其前面的一個I frame 或者B frame來生成一張完整的圖片。

B frame:則要參考其前一個I或者P幀及其後面的一個P幀來生成一張完整的圖片。

I frame 的解碼不依賴於任何的其它的幀.p frame的解碼則依賴於其前面的I frame或者P frame.B frame的解碼則依賴於其前的最近的一個I frame或者P frame 及其後的最近的一個P frame. 

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