前面一節介紹了H264協議,主要是讓大家有個基本概念,了解其基本作業原理,和一些基本術語,對于我們做應用開發而言,我們并不需要知道其壓縮演算法的實作細節,我們關心的是它是如何在網路上傳輸的,
文章目錄
- 1、H264/AVC 的分層結構
- 2、H264編碼程序中的三種不同資料形式
- 3、H264網路傳輸的結構
- 2.1 RBSP
- 2.2 NALU
- 2.2.1 **NALU頭結構**
- 2.2.2 NAL的開始和結束
1、H264/AVC 的分層結構
場和幀 : 視頻的一場或一幀可用來產生一個編碼影像,在電視中,為減少大面積閃爍現象,把一幀分成兩個隔行的場,
宏塊 :一個編碼影像通常劃分成若干宏塊組成,一個宏塊由一個16×16亮度像素和附加的一個8×8 Cb和一個8×8 Cr彩色像素塊組成,
片:每個圖象中,若干宏塊被排列成片的形式,片分為I片、B片、P片和其他一些片,
– I片只包含I宏塊,P片可包含P和I宏塊,而B片可包含B和I宏塊,
– I宏塊利用從當前片中已解碼的像素作為參考進行幀內預測,
– P宏塊利用前面已編碼圖象作為參考圖象進行幀內預測,
– B宏塊則利用雙向的參考圖象(前一幀和后一幀)進行幀內預測,? 片的目的是為了限制誤碼的擴散和傳輸,使編碼片相互間是獨立的,某片的預測不能以其它片中的宏塊為參考影像,這樣某一片中的預測誤差才不會傳播到其它片中去,
H.264的主要目標是:
1.高的視頻壓縮比;
2.良好的網路親和性;
為了完成這些目標H264的解決方案是:
1.VCL video coding layer 視頻編碼層,負責高效的視頻內容表示;
2.NAL network abstraction layer 網路提取層,負責以網路所要求的恰當的方式對資料進行打包和傳送,

其中,VCL層是對核心演算法引擎,塊,宏塊及片的語法級別的定義,他最終輸出編碼完的資料 SODB;
NAL層定義片級以上的語法級別(如序列引數集和影像引數集,針對網路傳輸),同時支持以下功能:獨立片解碼,起始碼唯一保證,SEI以及流格式編碼資料傳送,NAL層將SODB打包成RBSP然后加上NAL頭,組成一個NALU(NAL單元),
2、H264編碼程序中的三種不同資料形式
SODB(String ofData Bits)資料位元串:最原始的編碼資料,即VCL資料,沒有任何附加資料,
RBSP(Raw ByteSequence Payload)原始位元組序列載荷:在SODB的后面填加了結尾位元(RBSP trailing bits),一個bit“1”,若干bit “0”,以便位元組對齊;
EBSP(EncapsulationByte Sequence Packets)擴展位元組序列載荷:在RBSP基礎上填加了仿校驗位元組(0X03),它的原因是:在NALU加到Annexb上時,需要添加每組NALU之前的開始碼StartCodePrefix,如果該NALU對應的slice為一幀的開始則用4位位元組表示,ox00000001,否則用3位位元組表示ox000001(是一幀的一部分),解碼器檢測每個起始碼,作為一個NAL的起始標識,當檢測到下一個起始碼時,當前NAL結束,對于NAL中資料出現0x000001或0x000000時,H.264引入了防止競爭機制,如果編碼器遇到兩個位元組連續為0,就插入一個位元組的0x03,解碼時將0x03去掉,也稱為脫殼操作,
3、H264網路傳輸的結構
VCL層是對核心演算法引擎、塊、宏塊及片的語法級別的定義,最終輸出壓縮編碼后的資料 SODB,VCL資料在傳輸或存盤之前,先被映射或封裝進NAL單元中,NAL層將SODB打包成RBSP然后加上NAL頭,組成一個NALU(NAL單元),NAL層定義片級以上的語法級別(如序列引數集和影像引數集,針對網路傳輸),同時支持以下功能:獨立片解碼,起始碼唯一保證,SEI以及流格式編碼資料傳送,
每個NAL單元是一個一定字語法元素的可變長位元組字串,包括一個位元組的頭資訊(用來表示資料型別),以及若干個整數位元組的原始位元組序列負荷(RBSP),一個NAL單元可以攜帶一個編碼片,A/B/C型資料分割或一個序列或一個影像引數集,H.264采用NAL單元接入可適用多種網路,而且進一步提高其抗誤碼能力,序列號的設定可以發現丟失的是哪一個VCL單元,冗余編碼影像使得基本編碼影像丟失仍可得到較“粗糙”的影像,
H264在網路傳輸的是NALU,NALU的結構是:NAL頭+RBSP,實際傳輸中的資料流如圖所示:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1mxKFojw-1623603794670)(http://hi.csdn.net/attachment/201004/9/0_12708080040gID.gif)]
從前面的分析我們知道,VCL層出來的是編碼完的視頻幀資料,這些幀可能是I、B、P幀,而且這些幀可能屬于不同的序列,再者同一個序列還有相對應的一套序列引數集和圖片引數集等等,所以要完成視頻的解碼,不僅需要傳輸VCL層編碼出來的視頻幀資料,還需要傳輸序列引數集、影像引數集等資料,
NALU頭用來標識后面的RBSP是什么型別的資料,他是否會被其他幀參考以及網路傳輸是否有錯誤,
2.1 RBSP
RBSP用來存放下表中的一種:
| RBSP型別 | 縮寫 | 描述 |
|---|---|---|
| 引數集 | PS | 序列的全域資訊,如影像尺寸,視頻格式等 |
| 增強資訊 | SEI | 視頻序列解碼的增強資訊 |
| 影像界定符 | PD | 視頻影像的邊界 |
| 編碼片 | SLICE | 編碼片的頭資訊和資料 |
| 資料分割 | DP片層的資料,用于錯誤恢復解碼 | |
| 序列結束符 | 表明一個序列的結束,下一個影像為IDR影像 | |
| 流結束符 | 表明該流中已沒有影像 | |
| 填充資料 | 亞元資料,用于填充位元組 |
其中,
引數集:包括序列引數集 SPS 和影像引數集 PPS
SPS 包含的是針對一連續編碼視頻序列的引數,如識別符號 seq_parameter_set_id、幀數及 POC 的約束、參考幀數目、解碼影像尺寸和幀場編碼模式選擇標識等等,
PPS對應的是一個序列中某一幅影像或者某幾幅影像,其引數如識別符號 pic_parameter_set_id、可選的 seq_parameter_set_id、熵編碼模式選擇標識、片組數目、初始量化引數和去方塊濾波系數調整標識等等,
**資料分割:**組成片的編碼資料存放在 3 個獨立的 DP(資料分割,A、B、C)中,各自包含一個編碼片的子集,分割A包含片頭和片中每個宏塊頭資料,分割B包含幀內和 SI 片宏塊的編碼殘差資料,分割 C包含幀間宏塊的編碼殘差資料,每個分割可放在獨立的 NAL 單元并獨立傳輸,
2.2 NALU
2.2.1 NALU頭結構
NALU頭結構:nal_unit_type(5bit)+nal_reference_bit(2bit)+forbidden_bit(1bit)

1.nal_unit_type:NALU型別取值如下表所示,
| nal_unit_type | NAL型別 | C |
|---|---|---|
| 0 | 未使用 | |
| 1 | 非IDR影像中不采用資料劃分的片段 | 2,3,4 |
| 2 | 非IDR影像中A類資料劃分片段 | 2 |
| 3 | 非IDR影像中B類資料劃分片段 | 3 |
| 4 | 非IDR影像中C類資料劃分片段 | 4 |
| 5 | IDR影像的片 | 2,3 |
| 6 | 補充增強資訊單元(SEI) | 5 |
| 7 | 序列引數集 | 0 |
| 8 | 影像引數集 | 1 |
| 9 | 分界符 | 6 |
| 10 | 序列結束 | 7 |
| 11 | 碼流結束 | 8 |
| 12 | 填充 | 9 |
| 13…23 | 保留 | |
| 24…31 | 不保留 |
2.nal_reference_bit:nal重要性指示,標志該NAL單元的重要性,值越大,越重要,解碼器在解碼處理不過來的時候,可以丟掉重要性為0的NALU,不同型別的NALU的重要性指示如下表所示,
| nal_unit_type | NAL型別 | nal_reference_bit |
|---|---|---|
| 0 | 未使用 | 0 |
| 1 | 非IDR的片 | 此片屬于參考幀,則不等于0,不屬于參考幀,則等與0 |
| 2 | 片資料A磁區 | 同上 |
| 3 | 片資料B磁區 | 同上 |
| 4 | 片資料C磁區 | 同上 |
| 5 | IDR影像的片 | 5 |
| 6 | 補充增強資訊單元(SEI) | 0 |
| 7 | 序列引數集 | 非0 |
| 8 | 影像引數集 | 非0 |
| 9 | 分界符 | 0 |
| 10 | 序列結束 | 0 |
| 11 | 碼流結束 | 0 |
| 12 | 填充 | 0 |
| 13…23 | 保留 | 0 |
| 24…31 | 不保留 | 0 |
常見資料幀
序列引數集 SPS----7:
SPS即Sequence Paramater Set SPS中保存了一組編碼視頻序列(Coded video sequence)的全域引數,所謂的編碼視頻序列即原始視頻的一幀一幀的像素資料經過編碼之后的結構組成的序列,而每一幀的編碼后資料所依賴的引數保存于影像引數集中,一般情況SPS和PPS的NAL Unit通常位于整個碼流的起始位置,但在某些特殊情況下,在碼流中間也可能出現這兩種結構,主要原因可能為:
1:解碼器需要在碼流中間開始解碼;
2:編碼器在編碼的程序中改變了碼流的引數(如影像解析度等);
影像引數集 PPS----8:
除了序列引數集SPS之外,H.264中另一重要的引數集合為影像引數集Picture Paramater Set(PPS),通常情況下,PPS類似于SPS,在H.264的裸碼流中單獨保存在一個NAL Unit中,只是PPS NAL Unit的nal_unit_type值為8;而在封裝格式中,PPS通常與SPS一起,保存在視頻檔案的檔案頭中,
關鍵幀 IDR 幀----5:
I幀表示關鍵幀,你可以理解為這一幀畫面的完整保留;解碼時只需要本幀資料就可以完成(因為包含完整畫面)
P幀 ----1:
P幀表示的是這一幀跟之前的一個關鍵幀(或P幀)的差別,解碼時需要用之前快取的畫面疊加上本幀定義的差別,生成最侄訓面,(也就是差別幀,P幀沒有完整畫面資料,只有與前一幀的畫面差別的資料)
3.forbidden_bit:禁止位,初始為0,當網路發現NAL單元有位元錯誤時可設定該位元為1,以便接收方糾錯或丟掉該單元,
2.2.2 NAL的開始和結束
編碼器將每個NAL各自獨立、完整地放入一個分組,因為分組都有頭部,解碼器可以方便地檢測出NAL的分界,并依次取出NAL進行解碼,每個NAL前有一個起始碼 0x00 00 01(或者0x00 00 00 01),解碼器檢測每個起始碼,作為一個NAL的起始標識,當檢測到下一個起始碼時,當前NAL結束,同時H.264規定,當檢測到0x000000時,也可以表征當前NAL的結束,那么NAL中資料出現0x000001或0x000000時怎么辦?H.264引入了防止競爭機制,如果編碼器檢測到NAL資料存在0x000001或0x000000時,編碼器會在最后個位元組前插入一個新的位元組0x03,這樣:
0x000000->0x00000300
0x000001->0x00000301
0x000002->0x00000302
0x000003->0x00000303
解碼器檢測到0x000003時,把03拋棄,恢復原始資料,解碼器在解碼時,首先逐個位元組讀取NAL的資料,統計NAL的長度,然后再開始解碼,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/287709.html
標籤:其他
