H264 碼流結構詳解

2022-06-30 07:27:08 字數 3415 閱讀 6868

nal:負責以網路所要求的恰當的方式對 vcl 資料進行打包和傳送。

壓縮:**(幀內**和幀間**)-> dct 變化和量化 -> 位元流編碼;

切分資料,主要為了第三步。這裡一點,網上看到的「切片(slice)」、「巨集塊(macroblock)」是在vcl 中的概念,一方面提高編碼效率和降低誤位元速率、另一方面提高網路傳輸的靈活性。

壓縮切分後的 vcl 資料會包裝成為nal中的一部分。

下面要重點講解下 nal。

nal,英文全稱為network abstraction layer,這塊和 h264 壓縮演算法無關,涉設計出 nal 的目的就是為了獲得 「network-friendly」,即為了實現良好的網路親和性,即可適用於各種傳輸網路。

終於要講 nal 了,但是,我們需要先看 nal的組成單元 -nalu

nalu 的格式如下圖(引用h264 pdf)所示:

很明顯,nalu 由身體兩個部分組成:

首先,nalu header只佔 1 個位元組,即 8 位,其組成如下圖所示:

其中比較注意的應該是以下幾個:

特殊的 nalu 型別:sps和pps

spspps儲存了編譯碼需要一些影象引數,sps,pps 需要在 i 幀前出現,不然解碼器沒法解碼。而 sps,pps 出現的頻率也跟不同應用場景有關,對於乙個本地 h264 流,可能只要在第乙個 i 幀前面出現一次就可以,但對於直播流,每個 i 幀前面都應該插入 sps 或 pps,因為直播時客戶端進入的時間是不確定的。

很少有資料會稱身體部分為 payload,絕大部分資料對 nalu 組成的定義是這樣子的:

nalu = nalu header + sodb // 定義1

nalu = nalu header + rbsp // 定義2

nalu = nalu header + ebsp // 定義3

於是新的問題來了:sodb,rbsp和ebsp都是什麼東西呢?這塊概念,在部落格nalu詳解二(ebsp、rbsp與sodb)中介紹得非常清楚,總結來說就是:

sodb

英文全稱string of data bits,稱原始資料位元流,就是最原始的編碼/壓縮得到的資料。

rbsp

英文全稱raw byte sequence payload,又稱原始位元組序列載荷。和sodb關係如下:

rbsp = sodb + rbsp trailing bits(rbsp尾部補齊位元組)
引入 rbsp trailing bits 做 8 位位元組補齊。

ebsp

英文全稱encapsulated byte sequence payload,稱為擴充套件位元組序列載荷。和rbsp關係如下:

ebsp :rbsp插入防競爭位元組(`0x03`)
這裡說明下防止競爭位元組(0x03):讀者可以先認為 h264 會插入乙個叫做startcode的位元組串來分割nalu,於是問題來了,如果rbsp中也包括了startcode(0x000001 或 0x00000001)怎麼辦呢?所以,就有了防止競爭位元組(0x03)

編碼時,掃瞄 rbsp,如果遇到連續兩個 0x00 位元組,就在後面新增 防止競爭位元組(0x03);解碼時,同樣掃瞄 ebsp,進行逆向操作即可。
最後,以一幅圖總結 nalu 這段內容:

h264 碼流實際可以理解為由乙個乙個的 nalu 單元組成。(下圖中的 rbsp 類似 nalu payload)

前面提到的一幀影象(i 幀, p 幀, b 幀)就是乙個 nalu 單元,nalu 單元除了代表影象外還能包含其他型別的資料,如 pps 和 sps。

片的目的:

為了限制誤碼的擴散和傳輸,使編碼片相互間保持獨立。片共有 5 種型別: i 片(只包含 i 巨集塊)、p 片(p 和 i 巨集塊)、b 片(b 和 i 巨集塊)、sp 片(用於不同編碼流之 間的切換)和 si 片(特殊型別的編碼巨集塊)。

了解了nalu之後,關於 h264 格式,還有乙個問題:解碼器怎麼知道乙個 nalu 要結束了?或者說它怎麼區分 nalu 的邊界?

要回答這個問題,就必須了解 h264 的打包方式,通俗來說是h264 如何組織一連串的 nalu 為完整的 h264 碼流。目前 h264 主流的兩種格式:

至於為什麼要有這兩類格式,還需要查閱更多的資料。不過 stackoverflow 上關於possible locations for sequence/picture parameter set(s) for h.264 stream的回答可以幫助深入了解這兩種格式,推薦閱讀。

下面是乙個 h264 碼流,可以看到每個 nalu 前有乙個startcode(0x000001 或 0x00000001),作為 nalu 的分割符:

分析其中比較有代表性的3幀:

參考:

h264系列--碼流組成和分層結構

(十三) h264標準解析

H 264碼流結構

a 對照 h.263 的碼流結構 h.263 定義的碼流結構是分級結構,共四層。自上而下分別為 影象層 picture layer 塊組層 gob layer 巨集塊層 macroblock layer 和塊層 block layer psctr ptype pquant cpmpsbi trbdb...

H 264碼流結構

a 對照 h.263的碼流結構 h.263定義的碼流結構是分級結構,共四層。自上而下分別為 影象層 picture layer 塊組層 gob layer 巨集塊層 macroblock layer 和塊層 block layer psc tr ptype pquant cpmpsbi trbdbq...

H 264碼流結構

什麼是封裝格式 重新整理影象概念 在我們的印象中,一張就是一張影象,而在h264中影象是個集合的概念。逐行掃瞄與隔行掃瞄.png 幀與場.png h264原始碼流 h264碼流.png 乙個原始的h.264 nalu 單元常由 startcode nalu header nalu payload 三...