从Slice_Header学习H.264(二)--片头的子语法项目

来源:互联网 发布:简短软件开发合同 编辑:程序博客网 时间:2024/06/10 04:36

二、slice头的三个子语法项目

 

1.ref_pic_list_reordering( ) 参考图像列表重排序语法

 

 

$     上面已经提到,编码器给每个参考帧都会分配一个唯一性的标识,即句法元素frame_num。但是,当编码器要指定当前图像的参考图像时,并不是直接指定该图像的frame_num 值,而是使用通过下面步骤最终得出的 ref_id 号:frame_num -> PicNum -> ref_id。从frame_num 到变换到变量PicNum 主要是考虑到场模式的需要,当序列中允许出现场时,每个非场的图像(帧或  帧场自适应)解码后必须分解为一个场对,从而需要为它们分解后的两个场各自指定一个标识;进一步从PicNum到ref_id 是为了能节省码流,因为PicNum的值通常都比较大。

编码器和解码器都同步地维护一个参考帧队列, 每解码一个片就将该队列刷新一次, 把各图像按照特定的规则进行排序, 排序后各图像在队列中的序号就是该图像的ref_id 值。(所谓的重排序,其实就是指刷新PicNum和ref_id的值)。

 

$     本语法中的各元素只在  slice_type !=  I  && slice_type  !=  SI  情况下才有效,即当前片不是I片和SI片(说明当前片是需要参考图像的片,如果是I或SI片,那就不需要参考图像,既然不需要参考图像,又何来重排序一说)。

 

$     ref_pic_list_reordering_flag_l0  指明是否进行重排序操作, 这个句法元素等于1 时表明紧跟着会有一系列句法元素用于参考帧队列的重排序。如果进行重排序,表示会刷新各个参考图像的PicNum和ref_id值;如果不重新排序,各参考图像的ref_id值还和解码上一个片时一样。因为一个图像可以分成多个片,因此一个图像内的不同片可以使用不同的参考图像,对不同的参考图像又可以分配不同的参考号。

 

$     reordering_of_pic_nums_idc  指明执行哪种重排序操作,取值范围0-3。取不同值时对应的意义如下:

0  短期参考帧重排序,abs_diff_pic_num_minus1 会出现在码流中,从当前图像的PicNum减去(abs_diff_pic_num_minus1 + 1)  后指明需要重排序的图像。

1  短期参考帧重排序,abs_diff_pic_num_minus1 会出现在码流中,从当前图像的PicNum加上(abs_diff_pic_num_minus1 + 1)  后指明需要重排序的图像。

2  长期参考帧重排序,long_term_pic_num会出现在码流中,指明需要重排序的图像。

3  结束符。

       其中,“当前图像的PicNum”,即CurrPicNum的计算方法,在上面讲frame_num时提到了,很简单。即如果当前图像是场图像,那么CurrPicNum就是frame_num乘2加1(这个值代表,把之前所有的参考帧都折合成两个场后,当前场图像是第几个场);否则,CurrPicNum就是frame_num(这个值代表,把以前所有的参考图像都折合成帧来计算,当前帧图像是第几帧)。

       这个语法元素将循环出现,每一个元素描述一个参考图像,如果有多个参考图像,这个元素就会循环出现多次,直到遇到reordering_of_pic_nums_idc=3(结束符)时停止循环。

 

$     abs_diff_pic_num_minus1   在对短期参考帧重排序时指明重排序图像与当前的差。

$     long_term_pic_num   在对长期参考帧重排序时指明重排序图像。这两个元素的意义和出现的条件都在reordering_of_pic_nums_idc的介绍中刚提到了。

 

 

$     上面元素都是用于列表List0的。如果当前片是B片,那么还会有一组对应的用于List1的元素,基本是上面介绍的四个元素的拷贝,只不过ref_pic_list_reordering_flag_l0要变成ref_pic_list_reordering_flag_l1。

 

 

2.dec_ref_pic_marking( ) 解码的参考图像标识语法

 

$     上面介绍的重排序(reordering)操作是对参考帧队列重新排序,而标记(marking)操作负责将参考图像移入或移出参考帧队列、指定参考图像的符号。

 

$     语法元素 no_output_of_prior_pics_flag、long_term_reference_flag 、adaptive_ref_pic_marking_mode_flag 、memory_management_control_operation、difference_of_pic_nums_minus1、long_term_frame_idx 、long_term_pic_ num 和 max_long_term_frame_idx_plus1 这些都表示参考图像的符号。 参考图像的符号可以是“未用于参考”、“用于短期参考”或“用于长期参考”,但是只能是这三个中的一个。当一个参考图像是指被标记为“用于参考”时,表示共同引用了被标记为“用于长期参考”或“用于短期参考”的图像(但不是同时引用两者)。一个被标记为“用于短期参考”的参考图像表示一个短期参考图像,被标记为“用于长期参考”的图像表示一个长期参考图像。

 

$     no_output_of_prior_pics_flag   表示在解码图像缓冲器中先前解码的图像在一个IDR 图像解码之后是如何处理的,指明是否要将前面已解码的重建图像全部输出(清空),但不管是否清空,之前的重建图像都不会再用作本序列图像解码时的参考。当该IDR 图像是比特流中第一个IDR 图像时,no_output_of_prior_pics_flag 的值在解码过程中将不生效;当该IDR 图像不是比特流中的第一个 IDR 图像时,如果从活动的视频序列参数集中得到的PicWidthInMbs, 、FrameHeightInMbs 或 max_dec_frame_buffering 的值与从先前序列活动时的视频序列参数集中得到的PicWidthInMbs, 、FrameHeightInMbs或max_dec_frame_buffering 的值不同时,不管no_output_of_prior_pics_flag的实际值是什么,解码器可能会推断no_output_of_prior_pics_flag 等于1。

       本元素存在条件:       NAL单元中的nal_unit_type  = =  5,即当前帧是IDR。

 

 

$     long_term_reference_flag  等于0 表示变量MaxLongTermFrameIdx  被设为等于“无长期帧序号”而且该IDR图像被标记为“用于短期参考”。long_term_reference_flag  等于 1 表示变量MaxLongTermFrameIdx被设为等于0而当前的IDR 图像被标记为“用于长期参考”并且LongTermFrameIdx被分配为等于0。序列参数集中的num_ref_frames等于0时(num_ref_frames规定了可能在视频序列中任何图像帧间预测的解码过程中用到的短期参考帧和长期参考帧、互补参考场对以及不成对的参考场的最大数量,它等于0说明根本无参考帧),long_term_reference_flag应该也等于 0

       本元素存在条件:同上。

 

$     上面两个元素都是只出现在IDR中,如果当前帧不是IDR,那么下面的几个元素将会根据条件出现;而如果当前是IDR,下面的元素都不会出现。介绍下面几个元素提到存在条件时将不再重复声明这一点

 

$     adaptive_ref_pic_marking_mode_flag:指明标记(marking)操作的模式;当当前被标

记为“用于长期参考”的帧数、附加场对和非成对的场等于 Max( num_ref_frames, 1 ) 时(num_ref_frames可能是0),adaptive_ref_pic_marking_mode_flag  将等于 1。

      

adaptive_ref_pic_marking_mode_flag

标记(marking)模式

0

变化窗口的参考图像符号模式:符号模式为短期参考图像提供一个先进先出的机制。这种模式下无法对长期参考帧进行操作

1

自适应参考图像符号模式:后续码流会有一系列句法元素显式指明操作的步骤。自适应是指编码器可根据情况随机灵活地作出决策。

如果这个元素为0,那么下面的几个元素将不会出现。只有本元素为1,下面的元素才会出现。介绍下面几个元素提到存在条件时将不再重复声明这一点

 

$     memory_management_control_operation     自适应参考图像符号模式中,指明本次操作的具体内容。

memory_management_control_operation

标记(marking)操作

0

结束循环,退出标记(marding)操作。

1

将一个短期参考图像标记为非参考图像,也即将一个短期参考图像移出参考帧队列。

2

将一个长期参考图像标记为非参考图像,也即将一个长期参考图像移出参考帧队列。

3

将一个短期参考图像转为长期参考图像

4

指明长期参考帧的最大数目

5(特殊)

清空参考帧队列,将所有参考图像移出参考

帧队列,并禁用长期参考机制

6

将当前图像存为一个长期参考帧。

 

$     difference_of_pic_nums_minus1  :  当memory_management_control_operation等于 3 或1 时,由这个元素可以计算得到需要操作的图像在短期参考队列中的序号。参考帧队列中必须存在这个图像。 

$     long_term_pic_num   当memory_management_control_operation 等于2 时,  从此句法元素得到所要操作的长期参考图像的序号。

$     long_term_frame_idx   当 memory_management_control_operation等于3 或6  ,分配一个长期参考帧的序号给一个图像。

$     max_long_term_frame_idx_plus1:此句法元素减1 ,指明长期参考队列的最大数目取值的范围 0 - num_ref_frames。其中,num_ref_frames在序列参数集中指明,代表本序列中最大的参考帧数量。

 

 

3.pred_weight_table( ) 预测加权表格语法

 

$     luma_log2_weight_denom   给出参考帧列表中参考图像所有亮度的加权系数,是个初始值。luma_log2_weight_denom  值的范围是  0 to 7,它相当于为每个参考图像都分配了一个默认的权重。具体作用在下面的元素还会提到。

 

$     chroma_log2_weight_denom  给出参考帧列表中参考图像所有色度的加权系数,是个初始值chroma_log2_weight_denom  值的范围是  0 to 7。

存在条件:在比较老的H.264的版本中,这个元素跟上个元素一样,都是没有条件的;但在后来新出的版本中,序列参数集里新增了一些元素以支持更多的“profile”,其中有一个新增元素是chroma_format_idc,但只有当使用新出的高级的profile时(具体使用哪个profile由序列参数集中的profile_idc指明),这个元素才会出现在序列参数集里,它指明了色彩模式,即YUV格式,只有当chroma_format_idc 不为0时(如果chroma_format_idc为0,则表示YUV=4:0:0,纯灰度图像),chroma_log2_weight_denom才存在,也就是说只要当前图像是彩色图像就会出现chroma_log2_weight_denom。还有很重要的一点,就是兼容的问题,H.264新版本中,如果在序列参数集中没有检测到chroma_format_idc元素,那么就会默认chroma_format_idc=1,表示YUV=4:2:0,这恰好是旧版本的默认格式,因此对于旧版本H.264编码后的图像,虽然码流中没有出现chroma_format_idc,但依然可由新版本H.264正确解码。

 

$     luma_weight_l0_flag  等于 1  时,指的是在参考图像序列 0 中的亮度的加权系数存在;等于 0 时,在参考序列0 中的亮度的加权系数不存在。

如果luma_weight_l0_flag  等于 1,即亮度的加权系数存在,那么luma_weight_l0[ i ]和luma_offset_l0[ i ]也会出现,这两个之和就代表实际的加权系数。

luma_weight_l0[i ]表示用参考序列 0 预测亮度值时,所用的加权系数。如果luma_weight_l0_flag is = 0, luma_weight_l0[ i ] = 2 ^luma_log2_weight_denom,这就用到了上面刚说到的luma_log2_weight_denom初始化元素。

luma_offset_l0[i ]表示加权系数的额外偏移,luma_offset_l0[i ]  值的范围–128 to 127 。如果 luma_weight_l0_flag  is = 0,luma_offset_l0[ i ] = 0。

这一组元素(上面这三个元素,我暂时称他们为一个“亮度权重元素组”)在码流中将循环出现,循环次数为num_ref_idx_l0_active_minus1+1,代表List0中参考图像的数目(num_ref_idx_l0_active_minus1的含义上面已介绍),这也是为什么元素luma_weight_l0[ i ]和luma_offset_l0[ i ]中会出现角标“i”,因为我们要为参考图像列表中的每一个图像都分配一个亮度预测权重值。

       这三个元素,都是针对图像序列List0的。当当前图像时B帧时,还会出现另一组与List1相关的元素,也是三个,跟上面介绍的三个一样,就是元素名中的 “l0” 变成“l1”,各元素出现的条件和意义都跟上面介绍过的三个类似。

 

$     上面那组元素,指定了各个参考帧进行亮度预测时的权重,而在彩色图像中,除了亮度,色度预测也需要分配一个权重,因此就有了跟上面的亮度权重元素组对应的色度权重元素组,这组元素也是循环出现,每一组色度权重元素组紧跟在一个亮度权重元素组后面。

       chroma_weight_l0_flag:     其作用与luma_weight_l0_flag类似,只不过针对的是色度。

       chroma_weight_l0[i ][ j ]  ,chroma_offset_l0[ i ][ j ]  :与luma_weight_l0[ i ]和luma_offset_l0[ i ]类似。这里多出了一个角标j,这里j的取值是0和1,这是因为色度有两种,分别是Cr和Cb(或者叫U和V),这两种色度要分开处理。

       同刚才提到的chroma_log2_weight_denom一样,这几个元素在旧的H.264和新版的H.264中有不同的存在条件,在旧版中,它们都无条件存在(旧版大都默认YUV=4:2:0),而在新版中,要依赖当前图像的色彩模式,只要图像不是纯灰度的(序列参数集中的chroma_format_idc不为0),这些元素就存在。

       上面这几个元素都针对List0,如果当前帧是B 帧,同样会有一组一样的关于List1的元素,只是把元素名中的 “l0” 换成“l1”。各元素出现的条件和意义都跟上面介绍过的三个类似。

0 0
原创粉丝点击