【H.264/AVC 句法和语义详解】(九):图像参数集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节。

在这里插入图片描述

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、编码模式、参考图像列表等。

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值