AVC的参考帧管理

        AVC的参考帧管理有两部分构成。第一部分为DPB buffer的管理,它决定了每一帧编码之后,下一帧编码之前DPB buffer中的帧的变化情况,也就是哪些帧要留在buffer中,哪些帧要从buffer中移除(或者说标记为可以被移除)。而第二部分为参考帧队列构建,即每一帧编码前,需要从buffer中依次拿取哪一帧,放入当前的参考帧队列中。

1. DPB buffer的管理。

        步骤1:解码完一帧,随后判断当前帧的帧类型。如果当前帧为一个IDR帧,则进行以下操作:

        (1)将所有的参考帧标记为“不作为参考”;

        (2)对于当前帧,如果long_term_reference_flag为0,则该IDR帧被标记为“作为短期参考”,且MaxLongTermFrameIdx设为“无长期参考帧索引”;如果long_term_reference_flag为1,则该IDR帧被标记为“作为长期参考”,其LongTermFrameIdx设为0,并且MaxLongTermFrameIdx设为0;

        如果当前帧为非IDR帧,则执行以下操作:

        (1)如果adaptive_ref_pic_marking_mode_flag为1,则进行自适应内存控制法标记参考帧;如果adaptive_ref_pic_marking_mode_flag为0,则进行滑动窗口法标记参考帧;

        (2)如果当前帧没有因为memory_management_control_operation的值等于6而被标记为“用于长期参考”,则该帧被标记为“用于短期参考”。

        步骤2:对于当前帧非IDR帧,开始执行滑动窗口法或者自适应内存控制法标记DPB中的参考帧。

滑动窗口法:

        如果当前图像是一个 complementary reference field pair 中按照解码顺序的第二个场,且第一场被标记为“用作短期参考”,那么当前图像和该complementary reference field pair都被标记为“作为短期参考”。

        否则的话,根据如下步骤执行:设numShortTerm为作为短期参考的编码帧、编码场或互补场对的总数,numLongTerm为长期参考帧/场/场对的总数;当numShortTerm与numLongTerm之和达到Max(max_num_ref_frames, 1)时,在满足numShortTerm大于0的前提下,FrameNumWrap值最小的那个作为短期参考的编码帧、编码场或互补场对将被标记为“不作为参考”。

自适应内存控制法:

        执行自适应内存控制法标记参考帧的条件是adaptive_ref_pic_marking_mode_flag为1,此时slice_header中会包含一些附加的语法元素信息:

  •                         memory_management_control_operation;
    •                         difference_of_pic_nums_minus1;
      •                         long_term_pic_num;
        •                         long_term_frame_idx;
          •                         max_long_term_frame_idx_plus1

其中,memory_management_control_operation可以取的范围为1~6,分别代表了不同的操作。如表1所示

图表 1 memory_management_control_operation的含义

        (1)将短期参考帧标记为“不作为参考”

        当memory_management_control_operation为1时,自适应内存控制过程会将某一个短期参考帧标记为“不作为参考”。具体的执行过程为:首先计算picNumX。

        计算方法为:picNumX = CurrPicNum − ( difference_of_pic_nums_minus1 + 1 )

    其中,CurrPicNum为当前帧的frame_number,difference_of_pic_nums_minus1从dec_ref_pic_marking中解析得到。

        对于帧编码的图像,PicNum等于picNumX的短期参考帧会被标记为“不作为参考”;

        (2)将长期参考帧标记为“不作为参考”

        当memory_management_control_operation为2时,自适应内存控制过程会将某一个长期参考帧标记为“不作为参考”。具体的执行过程很简单,索引为LongTermPicNum等同于long_term_pic_num的长期参考帧将被标记为不作为参考。

        (3)将短期参考帧标记为“长期参考帧”

        当memory_management_control_operation为3时,自适应内存控制过程会将某一个短期参考帧标记为“作为长期参考帧”。在这种情况下,码流中会同时包含difference_of_pic_nums_minus1以及long_term_frame_idx这两个值。执行过程如下:

        按照(1)中的方法计算picNumX;

        如果long_term_frame_idx对应的长期参考帧存在,则该长期参考帧标记为“不作为参考”;

        对于帧编码图像,由picNumX所代表的短期参考帧,将被标记为长期参考帧,并将对应的LongTermFrameIdx设为long_term_frame_idx。

        (4)计算MaxLongTermFrameIdx

        当memory_management_control_operation为4时,执行计算MaxLongTermFrameIdx的操作。计算过程如下:

        如果码流中解析出的max_long_term_frame_idx_plus1的值为0,则MaxLongTermFrameIdx被设置为“无长期参考帧索引”;

        否则,MaxLongTermFrameIdx的值设置为max_long_term_frame_idx_plus1-1。所有被标记为“用作长期参考”且LongTermFrameIdx大于了MaxLongTermFrameIdx的图像都会被标记为“不作为参考”。

        (5)清空参考帧列表

        当memory_management_control_operation为5时,执行清空参考帧列表操作。该过程会将所有参考帧标记为“不作为参考”并将MaxLongTermFrameIdx设置为“无长期参考帧索引”。

        (6)将当前帧标记为长期参考帧

        当memory_management_control_operation为6时,将当前帧标记为长期参考帧。在这种情况下,需从码流中解析出long_term_frame_idx。执行过程如下:

        如果long_term_frame_idx对应的长期参考帧存在,则该长期参考帧标记为“不作为参考”;将当前帧标记为“作为长期参考”,并将其LongTermFrameIdx设置为long_term_frame_idx;在当前帧标记完成后,所有被标记为“作为参考帧”的帧、场和互补场对的数量综合不能超过Max( max_num_ref_frames, 1 )规定的值。

2.参考帧列表的构建

        分两步进行:第一步参考帧队列初始化;第二步为参考帧队列调整。

        第一步:参考帧队列初始化以B帧为例进行描述

        在两个参考帧列表RefPicList0和RefPicList1中,短期参考帧的顺序按照显示顺序,即POC进行排列。在排列短期参考帧时,会将当前帧的POC与DPB中参考帧的POC进行比较,然后根据结果进行以下操作:

        对参考帧列表refPicList0:

        如果DPB中短期参考帧的POC小于当前帧的DPB,则短期参考帧按照POC的降序排列在参考帧列表refPicList0的前部,其余短期参考帧按照POC的升序紧随其后排列;DPB中的长期参考帧按照LongTermPicNum递增的顺序在短期参考帧之后排列;

        对参考帧列表refPicList1:

        如果DPB中短期参考帧的POC大于当前帧的DPB,则短期参考帧按照POC的升序排列在参考帧列表refPicList1的前部,其余短期参考帧按照POC的降序紧随其后排列;DPB中的长期参考帧按照LongTermPicNum递增的顺序在短期参考帧之后排列;

        若refPicList1包含多于1个参考帧,且refPicList1与refPicList0等同时,refPicList1中前两个参考帧refPicList1[0]和refPicList1[1]将进行交换。

        在参考帧列表初始化后,还需要一项附加操作,即根据图像参数集PPS的参数来计算参考帧列表中图像数目的上限,该参数即为:

                                        num_ref_idx_l0_active_minus1;

                                        num_ref_idx_l1_active_minus1;

        第二步:参考帧队列调整

        若ref_pic_list_modification_flag_l0或者ref_pic_list_modification_flag_l1(对B帧)的值为1,参考帧列表RefPicList0和RefPicList1(对B帧)会进行修改操作;

    两个标识位ref_pic_list_modification_flag_l0和ref_pic_list_modification_flag_l1保存在slice_header中的ref_pic_list_modification结构中,该结构的定义如下:

        以P帧解码时修改参考帧列表RefPicList0为例讨论其执行过程。

        (1)首先设定一个值refIdxL0表示参考帧列表中参考帧的索引值,并初始化为0;

        (2)读取码流中的modification_of_pic_nums_idc值,并根据其取值进行计算:

                若modification_of_pic_nums_idc为0或1,执行短期参考帧的修改过程;

                若modification_of_pic_nums_idc为2,执行长期参考帧的修改过程;

                若modification_of_pic_nums_idc为3,参考帧列表的修改过程完成;

                参考帧列表修改过程以refIdxL0作为输入参数,执行完成后的结果也返回给refIdxL0。

        (3)短期参考帧的修改

        修改短期参考帧主要步骤如下:

        (3.1)计算picNumLXPred

        picNumLXPred可以认为是下一步骤中要计算的变量picNumLXNoWrap的预测值。当slice_header中出现第一个modification_of_pic_nums_idc值时,picNumLXPred设置为CurrPicNum,即当前帧的frame_num;随后,每当计算得到一个picNumLXNoWrap后,这一个picNumLXNoWrap值都会赋值给picNumLXPred。

        (3.2)计算picNumLXNoWrap

        计算picNumLXNoWrap的方法根据modification_of_pic_nums_idc的取值不同而不同。

     当modification_of_pic_nums_idc取值为0时,其含义为码流中读出的abs_diff_pic_num_minus1为picNumLXNoWrap为相对于picNumLXPred的负增量,即需要从picNumLXPred中减去该值。计算方法如下:

if( picNumLXPred − ( abs_diff_pic_num_minus1 + 1 ) < 0 )

    picNumLXNoWrap = picNumLXPred − ( abs_diff_pic_num_minus1 + 1 ) + MaxPicNum

else

    picNumLXNoWrap = picNumLXPred − ( abs_diff_pic_num_minus1 + 1 )

     当modification_of_pic_nums_idc取值为0时,其含义为码流中读出的abs_diff_pic_num_minus1为picNumLXNoWrap为相对于picNumLXPred的正增量,即需要从picNumLXPred中加上该值。计算方法如下:

if( picNumLXPred + ( abs_diff_pic_num_minus1 + 1 ) >= MaxPicNum )

    picNumLXNoWrap = picNumLXPred + ( abs_diff_pic_num_minus1 + 1 ) − MaxPicNum

else

    picNumLXNoWrap = picNumLXPred + ( abs_diff_pic_num_minus1 + 1 )

        (3.3)计算picNumLX

        picNumLX的值通过picNumLXNoWrap与当前frame_num的值比较后计算得到,具体计算方式如下:

if( picNumLXNoWrap > CurrPicNum )

    picNumLX = picNumLXNoWrap − MaxPicNum

else

    picNumLX = picNumLXNoWrap

该步骤中得到的picNumLX应等于参考帧列表中的某一个短期参考帧的PicNum值。

        (3.4)修改参考帧列表

        在计算得到picNumLX后,配合传入的的索引值refIdxLX,接着进行参考帧列表的修改。其方法为将picNumLX对应的短期参考帧置于refIdxLX位置,并且清除掉列表中PicNum等于picNumLX的参考帧。具体计算方法如下:

for( cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > refIdxLX; cIdx− − )

    RefPicListX[ cIdx ] = RefPicListX[ cIdx − 1]

RefPicListX[ refIdxLX++ ] = short-term reference picture with PicNum equal to picNumLX

nIdx = refIdxLX

for( cIdx = refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; cIdx++ )

    if( PicNumF( RefPicListX[ cIdx ] ) != picNumLX )

        RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ]

(4)长期参考帧的修改

        修改长期参考帧的方法相对简单。在ref_pic_list_modification结构中的long_term_pic_num即表示待操作的长期参考帧索引。修改的方式类似短期参考帧的修改。具体计算方法如下:

for( cIdx = num_ref_idx_lX_active_minus1 + 1; cIdx > refIdxLX; cIdx− − )

    RefPicListX[ cIdx ] = RefPicListX[ cIdx − 1]

RefPicListX[ refIdxLX++ ] = long-term reference picture with LongTermPicNum equal to long_term_pic_num

nIdx = refIdxLX

for( cIdx = refIdxLX; cIdx <= num_ref_idx_lX_active_minus1 + 1; cIdx++ )

    if( LongTermPicNumF( RefPicListX[ cIdx ] ) != long_term_pic_num )

        RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ]

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值