VTM3.0代码阅读:xCheckRDCostMerge2Nx2N函数

xCheckRDCostMerge2Nx2N在xCompressCU函数中调用,用来测试Merge模式、mmvd模式以及CIIP模式。
首先由getInterMergeCandidates获取merge候选模式信息,存储于,mergeCtx。同时由merge列表获取MMVD模式的两个baseMV。
如果不进行fastMerge,则跳过SATD直接进行RDO选最优
fastMerge时,对7个merge候选模式进行SATD,分别进行MC获得pred像素,选取cost最小的4个merge候选;对于MMVD模式分别以这两个mv为中心进行4方向8步长的计算,得到最优的baseMV、方向和步长。CIIP模式则选择经过SATD之后的前4个merge模式,分别于帧内模式结合,选取最优的merge模式和帧内模式。
对RdModeList中的merge候选、MMVD模式以及CIIP模式,统一进行RDO选择最优。

void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
   
  const Slice &slice = *tempCS->slice;

  CHECK( slice.getSliceType() == I_SLICE, "Merge modes not available for I-slices" );

  tempCS->initStructData( encTestMode.qp, encTestMode.lossless );		//tempCS清空初始化

  MergeCtx mergeCtx;
  const SPS &sps = *tempCS->sps;

  if( sps.getSpsNext().getUseSubPuMvp() )
  {
   
    Size bufSize = g_miScaling.scale( tempCS->area.lumaSize() );
    mergeCtx.subPuMvpMiBuf    = MotionBuf( m_SubPuMiBuf,    bufSize );
  }

#if JVET_L0124_L0208_TRIANGLE
  setMergeBestSATDCost( MAX_DOUBLE );
#endif

  {
   
    // first get merge candidates
    CodingUnit cu( tempCS->area );			//创建cu、pu用来获得merge列表
    cu.cs       = tempCS;
    cu.partSize = SIZE_2Nx2N;
    cu.predMode = MODE_INTER;
    cu.slice    = tempCS->slice;
#if HEVC_TILES_WPP
    cu.tileIdx  = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
#endif

    PredictionUnit pu( tempCS->area );
    pu.cu = &cu;
    pu.cs = tempCS;
    PU::getInterMergeCandidates(pu, mergeCtx		//获取merge列表,其中包含7个merge候选信息,存储于mergeCtx
#if JVET_L0054_MMVD
      , 0
#endif
    );
    PU::restrictBiPredMergeCands(pu, mergeCtx);
#if JVET_L0054_MMVD
    PU::getInterMMVDMergeCandidates(pu, mergeCtx);	//MMVD选择merge列表的前两个候选,作为baseMV
#endif
  }
  
  bool candHasNoResidual[MRG_MAX_NUM_CANDS + MMVD_ADD_NUM];		//若merge模式没有resi,则为skip模式
  for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS + MMVD_ADD_NUM; ui++)
  {
   
    candHasNoResidual[ui] = false;
  }

  bool                                        bestIsSkip = false;
  bool                                        bestIsMMVDSkip = true;
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
  PelUnitBuf                                  acMergeBuffer[MRG_MAX_NUM_CANDS];	//里面存储的是:merge列表里面候选模式0~6顺序排列的各模式的pred像素
#endif
  PelUnitBuf                                  acMergeRealBuffer[MMVD_MRG_MAX_RD_BUF_NUM];//存储RDModeList前7个mode的pred像素
  PelUnitBuf *                                acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM];	//acMergeTempBuffer中始终存储的是RDModeList前几个模式的pred像素
  PelUnitBuf *                                singleMergeTempBuffer;					//这两个是指针
  int                                         insertPos;
  unsigned                                    uiNumMrgSATDCand = mergeCtx.numValidMergeCand + MMVD_ADD_NUM;

  static_vector<unsigned, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  RdModeList;
  bool                                        mrgTempBufSet = false;

  for (unsigned i = 0; i < MRG_MAX_NUM_CANDS + MMVD_ADD_NUM; i++)
  {
   
    RdModeList.push_back(i);		//如果不进行SATD,那么RdModeList中存放7+64个merge候选,直接进行最后的RDO
  }

  const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height));
  for (unsigned i = 0; i < MMVD_MRG_MAX_RD_BUF_NUM; i++)
  {
   
    acMergeRealBuffer[i] = m_acMergeBuffer[i].getBuf(localUnitArea);
    if (i < MMVD_MRG_MAX_RD_NUM)
    {
   
      acMergeTempBuffer[i] = acMergeRealBuffer + i;
    }
    else
    {
   
      singleMergeTempBuffer = acMergeRealBuffer + i;
    }
  }/以上为初始化,并获取Merge列表

#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
#if JVET_L0054_MMVD
  static_vector<unsigned, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM>  RdModeList2; // store the Intra mode for Intrainter
#else
  static_vector<unsigned, MRG_MAX_NUM_CANDS>  RdModeList2; // store the Intra mode for Intrainter
#endif
  RdModeList2.clear();
  bool isIntrainterEnabled = sps.getSpsNext().getUseMHIntra();
  if (bestCS->area.lwidth() * bestCS->area.lheight() < 64 || bestCS->area.lwidth() >= MAX_CU_SIZE || bestCS->area.lheight() >= MAX_CU_SIZE)
  {
   
    isIntrainterEnabled = false;
  }
  bool isTestSkipMerge[MRG_MAX_NUM_CANDS]; // record if the merge candidate has tried skip mode 
  for (uint32_t idx = 0; idx < MRG_MAX_NUM_CANDS; idx++)
  {
   
    isTestSkipMerge[idx] = false;
  }
#endif
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
  if( m_pcEncCfg->getUseFastMerge() || isIntrainterEnabled)			// FastMerge || CIIP
#else
  if( m_pcEncCfg->getUseFastMerge() )
#endif
  {
   
    uiNumMrgSATDCand = NUM_MRG_SATD_CAND;		//SATD粗选择后的merge候选数目,4
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
    if (isIntrainterEnabled)
    {
   
      uiNumMrgSATDCand += 1;			//4加一个CIIP模式
    }
#endif
    bestIsSkip       = false;

    if( auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >( m_modeCtrl ) )
    {
   
#if JVET_L0293_CPR
      if (slice.getSPS()->getSpsNext().getCPRMode())
      {
   
        ComprCUCtx cuECtx = m_modeCtrl->getComprCUCtx();
        bestIsSkip = blkCache->isSkip(tempCS->area) && cuECtx.bestCU;
      }
      else
#endif
      bestIsSkip = blkCache->isSkip( tempCS->area );
#if JVET_L0054_MMVD
      bestIsMMVDSkip = blkCache->isMMVDSkip(tempCS->area);
#endif
    }

#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
    if (isIntrainterEnabled) // always perform low complexity check
    {
   
      bestIsSkip = false;
    }
#endif

#if JVET_L0054_MMVD
    static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> candCostList;		//存放SATD时得到的7+64个候选的cost
#else
    static_vector<double, MRG_MAX_NUM_CANDS> candCostList;
#endif

    // 1. Pass: get SATD-cost for selected candidates and reduce their count
    if( !bestIsSkip )				//不是skip模式,对7+64个merge候选模式进行SATD粗选择
    {
   
      RdModeList.clear();			//RdModeList前面有压栈操作,这里清空
      mrgTempBufSet       = true;
      const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda( encTestMode.lossless );

      CodingUnit &cu      = tempCS->addCU( tempCS->area, partitioner.chType );		//tempCS添加cu和pu
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
      const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda(cu.transQuantBypass) / double(1 << SCALE_BITS);
#endif

      partitioner.setCUData( cu );
      cu.slice            = tempCS->slice;
#if HEVC_TILES_WPP
      cu.tileIdx          = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endif
      cu.skip             = false;
#if JVET_L0054_MMVD
      cu.mmvdSkip		  = false;
#endif
#if JVET_L0124_L0208_TRIANGLE
      cu.triangle         = false;
#endif
      cu.partSize         = SIZE_2Nx2N;
    //cu.affine
      cu.predMode         = MODE_INTER;
    //cu.LICFlag
      cu.transQuantBypass = encTestMode.lossless;
      cu.chromaQpAdj      = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
      cu.qp               = encTestMode.qp;
    //cu.emtFlag  is set below

      PredictionUnit &pu  = tempCS->add
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值