H.266 / VVCコード学習:MIPテクノロジー関連コード

MIPテクノロジーの原則の概要:https//blog.csdn.net/BigDream123/article/details/104939645

次のコードに示すように、MIPの関連する関数コードがestIntraPredLumaQT関数で初めて呼び出されます。

  • initIntraMip関数は、参照ピクセルをダウンサンプリングし、MIP行列乗算用の入力データを準備するために使用されます。
  • getNumModesMip関数は、現在のブロックのサイズに応じて、さまざまなMIPモードの数を取得します。
  • predIntraMip関数は、行列演算とアップサンプリング補間を実行して、ブロック全体の予測値を取得します。

注:MIPの使用にはブロックサイズの制限があります。アスペクト比は1:8/8:1を超えることはできません。

    //MIP允许使用标志
    const bool mipAllowed = sps.getUseMIP() && isLuma(partitioner.chType) && ((cu.lfnstIdx == 0) || allowLfnstWithMip(cu.firstPU->lumaSize()));
    //MIP模式测试标志:宽高比不能超过1:8/8:1
    const bool testMip = mipAllowed && !(cu.lwidth() > (8 * cu.lheight()) || cu.lheight() > (8 * cu.lwidth()));
    //MIP支持的最大块尺寸为64
    const bool supportedMipBlkSize = pu.lwidth() <= MIP_MAX_WIDTH && pu.lheight() <= MIP_MAX_HEIGHT;
...
...
...
// 初始化Mip模式
              initIntraPatternChType(cu, pu.Y());//获取参考像素并滤波
              initIntraMip(pu, pu.Y());
              // getNumModesMip函数根据当前CU的块尺寸获取不同的Mip模式数量16 8 6
              const int transpOff    = getNumModesMip(pu.Y());
              const int numModesFull = (transpOff << 1);//MIP模式总数分别是32 16 12
              
              for (uint32_t uiModeFull = 0; uiModeFull < numModesFull; uiModeFull++)
              {
                //对于另一半MIP模式,其需要进行转置
                const bool     isTransposed = (uiModeFull >= transpOff ? true : false);
                const uint32_t uiMode       = (isTransposed ? uiModeFull - transpOff : uiModeFull);

                pu.mipTransposedFlag           = isTransposed;
                pu.intraDir[CHANNEL_TYPE_LUMA] = uiMode;
                // Mip预测模式的函数入口,进行MIP预测
                predIntraMip(COMPONENT_Y, piPred, pu);

                // Use the min between SAD and HAD as the cost criterion
                // SAD is scaled by 2 to align with the scaling of HAD
                Distortion minSadHad =
                  std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));

                m_CABACEstimator->getCtx() = SubCtx(Ctx::MipFlag, ctxStartMipFlag);

                uint64_t fracModeBits = xFracModeBitsIntra(pu, uiMode, CHANNEL_TYPE_LUMA);

                double cost            = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass;
                mipHadCost[uiModeFull] = cost;
                DTRACE(g_trace_ctx, D_INTRA_COST, "IntraMIP: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost,
                       uiModeFull);
                // 更新候选列表,将最优的Mip模式加入到RDCost的候选列表中
                updateCandList(ModeInfo(true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, uiMode), cost, uiRdModeList,
                               CandCostList, numModesForFullRD + 1);
                updateCandList(ModeInfo(true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, uiMode),
                               0.8 * double(minSadHad), uiHadModeList, CandHadList, numHadCand);
              }

MIPは、ブロックサイズに応じて次の3つのケースに分けることができます。

  ブロックサイズ MIPモード
mipSizeId = 0 4x4 32
mipSizeId = 1 4xN、Nx4、8x8 16
mipSizeId = 2 レストブロック 12

その中で、MIPの転置マークはMIPのモード番号に関連しています。

  • mipSizdId = 0の場合、最初の16モードのmipTransposedFlagは0であり、最後の16モードのmipTransposedFlagは1です。
  • mipSizeId = 1の場合、最初の8つのモードのmipTransposedFlagは0であり、最後の8つのモードのmipTransposedFlagは1です。
  • mipSizeId = 2の場合、最初の6つのモードではmipTransposedFlag = 0、最後の6つのモードではmipTransposedFlag = 1です。

getNumModesMip関数コードは次のとおりです。

int getNumModesMip(const Size& block)
{
  switch( getMipSizeId(block) )
  {
  case 0: return 16;
  case 1: return  8;
  case 2: return  6;
  default: THROW( "Invalid mipSizeId" );
  }
}

InitIntraMip関数関連のコードリファレンス:https://blog.csdn.net/BigDream123/article/details/107018446

PredIntraMip関数関連のコードリファレンス:https://blog.csdn.net/BigDream123/article/details/107019458

おすすめ

転載: blog.csdn.net/BigDream123/article/details/107015803