jm8.6之参考帧管理

来源:互联网 发布:python async def 编辑:程序博客网 时间:2024/06/04 18:15

管理概述:

        在默认情况下,图像列表list0中的短期图像按照从高到低的图像次序(PicNum)进行排序(由帧号推出的变量),而长期图像则按照从低到高的图像次序(LongTermPicNum)进行排序。编码器可以明确地指定默认参考图像列表顺序的改变。
        当一个新的图像被加到短期列表的位置0时,剩余的短期图像列表按递增顺序索引。如果短期和长期图像的数目等于参考帧的最大数目,则最先存入的短期图像(有最大的索引)将从缓存器中删除(这个策略被称为滑动窗口内存控制)。
        实际上,这个过程的实现是在编码器和解码器各自产生一个N长度短期参考图像的窗口,这个窗口内存记录当前图像和(N-1)个先进编码的图像。对于帧间编码的宏块,编码器为每个宏块进行分块是从图像列表list0中选择一个参考图像的。参考图像的选择用一个索引是进行标记,这里索引号0对应于短期列表中的第一幅图像,而长期图像的索引开始于最后一个短期图像之后。

为什么要分长期参考和短期参考呢?
    因为short term参考帧以frame_num做为索引,而frame_num是有最大值的,达到最大值后会进行取模,所以短期参考帧不能长期存在于参考列表中,因为一旦frame_num达到最大值后取模为0,该索引就失去意义了,而长期参考帧则不同!

什么时候做长期参考帧,什么时候做短期参考帧?
如果当前图像是IDR帧,则根据读入的语法元素,指明是否清空DPB,另外,还确定将IDR帧作为长期参考还是短期参考。
非IDR帧情况,当前帧作为短期参考插入DPB。

参考帧为什么要重排序?
    由于在解码每个MB时,都要用到参考帧的索引ref_idx_l0或ref_idx_l1。可能发生这样的情况,有个参考帧(短期参考帧或者长期参考帧)对于解码一个图像特别有用,但是这个参考帧在缺省的队列中并不位于索引值为0的位置,所以编码大的索引值需要花费多的比特。参考帧的重排序可以使这个参考帧位于索引值比较小的位置,以节省编码比特数。

重排短期参考帧

static void reorder_short_term(StorablePicture **RefPicListX, int num_ref_idx_lX_active_minus1, int picNumLX, int *refIdxLX)
{
 int cIdx, nIdx;
 StorablePicture *picLX;
 picLX = get_short_term_pic(picNumLX); //根据给定的picNumLX获取相应的短期参考帧
 for( cIdx = num_ref_idx_lX_active_minus1+1; cIdx > *refIdxLX; cIdx-- )
  RefPicListX[ cIdx ] = RefPicListX[ cIdx - 1];  //!< 将refIdxLX位置之后的参考帧依次后移
 RefPicListX[ (*refIdxLX)++ ] = picLX; //!< 将给定的picNumLX短期参考帧存至refIdxLX位置
 nIdx = *refIdxLX;
 for( cIdx = *refIdxLX; cIdx <= num_ref_idx_lX_active_minus1+1; cIdx++ )
  if (RefPicListX[ cIdx ])
  if( (RefPicListX[ cIdx ]->is_long_term ) ||  (RefPicListX[ cIdx ]->pic_num != picNumLX ))//!< 该操作可将参考帧列表中重复的序号为picNumLX的参考帧覆盖掉
  RefPicListX[ nIdx++ ] = RefPicListX[ cIdx ];
        /*  类似代码
 void main()
 {
 int test[6]={1,2,3,4,5,0};//这边的最后一个0相当于多出的那一位数据
 int i=0,j=1;
 for(i=5;i>0;i--){test[ i ]=test[i-1];}
 test[0]=3;
 for(i=0;i<6;i++){printf("test[%d]=%d\n",i,test[ i ]);}
 printf("\n");
 for(i=1;i<=5;i++){
        if(test[ i ]!=3){test[j++]=test[ i ];}
 }
 for(i=0;i<6;i++){printf("test[%d]=%d\n",i,test[ i ]);}
 }
 开始是:3 1 2 3 4 5       3 1 2 4 5 5
 */
}

参考图像的滑窗标记过程

/*!
 ************************************************************************
 * \brief
 *    Perform Sliding window decoded reference picture marking process 参考图像的滑窗标记过程
 *
 ************************************************************************
 */
static void sliding_window_memory_management(StorablePicture* p)
{
  unsigned i;
  assert (!p->idr_flag);
  // if this is a reference pic with sliding sliding window, unmark first ref frame
  if (dpb.ref_frames_in_buffer==dpb.num_ref_frames - dpb.ltref_frames_in_buffer)//!< 减去dpb.ltref_frames_in_buffer因滑窗标记不能使用在长期参考帧上
  {
    for (i=0; i<dpb.used_size;i++) //!< 采取FIFO策略,将dpb中第一个短期参考帧移出参考帧列表,并更新参考帧列表
    {
      if (dpb.fs[i]->is_reference  && (!(dpb.fs[i]->is_long_term)))
      {
        unmark_for_reference(dpb.fs[i]); //!< 标记该帧为非参考帧
        update_ref_list(); //!< 更新参考帧列表
        break;
      }
    }
  }
  p->is_long_term = 0;
}

0 0