本文主要介紹一種非常流行的視頻編碼:H.264。
計算一下:10秒鍾1080p(1920x1080)、30fps的YUV420P原始視頻,需要占用多大的存儲空間?
- (10 * 30) * (1920 * 1080) * 1.5 = 933120000字節 ≈ 889.89MB
- 可以看得出來,原始視頻的體積是非常巨大的
由於網絡帶寬和硬盤存儲空間都是非常有限的,因此,需要先使用視頻編碼技術(比如H.264編碼)對原始視頻進行壓縮,然后再進行存儲和分發。H.264編碼的壓縮比可以達到至少是100:1。
簡介
H.264,又稱為MPEG-4 Part 10,Advanced Video Coding。
- 譯為:MPEG-4第10部分,高級視頻編碼
- 簡稱:MPEG-4 AVC
H.264是迄今為止視頻錄制、壓縮和分發的最常用格式。截至2019年9月,已有91%的視頻開發人員使用了該格式。H.264提供了明顯優於以前任何標准的壓縮性能。H.264因其是藍光盤的其中一種編解碼標准而著名,所有藍光盤播放器都必須能解碼H.264。
編碼器
H.264標准允許制造廠商自由地開發具有競爭力的創新產品,它並沒有定義一個編碼器,而是定義了編碼器應該產生的輸出碼流。
x264是一款免費的高性能的H.264開源編碼器。x264編碼器在FFmpeg中的名稱是libx264。
AVCodec *codec = avcodec_find_encoder_by_name("libx264");
解碼器
H.264標准中定義了一個解碼方法,但是制造廠商可以自由地開發可選的具有競爭力的、新的解碼器,前提是他們能夠獲得與標准中采用的方法同樣的結果。
FFmpeg默認已經內置了一個H.264的解碼器,名稱是h264。
AVCodec *codec1 = avcodec_find_decoder_by_name("h264");
// 或者
AVCodec *codec2 = avcodec_find_decoder(AV_CODEC_ID_H264);
編碼過程與原理
H.264的編程過程比較復雜,本文只介紹大體的框架和脈絡,具體細節就不展開了。
大體可以歸納為以下幾個主要步驟:
- 划分幀類型
- 幀內/幀間編碼
- 變換 + 量化
- 濾波
- 熵編碼
划分幀類型
有統計結果表明:在連續的幾幀圖像中,一般只有10%以內的像素有差別,亮度的差值變化不超過2%,而色度的差值變化只在1%以內。
GOP
於是可以將一串連續的相似的幀歸到一個圖像群組(Group Of Pictures,GOP)。
GOP中的幀可以分為3種類型:
- I幀(I Picture、I Frame、Intra Coded Picture),譯為:幀內編碼圖像,也叫做關鍵幀(Keyframe)
- 是視頻的第一幀,也是GOP的第一幀,一個GOP只有一個I幀
- 編碼
- 對整幀圖像數據進行編碼
- 解碼
- 僅用當前I幀的編碼數據就可以解碼出完整的圖像
- 是一種自帶全部信息的獨立幀,無需參考其他圖像便可獨立進行解碼,可以簡單理解為一張靜態圖像
- P幀(P Picture、P Frame、Predictive Coded Picture),譯為:預測編碼圖像
- 編碼
- 並不會對整幀圖像數據進行編碼
- 以前面的I幀或P幀作為參考幀,只編碼當前P幀與參考幀的差異數據
- 解碼
- 需要先解碼出前面的參考幀,再結合差異數據解碼出當前P幀完整的圖像
- 編碼
- B幀(B Picture、B Frame、Bipredictive Coded Picture),譯為:前后預測編碼圖像
- 編碼
- 並不會對整幀圖像數據進行編碼
- 同時以前面、后面的I幀或P幀作為參考幀,只編碼當前B幀與前后參考幀的差異數據
- 因為可參考的幀變多了,所以只需要存儲更少的差異數據
- 解碼
- 需要先解碼出前后的參考幀,再結合差異數據解碼出當前B幀完整的圖像
- 編碼
不難看出,編碼后的數據大小:I幀 > P幀 > B幀。
在較早的視頻編碼標准(例如MPEG-2)中,P幀只能使用一個參考幀,而一些現代視頻編碼標准(比如H.264),允許使用多個參考幀。
GOP的長度
GOP的長度表示GOP的幀數。GOP的長度需要控制在合理范圍,以平衡視頻質量、視頻大小(網絡帶寬)和seek效果(拖動、快進的響應速度)等。
-
加大GOP長度有利於減小視頻文件大小,但也不宜設置過大,太大則會導致GOP后部幀的畫面失真,影響視頻質量
-
由於P、B幀的復雜度大於I幀,GOP值過大,過多的P、B幀會影響編碼效率,使編碼效率降低
-
如果設置過小的GOP值,視頻文件會比較大,則需要提高視頻的輸出碼率,以確保畫面質量不會降低,故會增加網絡帶寬
-
GOP長度也是影響視頻seek響應速度的關鍵因素,seek時播放器需要定位到離指定位置最近的前一個I幀,如果GOP太大意味着距離指定位置可能越遠(需要解碼的參考幀就越多)、seek響應的時間(緩沖時間)也越長
GOP的類型
GOP又可以分為開放(Open)、封閉(Closed)兩種。
- Open
- 前一個GOP的B幀可以參考下一個GOP的I幀
- Closed
- 前一個GOP的B幀不能參考下一個GOP的I幀
- GOP不能以B幀結尾
需要注意的是:
-
由於P幀、B幀都對前面的參考幀(P幀、I幀)有依賴性,因此,一旦前面的參考幀出現數據錯誤,就會導致后面的P幀、B幀也出現數據錯誤,而且這種錯誤還會繼續向后傳播
-
對於普通的I幀,其后的P幀和B幀可以參考該普通I幀之前的其他I幀
在Closed GOP中,有一種特殊的I幀,叫做IDR幀(Instantaneous Decoder Refresh,譯為:即時解碼刷新)。
- 當遇到IDR幀時,會清空參考幀隊列
- 如果前一個序列出現重大錯誤,在這里可以獲得重新同步的機會,使錯誤不會繼續往下傳播
- 一個IDR幀之后的所有幀,永遠都不會參考該IDR幀之前的幀
- 視頻播放時,播放器一般都支持隨機seek(拖動)到指定位置,而播放器直接選擇到指定位置附近的IDR幀進行播放最為便捷,因為可以明確知道該IDR幀之后的所有幀都不會參考其之前的其他I幀,從而避免較為復雜的反向解析
幀內/幀間編碼
I幀采用的是幀內(Intra Frame)編碼,處理的是空間冗余。
P幀、B幀采用的是幀間(Inter Frame)編碼,處理的是時間冗余。
划分宏塊
在進行編碼之前,首先要將一張完整的幀切割成多個宏塊(Macroblock),H.264中的宏塊大小通常是16x16。
宏塊可以進一步拆分為多個更小的變換塊(Transform blocks)、預測塊(Prediction blocks)。
-
變換塊的尺寸有:16x16、8x8、4x4
-
預測塊的尺寸有:16×16、16×8、8×16、8×8、8×4、4×8、4×4
幀內編碼
幀內編碼,也稱幀內預測。以4x4的預測塊為例,共有9種可選的預測模式。
利用幀內預測技術,可以得到預測幀,最終只需要保留預測模式信息、以及預測幀與原始幀的殘差值。
編碼器會選取最佳預測模式,使預測幀更加接近原始幀,減少相互間的差異,提高編碼的壓縮效率。
幀間編碼
幀間編碼,也稱幀間預測,用到了運動補償(Motion compensation)技術。
編碼器利用塊匹配算法,嘗試在先前已編碼的幀(稱為參考幀)上搜索與正在編碼的塊相似的塊。如果編碼器搜索成功,則可以使用稱為運動矢量的向量對塊進行編碼,該向量指向匹配塊在參考幀處的位置。
在大多數情況下,編碼器將成功執行,但是找到的塊可能與它正在編碼的塊不完全匹配。這就是編碼器將計算它們之間差異的原因。這些殘差值稱為預測誤差,需要進行變換並將其發送給解碼器。
綜上所述,如果編碼器在參考幀上成功找到匹配塊,它將獲得指向匹配塊的運動矢量和預測誤差。使用這兩個元素,解碼器將能夠恢復該塊的原始像素。
如果一切順利,該算法將能夠找到一個幾乎沒有預測誤差的匹配塊,因此,一旦進行變換,運動矢量加上預測誤差的總大小將小於原始編碼的大小。
如果塊匹配算法未能找到合適的匹配,則預測誤差將是可觀的。因此,運動矢量的總大小加上預測誤差將大於原始編碼。在這種情況下,編碼器將產生異常,並為該特定塊發送原始編碼。
變換與量化
接下來對殘差值進行DCT變換(Discrete Cosine Transform,譯為離散余弦變換)。
規格
H.264的主要規格有:
- Baseline Profile(BP)
- 支持I/P幀,只支持無交錯(Progressive)和CAVLC
- 一般用於低階或需要額外容錯的應用,比如視頻通話、手機視頻等即時通信領域
- Extended Profile(XP)
- 在Baseline的基礎上增加了額外的功能,支持流之間的切換,改進誤碼性能
- 支持I/P/B/SP/SI幀,只支持無交錯(Progressive)和CAVLC
- 適合於視頻流在網絡上的傳輸場合,比如視頻點播
- Main Profile(MP)
- 提供I/P/B幀,支持無交錯(Progressive)和交錯(Interlaced),支持CAVLC和CABAC
- 用於主流消費類電子產品規格如低解碼(相對而言)的MP4、便攜的視頻播放器、PSP和iPod等
- High Profile(HiP)
- 最常用的規格
- 在Main的基礎上增加了8x8內部預測、自定義量化、無損視頻編碼和更多的YUV格式(如4:4:4)
- High 4:2:2 Profile(Hi422P)
- High 4:4:4 Predictive Profile(Hi444PP)
- High 4:2:2 Intra Profile
- High 4:4:4 Intra Profile
- 用於廣播及視頻碟片存儲(藍光影片),高清電視的應用