H.264 入門知識
大家如果有做過音視頻相關的項目,那么肯定對 H.264 相關的概念了解的比較通透,這里我為什么還要寫這樣一篇文章呢?一來是為了對知識的總結,二來是為了給剛入門音視頻的同學一個參考。
基礎概念
H.264 又稱為 MPEG-4 , 它是一種面向塊,基于運動補償?shù)囊曨l編碼標準,是目前市面上最常用的一種視頻編碼格式,在 Android 中你可以通過 MediaCodec.createEncoderByType("video/avc") 的形式來創(chuàng)建一個編碼器,也可以通過軟編 avcodec_find_encoder(AV_CODEC_ID_H264) / avcodec_find_encoder_by_name("libx264") 的形式來創(chuàng)建一個編碼器。因為該篇文章的主題是分析 H.264 碼流,就不再過多介紹怎么來進行編碼了?,F(xiàn)在就直接來了解一些常用概念吧。

GOP
兩個 I 幀之間形成的一組圖片,就是 GOP (Group Of Picture) 的概念。
I 幀
I 幀又稱為視頻的關鍵幀,你可以理解為它是一幀畫面的完整圖像,可以直接拿這個 I 幀來解碼
特點:
1、它是一個全幀壓縮編碼幀,它將全幀圖像信息進行 JPEG 壓縮編碼及傳輸
2、解碼時僅用 I 幀的數(shù)據(jù)就可以重構完整圖像
3、I 幀描述了圖像背景和運動主體的詳情
4、I 幀不需要參考其它畫面而生成
5、I 幀是 P/B 幀的參考幀(其質量直接影響到同組中以后個幀的質量)
6、I 幀是幀組 GOP 的第一幀,在一組中只有一個 I 幀
7、I 幀不需要考慮運動矢量
8、I 幀所占數(shù)據(jù)的信息量比較大
B 幀
B 幀又稱為雙向差別幀,也就是本幀與前后幀的差別,大白話的意思就是要解碼 B 幀,不僅要拿到之前緩存的畫面,還要解碼之后的畫面,通過前后畫面的疊加來還原最終的畫面。
特點:
1、B 幀是由前面的 I 幀或 P 幀和后面的 P 幀來進行預測的
2、B 幀傳送的是它前面的 I 幀或 P 幀和后面的 P 幀之前的預測誤差及運動矢量
3、B 幀是雙向預測編碼幀
4、B 幀壓縮率最高,因為它只反映參考幀間運動主體的變化情況,預測比較準確
5、B 幀不是參考幀,不會造成解碼錯誤的擴散
P 幀
P 幀又稱為前預測編碼幀。P 幀表示的是這一幀跟之前的一個 I 或 P 幀的差別,解碼時需要用之前緩存的畫面疊加上本幀定義的差別,來生成最終畫面。
特點:
1、P 幀是 I 幀后面相隔 1~2 幀的編碼幀
2、P 幀采用運動補償?shù)姆椒▊魉退c前面的 I 或 P 幀的差值及運動矢量
3、解碼時必須將 I 幀中的預測值與預測誤差求和后才能重構完整的 P 幀圖像
4、P 幀屬于前向預測的幀間編碼。它只參考前面最靠近它的 I 或者 P 幀
5、P 幀可以是其后面的 P 幀的參考幀,也可以是其前后的 B 幀的參考幀
6、由于 P 幀是參考幀,所以它可能造成解碼錯誤的擴散
7、由于是差值傳送,所以 P 幀的壓縮率比較高
基本的幀概念了解的差不多了,下一步我們基于代碼來分析碼流
碼流分析
H.264 又稱為裸流,是由多個 NALU 組成。如果 NALU 對應的 Slice 為一幀的開始,那么就用 4 個 字節(jié)表示,即 0x00 00 00 01 , 否則用 3 字節(jié)表示,0x00 00 01。要分析 H.264 碼流首先是從碼流中搜索起始位,也就是剛剛說的 0x00 00 00 01 或者 0x00 00 01 起始位,然后在分離 NALU, 最后再解析各個字段。下面我們先來看下 NALU Header type 代表的含義:
| type | 說明 |
|---|---|
| 0 | 保留 |
| 1 | 非 IDR 圖像中不采用數(shù)據(jù)劃分的片段 |
| 2 | 非 IDR 圖像中 A 類數(shù)據(jù)劃分的片段 |
| 3 | 非 IDR 圖像中 B 類數(shù)據(jù)劃分的片段 |
| 4 | 非 IDR 圖像中 C 類數(shù)據(jù)劃分的片段 |
| 5 | IDR 圖像的片段 |
| 6 | 補充增強信心 (SEI) |
| 7 | SPS (序列參數(shù)集) |
| 8 | PPS (圖像參數(shù)集) |
| 9 | 分割符 |
| 10 | 序列結束符 |
| 11 | 流結束符 |
| 12 | 填充數(shù)據(jù) |
| 13 | 序列參數(shù)集擴展 |
| 14 | 帶前綴的 NAL 單元 |
| 15 | 子序列參數(shù)集 |
| 16 - 18 | 保留 |
| 19 | 不采用數(shù)據(jù)劃分的輔助編碼圖像片段 |
| 20 | 編碼片段擴展 |
| 21 - 23 | 保留 |
| 24 - 31 | 保留 |
在實際開發(fā)中用的最多的也就是 1 、5 、7、8 , 下面我們用代碼來進行分析:
代碼分析
代碼很簡單,就是讀文件,搜索起始碼然后一個字節(jié)一個字節(jié)讀,這里直接貼結果吧,詳細代碼可以打開鏈接:
https://github.com/yangkun19921001/YKAVStudyPlatform/blob/main/avcore/parser/h264_parser.c

參考
- 雷神 - 視音頻數(shù)據(jù)處理入門:H.264視頻碼流解析
