本文涉及視頻編解碼最基礎概念,從工程應用角度出發,幫助理解和編寫源碼。本文並不涉及深層次原理和算法。錯誤不免,逐漸完善。html
本文爲做者原創,轉載請註明出處:http://www.javashuo.com/article/p-kfylstit-o.html算法
音視頻領域早期採用模擬化技術,目前已發展爲數字化技術。數字化的主要好處有:可靠性高、可以消除傳輸及存儲損耗,便於計算機處理及網絡傳輸等。數字化後,音視頻處理就進入了計算機技術領域,音視頻處理本質上就是對計算機數據的處理。網絡
圖像信息經採集後生成的原始視頻數據,數據量很是大,對於某些採集後直接本地播放的應用場合,不須要考慮壓縮技術。但現實中更多的應用場合,涉及視頻的傳輸與存儲,傳輸網絡與存儲設備沒法容忍原始視頻數據的巨大數據量,必須將原始視頻數據通過編碼壓縮後,再進行傳輸與存儲。大數據
本文僅關注視頻,不關注音頻。編碼
引自參考資料[1]第1.5節.net
在全部的實際節目素材中,存在着兩種類型的信號份量:即異常的、不可預見的信號份量和能夠預見的信號份量。異常份量稱爲熵,它是信號中的真正信息。其他部分稱爲冗餘,由於它不是必需的信息。冗餘能夠是空間性的,如在圖像的大片區域中,鄰近像素幾乎具備相同的數值。冗餘也能夠是時間性的,例如連續圖像之間的類似部分。在全部的壓縮系統編碼器中都是將熵與冗餘相分離,只有熵被編碼和傳輸,而在解碼器中再從編碼器的發送的信號中計算出冗餘。code
幀內編碼是空間域編碼,利用圖像空間性冗餘度進行圖像壓縮,處理的是一幅獨立的圖像,不會跨越多幅圖像。空間域編碼依賴於一幅圖像中相鄰像素間的類似性和圖案區的主要空間域頻率。視頻
JPEG標準用於靜止圖像(即圖片),只使用了空間域壓縮,只使用幀內編碼。htm
幀間編碼是時間域編碼,是利用一組連續圖像間的時間性冗餘度進行圖像壓縮。若是某幀圖像可被解碼器使用,那麼解碼器只須利用兩幀圖像的差別便可獲得下一幀圖像。好比運動平緩的幾幀圖像的類似性大,差別性小,而運動劇烈的幾幅圖像則類似性小,差別性大。當獲得一幀完整的圖像信息後,能夠利用與後一幀圖像的差別值推算獲得後一幀圖像,這樣就實現了數據量的壓縮。時間域編碼依賴於連續圖像幀間的類似性,儘量利用已接收處理的圖像信息來「預測」生成當前圖像。blog
MPEG標準用於運動圖像(即視頻),會使用空間域編碼和時間域編碼,所以是幀內編碼和幀間編碼結合使用。
一組連續圖像記錄了目標的運動。運動矢量用於衡量兩幀圖像間目標的運動程度,運動矢量由水平位移量和垂直位移量兩者構成。
目標的運動下降了圖像間的類似性,增長了差別數據量。而運動補償則經過運行矢量來下降圖像間的差別數據量。
下圖爲運動補償的示意圖。當某一目標運動時,其位置會變化但形狀顏色等基本不變。編碼器則可利用運動矢量減低圖像差值,解碼器根據圖像差值中的運動適量移動目標到合適的位置便可。假設圖中是理想狀況,目標除移動位置外其餘任何屬性無任何變化,則兩幅圖像間的差值僅包含運動矢量這一數據量。顯然運動補償能夠顯著減小圖像差值數據量。
先看示意圖:
連續的三幅圖像中,目標塊有垂直位置上的移動,背景塊無位置移動。咱們考慮如何取得當前幀圖像(畫面N):
畫面N中,目標向上移動後,露出背景塊。
畫面N-1中,由於背景塊被目標塊遮擋住了,所以沒有背景塊相關信息。
畫面N+1中,完整包含背景塊的數據,所以畫面N能夠從畫面N-1中取得背景塊。
如何能夠獲得畫面N呢?解碼器能夠先解碼獲得畫面N-1和畫面N+1,經過畫面N-1中的目標塊數據結合運動矢量便可獲得畫面N中的目標塊數據,經過畫面N+1中的背景塊數據則可獲得畫面N中的背景塊數據。三幅畫面的解碼順序爲:N-1, N+1, N。三幅畫面的顯示順序爲:N-1, N, N+1。畫面N經過其前一幅畫面N-1和後一幅畫面N+1推算(預測,predicted)獲得,所以這種方式稱爲雙向預測(或前面預測、雙向參考)。
I幀:I幀(Intra-coded picture, 幀內編碼幀,常稱爲關鍵幀)包含一幅完整的圖像信息,屬於幀內編碼圖像,不含運動矢量,在解碼時不須要參考其餘幀圖像。所以在I幀圖像處能夠切換頻道,而不會致使圖像丟失或沒法解碼。I幀圖像用於阻止偏差的累積和擴散。在閉合式GOP中,每一個GOP的第一個幀必定是I幀,且當前GOP的數據不會參考先後GOP的數據。
IDR幀:IDR幀(Instantaneous Decoding Refresh picture, 即時解碼刷新幀)是一種特殊的I幀。當解碼器解碼到IDR幀時,會將DPB(Decoded Picture Buffer,指先後向參考幀列表)清空,將已解碼的數據所有輸出或拋棄,而後開始一次全新的解碼序列。IDR幀以後的圖像不會參考IDR幀以前的圖像。
P幀:P幀(Predictive-coded picture, 預測編碼圖像幀)是幀間編碼幀,利用以前的I幀或P幀進行預測編碼。
B幀:B幀(Bi-directionally predicted picture, 雙向預測編碼圖像幀)是幀間編碼幀,利用以前和(或)以後的I幀或P幀進行雙向預測編碼。B幀不能夠做爲參考幀。
GOP(Group Of Pictures, 圖像組)是一組連續的圖像,由一個I幀和多個B/P幀組成,是編解碼器存取的基本單位。GOP結構經常使用的兩個參數M和N,M指定GOP中首個P幀和I幀之間的距離,N指定一個GOP的大小。例如M=1,N=15,GOP結構爲:IPBBPBBPBBPBBPBGOP有兩種:閉合式GOP和開放式GOP:
閉合式GOP:閉合式GOP只須要參考本GOP內的圖像便可,不需參考先後GOP的數據。這種模式決定了,閉合式GOP的顯示順序老是以I幀開始以P幀結束
開放式GOP :開放式GOP中的B幀解碼時可能要用到其前一個GOP或後一個GOP的某些幀。碼流裏面包含B幀的時候纔會出現開放式GOP。
開放式GOP和閉合式GOP中I幀、P幀、B幀的依賴關係以下圖所示:
DTS(Decoding Time Stamp, 解碼時間戳),表示packet的解碼時間。
PTS(Presentation Time Stamp, 顯示時間戳),表示packet解碼後數據的顯示時間。
音頻中DTS和PTS是相同的。視頻中因爲B幀須要雙向預測,B幀依賴於其前和其後的幀,所以含B幀的視頻解碼順序與顯示順序不一樣,即DTS與PTS不一樣。固然,不含B幀的視頻,其DTS和PTS是相同的。下圖以一個開放式GOP示意圖爲例,說明視頻流的解碼順序和顯示順序
採集順序指圖像傳感器採集原始信號獲得圖像幀的順序。
編碼順序指編碼器編碼後圖像幀的順序。存儲到磁盤的本地視頻文件中圖像幀的順序與編碼順序相同。
傳輸順序指編碼後的流在網絡中傳輸過程當中圖像幀的順序。
解碼順序指解碼器解碼圖像幀的順序。
顯示順序指圖像幀在顯示器上顯示的順序。
採集順序與顯示順序相同。編碼順序、傳輸順序和解碼順序相同。
圖中「B[1]」幀依賴於「I[0]」幀和「P[3]」幀,所以「P[3]」幀必須比「B[1]」幀先解碼。這就致使瞭解碼順序和顯示順序的不一致,後顯示的幀須要先解碼。
[1] 泰克Tektronic, MPEG基礎和協議分析指南
[2] 視頻直播的理論知識,https://www.jianshu.com/p/04b5b1e4ff27
[3] open GOP & close GOP, https://www.jianshu.com/p/d30c051b4106
[4] I幀/B幀/P幀/GOP, https://blog.csdn.net/abcsunl/article/details/68190136
[5] FFmpeg音視頻同步原理與實現, https://www.jianshu.com/p/3578e794f6b5
[6] FFmpeg音視頻同步, https://www.jianshu.com/p/27279255f67e
2018-12-08 V1.0 初稿