H.266/VVC VTM 6-BCW符号化端子加速アルゴリズムを読む


VVVCのBCWは多様な双方向予測重みを提供し,符号化の必要性を決定する.ここでは、文書JVET−N 0646に記載されている符号化端子加速アルゴリズムおよびVTMの実装の一部を記録する.
1、加速アルゴリズム
1.1 affineモーション推定の一部スキップ
  不等重み条件下でaffineモード部分条件下で運動推定をスキップした.等重みのaffine動き推定後、affine interモードが現在の最適モードである場合にのみ動き推定を行い、他の重みの動き推定を行う.
1.2 low-delay画像RD検出回数の減少
  low-delay画像については、1/4画素、1画素、および4画素精度を含む5種類の重みのRD検出が必要であり、まず1/4画素精度を検出し、1画素および4画素精度で部分重みRDをスキップする.まず,1/4画素精度で不等重みのRDcostを計算し,1画素と4画素条件下で対等重み条件と1/4画素精度で最小の重みのセットのみをRD検出した.
1.3参照画像が同じ場合のスキップモーション推定
  いくつかのRAモードの画像について、同じフレームが2つの参照フレームリストに同時に現れることがある.同時に満たす(a.参照フレームは同じ;b.時間層は1より大きい;c.動きベクトル精度は1/4である.)3つの条件下で不等重みの動き推定をスキップします.この規則は4パラメータのaffine双方向予測にも適用できる.
1.4時間層とPOC距離に基づいてRD検出をスキップする
  は同時に満足する(a.時間層は4;b.任意の参照フレームPOCは現在のフレームから1未満、c.QPは32より大きい).をクリックして、不等重みのRDO決定をスキップします.
1.5運動推定における定点計算の使用
双方向予測の動き推定では、1つのMVを固定して別のMVを検索し、MV 1を固定してMV 0を調整します.MV 0の検索対象は
T=((O≪3)-w·P_1 )·(1/(8-w))
  定点計算を行うため、検索対象を
T=(O·a_1-P_1·a_2+round)≫N
そのうちγ=(1≪N)/(8-w);  a_1=γ≪3; a_2=γ*w;  round=1≪(N-1)
2、部分コード実現
  VTMはEncCfgオブジェクトにm_を加えたBcwFastは、関数getUseBcwFast()を使用して取得できるオープン高速アルゴリズムを表します.
2.1 EncCu::xCheckRDCostInter()
  は1.2内容に対応する.
    if( m_pcEncCfg->getUseBcwFast() && tempCS->slice->getCheckLDC() && g_BcwSearchOrder[bcwLoopIdx] != BCW_DEFAULT
      && (m_bestBcwIdx[0] >= 0 && g_BcwSearchOrder[bcwLoopIdx] != m_bestBcwIdx[0])
      && (m_bestBcwIdx[1] >= 0 && g_BcwSearchOrder[bcwLoopIdx] != m_bestBcwIdx[1]))
    {
      continue;
    }

 現在の最適モードがフレーム間モードであり、現在の重みが不等重みであり、現在の重みが不等重みである場合、今回のRD検出をスキップする.すなわち、最適モードがフレーム間モードである場合には、対等重みまたは最適重みのみRD検出を行う.
if( m_pcEncCfg->getUseBcwFast() )
    {
      auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >(m_modeCtrl);

      if( blkCache )
      {
        bool isBestInter = blkCache->getInter(bestCS->area);
        uint8_t bestBcwIdx = blkCache->getBcwIdx(bestCS->area);

        if( isBestInter && g_BcwSearchOrder[bcwLoopIdx] != BCW_DEFAULT && g_BcwSearchOrder[bcwLoopIdx] != bestBcwIdx )
        {
          continue;
        }
      }
    }

等重みでcostが他のモードの1.05倍より大きい場合、不等重みRD検出はスキップされる.一方向予測であれば,不等重みのRD検出をスキップする.1回目の検出後、条件(1.4中の条件に対応)を満たすと、後続のRDO検出はスキップされる.
  double skipTH = MAX_DOUBLE;
  skipTH = (m_pcEncCfg->getUseBcwFast() ? 1.05 : MAX_DOUBLE);
  if( equBcwCost > curBestCost * skipTH )
  {
    break;
  }
  if( m_pcEncCfg->getUseBcwFast() )
  {
    if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
    {
      break;
    }
  }
  if( g_BcwSearchOrder[bcwLoopIdx] == BCW_DEFAULT && xIsBcwSkip(cu) && m_pcEncCfg->getUseBcwFast() )
  {
    break;
  }

 bool xIsBcwSkip(const CodingUnit& cu)
  {
    if (cu.slice->getSliceType() != B_SLICE)
    {
      return true;
    }
    return((m_pcEncCfg->getBaseQP() > 32) && ((cu.slice->getTLayer() >= 4)
       || ((cu.refIdxBi[0] >= 0 && cu.refIdxBi[1] >= 0)
       && (abs(cu.slice->getPOC() - cu.slice->getRefPOC(REF_PIC_LIST_0, cu.refIdxBi[0])) == 1
       ||  abs(cu.slice->getPOC() - cu.slice->getRefPOC(REF_PIC_LIST_1, cu.refIdxBi[1])) == 1))));
  }

2.2 void InterSearch::predInterSearch()
  affineが最適モード条件である場合にのみ、不等重みのaffine動き探索が行われる.
    if (cu.Y().width > 8 && cu.Y().height > 8 && cu.slice->getSPS()->getUseAffine()
      && checkAffine
      && (bcwIdx == BCW_DEFAULT || m_affineModeSelected || !m_pcEncCfg->getUseBcwFast())
      )
    {
      ...
      MvField cHevcMvField[2];
      cHevcMvField[0].setMvField( pu.mv[REF_PIC_LIST_0], pu.refIdx[REF_PIC_LIST_0] );
      cHevcMvField[1].setMvField( pu.mv[REF_PIC_LIST_1], pu.refIdx[REF_PIC_LIST_1] );

      // do affine ME & Merge
      cu.affineType = AFFINEMODEL_4PARAM;
      Mv acMvAffine4Para[2][33][3];
      int refIdx4Para[2] = { -1, -1 };
      
      xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, acMvAffine4Para, refIdx4Para, bcwIdx, enforceBcwPred,
        ((cu.slice->getSPS()->getUseBcw() == true) ? getWeightIdxBits(bcwIdx) : 0));

      if ( pu.cu->imv == 0 )
      {
        storeAffineMotion( pu.mvAffi, pu.refIdx, AFFINEMODEL_4PARAM, bcwIdx );
      }

      if ( cu.slice->getSPS()->getUseAffineType() )
      {
        if ( uiAffineCost < uiHevcCost * 1.05 ) ///< condition for 6 parameter affine ME
        {
          ...
          
          xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, acMvAffine4Para, refIdx4Para, bcwIdx, enforceBcwPred,
            ((cu.slice->getSPS()->getUseBcw() == true) ? getWeightIdxBits(bcwIdx) : 0));
          ...
          
        }
        uiAffineCost += m_pcRdCost->getCost( 1 ); // add one bit for affine_type
      }
     ...
    }

非LDC条件でaffineモードを選択すると、不等重みのフレーム間双方向動き推定がスキップされる.
      //  Bi-predictive Motion estimation
      if( ( cs.slice->isInterB() ) && ( PU::isBipredRestriction( pu ) == false )
        && (cu.slice->getCheckLDC() || bcwIdx == BCW_DEFAULT || !m_affineModeSelected || !m_pcEncCfg->getUseBcwFast())
        )
        {...}

参照フレームPOCが同じ場合、動き推定値はスキップされ、1.3の条件に対応する.
if( m_pcEncCfg->getUseBcwFast() && (bcwIdx != BCW_DEFAULT)
              && (pu.cu->slice->getRefPic(eRefPicList, iRefIdxTemp)->getPOC() == pu.cu->slice->getRefPic(RefPicList(1 - iRefList), pu.refIdx[1 - iRefList])->getPOC())
              && (!pu.cu->imv && pu.cu->slice->getTLayer()>1))
            {
              continue;
            }