H.266/VVC相關技術學習筆記23:VVC中成對平均候選技術(用於Merge列表的構建)

組合平均法是在Merge列表構建過程中的一種填充候選的方法。

一、 在HEVC中,使用組合候選的方法作爲Merge候選列表構建的一種備選方法,該方法比較複雜,對於一個BSlice中的PU而言,其中需要兩個MV(一個前向、一個後向),因此在構建Merge候選列表的時候,每個候選需要提供兩個MV,當需要用到組合候選法去填充Merge列表的時候,需要對前面已經填充進列表中的前4個候選中的前後向MV使用兩兩組合的方式產生新的候選再放入到Merge列表中。組合的方式具體爲下表所示:
在這裏插入圖片描述

其中combIdx爲進行組合的候選MV對的序號,也是可能添加進Merge列表中最後一個候選的組合MV;L0CandIdx和L1CandIdx分別表示進行組合的兩個MV所在的候選項在原Merge候選列表中的序號。
如列表中所示,Merge列表中前4個候選的任意一個候選的前向MV和另一個候選的後向MV相互組合出一個新的MV對(新候選),總共12種組合方式,在這12中選出一個添加到Merge列表中,在檢查冗餘的基礎上,最多隻允許添加一個。

二、 在目前的VVC中,擯棄之前繁雜的組合候選的方式,L次會議上的L0090提出了簡化的成對平均候選的方法,不需要12種繁雜的組合,只需要將Merge列表中已經添加進去的前兩個候選(0、1)的前向MV進行兩兩平均得到新的前向MV,以及後向MV進行兩兩平均得到新的後向MV。然後用這兩個平均後的MV組合成一個新的候選,將該新候選添加到Merge列表中。在檢查冗餘的基礎上最多隻允許添加一個成對平均候選。
成對平均候選在VTM6.0中的代碼如下,有較爲詳細的註釋,如有註釋不對的地方歡迎指正:

#if JVET_L0090_PAIR_AVG
  // pairwise-average candidates
  //這裏開始成對平均候選的填充
  {

    if (cnt > 1 && cnt < maxNumMergeCand)//如果此時Merge列表還沒有被填滿
    {
      //對當前Merge候選項中進行初始化,即賦予零MV
      mrgCtx.mvFieldNeighbours[cnt * 2].setMvField( Mv( 0, 0 ), NOT_VALID );
      mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField( Mv( 0, 0 ), NOT_VALID );
      // calculate average MV for L0 and L1 seperately
      //接下來計算前後向各自的平均MV
      unsigned char interDir = 0;


#if JVET_O0057_ALTHPELIF
      //半像素插值濾波器是否可用
      mrgCtx.useAltHpelIf[cnt] = (mrgCtx.useAltHpelIf[0] == mrgCtx.useAltHpelIf[1]) ? mrgCtx.useAltHpelIf[0] : false;
#endif
      //對Merge列表中前兩個候選的前向和後向的MV分別進行循環
      for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ )
      {
        const short refIdxI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].refIdx;//第一個候選的參考幀索引
        const short refIdxJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].refIdx;//第二個候選的參考幀索引

        //如果兩個候選的MV都不可用,則直接跳出進行另一向MV的平均
        if( (refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID) )
        {
          continue;
        }

        interDir += 1 << refListId;
        //如果兩個MV都有效,則對兩個MV進行兩兩平均
        if( (refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID) )
        {
          const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;//第一個候選的MV
          const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;//第二個候選的MV

          // average two MVs
          Mv avgMv = MvI;
          avgMv += MvJ;
          roundAffineMv(avgMv.hor, avgMv.ver, 1);

          mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( avgMv, refIdxI );
        }
        // only one MV is valid, take the only one MV
        //若只有其中一個MV有效,則僅僅將該有效的MV作爲平均的MV
        else if( refIdxI != NOT_VALID )
        {
          Mv singleMv = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
          mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxI );
        }
        else if( refIdxJ != NOT_VALID )
        {
          Mv singleMv = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
          mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxJ );
        }
      }

      mrgCtx.interDirNeighbours[cnt] = interDir;
      //如果預測方向有效,則將該成對候選MV添加到Merge列表中去
      if( interDir > 0 )
      {
        cnt++;
      }
    }

    // early termination
    if( cnt == maxNumMergeCand )
    {
      return;
    }
  }
#endif
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章