天天看點

【H.264/AVC 句法和語義詳解】(九):圖像參數集PPS句法和語義1、PPS的句法結構2、PPS語義

同序列參數集SPS一樣,圖像參數集PPS在解碼的過程中,也将起到至關重要的作用。我們已經知道,在h264的句法元素分層結構上,由片引用PPS,PPS再引用SPS,進而得到解碼所需的全部句法元素。

PPS同SPS一樣,也是從一段視訊序列的基礎上,抽取出大部分公共編解碼資訊,進而形成的SPS和PPS。是以呢,我們接下來就會感受到,PPS裡的句法元素的語義,也是作用在視訊序列上的。

因為SPS和PPS是h264碼流中最重要的兩個NAL單元,是以它們通常位于碼流的最前面,也即碼流開頭的兩個NALU,第一個是SPS,第二個就是PPS。是以由前面可知,當從碼流中解析到第二個NALU時,它的nal_unit_type的值應為8。

同樣根據h264協定文檔7.4.1節可知,PPS的RBSP資料的元素構成,可參考pic_parameter_set_rbsp()部分,也即7.3.2.2節。

【H.264/AVC 句法和語義詳解】(九):圖像參數集PPS句法和語義1、PPS的句法結構2、PPS語義

1、PPS的句法結構

在7.3.2.2節規定了PPS的RBSP句法,不過與SPS不同,PPS在文檔裡,并沒有顯式的分為pic_parameter_set_data()和rbsp_trailing_bits() 。不過我們友善起見,可以在心裡默默的将它劃分為兩大類:

pic_parameter_set_rbsp() {
   pic_parameter_set_data();
   rbsp_trailing_bits();
}
           

其中的pic_parameter_set_data()也即包含在RBSP中的SODB部分,所有編解碼所需的句法元素都在裡面。下面我們忽略rbsp_trailing_bits(),來簡單看一下pic_parameter_set_rbsp()中句法元素所具有的功能。

1.1 pic_parameter_set_rbsp()結構

如7.3.2.2節所示的一樣,裡面的句法元素很多,它們的功能如下:

pic_parameter_set_rbsp() {
   // 1. pps_id(唯一辨別這個pps)和sps_id(這個pps引用的sps的id),
   // 2. 熵編碼flag,采用的是CAVLC還是CABAC
   // 3. 計算poc所需句法元素
   // 4. FMO相關
   // 5. 參考圖像清單相關
   // 6. 權重預測
   // 7. 量化相關
   // 8. DCT相關
   // 9. scaling_list相關
}
           

因為更接近片層,是以PPS所表現出的功能,相對SPS來說也更具體。像熵編碼模式、FMO等這些呢,PPS裡都能描述到。不過也正因如此呢,要了解PPS裡的句法元素的語義,也需要更寬廣的知識面,需要對h264的編解碼流程較為熟悉。

但是呢,即使我們現在對CAVLC、CABAC、POC、FMO、參考圖像清單、預測、量化、DCT等這些重要的知識點不太了解,我們也不用灰心。因為這些以後都會詳細講到,在這裡呢,我們隻需知道,這幾項的編解碼所用到的句法元素,在PPS裡都有涉及。在後面深入學習各知識點的時候,再對照PPS裡的句法元素前來查閱即可。

我們先将上述的幾個功能,對照pic_parameter_set_rbsp()的句法元素進行劃分如下:

pic_parameter_set_rbsp( ) {
/*  —————————— pps_id、sps_id Start  —————————— */
    pic_parameter_set_id
    seq_parameter_set_id
/*  —————————— pps_id、sps_id  End  —————————— */

    entropy_coding_mode_flag  // 熵編碼
    bottom_field_pic_order_in_frame_present_flag // POC

/*  —————————— FMO相關 Start  —————————— */
    num_slice_groups_minus1 
    if( num_slice_groups_minus1 > 0 ) {
        slice_group_map_type
        if( slice_group_map_type = = 0 )
            for( iGroup = 0; iGroup <= num_slice_groups_minus1; iGroup++ )
                run_length_minus1[ iGroup ] 
        else if( slice_group_map_type = = 2 )
            for( iGroup = 0; iGroup < num_slice_groups_minus1; iGroup++ ) {
                top_left[ iGroup ] 
                bottom_right[ iGroup ] 
            }
        else if( slice_group_map_type = = 3 | |
            slice_group_map_type = = 4 | |
            slice_group_map_type = = 5 ) {
            slice_group_change_direction_flag
            slice_group_change_rate_minus1
        } else if( slice_group_map_type = = 6 ) {
            pic_size_in_map_units_minus1 
            for( i = 0; i <= pic_size_in_map_units_minus1; i++ )
                slice_group_id[ i ] 
        }
    }
/*  —————————— FMO相關 End  —————————— */


/*  —————————— 參考圖像清單 Start  —————————— */
    num_ref_idx_l0_default_active_minus1 
    num_ref_idx_l1_default_active_minus1 
/*  —————————— 參考圖像清單 End  —————————— */


/*  —————————— 權重預測 Start  —————————— */
    weighted_pred_flag 
    weighted_bipred_idc
/*  —————————— 權重預測 End  —————————— */


/*  —————————— 量化 Start  —————————— */
    pic_init_qp_minus26 /* relative to 26 */ 
    pic_init_qs_minus26 /* relative to 26 */ 
    chroma_qp_index_offset
/*  —————————— 量化 End  —————————— */

    deblocking_filter_control_present_flag
    constrained_intra_pred_flag  
    redundant_pic_cnt_present_flag


    if( more_rbsp_data( ) ) {
        // DCT變換
        transform_8x8_mode_flag  
/*  —————————— Scaling_list Start  —————————— */
        pic_scaling_matrix_present_flag 
        if( pic_scaling_matrix_present_flag )
            for( i = 0; i < 6 +
                ( ( chroma_format_idc != 3 ) ? 2 : 6 ) * transform_8x8_mode_flag;
                i++ ) {
                pic_scaling_list_present_flag[ i ] 
                if( pic_scaling_list_present_flag[ i ] )
                    if( i < 6 )
                        scaling_list( ScalingList4x4[ i ], 16,
                        UseDefaultScalingMatrix4x4Flag[ i ] ) 
                    else
                        scaling_list( ScalingList8x8[ i − 6 ], 64,
                        UseDefaultScalingMatrix8x8Flag[ i − 6 ] ) 
            }
/*  —————————— Scaling_list End  —————————— */

        second_chroma_qp_index_offset 
    }
    rbsp_trailing_bits( ) 
}
           

2、PPS語義

詳細語義如下:

pic_parameter_set_rbsp( ) {
/*  —————————— pps_id、sps_id Start  —————————— */
   // 唯一辨別這個pps,供片頭引用使用
    pic_parameter_set_id 
   // 本圖像參數集所引用的序列參數集的id
    seq_parameter_set_id 
/*  —————————— pps_id、sps_id  End  —————————— */

   /*
   在講描述子時,曾提到這個文法元素。它用于指定文法元素的熵編碼方式,
   當entropy_coding_mode_flag為0時,表示熵編碼使用CAVLC,解析文法元素時使用左邊的描述子
   當entropy_coding_mode_flag為1時,表示熵編碼使用CABAC,解析文法元素時使用右邊的描述子
   */
    entropy_coding_mode_flag 
   /*
   PPS裡唯一一個與計算POC相關的句法元素,用于控制在slice_header中,是否有用于計算底場POC的句法元素出現
   */
    bottom_field_pic_order_in_frame_present_flag 


/*  —————————— FMO相關 Start  —————————— */
   /*
   這個句法元素加1,用于表明圖像中的片組個數。h264沒有專門的句法元素表明是否使用FMO。是以
   當num_slice_groups_minus1 等于 0時,表示隻有1個片組,也即不使用FMO
   當num_slice_groups_minus1大于0時,即表示使用FMO,這時後面會有用于計算片組映射的其他句法元素
   */
    num_slice_groups_minus1 
    if( num_slice_groups_minus1 > 0 ) {
       /*
       指定FMO的映射模式,取值為[0, 6],0~6的每個值都對應一種映射模式,我們曾在【H.264/AVC 的分層結構與畫面劃分】裡講過。不過 
       聯系到句法元素,更具體的還需要另行介紹,後面視情形可能會單獨開一篇再次介紹FMO
       */
        slice_group_map_type
        if( slice_group_map_type = = 0 )
            for( iGroup = 0; iGroup <= num_slice_groups_minus1; iGroup++ )
               /*
               當映射模式為0時,需要參數的句法元素,表示每個片組連續的map_units數目。取值範圍為[0, PicSizeInMapUnits-1]
               */
                run_length_minus1[ iGroup ] 
        else if( slice_group_map_type = = 2 )
           /*
           當映射模式為0時,需要參數的句法元素,top_left[ i ] 和 bottom_right[ i ] 分别表示一個矩形的左上角和右下角。
           */
            for( iGroup = 0; iGroup < num_slice_groups_minus1; iGroup++ ) {
                top_left[ iGroup ] 
                bottom_right[ iGroup ] 
            }
        else if( slice_group_map_type = = 3 | |
            slice_group_map_type = = 4 | |
            slice_group_map_type = = 5 ) {
           /*
           通常與slice_group_change_rate_minus1一起,用來表示當slice_group_map_type為3、4、5時精确的映射類型。
           */
            slice_group_change_direction_flag
           /*
           slice_group_change_rate_minus1用來指定 
           SliceGroupChangeRate的值,它表示一個片組的大小, 
           從一個圖像到下一個圖像的改變的倍數,以map_units為 
           機關。取值範圍為[0, PicSizeInMapUnits-1]
           */
            slice_group_change_rate_minus1
        } else if( slice_group_map_type = = 6 ) {
           /*
           用于指明當slice_group_map_type等于6時,圖像以map_units為機關的大小
           */
            pic_size_in_map_units_minus1 
            for( i = 0; i <= pic_size_in_map_units_minus1; i++ )
               /*
               用于指明當slice_group_map_type等于6時,某個map_units屬于哪個片組
               */
                slice_group_id[ i ] 
        }
    }
/*  —————————— FMO相關 End  —————————— */


/*  —————————— 參考圖像清單 Start  —————————— */
   /*
   加1後表明參考圖像清單0的最大參考索引号,這個句法元素是針對幀宏塊 
   來說的,比如假設編碼模式為宏塊級别的幀場自适應,那麼幀場自适應下 
   的幀宏塊解碼的最大索引值就是 
   num_ref_idx_l0_default_active_minus1,而 
   2*num_ref_idx_l0_default_active_minus1+1是場宏塊解碼的最 
   大索引值。num_ref_idx_l0_default_active_minus1的取值範圍 
   為:[0, 31]
   */
    num_ref_idx_l0_default_active_minus1 
   /*
   和num_ref_idx_l0_default_active_minus1具有同樣的定義, 
   隻不過這個是用來描述清單1的
   */
    num_ref_idx_l1_default_active_minus1 
/*  —————————— 參考圖像清單 End  —————————— */


/*  —————————— 權重預測 Start  —————————— */
   /*
   表示P和SP片是否應該使用權重預測,等于0表示不應使用,等于1表 
   示應使用。
   */
    weighted_pred_flag 
   /*
   取值[0, 2]
   等于0表示B片應該采取預設的權重預測
   等于1表示B片應使用顯式的權重預測
   等于2表示B片應使用隐式的權重預測
   */
    weighted_bipred_idc
/*  —————————— 權重預測 End  —————————— */


/*  —————————— 量化 Start  —————————— */
   /*
   取值[-26, 25]
   加26後表示每個片的亮度分量的量化參數的初始值,在片頭和宏塊 
   中,進一步會有額外的量化參數給出,幾個量化參數一起決定真正的 
   量化值
   */
    pic_init_qp_minus26 /* relative to 26 */ 
   /*
   與pic_init_qp_minus26的語義一緻,隻不過作用于SI和SP片。
   */
    pic_init_qs_minus26 /* relative to 26 */ 
   /*
   取值[-12, 12]
   用于計算色度分量的量化參數,需要注意的時,計算時需要結合亮度 
   分量的量化參數
   */
    chroma_qp_index_offset
/*  —————————— 量化 End  —————————— */

   /*
   用于表示,是否有控制去塊濾波強度的文法元素值,在片頭出現。
   如果deblocking_filter_control_present_flag等于1, 表 
   示編碼器已經設定了去塊濾波強度,也即片頭中句法元素的值
   如果deblocking_filter_control_present_flag等于0,表示 
   編碼器沒有設定,那麼解碼器就要獨立計算出去塊濾波強度
   */
    deblocking_filter_control_present_flag
   /*
   在P和B片中,當宏塊進行幀内編碼時,它的鄰近宏塊可能采用的是幀 
   間編碼。
   那麼當constrained_intra_pred_flag等于1時,表示幀内編碼的 
   宏塊,不能使用幀間編碼的宏塊的像素值作為自己的預測值,也就是 
   它隻能使用鄰近幀内編碼的宏塊的像素值作為自己的預測
   當constrained_intra_pred_flag等于0時,表示不存在這種限制
   */
    constrained_intra_pred_flag  
   /*
   用于控制是否顯示redundant_pic_cnt
   */
    redundant_pic_cnt_present_flag


    if( more_rbsp_data( ) ) {
       /*
       等于1表示目前亮度宏塊使用的是8x8的DCT變換
       等于0表示目前亮度宏塊沒有使用8x8的DCT變換
       */
        transform_8x8_mode_flag  
/*  —————————— Scaling_list Start  —————————— */
       /*
       用于表示是否存在縮放比例清單Scaling_list
       */
        pic_scaling_matrix_present_flag 
        if( pic_scaling_matrix_present_flag )
            for( i = 0; i < 6 +
                ( ( chroma_format_idc != 3 ) ? 2 : 6 ) * transform_8x8_mode_flag;
                i++ ) {
                pic_scaling_list_present_flag[ i ] 
                if( pic_scaling_list_present_flag[ i ] )
                    if( i < 6 )
                        scaling_list( ScalingList4x4[ i ], 16,
                        UseDefaultScalingMatrix4x4Flag[ i ] ) 
                    else
                        scaling_list( ScalingList8x8[ i − 6 ], 64,
                        UseDefaultScalingMatrix8x8Flag[ i − 6 ] ) 
            }
/*  —————————— Scaling_list End  —————————— */

       /*
       色度分量Cr與亮度分量Y的量化內插補點,取值範圍為[-12, 12]
       當second_chroma_qp_index_offset不存在時,預設值為 
       chroma_qp_index_offset 
       */
        second_chroma_qp_index_offset 
    }
    rbsp_trailing_bits( ) 
}
           

準确的來說,以上語義看不懂也沒關系,因為關系到每個知識點,我們都可以單開一篇文章來詳細介紹。而且在圖像參數集裡面,我們并沒有擷取到用于講解某一知識點的全部句法元素。是以在後面講到slice_header以後,一些知識點就可以詳細介紹,比如如何計算POC、編碼模式、參考圖像清單等。

繼續閱讀