1. 程式人生 > >H.264(層次結構,NAL,SPS) 詳細重要引數

H.264(層次結構,NAL,SPS) 詳細重要引數

一 H.264句法

1.1元素分層結構

H.264編碼器輸出的Bit流中,每個Bit都隸屬於某個句法元素。句法元素被組織成有層次的結構,分別描述各個層次的資訊。

圖1

H.264分層結構由五層組成,分別是序列引數集、影象引數集、片(Slice)、和巨集塊和子塊。引數集是一個獨立的資料單位,不依賴於引數集外的其它句法元素。圖2描述了引數集與引數集外的句法元素之間的關係。

圖2

一個引數集不對應某一個特定的影象或序列,同一序列引數集可以被多個影象引數集引用,同理,同一個影象引數集也可以被多個影象引用。只在編碼器認為需要更新引數集的內容時,才會發出新的引數集。

在H.264中,影象以序列為單位進行組織。一個序列的第一個影象叫做IDR影象,IDR影象都是I幀,

H.264引入IDR影象為了解碼的同步,當解碼器解碼到IDR影象時,立即將參考幀佇列清空,將已解碼的資料全部輸出或拋棄,重新查詢引數集,開始一個新的序列。這樣,如果前一個序列出現重大錯誤,在這裡可以獲得重新同步的機會。IDR影象之後的影象永遠不會使用IDR之前的影象的資料來解碼

IDR是I幀,但I幀不一定是IDR。I幀之後的影象有可能會使用I幀之前的影象做運動參考。

1.2描述子

描述子描述從Bit流中取出句法元素的方法。

編號

語法

說明

1

ae(e)

CABAC

2

b(8)

讀進連續的8個Bit

3

ce(v)

CAVLC

4

f(n)

讀進連續的n個Bit

5

i(n)/i(v)

讀進連續的若干Bit,並把它們解釋為有符號整數

6

me(v)

對映指數Golomb熵編碼

7

se(v)

有符號指數Golomb熵編碼

8

te(v)

截斷指數Golomb熵編碼

9

u(n)/u(v)

讀進連續的若干Bit,並把它們解釋為無符號整數

10

ue(v)

無符號指數Golomb熵編碼

表1

1.3句法的表示方法

句法元素的名稱由小寫字母和一系列下劃線組成,變數名稱是大小寫字母組成,中間沒有下劃線。

二 句法表

定義了H.264的句法,指明在碼流中依次出現的句法元素及它們出現的條件、提取描述子等。句法表是分層巢狀的。

句法表中的C欄位表示該句法元素的分類,這是為片區服務,分類的具體含義如下表描述。

nal_unit_type

NAL型別

C

0

未使用

1

不分割槽、非IDR的片

2,3,4

2

片分割槽A

2

3

片分割槽B

3

4

版分割槽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

2.1 NAL語法

編碼器將每個NAL各自獨立、完整地放入一個分組,因為分組都有頭部,解碼器可以方便地檢測出NAL的分界,並依次取出NAL進行解碼。

每個NAL前有一個起始碼 0x000001,解碼器檢測每個起始碼,作為一個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的長度,然後再開始解碼。

句法

C

Desc

nal_nuit(NumBytesInNALunit){/* NumBytesInNALunit為統計出來的資料長度 */

    forbidden_zero_bit /* 等於0 */

All

f(1)

    nal_ref_idc/* 當前NAL的優先順序,取值範圍0-3 */

All

u(2)

    nal_unit_type /* NAL型別,見表2描述 */

All

u(5)

    NumBytesInRBSP=0

    for(i=1;i<NumBytesInNALunit;i++){

        if(i+2<NumBytesInNALunit && next_bits(24)==0x000003{

        /* 0x000003偽起始碼,需要刪除0x03這個位元組 */

        rbsp_byte[NumBytesInRBSP++]

All

b(8)

        rbsp_byte[NumBytesInRBSP++]

All

b(8)

        i+=2/* 取出前兩個0x00後,跳過0x03 */

        emulation_prevention_three_byte/* equal to 0x03 */

All

f(8)

    }else{

        rbsp_byte[NumBytesInRBSP++] /* 繼續讀取後面的位元組 */

All

b(8)

    }

}

表3

2.2序列引數集(SPS)

句法

C

Desc

seq_parameter_set_rbsp(){

profile_idc/* 指明所用的Profile */

0

u(8)

    constraint_set0_flag

0

u(1)

    constraint_set1_flag

0

u(1)

    constraint_set1_flag

0

u(1)

    reserved_zero_5bits /* equal to 0 */

0

u(5)

    level_idc /* 指明所用的Level */

0

u(8)

    seq_parameter_set_id /* 指明本序列引數集的id號,0-31,被影象集引用,編碼需要產生新的序列集時,使用新的id,而不是改變原來引數集的內容 */

0

ue(v)

    log2_max_frame_num_minus4/* 為讀取元素frame_num服務,frame_num標識影象的解碼順序,frame_num的解碼函式是ue(v),其中v=log2_max_frame_num_minus4+4,該元素同時指明frame_num的最大值MaxFrameNum=2( log2_max_frame_num_minus4+4)*/

0

ue(v)

    pic_order_cnt_type /* 指明poc的編碼方法,poc標識影象的播放順序,poc可以由frame_num計算,也可以顯示傳送。poc共三種計算方式 */

0

ue(v)

    if(pic_order_cnt_type==0)

        log2_max_pic_order_cnt_lsb_minus4 /* 指明變數MaxPicOrderCntLsb的值, MaxPicOrderCntLsb2(log2_max_pic_order_cnt_lsb_minus4+4) */

0

ue(v)

    else if(pic_order_cnt_type==1){

        delta_pic_order_always_zero_flag /* 等於1時,元素delta_pic_order_cnt[0]delta_pic_order_cnt[1]不在片頭中出現,並且它們的預設值是0,等於0時,上述兩元素出現的片頭中 */

0

u(1)

        offset_for_non_ref_pic /* 用來計算非參考幀或場的poc[-231,231-1] */

0

se(v)

        offset_for_top_to_bottom_field/* 計算幀的底場的poc */

0

se(v)

        num_ref_frames_inpic_order_cnt_cycle /* 用來解碼poc,[0.255] */

0

ue(v)

        for(i=0;i<num_ref_frames_inpic_order_cnt_cycle;i++)

            offset_for_ref_frame[i]/* 用來解碼poc,對於迴圈中的每個元素指定一個偏移 */

0

se(v)

    }

    num_ref_frames /* 參考幀佇列可達到的最大長度,[0,16] */

0

ue(v)

    gaps_in_frame_num_value_allowed_flag /* 為1,允許slice header中的frame_num不連續 */

0

u(1)

    pic_width_inmbs_minus1 /* 本元素加1,指明以巨集塊為單位的影象寬度PicWidthInMbs=pic_width_in_mbs_minus1+1 */

0

ue(v)

    pic_height_in_map_units_minus1 /* 本元素加1,指明以巨集塊為單位的影象高寬度PicHeightInMapUnitsMbs=pic_height_in_map_units_minus1+1 */

0

ue(v)

    frame_mbs_only_flag /* 等於0表示本序列中所有影象均為幀編碼;等於1,表示可能是幀,也可能場或幀場自適應,具體編碼方式由其它元素決定。結合前一元素:FrameHeightInMbs=(2-frame_mbs_only_flag)*PicHeightInMapUnits */

0

ue(v)

    if(frame_mbs_only_flag)

      mb_adaptiv_frame_field_flag /* 指明本序列是否是幀場自適應模式:

frame_mbs_only_flag=1,全部是幀

frame_mbs_only_flag=0 mb_adaptiv_frame_field_flag=0,幀場共存

frame_mbs_only_flag=0 mb_adaptiv_frame_field_flag=1,幀場自適應和場共存*/

0

u(1)

    direct_8x8_inference_flag /* 用於指明B片的直接和skip模式下的運動向量的計算方式 */

0

u(1)

    frame_cropping_flag /* 解碼器是否要將影象裁剪後輸出,如果是,後面為裁剪的左右上下的寬度 */

0

u(1)

    if(frame_cropping_flag){

        frame_crop_left_offset

0

ue(1)

        frame_crop_right_offset

0

ue(1)

        frame_crop_top_offset

0

ue(1)

        frame_crop_bottom_offset

0

ue(1)

    }

    vui_parameters_present_flag /* 指明vui子結構是否出現在碼流中,vui子結構在附錄中指明,用於表徵視訊格式的資訊 */

0

u(1)

    if(vui_parameters_present_flag)

        vui_parameters()

0

    rbsp_trailing_bits()

0

}

表4