音視頻同步原理解析
2013-04-18 15:21:11
標簽:[音頻視頻](http://blog.51cto.com/tag-%E9%9F%B3%E9%A2%91%E8%A7%86%E9%A2%91.html)
### 視頻流中的DTS/PTS到底是什么?
DTS(解碼時間戳)和PTS(顯示時間戳)分別是解碼器進行解碼和顯示幀時相對于SCR(系統參考)的時間戳。SCR可以理解為解碼器應該開始從磁盤讀取數據時的時間。
mpeg文件中的每一個包都有一個SCR時間戳并且這個時間戳就是讀取這個數據包時的系統時間。通常情況下,解碼器會在它開始讀取mpeg流時啟動系統時鐘(系統時鐘的初始值是第一個數據包的SCR值,通常為0但也可以不從0開始)。
DTS?時間戳決定了解碼器在SCR時間等于DTS時間時進行解碼,PTS時間戳也是類似的。通常,DTS/PTS時間戳指示的是晚于音視頻包中的SCR的一個時?間。例如,如果一個視頻數據包的SCR是100ms(意味著此包是播放100ms以后從磁盤中讀取的),那么DTS/PTS值就差不多是200 /280ms,表明當SCR到200ms時這個視頻數據應該被解碼并在80ms以后被顯示出來(視頻數據在一個buffer中一直保存到開始解碼)下?溢通常發生在設置的視頻數據流相關mux率太高。
如果mux率是1000000bits/sec(意味著解碼器要以1000000bits/sec的速率?讀取文件),可是視頻速率是2000000bits/sec(意味著需要以2000000bits/sec的速率顯示視頻數據),從磁盤中讀取視頻數據時?速度不夠快以至于1秒鐘內不能夠讀取足夠的視頻數據。這種情況下DTS/PTS時間戳就會指示視頻在從硬盤中讀出來之前進行解碼或顯示(DTS/PTS時間戳就要比包含它們的數據包中的SCR時間要早了)。
如今依靠解碼器,這基本已經不是什么問題了(盡管MPEG文件因為應該沒有下溢而并不完全符合MPEG標準)。一些解碼器(很多著名的基于PC的播放器)盡可能快的讀取文件以便顯示視頻,可以的話直接忽略SCR。
注意在你提供的列表中,平均的視頻流速率為~3Mbps(3000000bits/sec)但是它的峰值達到了14Mbps(相當大,DVD限制在?9.8Mbps內)。這意味著mux率需要調整足夠大以處理14Mbps的部分,?bbMPEG計算出來的mux率有時候太低而導致下溢。
你計劃讓視頻流速率這么高么?這已經超過了DVD的說明了,而且很可能在大多數獨立播放其中都不能播放。如果你不是這么計劃,我會從1增加mquant的值并且在視頻設置中將最大碼流設置為9Mbps以保持一個小一點的碼流。
如果你確實想讓視頻碼率那么高,你需要增大mux率。從提供的列表可以得出bbMPEG使用14706800bits/sec或者1838350bytes /sec的mux率(總數據速率為:1838350bytes/sec(14706800bits/sec)行)。你在強制mux率字段設置的值應該是以?bytes/sec為單位并被50整除。所以我會從36767(1838350/50)開始,一直增加直到不會再出現下溢錯誤為止。
### 音視頻同步原理[ffmpeg]
ffmpeg對視頻文件進行解碼的大致流程:
1.?注冊所有容器格式和CODEC: av_register_all()
2.?打開文件: av_open_input_file()
3.?從文件中提取流信息: av_find_stream_info()
4.?窮舉所有的流,查找其中種類為CODEC_TYPE_VIDEO
5.?查找對應的解碼器: avcodec_find_decoder()
6.?打開編解碼器: avcodec_open()
7.?為解碼幀分配內存: avcodec_alloc_frame()
8.?不停地從碼流中提取中幀數據: av_read_frame()
9.?判斷幀的類型,對于視頻幀調用: avcodec_decode_video()
10.?解碼完后,釋放解碼器: avcodec_close()
11.?關閉輸入文件:av_close_input_file()
output_example.c?中AV同步的代碼如下(我的代碼有些修改),這個實現相當簡單,不過挺說明問題。
### 音視頻同步-時間戳
媒體內容在播放時,最令人頭痛的就是音視頻不同步。從技術上來說,解決音視頻同步問題的最佳方案就是時間戳:首先選擇一個參考時鐘(要求參考時鐘上的時間是線性遞增的);生成數據流時依據參考時鐘上的時間給每個數據塊都打上時間戳(一般包括開始時間和結束時間);在播放時,讀取數據塊上的時間戳,同時參考當前參考時鐘上的時間來安排播放(如果數據塊的開始時間大于當前參考時鐘上的時間,則不急于播放該數據塊,直到參考時鐘達到數據塊的開始時間;如果數據塊的開始時間小于當前參考時鐘上的時間,則“盡快”播放這塊數據或者索性將這塊數據“丟棄”,以使播放進度追上參考時鐘)。
可見,避免音視頻不同步現象有兩個關鍵——一是在生成數據流時要打上正確的時間戳。如果數據塊上打的時間戳本身就有問題,那么播放時再怎么調整也于事無補。假如,視頻流內容是從0s開始的,假設10s時有人開始說話,要求配上音頻流,那么音頻流的起始時間應該是10s,如果時間戳從0s或其它時間開始打,則這個混合的音視頻流在時間同步上本身就出了問題。打時間戳時,視頻流和音頻流都是參考參考時鐘的時間,而數據流之間不會發生參考關系;也就是說,視頻流和音頻流是通過一個中立的第三方(也就是參考時鐘)來實現同步的。第二個關鍵的地方,就是在播放時基于時間戳對數據流的控制,也就是對數據塊早到或晚到采取不同的處理方法。圖2.8中,參考時鐘時間在0-10s內播放視頻流內容過程中,即使收到了音頻流數據塊也不能立即播放它,而必須等到參考時鐘的時間達到10s之后才可以,否則就會引起音視頻不同步問題。
基于時間戳的播放過程中,僅僅對早到的或晚到的數據塊進行等待或快速處理,有時候是不夠的。如果想要更加主動并且有效地調節播放性能,需要引入一個反饋機制,也就是要將當前數據流速度太快或太慢的狀態反饋給“源”,讓源去放慢或加快數據流的速度。熟悉DirectShow的讀者一定知道,DirectShow中的質量控制(Quality Control)就是這么一個反饋機制。DirectShow對于音視頻同步的解決方案是相當出色的。但WMF SDK在播放時只負責將ASF數據流讀出并解碼,而并不負責音視頻內容的最終呈現,所以它也缺少這樣的一個反饋機制。
音視頻同步通訊SDK源碼包分享:
Android:http://down.51cto.com/data/711001
Windows:http://down.51cto.com/data/715497
Linux:http://download.csdn.net/detail/weixiaowenrou/5169796
IOS:http://down.51cto.com/data/715486
WEB:http://down.51cto.com/data/710983!
http://6352513.blog.51cto.com/6342513/1180742