VVC/JEM代码学习18:xCheckRDCostInter

26 篇文章 2 订阅

在xCheckRDCostMerge2N*2N执行完,如果m_useEarlySkipDetection==false,则继续执行xCheckRDCostInter函数。(如果m_useEarlySkipDetection==true,则此函数在帧间的最开始执行)

#if AMP_MRG
Void TEncCu::xCheckRDCostInter( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, PartSize ePartSize DEBUG_STRING_FN_DECLARE(sDebug), Bool bUseMRG
#if VCEG_AZ07_IMV
#if JVET_E0076_MULTI_PEL_MVD
  , UChar bIMV , TComDataCU * pcCUInfo2Reuse 
#else
  , Bool bIMV , TComDataCU * pcCUInfo2Reuse 
#endif
#endif
  )
#else
Void TEncCu::xCheckRDCostInter( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, PartSize ePartSize 
#if VCEG_AZ07_IMV
  , Bool bIMV , TComDataCU * pcCUInfo2Reuse 
#endif
  )
#endif
{
#if JVET_C0024_QTBT
  UInt uiWIdx = g_aucConvertToBit[rpcBestCU->getWidth(0)];
  UInt uiHIdx = g_aucConvertToBit[rpcBestCU->getHeight(0)];
#endif

  DEBUG_STRING_NEW(sTest)

  if(getFastDeltaQp()) //快速deltaQP模式,只有在2Nx2N的帧间模式中使用;
  {
    const TComSPS &sps=*(rpcTempCU->getSlice()->getSPS());
#if JVET_C0024_QTBT
    const UInt fastDeltaQPCuMaxSize = Clip3(sps.getMinQTSize(rpcBestCU->getSlice()->getSliceType(), rpcBestCU->getTextType()), sps.getCTUSize(), 32u);
#else
    const UInt fastDeltaQPCuMaxSize = Clip3(sps.getMaxCUHeight()>>(sps.getLog2DiffMaxMinCodingBlockSize()), sps.getMaxCUHeight(), 32u);
#endif
    if(ePartSize != SIZE_2Nx2N || rpcTempCU->getWidth( 0 ) > fastDeltaQPCuMaxSize)
    {
      return; // only check necessary 2Nx2N Inter in fast deltaqp mode
    }
  }

  // prior to this, rpcTempCU will have just been reset using rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );
  UChar uhDepth = rpcTempCU->getDepth( 0 );

#if COM16_C806_LARGE_CTU && !JVET_C0024_QTBT
  if( m_pcEncCfg->getUseFastLCTU() )
  {
    if( ePartSize != SIZE_2Nx2N && rpcTempCU->getWidth( 0 ) > 64 )
    {
      rpcTempCU->getTotalCost() = MAX_DOUBLE / 4;
      rpcTempCU->getTotalDistortion() = MAX_INT;
      xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth);
      return;
    }
  }
#endif

#if !JVET_C0024_QTBT
  rpcTempCU->setPartSizeSubParts  ( ePartSize,  0, uhDepth );
#endif
  rpcTempCU->setPredModeSubParts  ( MODE_INTER, 0, uhDepth );//初始化预测模式为帧间;
  rpcTempCU->setChromaQpAdjSubParts( rpcTempCU->getCUTransquantBypass(0) ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uhDepth );//设置色度QP自适应标记
#if COM16_C806_OBMC
  rpcTempCU->setOBMCFlagSubParts( true, 0, uhDepth );//初始化OBMC flag;
#endif
#if VCEG_AZ06_IC
  Bool bICFlag = rpcTempCU->getICFlag( 0 );//得到局部光照补偿标记;
#endif
#if VCEG_AZ07_IMV
  rpcTempCU->setiMVFlagSubParts( bIMV,  0, uhDepth );//初始化IMV的flag;
  if( bIMV && pcCUInfo2Reuse != NULL )//bIMV,局部自适应运动矢量分辨率且重复使用的信息不为空;
  {
    // reuse the motion info from pcCUInfo2Reuse,从pcCUInfo2Reuse中重复使用运动信息;
#if JVET_C0024_QTBT
      rpcTempCU->copyPartFrom( pcCUInfo2Reuse , 0 , uhDepth, rpcTempCU->getWidth(0), rpcTempCU->getHeight(0) );//把pcCUInfo2Reuse存储的信息复制给TempCU;
#else
    assert( pcCUInfo2Reuse->getPartitionSize( 0 ) == ePartSize );
    rpcTempCU->copyPartFrom( pcCUInfo2Reuse , 0 , uhDepth );
#endif
    rpcTempCU->setiMVFlagSubParts( bIMV , 0 , uhDepth );//设置imv的标记;
    rpcTempCU->resetMVDandMV2Int( true 
#if VCEG_AZ07_FRUC_MERGE
      , m_pcPredSearch
#endif
      );
#if VCEG_AZ06_IC
    bICFlag = rpcTempCU->getICFlag( 0 );//得到局部光照补偿标记;
#endif
    if( !rpcTempCU->hasSubCUNonZeroMVd() )//没有非0MVD,即MVD全为0,则退出;
    {
      return;
    }
    else//有非零MVD,则做运动补偿
    {
#if JVET_C0024_QTBT
      m_pcPredSearch->motionCompensation( rpcTempCU , m_pppcPredYuvTemp[uiWIdx][uiHIdx] );//运动补偿
#if COM16_C806_OBMC //OBMC,重叠块运动补偿,JEM中新加的;
      m_pppcPredYuvTemp[uiWIdx][uiHIdx]->copyToPartYuv( m_pppcPredYuvWoOBMC[uiWIdx][uiHIdx] , 0 );
      rpcTempCU->setOBMCFlagSubParts( true, 0, uhDepth );//设置OBMC的标记
      m_pcPredSearch->subBlockOBMC( rpcTempCU, 0, m_pppcPredYuvTemp[uiWIdx][uiHIdx], m_pppcTmpYuv1[uiWIdx][uiHIdx], m_pppcTmpYuv2[uiWIdx][uiHIdx] );//重叠块运动补偿
#endif
#else
      m_pcPredSearch->motionCompensation( rpcTempCU , m_ppcPredYuvTemp[uhDepth] );
#if COM16_C806_OBMC
      m_ppcPredYuvTemp[uhDepth]->copyToPartYuv( m_ppcPredYuvWoOBMC[uhDepth] , 0 );
      rpcTempCU->setOBMCFlagSubParts( true, 0, uhDepth );
      m_pcPredSearch->subBlockOBMC( rpcTempCU, 0, m_ppcPredYuvTemp[uhDepth], m_ppcTmpYuv1[uhDepth], m_ppcTmpYuv2[uhDepth] );
#endif
#endif
    }
  }
  else//bIMV==false || pcCUInfo2Reuse == NULL
  {
#endif
#if AMP_MRG
#if !JVET_C0024_QTBT
  rpcTempCU->setMergeAMP (true);
#endif
#if COM16_C806_OBMC
#if JVET_C0024_QTBT//predInterSearch的主要工作是运动估计和运动补偿;
  m_pcPredSearch->predInterSearch ( rpcTempCU, m_pppcOrigYuv[uiWIdx][uiHIdx], m_pppcPredYuvTemp[uiWIdx][uiHIdx], m_pppcResiYuvTemp[uiWIdx][uiHIdx], m_pppcRecoYuvTemp[uiWIdx][uiHIdx], m_pppcPredYuvWoOBMC[uiWIdx][uiHIdx], m_pppcTmpYuv1[uiWIdx][uiHIdx], m_pppcTmpYuv2[uiWIdx][uiHIdx], false, bUseMRG );
#else
  m_pcPredSearch->predInterSearch ( rpcTempCU, m_ppcOrigYuv[uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcRecoYuvTemp[uhDepth], m_ppcPredYuvWoOBMC[uhDepth], m_ppcTmpYuv1[uhDepth], m_ppcTmpYuv2[uhDepth], false, bUseMRG );
#endif
#else
#if JVET_C0024_QTBT
  m_pcPredSearch->predInterSearch ( rpcTempCU, m_pppcOrigYuv[uiWIdx][uiHIdx], m_pppcPredYuvTemp[uiWIdx][uiHIdx], m_pppcResiYuvTemp[uiWIdx][uiHIdx], m_pppcRecoYuvTemp[uiWIdx][uiHIdx] , false, bUseMRG );
#else
  m_pcPredSearch->predInterSearch ( rpcTempCU, m_ppcOrigYuv[uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcRecoYuvTemp[uhDepth] DEBUG_STRING_PASS_INTO(sTest), false, bUseMRG );
#endif
#endif
#else
#if COM16_C806_OBMC
  m_pcPredSearch->predInterSearch ( rpcTempCU, m_ppcOrigYuv[uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcRecoYuvTemp[uhDepth], m_ppcPredYuvWoOBMC[uhDepth], m_ppcTmpYuv1[uhDepth], m_ppcTmpYuv2[uhDepth] );
#else
  m_pcPredSearch->predInterSearch ( rpcTempCU, m_ppcOrigYuv[uhDepth], m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcRecoYuvTemp[uhDepth] );
#endif
#endif

#if AMP_MRG && !JVET_C0024_QTBT
  if ( !rpcTempCU->getMergeAMP() )
  {
    return;
  }
#endif

#if VCEG_AZ07_IMV
  if( bIMV )
  {
    if( !rpcTempCU->hasSubCUNonZeroMVd() )//没有非零MVD,就返回;
    {
      return;
    }
  }
  }
#endif

#if COM16_C806_OBMC
#if JVET_C0024_QTBT
  m_pppcTempCUWoOBMC[uiWIdx][uiHIdx]->initEstData( uhDepth, rpcTempCU->getQP( 0 ), rpcTempCU->getCUTransquantBypass( 0 ) );
  m_pppcTempCUWoOBMC[uiWIdx][uiHIdx]->copyPartFrom( rpcTempCU, 0, uhDepth, rpcTempCU->getWidth(0), rpcTempCU->getHeight(0) );
#else
  m_ppcTempCUWoOBMC[uhDepth]->initEstData( uhDepth, rpcTempCU->getQP( 0 ), rpcTempCU->getCUTransquantBypass( 0 ) );
  m_ppcTempCUWoOBMC[uhDepth]->copyPartFrom( rpcTempCU, 0, uhDepth );
#endif
  Bool bCheckOBMC[2] = { true , true };
  bCheckOBMC[0] = rpcTempCU->isOBMCFlagCoded( 0 ); // check OBMC off only when the flag is to be coded
  if( !rpcTempCU->getSlice()->getSPS()->getOBMC() )//不使用OBMC
  {
    bCheckOBMC[1] = false; bCheckOBMC[0] = true;
  }
  else if( rpcTempCU->isOBMCFlagCoded( 0 ) )
  {
    const Double dOBMCThOn  = 0.0;
    const Double dOBMCThOff = 1.0;
#if JVET_C0024_QTBT
    UInt uiSADOBMCOff = m_pppcOrigYuv[uiWIdx][uiHIdx]->sadLuma( m_pppcPredYuvWoOBMC[uiWIdx][uiHIdx] );//计算亮度分量的SAD;
    UInt uiSADOBMCOn  = m_pppcOrigYuv[uiWIdx][uiHIdx]->sadLuma( m_pppcPredYuvTemp[uiWIdx][uiHIdx] );
#else
    UInt uiSADOBMCOff = m_ppcOrigYuv[uhDepth]->sadLuma( m_ppcPredYuvWoOBMC[uhDepth] );
    UInt uiSADOBMCOn  = m_ppcOrigYuv[uhDepth]->sadLuma( m_ppcPredYuvTemp[uhDepth] );
#endif
    // OBMC off
    bCheckOBMC[0] = uiSADOBMCOff * dOBMCThOff < uiSADOBMCOn;//如果OBMC off的SAD小于OBMC on的SAD,则bCheckOBMC[0]为true;
    // OBMC on
    bCheckOBMC[1] = !bCheckOBMC[0] || uiSADOBMCOn * dOBMCThOn < uiSADOBMCOff;// bCheckOBMC[0]为false或者如果OBMC off的SAD大于OBMC on的SAD,则bCheckOBMC[1]为true;
  }
  循环两次,第一次不执行OBMC,第二次执行OBMC//
  for( Int nOBMC = 1 ; nOBMC >= 0 ; nOBMC-- )
  {
    if( !bCheckOBMC[nOBMC] )//如果bCheckOBMC[1]是false,即不执行OBMC,所以跳出
    {
      continue;
    }
#if JVET_C0024_QTBT
    rpcTempCU->copyPartFrom( m_pppcTempCUWoOBMC[uiWIdx][uiHIdx], 0, uhDepth, rpcTempCU->getWidth(0), rpcTempCU->getHeight(0) );
    if (nOBMC == 0)
      m_pppcPredYuvWoOBMC[uiWIdx][uiHIdx]->copyToPartYuv(m_pppcPredYuvTemp[uiWIdx][uiHIdx], 0);
#else
    rpcTempCU->copyPartFrom( m_ppcTempCUWoOBMC[uhDepth], 0, uhDepth );
    if (nOBMC == 0)
      m_ppcPredYuvWoOBMC[uhDepth]->copyToPartYuv(m_ppcPredYuvTemp[uhDepth], 0);
#endif
    rpcTempCU->setOBMCFlagSubParts( ( Bool )nOBMC , 0 , uhDepth );//用nOBMC初始化OBMC标记,所以只有bCheckOBMC[1]==1时OBMCFlag才为true;
#endif
#if VCEG_AZ06_IC
    rpcTempCU->setICFlagSubParts( bICFlag, 0, uhDepth );//初始化局部光照补偿的标记;
#endif
#if JVET_C0024_QTBT//编码残差并计算率失真代价;
    m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU, m_pppcOrigYuv[uiWIdx][uiHIdx], 
    m_pppcPredYuvTemp[uiWIdx][uiHIdx], m_pppcResiYuvTemp[uiWIdx][uiHIdx], m_pppcResiYuvBest[uiWIdx][uiHIdx], m_pppcRecoYuvTemp[uiWIdx][uiHIdx], false 
#else
  m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU, m_ppcOrigYuv[uhDepth], 
    m_ppcPredYuvTemp[uhDepth], m_ppcResiYuvTemp[uhDepth], m_ppcResiYuvBest[uhDepth], m_ppcRecoYuvTemp[uhDepth], false 
#endif
#if COM16_C806_EMT
    , rpcBestCU->getTotalCost() 
#endif
    DEBUG_STRING_PASS_INTO(sTest) 
  );
  rpcTempCU->getTotalCost()  = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() );//计算总的率失真代价;
#if VCEG_AZ07_IMV
#if !JVET_C0024_QTBT
  if( rpcTempCU->getiMVFlag( 0 ) == 0 )
  {
    if( rpcTempCU->getTotalCost() < m_ppcTempCUIMVCache[ePartSize][uhDepth]->getTotalCost() )
    {
      SModeCand tmpCand;
      tmpCand.eInterPartSize = ePartSize;
      tmpCand.bUseMrg = bUseMRG;
      tmpCand.dRDCost = rpcTempCU->getTotalCost();
      m_ppcTempCUIMVCache[ePartSize][uhDepth]->copyPartFrom( rpcTempCU , 0 , uhDepth );
      m_ppcTempCUIMVCache[ePartSize][uhDepth]->getTotalCost() = tmpCand.dRDCost;
      tmpCand.pcCUMode = m_ppcTempCUIMVCache[ePartSize][uhDepth];
      m_setInterCand.insert( tmpCand );
    }
  }
#endif
#endif

#if JVET_E0076_MULTI_PEL_MVD//指的是多精度MVD
  if (rpcTempCU->getTotalCost() < m_dBestMvDPelCost[rpcTempCU->getiMVFlag(0)])//如果当前CU的总代价小于最优MVD精度的代价
  {
    m_dBestMvDPelCost[rpcTempCU->getiMVFlag(0)] = rpcTempCU->getTotalCost();//把最优MVD精度代价更新为当前CU的代价;
  }
#endif

#if DEBUG_STRING
  DebugInterPredResiReco(sTest, *(m_ppcPredYuvTemp[uhDepth]), *(m_ppcResiYuvBest[uhDepth]), *(m_ppcRecoYuvTemp[uhDepth]), DebugStringGetPredModeMask(rpcTempCU->getPredictionMode(0)));
#endif

#if JVET_C0024_DELTA_QP_FIX && COM16_C806_OBMC
  Int orgQP = rpcTempCU->getQP( 0 );
#endif
  xCheckDQP( rpcTempCU );
  xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth DEBUG_STRING_PASS_INTO(sDebug) DEBUG_STRING_PASS_INTO(sTest));
#if COM16_C806_OBMC
#if JVET_C0024_DELTA_QP_FIX
  rpcTempCU->initEstData( uhDepth, orgQP, rpcTempCU->getCUTransquantBypass( 0 ) );//重新初始化TempCU;

#else
  rpcTempCU->initEstData( uhDepth, rpcTempCU->getQP( 0 ), rpcTempCU->getCUTransquantBypass( 0 ) );
#endif
  }
  /OBMC循环结束/
#endif
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值