VVC/JEM代码学习16:xCheckRDCostMerge2Nx2N

26 篇文章 2 订阅

在执行完xCheckRDCostAffineMerge2N*2N函数后,执行此函数,在HEVC中,merge的候选模式个数为5个,在JEM中,候选模式的个数增加到了7个(加了两个额外ATMVP和STMVP推导得到的merge模式)。并且为了加速,先对7个候选模式计算SATD,选取其中4个最小的模式,并且如果在前四个中有模式的代价大于最小SATD的1.25倍,则该模式及其后面模式被取消候选资格。最后,对有效的候选模式(小于等于4个)进行RD COST的比较,选取最优merge模式。

Void TEncCu::xCheckRDCostMerge2Nx2N( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU DEBUG_STRING_FN_DECLARE(sDebug), Bool *earlyDetectionSkipMode )
{
#if JVET_C0024_QTBT
  UInt uiWIdx = g_aucConvertToBit[rpcBestCU->getWidth(0)];
  UInt uiHIdx = g_aucConvertToBit[rpcBestCU->getHeight(0)];
#else
#if COM16_C806_LARGE_CTU
  if( m_pcEncCfg->getUseFastLCTU() && rpcTempCU->getHeight( 0 ) * 2 > rpcTempCU->getSlice()->getSPS()->getPicHeightInLumaSamples() )
  {
    rpcTempCU->getTotalCost() = MAX_DOUBLE / 4;
    rpcTempCU->getTotalDistortion() = MAX_INT;
    xCheckBestMode(rpcBestCU, rpcTempCU, rpcTempCU->getDepth( 0 ));
    return;
  }
#endif
#endif

  assert( rpcTempCU->getSlice()->getSliceType() != I_SLICE );
  if(getFastDeltaQp())
  {
    return;   // never check merge in fast deltaqp mode
  }
  TComMvField  cMvFieldNeighbours[2 * MRG_MAX_NUM_CANDS]; // double length for mv of both lists,MRG_MAX_NUM_CANDS=7;
  UChar uhInterDirNeighbours[MRG_MAX_NUM_CANDS];
  Int numValidMergeCand = 0;
  const Bool bTransquantBypassFlag = rpcTempCU->getCUTransquantBypass(0);
#if COM16_C806_VCEG_AZ10_SUB_PU_TMVP
  UChar  eMergeCandTypeNieghors[MRG_MAX_NUM_CANDS];
  memset ( eMergeCandTypeNieghors, MGR_TYPE_DEFAULT_N, sizeof(UChar)*MRG_MAX_NUM_CANDS );
#endif
#if VCEG_AZ06_IC
  Bool abICFlag[MRG_MAX_NUM_CANDS];
#endif
  //初始化 uhInterDirNeighbours[];
  for( UInt ui = 0; ui < rpcTempCU->getSlice()->getMaxNumMergeCand(); ++ui )
  {
    uhInterDirNeighbours[ui] = 0;
  }
  UChar uhDepth = rpcTempCU->getDepth( 0 );
#if !JVET_C0024_QTBT
  rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to CTU level
#endif


#if COM16_C806_VCEG_AZ10_SUB_PU_TMVP
#if !JVET_C0024_QTBT  
  for (Int i=0 , i2 = 0 ; i< rpcTempCU->getTotalNumPart(); i++ , i2 += 2)
  {
#if JVET_C0035_ATMVP_SIMPLIFICATION
    for (Int j=0; j < NUM_MGR_TYPE ; j++)
    {
      m_phInterDirSP[j][i] = 0;
      m_pMvFieldSP[j][i2].setRefIdx(-1);
      m_pMvFieldSP[j][i2+1].setRefIdx(-1);
    }
#else
    m_phInterDirSP[1][i] = 0;
    m_pMvFieldSP[1][i2].setRefIdx(-1);
    m_pMvFieldSP[1][i2+1].setRefIdx(-1);
#endif
  }
#endif
#endif
  //得到帧间merge候选模式,7个;
  rpcTempCU->getInterMergeCandidates( 0, 0, cMvFieldNeighbours,uhInterDirNeighbours, numValidMergeCand
#if VCEG_AZ06_IC
    , abICFlag
#endif
#if COM16_C806_VCEG_AZ10_SUB_PU_TMVP
    , eMergeCandTypeNieghors
    , m_pMvFieldSP
    , m_phInterDirSP
#endif
    );

  Int mergeCandBuffer[MRG_MAX_NUM_CANDS];
  for( UInt ui = 0; ui < numValidMergeCand; ++ui )//numValidMergeCand=7;
  {
    mergeCandBuffer[ui] = 0;
  }

#if JVET_C0024_FAST_MRG
  Bool bestIsSkip = rpcBestCU->getPic()->getSkiped(rpcBestCU->getZorderIdxInCtu(), rpcBestCU->getWidth(0), rpcBestCU->getHeight(0));
  UInt uiNumMrgSATDCand = NUM_MRG_SATD_CAND;//4
  UInt uiRdModeList[MRG_MAX_NUM_CANDS];
  Double CandCostList[MRG_MAX_NUM_CANDS];
  for (UInt i=0; i<MRG_MAX_NUM_CANDS; i++)//初始化;
  {
    uiRdModeList[i] = i;
    CandCostList[i] = MAX_DOUBLE;
  }

  Bool bMrgTempBufSet = false;
  if (!bestIsSkip)//如果最优模式不是skip
  {
#if JVET_D0123_ME_CTX_LUT_BITS
    UInt uiMrgIdxBits[MRG_MAX_NUM_CANDS];
    m_pcPredSearch->getMrgCandBits(rpcBestCU, 0, uiMrgIdxBits);
#endif
    bMrgTempBufSet = true;
    for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand )//遍历7种有效的merge候选模式,计算每个候选的SATD;
    {
      // set MC parameters,设置预测补偿参数
      rpcTempCU->setPredModeSubParts( MODE_INTER, 0, uhDepth ); // interprets depth relative to CTU level
      rpcTempCU->setCUTransquantBypassSubParts( bTransquantBypassFlag, 0, uhDepth );
      rpcTempCU->setChromaQpAdjSubParts( bTransquantBypassFlag ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uhDepth );

      rpcTempCU->setMergeFlagSubParts( true, 0, 0, uhDepth ); // interprets depth relative to CTU level
      rpcTempCU->setMergeIndexSubParts( uiMergeCand, 0, 0, uhDepth ); // interprets depth relative to CTU level
#if COM16_C806_OBMC
      rpcTempCU->setOBMCFlagSubParts( true, 0, uhDepth );
#endif
#if VCEG_AZ06_IC
      rpcTempCU->setICFlagSubParts( rpcTempCU->getSlice()->getApplyIC() ? abICFlag[uiMergeCand] : 0, 0, uhDepth );
#endif
#if COM16_C806_VCEG_AZ10_SUB_PU_TMVP
      rpcTempCU->setMergeTypeSubParts(eMergeCandTypeNieghors[uiMergeCand] , 0, 0, uhDepth ); //设置merge类型,什么鬼???
      if( eMergeCandTypeNieghors[uiMergeCand])
      {
        UInt uiSPAddr;
        Int iWidth = rpcTempCU->getWidth(0);
        Int iHeight = rpcTempCU->getHeight(0);

        Int iNumSPInOneLine, iNumSP, iSPWidth, iSPHeight;
#if JVET_C0035_ATMVP_SIMPLIFICATION
        UInt uiSPListIndex = eMergeCandTypeNieghors[uiMergeCand];
#else
        UInt uiSPListIndex = eMergeCandTypeNieghors[uiMergeCand] == MGR_TYPE_SUBPU_TMVP?0:1;
#endif
        rpcTempCU->getSPPara(iWidth, iHeight, iNumSP, iNumSPInOneLine, iSPWidth, iSPHeight);

        for (Int iPartitionIdx = 0; iPartitionIdx < iNumSP; iPartitionIdx++)//iNumSP=1024,即遍历每个4*4的block;
        {
          rpcTempCU->getSPAbsPartIdx(0, iSPWidth, iSPHeight, iPartitionIdx, iNumSPInOneLine, uiSPAddr);
          rpcTempCU->setInterDirSP(m_phInterDirSP[uiSPListIndex][iPartitionIdx], uiSPAddr, iSPWidth, iSPHeight);
          rpcTempCU->getCUMvField( REF_PIC_LIST_0 )->setMvFieldSP(rpcTempCU, uiSPAddr, m_pMvFieldSP[uiSPListIndex][2*iPartitionIdx], iSPWidth, iSPHeight);
          rpcTempCU->getCUMvField( REF_PIC_LIST_1 )->setMvFieldSP(rpcTempCU, uiSPAddr, m_pMvFieldSP[uiSPListIndex][2*iPartitionIdx + 1], iSPWidth, iSPHeight);
        }
      }
      else//eMergeCandTypeNieghors[uiMergeCand]==0
      {
#endif
        rpcTempCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeCand], 0, 0, uhDepth ); // interprets depth relative to CTU level
        rpcTempCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMvFieldNeighbours[0 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level
        rpcTempCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMvFieldNeighbours[1 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level
#if COM16_C806_VCEG_AZ10_SUB_PU_TMVP
      }
#endif

      m_pcMrgPredTempYuv[uiMergeCand]->setWidth(rpcBestCU->getWidth(0));
      m_pcMrgPredTempYuv[uiMergeCand]->setHeight(rpcBestCU->getHeight(0));
	  //在merge模式中,MVP直接被当作MV(意味着没有MVD),因此没有运动估计这一步骤,直接进行运动补偿
      m_pcPredSearch->motionCompensation ( rpcTempCU, m_pcMrgPredTempYuv[uiMergeCand] );
#if COM16_C806_OBMC
      m_pcPredSearch->subBlockOBMC( rpcTempCU, 0, m_pcMrgPredTempYuv[uiMergeCand], m_pppcTmpYuv1[uiWIdx][uiHIdx], m_pppcTmpYuv2[uiWIdx][uiHIdx] );
#endif
#if JVET_E0052_DMVR
// the mv may be changed in the mv refinement during the MC,运动补偿期间在MV细化中MV可能会改变
  if (uhInterDirNeighbours[uiMergeCand]==3 && eMergeCandTypeNieghors[uiMergeCand]== MGR_TYPE_DEFAULT_N)
  {
      cMvFieldNeighbours[0 + 2*uiMergeCand].getMv() = rpcTempCU->getCUMvField(REF_PIC_LIST_0)->getMv(0);
      cMvFieldNeighbours[1 + 2*uiMergeCand].getMv() = rpcTempCU->getCUMvField(REF_PIC_LIST_1)->getMv(0);
  }
  else if (eMergeCandTypeNieghors[uiMergeCand] != MGR_TYPE_DEFAULT_N)
  {
      UInt uiSPAddr;
      Int iWidth = rpcTempCU->getWidth(0);
      Int iHeight = rpcTempCU->getHeight(0);

      Int iNumSPInOneLine, iNumSP, iSPWidth, iSPHeight;
#if JVET_C0035_ATMVP_SIMPLIFICATION
      UInt uiSPListIndex = eMergeCandTypeNieghors[uiMergeCand];
#else
      UInt uiSPListIndex = eMergeCandTypeNieghors[uiMergeCand] == MGR_TYPE_SUBPU_TMVP ? 0 : 1;
#endif
      rpcTempCU->getSPPara(iWidth, iHeight, iNumSP, iNumSPInOneLine, iSPWidth, iSPHeight);

    for (Int iPartitionIdx = 0; iPartitionIdx < iNumSP; iPartitionIdx++)
    {
      if (m_phInterDirSP[uiSPListIndex][iPartitionIdx] == 3)
      {
        rpcTempCU->getSPAbsPartIdx(0, iSPWidth, iSPHeight, iPartitionIdx, iNumSPInOneLine, uiSPAddr);
        m_pMvFieldSP[uiSPListIndex][2 * iPartitionIdx].getMv() = rpcTempCU->getCUMvField(REF_PIC_LIST_0)->getMv(uiSPAddr);
        m_pMvFieldSP[uiSPListIndex][2 * iPartitionIdx + 1].getMv() = rpcTempCU->getCUMvField(REF_PIC_LIST_1)->getMv(uiSPAddr);
      }
    }
  }   
#endif
      // use hadamard transform here,使用哈达玛变换;
      DistParam distParam;
      const Bool bUseHadamard=rpcTempCU->getCUTransquantBypass(0) == 0;
      m_pcRdCost->setDistParam(distParam, rpcTempCU->getSlice()->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA), m_pppcOrigYuv[uiWIdx][uiHIdx]->getAddr(COMPONENT_Y)
        , m_pppcOrigYuv[uiWIdx][uiHIdx]->getStride(COMPONENT_Y)
        , m_pcMrgPredTempYuv[uiMergeCand]->getAddr(COMPONENT_Y), m_pcMrgPredTempYuv[uiMergeCand]->getStride(COMPONENT_Y)
        , rpcTempCU->getWidth(0), rpcTempCU->getHeight(0), bUseHadamard);
      distParam.bApplyWeight = false;

      UInt uiSad = distParam.DistFunc(&distParam);
#if JVET_D0123_ME_CTX_LUT_BITS
      UInt uiBitsCand = uiMrgIdxBits[uiMergeCand];
      Double cost  = (Double)uiSad + (Double)uiBitsCand/((Double)EPBIT) * m_pcRdCost->getSqrtLambda();
#else
      UInt uiBitsCand = uiMergeCand + 1;                                         
      if (uiMergeCand == rpcTempCU->getSlice()->getMaxNumMergeCand() -1)
      {
        uiBitsCand--;
      }   
      Double cost      = (Double)uiSad + (Double)uiBitsCand * m_pcRdCost->getSqrtLambda();
#endif
      TEncSearch::updateCandList( uiMergeCand, cost, uiNumMrgSATDCand, uiRdModeList, CandCostList );
    }
	/7种merge候选模式遍历结束,4个SATD最小的候选模式被挑选出来,CandCostList前面4个的代价进行了更新///
    for (UInt i=1; i<uiNumMrgSATDCand; i++)
    {//如果4个候选模式中的后面3个中有模式的代价大于最小代价的1.25倍,则把它及其后面的候选模式取消候选资格,退出;
      if (CandCostList[i] > MRG_FAST_RATIO*CandCostList[0])//MRG_FAST_RATIO=1.25:
      {
        uiNumMrgSATDCand = i;
        break;
      }
    }
  }
#else
  Bool bestIsSkip = false;
#endif

  UInt iteration;
  if ( rpcTempCU->isLosslessCoded(0))//默认是false,所以iteration=2;
  {
    iteration = 1;
  }
  else
  {
    iteration = 2;
  }
  DEBUG_STRING_NEW(bestStr)
   //bestIsSkip==false则进行第一次迭代过程,残差系数不全为0才进行第二次迭代过程//
  for( UInt uiNoResidual = 0; uiNoResidual < iteration; ++uiNoResidual )
  {
#if JVET_C0024_FAST_MRG
      for( UInt uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; ++uiMrgHADIdx )//遍历剩余的有效的merge候选(最多是4),计算RD cost,选取最优的模式;
      {
        UInt uiMergeCand = uiRdModeList[uiMrgHADIdx];
#else
    for( UInt uiMergeCand = 0; uiMergeCand < numValidMergeCand; ++uiMergeCand )
    {
#endif
      if(!(uiNoResidual==1 && mergeCandBuffer[uiMergeCand]==1))//第一次迭代时这个if条件一定成立;
      {
        if( !(bestIsSkip && uiNoResidual == 0) )//如果bestIsSkip==false时则if条件成立;
        {
          DEBUG_STRING_NEW(tmpStr)
          // set MC parameters,设置运动补偿参数
          rpcTempCU->setPredModeSubParts( MODE_INTER, 0, uhDepth ); // interprets depth relative to CTU level
          rpcTempCU->setCUTransquantBypassSubParts( bTransquantBypassFlag, 0, uhDepth );
          rpcTempCU->setChromaQpAdjSubParts( bTransquantBypassFlag ? 0 : m_cuChromaQpOffsetIdxPlus1, 0, uhDepth );
#if !JVET_C0024_QTBT
          rpcTempCU->setPartSizeSubParts( SIZE_2Nx2N, 0, uhDepth ); // interprets depth relative to CTU level
#endif
          rpcTempCU->setMergeFlagSubParts( true, 0, 0, uhDepth ); // interprets depth relative to CTU level
          rpcTempCU->setMergeIndexSubParts( uiMergeCand, 0, 0, uhDepth ); // interprets depth relative to CTU level
#if COM16_C806_OBMC
          rpcTempCU->setOBMCFlagSubParts( true, 0, uhDepth );
#endif
#if VCEG_AZ06_IC
          rpcTempCU->setICFlagSubParts( rpcTempCU->getSlice()->getApplyIC() ? abICFlag[uiMergeCand] : 0, 0, uhDepth );
#endif
#if COM16_C806_VCEG_AZ10_SUB_PU_TMVP
          rpcTempCU->setMergeTypeSubParts(eMergeCandTypeNieghors[uiMergeCand] , 0, 0, uhDepth ); 
          if( eMergeCandTypeNieghors[uiMergeCand])
          {
            UInt uiSPAddr;
            Int iWidth = rpcTempCU->getWidth(0);
            Int iHeight = rpcTempCU->getHeight(0);

            Int iNumSPInOneLine, iNumSP, iSPWidth, iSPHeight;
#if JVET_C0035_ATMVP_SIMPLIFICATION
            UInt uiSPListIndex = eMergeCandTypeNieghors[uiMergeCand];
#else
            UInt uiSPListIndex = eMergeCandTypeNieghors[uiMergeCand] == MGR_TYPE_SUBPU_TMVP?0:1;
#endif
            rpcTempCU->getSPPara(iWidth, iHeight, iNumSP, iNumSPInOneLine, iSPWidth, iSPHeight);

            for (Int iPartitionIdx = 0; iPartitionIdx < iNumSP; iPartitionIdx++)
            {
              rpcTempCU->getSPAbsPartIdx(0, iSPWidth, iSPHeight, iPartitionIdx, iNumSPInOneLine, uiSPAddr);
              rpcTempCU->setInterDirSP(m_phInterDirSP[uiSPListIndex][iPartitionIdx], uiSPAddr, iSPWidth, iSPHeight);
              rpcTempCU->getCUMvField( REF_PIC_LIST_0 )->setMvFieldSP(rpcTempCU, uiSPAddr, m_pMvFieldSP[uiSPListIndex][2*iPartitionIdx], iSPWidth, iSPHeight);
              rpcTempCU->getCUMvField( REF_PIC_LIST_1 )->setMvFieldSP(rpcTempCU, uiSPAddr, m_pMvFieldSP[uiSPListIndex][2*iPartitionIdx + 1], iSPWidth, iSPHeight);
            }
          }
          else//eMergeCandTypeNieghors[uiMergeCand]==0
          {
#endif
          rpcTempCU->setInterDirSubParts( uhInterDirNeighbours[uiMergeCand], 0, 0, uhDepth ); // interprets depth relative to CTU level
          rpcTempCU->getCUMvField( REF_PIC_LIST_0 )->setAllMvField( cMvFieldNeighbours[0 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level
          rpcTempCU->getCUMvField( REF_PIC_LIST_1 )->setAllMvField( cMvFieldNeighbours[1 + 2*uiMergeCand], SIZE_2Nx2N, 0, 0 ); // interprets depth relative to rpcTempCU level
#if COM16_C806_VCEG_AZ10_SUB_PU_TMVP
          }
#endif
          // do MC,做运动补偿
#if JVET_C0024_QTBT
#if JVET_C0024_FAST_MRG
            if (bMrgTempBufSet)
            {
              m_pcMrgPredTempYuv[uiMergeCand]->copyToPartYuv(m_pppcPredYuvTemp[uiWIdx][uiHIdx], 0);
            }
            else
            {
              m_pcPredSearch->motionCompensation ( rpcTempCU, m_pppcPredYuvTemp[uiWIdx][uiHIdx] );
#if COM16_C806_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_pppcPredYuvTemp[uiWIdx][uiHIdx] );
#if COM16_C806_OBMC
            m_pcPredSearch->subBlockOBMC( rpcTempCU, 0, m_pppcPredYuvTemp[uiWIdx][uiHIdx], m_pppcTmpYuv1[uiWIdx][uiHIdx], m_pppcTmpYuv2[uiWIdx][uiHIdx] );
#endif
#endif
            // estimate residual and encode everything,估计残差并计算失真
            m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU,
              m_pppcOrigYuv    [uiWIdx][uiHIdx],
              m_pppcPredYuvTemp[uiWIdx][uiHIdx],
              m_pppcResiYuvTemp[uiWIdx][uiHIdx],
              m_pppcResiYuvBest[uiWIdx][uiHIdx],
              m_pppcRecoYuvTemp[uiWIdx][uiHIdx],
              (uiNoResidual != 0) 
#if COM16_C806_EMT
              , rpcBestCU->getTotalCost()
#endif
              DEBUG_STRING_PASS_INTO(tmpStr) );

#if DEBUG_STRING
            DebugInterPredResiReco(tmpStr, *(m_ppcPredYuvTemp[uhDepth]), *(m_ppcResiYuvBest[uhDepth]), *(m_ppcRecoYuvTemp[uhDepth]), DebugStringGetPredModeMask(rpcTempCU->getPredictionMode(0)));
#endif
#else
          m_pcPredSearch->motionCompensation ( rpcTempCU, m_ppcPredYuvTemp[uhDepth] );
#if COM16_C806_OBMC
          m_pcPredSearch->subBlockOBMC( rpcTempCU, 0, m_ppcPredYuvTemp[uhDepth], m_ppcTmpYuv1[uhDepth], m_ppcTmpYuv2[uhDepth] );
#endif
          // estimate residual and encode everything
          m_pcPredSearch->encodeResAndCalcRdInterCU( rpcTempCU,
                                                     m_ppcOrigYuv    [uhDepth],
                                                     m_ppcPredYuvTemp[uhDepth],
                                                     m_ppcResiYuvTemp[uhDepth],
                                                     m_ppcResiYuvBest[uhDepth],
                                                     m_ppcRecoYuvTemp[uhDepth],
                                                     (uiNoResidual != 0) 
#if COM16_C806_EMT
                                                     , rpcBestCU->getTotalCost()
#endif
                                                     DEBUG_STRING_PASS_INTO(tmpStr) );

#if DEBUG_STRING
          DebugInterPredResiReco(tmpStr, *(m_ppcPredYuvTemp[uhDepth]), *(m_ppcResiYuvBest[uhDepth]), *(m_ppcRecoYuvTemp[uhDepth]), DebugStringGetPredModeMask(rpcTempCU->getPredictionMode(0)));
#endif
#endif
          if ((uiNoResidual == 0) && (rpcTempCU->getQtRootCbf(0) == 0))
          {
            // If no residual when allowing for one, then set mark to not try case where residual is forced to 0
            mergeCandBuffer[uiMergeCand] = 1;
          }

          Int orgQP = rpcTempCU->getQP( 0 );
          xCheckDQP( rpcTempCU );
          xCheckBestMode(rpcBestCU, rpcTempCU, uhDepth DEBUG_STRING_PASS_INTO(bestStr) DEBUG_STRING_PASS_INTO(tmpStr));

          rpcTempCU->initEstData( uhDepth, orgQP, bTransquantBypassFlag );

          if( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip )
          {
            bestIsSkip = rpcBestCU->getQtRootCbf(0) == 0;//如果残差系数全为0,则bestIsSkip=true;
          }
        }
      }
    }
    ///遍历merge候选模式循环结束
    if(uiNoResidual == 0 && m_pcEncCfg->getUseEarlySkipDetection())
    {
      if(rpcBestCU->getQtRootCbf( 0 ) == 0)
      {
        if( rpcBestCU->getMergeFlag( 0 ))
        {
          *earlyDetectionSkipMode = true;
        }
        else if(m_pcEncCfg->getFastSearch() != SELECTIVE)
        {
          Int absoulte_MV=0;
          for ( UInt uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
          {
            if ( rpcBestCU->getSlice()->getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 )
            {
              TComCUMvField* pcCUMvField = rpcBestCU->getCUMvField(RefPicList( uiRefListIdx ));
              Int iHor = pcCUMvField->getMvd( 0 ).getAbsHor();
              Int iVer = pcCUMvField->getMvd( 0 ).getAbsVer();
              absoulte_MV+=iHor+iVer;
            }
          }

          if(absoulte_MV == 0)
          {
            *earlyDetectionSkipMode = true;
          }
        }
      }
    }
  }/迭代结束
  DEBUG_STRING_APPEND(sDebug, bestStr)
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值