通常情况下,PPS类似于SPS,在H.264的裸码流中单独保存在一个NAL Unit中,只是PPS NAL Unit的nal_unit_type值为8;
而在封装格式中,PPS通常与SPS一起,保存在视频文件的文件头中。
pic_parameter_set_rbsp() {
RBSP=SODB + 字节对齐
pic_parameter_set_data(); 即SODB
rbsp_trailing_bits(); 即字节对齐
}
图像参数集PPS的定义(7.3.2.2节)
/**
Picture Parameter Set
@see 7.3.2.2 Picture parameter set RBSP syntax
*/
pic_parameter_set_rbsp()
{
/* —————————— pps_id、sps_id Start —————————— */
int pic_parameter_set_id; /*ue(v)*/ [0,255]
int seq_parameter_set_id; /*ue(v)*/ 本pps引用的spsID [0,31]
/* —————————— pps_id、sps_id End —————————— */
int entropy_coding_mode_flag; /*u(1)*/ //熵编码模式标识
//=0表示使用左侧的描述子(通常为CAVLC/指数哥伦布编码)
//=1表示使用右侧的描述子(通常为CABAC)
//对于部分语法元素,在不同的编码配置下,选择的熵编码方式不同。
//例如宏块类型mb_type的语法元素描述符为“ue(v) | ae(v)”,在baseline profile等设置下采用指数哥伦布编码,在main profile等设置下采用CABAC编码。
int bottom_field_pic_order_in_frame_present_flag; // u(1) //PPS里唯一一个与计算POC相关的句法元素,用于控制在slice_header中,是否有用于计算底场POC的句法元素出现
/* —————————— FMO相关 Start —————————— */
int num_slice_groups_minus1; // ue(v) //一帧中的片组数量 即是否使用FMOf分组
//=0:表示只有1个片组,也即不使用FMO
//>0:即表示使用FMO,这时后面会有用于计算片组映射的其他句法元素
// if( num_slice_groups_minus1 > 0 ) {
int slice_group_map_type; /*ue(v)*/ FMO映射模式,[0,6] 6为用户自定义
// if( slice_group_map_type = = 0 )
// for( iGroup = 0; iGroup <= num_slice_groups_minus1; iGroup++ )
// num_slice_groups_minus1取值范围[0, 7],见附录A
int run_length_minus1[8]; /*ue(v)*/ 当映射模式为0时,需要参数的句法元素,表示每个片组连续的map_units数目。取值范围为[0, PicSizeInMapUnits-1]
// else if( slice_group_map_type = = 2 )
// for( iGroup = 0; iGroup < num_slice_groups_minus1; iGroup++ ) {
int top_left[8]; // ue(v) // 当映射模式为0时,需要参数的句法元素,top_left[ i ] 和 bottom_right[ i ] 分别表示一个矩形的左上角和右下角。
int bottom_right[8]; // ue(v)
// else if( slice_group_map_type = = 3 | | slice_group_map_type = = 4 | | slice_group_map_type = = 5 ) {
int slice_group_change_direction_flag; // u(1) //通常与slice_group_change_rate_minus1一起,用来表示当slice_group_map_type为3、4、5时精确的映射类型。
int slice_group_change_rate_minus1; // ue(v)
//slice_group_change_rate_minus1用来指定 SliceGroupChangeRate的值,它表示一个片组的大小,
//从一个图像到下一个图像的改变的倍数,以map_units为 单位。取值范围为[0, PicSizeInMapUnits-1]
// } else if( slice_group_map_type = = 6 ) {
int pic_size_in_map_units_minus1; /*ue(v)*/ 图像中的条带组映射单元数(以map_units为单元) = PicSizeInMapUnits – 1。
注:pic_size_in_map_units_minus1为从0开始的最大序号 PicSizeInMapUnits为实际数量
// for( i = 0; i <= pic_size_in_map_units_minus1; i++ )
int *slice_group_id; /*u(v)*/ (=6,自定义映射关系时)slice_group_id[i]表示:序号为i的map_unit对应的片组号
需要为每一个map_uit指明所属片组号👉slice_group_id指向的数组大小 = pps->pic_size_in_map_units_minus1+1 = pic_size_in_map_units
/* —————————— FMO相关 End —————————— */
/* —————————— 加权预测 Start —————————— */
int num_ref_idx_l0_active_minus1; // ue(v)
/* 加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] */
int num_ref_idx_l1_active_minus1; // ue(v) //和num_ref_idx_l0_default_active_minus1具有同样的定义, 只不过这个是用来描述列表1的
/* —————————— 加权预测 —————————— */
int weighted_pred_flag; // u(1) //表示P和SP片是否应该使用加权预测,等于0表示不应使用,等于1表示应使用。
int weighted_bipred_idc; // u(2) //取值[0,