解碼H264檔案的一些基礎知識

2021-07-11 21:46:03 字數 4174 閱讀 4470

b. p - 該幀可以引用前面的幀的資料來解壓縮並且相對於i幀來說,該幀可以壓縮程度更高。

c. b - 該幀可以引用前面的幀和後面的幀的資料,從而壓縮程度最高。

乙個條帶是乙個幀中比較獨特的區域,不同於該幀中的其他區域。在最新的國際標準中,這裡已經存在 i-slices(i-條帶),p-slices(p-條帶)和 b-slices(b-條帶)。

1. i-幀 編碼不依賴於其他幀

2. 可能被編碼器生成並建立於乙個隨機訪問點(來允許解碼器在的該位置開始解碼)

3. 當區分細節時也可能為了避免產生有效的 p-幀 或 b-幀 而生成

4. 普遍來說比其他型別的幀需要更多的位數來編碼

1. 為了解碼的需要,要優先解碼一些其他(幀)

2. 可能包含影象資料或運動向量偏移量或者兩者的組合

3. 能夠按照解碼順序引用前面的

4. 舊的設計標準在解碼時只使用一張前面的解碼作為引用,並且需要該也要在p-幀之前顯示。

5. 在h.264檔案中,在解碼過程中能夠使用多個先前解碼的作為引用,並且相對於被用來做**的幀,該幀能夠以任意順序顯示。

6. 通常,相對於編碼i-幀來說,編碼**幀需要更少的位元位數。

1. 為了解碼的需要,要優先解碼一些其他(幀)

2. 可能包含影象資料或運動向量偏移量或者兩者的組合

a. 舊的標準有乙個關於整個幀的全域性運動補償向量

b. 一些標準關於每個巨集塊都有乙個運動補償向量

3. 一些標準允許每個巨集塊使用兩個運動補償向量(雙向**)

4. 在舊的設計標準中(比如mpeg-2),b-幀從不用來作為其他(幀)的**引用。因此,b-幀可以用乙個稍低質量的編碼(編碼量少的)來完成,因為一些細節的丟失不會對**後續(幀)的質量帶來影響。

5. 在h.264檔案中,有可能被作為解碼其他(幀)的引用(由編碼器決定)

6. 在舊的設計標準中(比如mpeg-2),在解碼過程中會使用前面的2幀解碼作為引用,並且需要其中一幀在b-幀之前顯示,另外一幀在b-幀之後顯示。

8. 通常,相對於編碼i-幀 和 p-幀來說,編碼該幀需要更少的位元位數。

有了已上的基本知識以後,我們已經了解到i-幀是關鍵幀,並且是佔空間最多的幀,因為很多資料都是內編碼的,而p-幀是**幀,需要借助前面的幀來作為引用,從而得到完整的資料,而b-幀是雙向**幀,需要借助前面和後面的幀來作為引用。因此一般來說占用空間排序:i-幀 > p-幀 > b-幀 (i-幀占用空間最多)。

對於如何解析幀型別(i,p還是b幀等等),需要用到nal_unit_type這一字段,在nalu中它佔據第乙個位元組的3~8位,nalu的第乙個位元組(忽略起始碼startcode:0x000001 or 0x00000001)如下:

forbidden_zero_bit: 1 bit

nal_ref_idc: 2 bit

nal_unit_type: 5 bit

官方文件也給出了語**析,以偽**的形式給出的:

後面的f(1),u(2),u(5)是代表要使用的解析方法,前面加深的粗體forbidden_zero_bit,nal_ref_idc,nal_unit_type稱為syntax_element,語法元素,即:解析這些語法元素要用到後面的f(1),u(2),u(5)方法,下面是官方文件中給出的解析方法:

這裡面的解析方法,個人感覺只有exp-golomb-coded的解析有些麻煩(解析具體是什麼幀需要用到該方法),其他的用簡單的幾個位操作就能輕鬆應對了吧,下面講講指數哥倫布編碼的相關資訊:

以下是wiki上給出的解釋(給翻譯過來的,英文水平不好,請輕噴,thanks)

1. (預設k=0的形式)

a. 將原數加1寫成二進位制形式

b. 將1中的二進位制的位數減一併記下,新增這麼多個0到1中二進位制位數的前面

例子:0 ⇒ 1 ⇒ 1

1 ⇒ 10 ⇒ 010

2 ⇒ 11 ⇒ 011

3 ⇒ 100 ⇒ 00100

4 ⇒ 101 ⇒ 00101

5 ⇒ 110 ⇒ 00110

6 ⇒ 111 ⇒ 00111

7 ⇒ 1000 ⇒ 0001000

8 ⇒ 1001 ⇒ 0001001

將其推廣到負數範圍表示,方法如下:

(1) 非負整數x≤0對映到偶數-2x上

(2) 正整數x>0對映到奇數2x - 1上

例子:0 ⇒ 0 ⇒ 1 ⇒ 1

1 ⇒ 1 ⇒ 10 ⇒ 010

−1 ⇒ 2 ⇒ 11 ⇒ 011

2 ⇒ 3 ⇒ 100 ⇒ 00100

−2 ⇒ 4 ⇒ 101 ⇒ 00101

3 ⇒ 5 ⇒ 110 ⇒ 00110

−3 ⇒ 6 ⇒ 111 ⇒ 00111

4 ⇒ 7 ⇒ 1000 ⇒ 0001000

−4 ⇒ 8 ⇒ 1001 ⇒ 0001001

2. 衍生到k階(k≥0)形式

a. 用於編碼更大的數,編碼後形成更少的二進位制位(編碼比較小的數需要使用更多的二進位制位數)

b. 要以k階形式編碼乙個非負整數x,方法如下:

i. 以0階方式編碼⌊x/2^k ⌋

ii. 將x取模2^k

等價方式:

i. 使用0階exp-golomb編碼方式編碼x+2k−1

ii. 從編碼結構中刪除前面的k個0位

官方文件有關於解析哥倫布指數編碼的方法,of course,仍然是以偽**的形式給出: )

再繼續說解析幀型別的方法…

依然是官方文件….

發現了這麼乙個東東

這應該就是我們要分析該nalu是什麼幀型別的關鍵吧!於是找找它在**出現過

很明顯,第3行出現了,再找找slice_header出現的地方

然後再繼續逆向查詢它們分別出現在**,結果最後都在一張表中找到了

於是開始分析:

對於slice_layer_without_partitioning_rbsp:

nal_unit_type = 1,5,19

對於slice_data_partition_a_layer_rbsp:

nal_unit_type = 2

對於slice_layer_extension_rbsp:

nal_unit_type = 20

於是下面就是具體分析nal_unit_type的值來進行相應處理的過程:

首先,在**中列舉如下nal單元型別(參考了下ffmpeg)

相應的,列舉如下slice型別,根據slice型別即能得出幀型別

(具體為什麼要都定義2種,因為根據官方文件來寫的,其實每個第二種型別數值-5即為第一種型別,沒有仔細研究)

具體的解析**在我的github上,歡迎參觀:yijiazhen的github

剛剛接觸h264檔案解析不久,如有分析錯誤或是不到位的地方,懇請各路好漢批評指正,希望可以互相交流,共同提高。

直播一 H 264編碼基礎知識詳解

h.26x系列 由itu 國際電傳視訊聯盟 主導 mpeg系列 由iso 國際標準組織機構 下屬的mpeg 運 象專家組 開發 mpeg 4第二部分 mpeg 4第二部分標準可以使用在網路傳輸 廣播和 儲存上 3 編碼流程 在進行當前訊號編碼時,編碼器首先會產生對當前訊號做 的訊號,稱作 訊號 pr...

針對 H 264, 這裡有一些常用的位元速率方案

針對 h.264,這裡有一些常用的位元速率方案 畫面尺寸 1920 x 1080 真正高畫質 選擇位元速率為7,000 8,000 kbps。畫面尺寸 1280 x 720 通用高畫質 選擇位元速率為5,000 6,000 kbps。畫面尺寸 640 x 480 標清 選擇位元速率為1,000 2,...

模組的一些基礎知識

對linux核心而言,模組是可有可無的特色。這項特色必得在編譯核心時,選擇適當的選項才得以成功。就我所知道的,所有發行系統的核心,都是以模組化定為預設選項的。我們甚至於可以替系統設計新的模組,並且有核心載入執行,而不用重新編譯核心,也不用重新啟動系統。當一模組載入核心時,便成了核心的一部份,因此 這...