H264 編解碼協議詳解

1.、什麼是 H264?

H264 是 MPEG-4 標準所定義的最新編碼格式,同時也是技術含量最高、代表最新技術水平的視頻編碼格式之一,標準寫法應該是H.264

H264 視頻格式是經過有損壓縮的,但在技術上儘可能做的降低存儲體積下獲得較好圖像質量和低帶寬圖像快速傳輸。

2、一些相關名詞解釋

下圖爲 H264 碼流分層圖
image

2.1、VCL & NAL

H264 原始碼流是由一個接一個 NALU(NAL Unit) 組成,它的功能分爲兩層,VCL(Video Coding Layer)視頻編碼層和 NAL(Network Abstraction Layer)網絡提取層。

  1. VCL:包括核心壓縮引擎和塊、宏塊和片的語法級別定義,設計目標是儘可能地獨立於網絡進行高效的編碼;
  2. NAL:負責將 VCL 產生的比特字符串適配到各種各樣的網絡和多元環境中,覆蓋了所有片級以上的語法級別;

NAL是 H.264 爲適應網絡傳輸應用而制定的一層數據打包操作。傳統的視頻編碼算法編完的視頻碼流在任何應用領域下(無論用於存儲、傳輸等)都是統一的碼流模式,視頻碼流僅有視頻編碼層 VCL(Video Coding Layer)。而 H.264 可根據不同應用增加不同的 NAL 片頭,以適應不同的網絡應用環境,減少碼流的傳輸差錯。

在 VCL 進行數據傳輸或存儲之前,這些編碼的 VCL 數據,被映射或封裝進NAL單元(NALU)。

一個 NALU = 一組對應於視頻編碼的 NALU 頭部信息 + 一個原始字節序列負荷(RBSP,Raw Byte Sequence Payload)

image

一個原始的 H.264 NALU 單元常由 [StartCode] [NALU Header] [NALU Payload] 三部分組成,其中 Start Code 用於標示這是一個NALU 單元的開始,必須是 “00 00 00 01”

實際原始視頻圖像數據保存在 VCL 分層的 NAL Units 中

2.2、片(slice)

一個片 = Slice Header + Slice Data

片是 H.264 提出的新概念,實際原始視頻圖像數據保存在 VCL 層級的 NAL Unit 中,這部分數據在碼流中被稱作是片(slice)。一個 slice 包含一幀圖像的部分或全部數據,換言之,一幀視頻圖像可以編碼爲一個或若干個 slice。一個 slice 最少包含一個宏塊,最多包含整幀圖像的數據。在不同的編碼實現中,同一幀圖像中所構成的 slice 數目不一定相同。

一個 slice 編碼之後被打包進一個 NALU,所以 slice = NALU

那麼爲什麼要設置片呢?

設置片的目的是爲了限制誤碼的擴散和傳輸,應使編碼片相互間是獨立的。某片的預測不能以其他片中的宏塊爲參考圖像,這樣某一片中的預測誤差纔不會傳播到其他片中。

在上圖中,可以看到每個圖像中,若干宏塊(Macroblock)被排列成片。一個視頻圖像可編成一個或更多個片,每片包含整數個宏塊 (MB),每片至少包含一個宏塊。

slice 類型
slice 意義
I slice 只包含 I 宏塊
P slice 包含 P 和 I 宏塊
B slice 包含 B 和 I 宏塊
SP slice 包含 P 或 I 宏塊,用於不同碼流之間的切換
SI slice 一種特殊類型的編碼宏塊

slice 組成

每一個 slice 總體來看都由兩部分組成,一部分作爲 slice header,用於保存 slice 的總體信息(如當前 slice 的類型等),另一部分爲 slice body,通常是一組連續的宏塊結構(或者宏塊跳過信息)

image

2.3、宏塊(Macroblock)

剛纔在片中提到了宏塊,那麼什麼是宏塊呢?

宏塊是視頻信息的主要承載者。一個編碼圖像通常劃分爲多個宏塊組成.包含着每一個像素的亮度和色度信息。視頻解碼最主要的工作則是提供高效的方式從碼流中獲得宏塊中像素陣列。

一個宏塊由一個 16×16 亮度像素和附加的一個 8×8 Cb 和一個 8×8 Cr 彩色像素塊組成。

宏塊分類 意義
I 宏塊 利用從當前片中已解碼的像素作爲參考進行幀內預測
P 宏塊 利用前面已編碼圖像作爲參考進行幀內預測
B 宏塊 利用雙向的參考圖像(當前和未來的已編碼圖像幀)進行幀內預測

2.4、幀(frame)和場(filed)

視頻的一場和一幀用來產生一個編碼圖像,一幀通常是一個完整的圖像,當採集視頻信號時,如果採用隔行掃描(奇、偶數行),則掃描下來的一幀圖像就被分成了兩個部分,這每一部分都被稱爲 [場],根據次序,分爲 [頂場] 和 [底場]。

擴展閱讀:爲什麼會產生場的概念?

人眼可察覺到的電視視頻圖像刷新中的閃爍爲 0.02 秒,即當電視系統的幀率低於 50 幀/秒,人眼可感覺得出畫面的閃爍。常規如 PAL 制式電視系統幀率爲 25 幀/秒、NTSC 制式的則爲 30 幀/秒,如果採用逐行掃描將不可避免地在視頻刷新時產生閃爍現象。而另一方面如果單純的提高幀率達到避免閃爍刷新效果,則會增加系統的頻帶寬度。

這便引出了隔行掃描技術及 [場] 的概念

在隔行掃描中,每一幀包含兩個場(top field)和(bottom field),其中每個 field 包含一幀中一半數量的水平線,top field 包含所有奇數線,bottom field 則包含所有偶數線。則在電視顯示過程中,電子槍每發射一行隔一行—先發射奇數行13579…(top field)回頭再發射2468…(bottom field)利用兩次掃描來完成一幅圖像,因爲視覺的滯留性,我們看到的效果是差不多的。如在 NTSC 視頻中 frame 的頻率爲30次/秒-àfield的頻率則爲 60 次/秒,大於了人眼可察覺閃爍的頻率。

適用類型
方式 作用域
幀編碼方式 活動量較小或者靜止的圖像宜採用
場編碼方式 活動量較大的運動圖像

image

2.5、I 幀、P 幀、B 幀與 pts/dts

幀的分類 中文 意義
I 幀 幀內編碼幀,又稱 intra picture I 幀通常是每個 GOP(MPEG 所使用的一種視頻壓縮技術)的第一個幀,經過適度地壓縮,做爲隨機訪問的參考點,可以當成圖象。I幀可以看成是一個圖像經過壓縮後的產物
P 幀 前向預測編碼幀,又稱 predictive-frame 通過充分將低於圖像序列中前面已編碼幀的時間冗餘信息來壓縮傳輸數據量的編碼圖像,也叫預測幀
B 幀 雙向預測幀,又稱 bi-directional interpolated prediction frame 既考慮與源圖像序列前面已編碼幀,也顧及源圖像序列後面已編碼幀之間的時間冗餘信息來壓縮傳輸數據量的編碼圖像,也叫雙向預測幀
  • I frame: 自身可以通過視頻解壓算法解壓成一張單獨的完整的圖片;
  • P frame:需要參考其前面的一個 I frame 或者 B frame 來生成一張完整的圖片;
  • B frame: 則要參考其前一個 I 或者 P幀 及其後面的一個 P 幀來生成一張完整的圖片;
pts/dts
名稱 意義
PTS(Presentation Time Stamp) PTS 主要用於度量解碼後的視頻幀什麼時候被顯示出來
DTS(Decode Time Stamp) DTS 主要是標識內存中的 bit 流什麼時候開始送入解碼器中進行解碼

image

DTS 與 PTS 的不同:
DTS 主要用戶視頻的解碼,在解碼階段使用。PTS主要用於視頻的同步和輸出,在 display 的時候使用。再沒有 B frame 的時候輸出順序是一樣的。

2.6、GOP

GOP 是畫面組,一個 GOP 是一組連續的畫面。
GOP 一般有兩個數字,如 M = 3,N = 12,M 制定 I 幀與 P 幀之間的距離,N 指定兩個 I 幀之間的距離。那麼現在的 GOP 結構是

I BBP BBP BBP BB I

增大圖片組能有效的減少編碼後的視頻體積,但是也會降低視頻質量,至於怎麼取捨,得看需求了。

2.7、IDR

一個序列的第一幀叫做 IDR幀(Instantaneous Decoding Refresh,立即解碼刷新)。

I 幀和 IDR 幀都是使用幀內預測,本質上是同一個東西,在解碼和編碼中爲了方便,將視頻序列中第一個 I 幀和其他 I 幀區分開,所以把第一個 I 幀稱作 IDR,這樣就方便控制編碼和解碼流程。

IDR 幀的作用是立刻刷新,使錯誤不致傳播,從 IDR 幀開始,重新算一個新的序列開始編碼。

核心作用

H.264 引入 IDR 幀是爲了解碼的重同步,當解碼器解碼到 IDR 幀時,立即將參考幀隊列清空,將已解碼的數據全部輸出或拋棄,重新查找參數集,開始一個新的序列。這樣,如果前一個序列出現重大錯誤,在這裏可以獲得重新同步的機會,IDR 幀之後的幀永遠不會使用 IDR 之前的圖像的數據來解碼。

3、H264 碼流分層結構

image

如上圖,在 H264 中,句法元素共被組織成:序列、圖像(幀)、片、宏塊、子宏塊五個層次。

句法元素的分層結構有助於更有效地節省碼流。例如,在一個圖像中,經常會在各個片之間有相同的數據,如果每個片都同時攜帶這些數據,勢必會造成碼流的浪費。更爲有效的做法是將該圖像的公共信息抽取出來,形成圖像一級的句法元素,而在片級只攜帶該片自身獨有的句法元素。

4、NALU Header & RBSP 結構

image

如上圖:NALU = NAL Header + RBSP

4.1、NALU Header

前面已經說到,每個 NALU 由一個字節的 Header 和 RBSP(Raw Byte Sequence Payload) 組成。

NALU Header 由三部分組成,forbidden_bit(1bit),nal_ref_idc(2bits)代表優先級,nal_unit_type(5bits)代表該 NALU 的類型。

forbidden_zero_bit

1 bit,H264 規定此位必須爲 0

nal_ref_idc

用於表示當前 NALU 的重要性,值越大,越重要

解碼器在解碼處理不過來的時候,可以丟掉重要性爲 0 的 NALU

  1. nal_ref_idc 不等於 0 時, NAL unit 的內容可能是 SPS/PPS/參考幀 的片
  2. nal_ref_idc 等於 0 時,NAL unit 的內容可能是非參考圖像的片
  3. 當某個圖像的片的 nal_ref_id 等於 0 時,該圖像的所有片均應等於 0

nal_unit_type

nal_unit_type 是否包含 VCL 層編碼數據分爲 VCL NAL units 和 non-VCL NAL units;

VCL NAL units 中包含 VCL 層編碼輸出的數據, 而 non-VCL NAL units 則不包含。

nal_unit_type the content of NAL unit
1 ~ 5 VCL NAL units
others(SPS/PPS .etc) non-VCL NAL units

所有的值對於類型如下:

image

4.2、RBSP

image

上圖是 RBSP 序列舉例

image

上圖是 RBSP 的描述

SODB 與 RBSP

SODB 數據比特串 -> 是編碼後的原始數據.
RBSP 原始字節序列載荷 -> 在原始編碼數據的後面添加了 結尾比特。一個 bit “1” 若干比特 “0”,以便字節對齊。

image

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