1. 程式人生 > >H264 編解碼協議詳解

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