VVC/JEM代码学习24:xRecurIntraChromaCodingQT()

26 篇文章 2 订阅

在执行色度分量的预测时,对色度分量的11种候选模式都调用一次xRecurIntraChromaCodingQT函数,在里面完成预测,求残差,变换量化和重建,并返回失真。

Void
TEncSearch::xRecurIntraChromaCodingQT(TComYuv*    pcOrgYuv,
                                      TComYuv*    pcPredYuv,
                                      TComYuv*    pcResiYuv,
#if COM16_C806_LARGE_CTU
                                      Pel*        resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES],
#else
                                      Pel         resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],
#endif
                                      Distortion& ruiDist,
                                      TComTU&     rTu
                                      DEBUG_STRING_FN_DECLARE(sDebug))
{
  TComDataCU         *pcCU                  = rTu.getCU();
  const UInt          uiTrDepth             = rTu.GetTransformDepthRel();//一定为0;
#if JVET_C0024_QTBT
  assert(rTu.GetAbsPartIdxTU()==0 && uiTrDepth==0);
  UInt uiWIdx = g_aucConvertToBit[pcCU->getWidth(0)];
  UInt uiHIdx = g_aucConvertToBit[pcCU->getHeight(0)];
#else
  const UInt          uiAbsPartIdx          = rTu.GetAbsPartIdxTU();
#endif
  const ChromaFormat  format                = rTu.GetChromaFormat();
#if !JVET_C0024_QTBT
  UInt                uiTrMode              = pcCU->getTransformIdx( uiAbsPartIdx );
#endif
  const UInt          numberValidComponents = getNumberValidComponents(format);

#if JVET_C0024_QTBT
  assert(uiTrDepth==0);
#else
  if(  uiTrMode == uiTrDepth )
  {
#endif
    if (!rTu.ProcessChannelSection(CHANNEL_TYPE_CHROMA))
    {
      return;
    }

#if !JVET_C0024_QTBT
    const UInt uiFullDepth = rTu.GetTransformDepthTotal();
#endif

    Bool checkTransformSkip = pcCU->getSlice()->getPPS()->getUseTransformSkip();
#if JVET_C0024_QTBT
    checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(pcCU->getSlice()->isIntra(), rTu.getRect(COMPONENT_Cb), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize());
#else
    checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Cb), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize());
#endif

    if ( m_pcEncCfg->getUseTransformSkipFast() )
    {
#if JVET_C0024_QTBT//只有亮度分量使用跳过变换时才允许色度分量使用
      checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(pcCU->getSlice()->isIntra(), rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize());
#else
      checkTransformSkip &= TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(COMPONENT_Y), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize());

      if (checkTransformSkip)
      {
        Int nbLumaSkip = 0;
        const UInt maxAbsPartIdxSub=uiAbsPartIdx + (rTu.ProcessingAllQuadrants(COMPONENT_Cb)?1:4);
        for(UInt absPartIdxSub = uiAbsPartIdx; absPartIdxSub < maxAbsPartIdxSub; absPartIdxSub ++)
        {
          nbLumaSkip += pcCU->getTransformSkip(absPartIdxSub, COMPONENT_Y);
        }
        checkTransformSkip &= (nbLumaSkip > 0);
      }
#endif
    }

//循环两次,第一次是Cb分量,第二次是Cr分量
    for (UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++)
    {
      const ComponentID compID = ComponentID(ch);
      DEBUG_STRING_NEW(sDebugBestMode)

      //use RDO to decide whether Cr/Cb takes TS
#if JVET_C0024_QTBT
      m_pcRDGoOnSbacCoder->store( m_ppppcRDSbacCoder[uiWIdx][uiHIdx][CI_QT_TRAFO_ROOT] );
      const Bool splitIntoSubTUs = false;//是否分割成子TU,默认false
#else
      m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[uiFullDepth][CI_QT_TRAFO_ROOT] );

      const Bool splitIntoSubTUs = rTu.getRect(compID).width != rTu.getRect(compID).height;
#endif
	  //初始化TUIterator;
      TComTURecurse TUIterator(rTu, false, (splitIntoSubTUs ? TComTU::VERTICAL_SPLIT : TComTU::DONT_SPLIT), true, compID);

#if !JVET_C0024_QTBT
      const UInt partIdxesPerSubTU = TUIterator.GetAbsPartIdxNumParts(compID);
#endif

      do
      {
        const UInt subTUAbsPartIdx   = TUIterator.GetAbsPartIdxTU(compID);
		//初始化失真,代价,等等参数
        Double     dSingleCost               = MAX_DOUBLE;
        Int        bestModeId                = 0;
        Distortion singleDistC               = 0;
        UInt       singleCbfC                = 0;
        Distortion singleDistCTmp            = 0;
        Double     singleCostTmp             = 0;
        UInt       singleCbfCTmp             = 0;
        Char       bestCrossCPredictionAlpha = 0;
        Int        bestTransformSkipMode     = 0;
#if JVET_E0062_MULTI_DMS
#if JVET_E0077_ENHANCED_LM
        const Bool checkCrossComponentPrediction = (!IsLMMode(pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, subTUAbsPartIdx)))
            &&  pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()
            && (pcCU->getCbf(subTUAbsPartIdx,  COMPONENT_Y, uiTrDepth) != 0);//如果色度模式不是LM模式且允许使用CCP且Y分量的cbf不为0,则checkCrossComponentPrediction为true;
#else
        const Bool checkCrossComponentPrediction = (pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, subTUAbsPartIdx) != LM_CHROMA_IDX)
                                                   &&  pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()
                                                   && (pcCU->getCbf(subTUAbsPartIdx,  COMPONENT_Y, uiTrDepth) != 0);
#endif
#else
        const Bool checkCrossComponentPrediction =    (pcCU->getIntraDir(CHANNEL_TYPE_CHROMA, subTUAbsPartIdx) == DM_CHROMA_IDX)
                                                   &&  pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()
                                                   && (pcCU->getCbf(subTUAbsPartIdx,  COMPONENT_Y, uiTrDepth) != 0);
#endif
        const Int  crossCPredictionModesToTest = checkCrossComponentPrediction ? 2 : 1;//checkCrossComponentPrediction为true,则为2,否则为1
        const Int  transformSkipModesToTest    = checkTransformSkip            ? 2 : 1;//checkTransformSkip为true,则为2,否则为1
        const Int  totalModesToTest            = crossCPredictionModesToTest * transformSkipModesToTest;//总的测试次数
              Int  currModeId                  = 0;
              Int  default0Save1Load2          = 0;

        for(Int transformSkipModeId = 0; transformSkipModeId < transformSkipModesToTest; transformSkipModeId++)//选取最优的transformSkip模式
        {
          for(Int crossCPredictionModeId = 0; crossCPredictionModeId < crossCPredictionModesToTest; crossCPredictionModeId++)//选取最优的CCP模式
          {
#if JVET_C0024_QTBT
            pcCU->setCrossComponentPredictionAlphaPartRange(0, compID, subTUAbsPartIdx, 0);//将CrossComponentPredictionAlpha设置为0;
            pcCU->setTransformSkipPartRange( transformSkipModeId, compID, subTUAbsPartIdx, 0 );//将TransformSkip设置为transformSkipModeId
#else
            pcCU->setCrossComponentPredictionAlphaPartRange(0, compID, subTUAbsPartIdx, partIdxesPerSubTU);
            DEBUG_STRING_NEW(sDebugMode)
            pcCU->setTransformSkipPartRange( transformSkipModeId, compID, subTUAbsPartIdx, partIdxesPerSubTU );
#endif
            currModeId++;

            const Bool isOneMode  = (totalModesToTest == 1);//判断总的测试模式是否为1;
            const Bool isLastMode = (currModeId == totalModesToTest); // currModeId is indexed from 1,判断当前模式是否为最后一个模式;

            if (isOneMode)//如果只有一个模式,则执行正常的预测步骤;
            {
              default0Save1Load2 = 0;
            }
            else if (!isOneMode && (transformSkipModeId == 0) && (crossCPredictionModeId == 0))
            {//如果不只有1个模式且是第一遍循环,则保存此第一个模式的预测
              default0Save1Load2 = 1; //save prediction on first mode
            }
            else//不只有1个模式且不是第一遍循环,在后面的模式上加载预测;
            {
              default0Save1Load2 = 2; //load it on subsequent modes
            }

            singleDistCTmp = 0;

#if COM16_C983_RSAF
#if JVET_C0024_QTBT
            pcCU->setLumaIntraFilter(0, false);
            pcCU->setLumaIntraFilterHidden(0, true);
#else
            pcCU->setLumaIntraFilter(uiAbsPartIdx, false);
            pcCU->setLumaIntraFilterHidden(uiAbsPartIdx, true);
#endif
#endif      //对当前CU的色度信息进行一系列的编码工作,如求残差,变换,量化,反量化,反变换,重建等工作;
            xIntraCodingTUBlock( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, (crossCPredictionModeId != 0), singleDistCTmp, compID, TUIterator DEBUG_STRING_PASS_INTO(sDebugMode), default0Save1Load2);//倒数第5个参数指示是否使用CCP,0时为false,1时为true;

            singleCbfCTmp = pcCU->getCbf( subTUAbsPartIdx, compID, uiTrDepth);

            if (  ((crossCPredictionModeId == 1) && (pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) == 0))
               || ((transformSkipModeId    == 1) && (singleCbfCTmp == 0))) //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
            {
              singleCostTmp = MAX_DOUBLE;
            }
            else if (!isOneMode)
            {
              UInt bitsTmp = xGetIntraBitsQTChroma( TUIterator, compID, false );//计算所需的比特数;
              singleCostTmp  = m_pcRdCost->calcRdCost( bitsTmp, singleDistCTmp);//计算率失真代价;
            }

            if(singleCostTmp < dSingleCost)
            {
              DEBUG_STRING_SWAP(sDebugBestMode, sDebugMode)
              dSingleCost               = singleCostTmp;
              singleDistC               = singleDistCTmp;
              bestCrossCPredictionAlpha = (crossCPredictionModeId != 0) ? pcCU->getCrossComponentPredictionAlpha(subTUAbsPartIdx, compID) : 0;
              bestTransformSkipMode     = transformSkipModeId;
              bestModeId                = currModeId;
              singleCbfC                = singleCbfCTmp;

              if (!isOneMode && !isLastMode)//不只有一种模式且不是最后一个模式
              {
#if COM16_C806_LMCHROMA
                xStoreIntraResultQT(compID, TUIterator, pcResiYuv);//保存最优的结果
#else
                xStoreIntraResultQT(compID, TUIterator);
#endif
#if JVET_C0024_QTBT
                m_pcRDGoOnSbacCoder->store( m_ppppcRDSbacCoder[ uiWIdx][uiHIdx ][ CI_TEMP_BEST ] );
#else
                m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] );
#endif
              }
            }

            if (!isOneMode && !isLastMode)//不只有一种模式且不是最后一个模式
            {
#if JVET_C0024_QTBT
              m_pcRDGoOnSbacCoder->load ( m_ppppcRDSbacCoder[ uiWIdx][uiHIdx ][ CI_QT_TRAFO_ROOT ] );
#else
              m_pcRDGoOnSbacCoder->load ( m_pppcRDSbacCoder[ uiFullDepth ][ CI_QT_TRAFO_ROOT ] );
#endif
            }
          }//crossCPreditionModelToTest遍历结束,最多两次,最少一次;
        }//transformSkipModesToTest遍历结束,最多两次,最少一次;

        if(bestModeId < totalModesToTest)//最优的模式索引小于测试模式的总数
        {
#if COM16_C806_LMCHROMA
          xLoadIntraResultQT(compID, TUIterator, pcResiYuv);
#else
          xLoadIntraResultQT(compID, TUIterator);
#endif
#if JVET_C0024_QTBT
          pcCU->setCbfPartRange( singleCbfC, compID, subTUAbsPartIdx, 0 );
          m_pcRDGoOnSbacCoder->load( m_ppppcRDSbacCoder[ uiWIdx][uiHIdx ][ CI_TEMP_BEST ] );
#else
          pcCU->setCbfPartRange( singleCbfC << uiTrDepth, compID, subTUAbsPartIdx, partIdxesPerSubTU );

          m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[ uiFullDepth ][ CI_TEMP_BEST ] );
#endif
        }

        DEBUG_STRING_APPEND(sDebug, sDebugBestMode)
#if JVET_C0024_QTBT
        pcCU ->setTransformSkipPartRange                ( bestTransformSkipMode,     compID, subTUAbsPartIdx, 0 );//将TransformSkip设置为bestTransformSkipMode
        pcCU ->setCrossComponentPredictionAlphaPartRange( bestCrossCPredictionAlpha, compID, subTUAbsPartIdx, 0 );//将CrossComponentPrediction设置为bestCrossCPredictionAlpha
#else
        pcCU ->setTransformSkipPartRange                ( bestTransformSkipMode,     compID, subTUAbsPartIdx, partIdxesPerSubTU );
        pcCU ->setCrossComponentPredictionAlphaPartRange( bestCrossCPredictionAlpha, compID, subTUAbsPartIdx, partIdxesPerSubTU );
#endif
        ruiDist += singleDistC;//累加Cb和Cr的失真
      } while (TUIterator.nextSection(rTu));//nextSection,如果不继续划分则返回false,否则返回true;

#if !JVET_C0024_QTBT
      if (splitIntoSubTUs)
      {
        offsetSubTUCBFs(rTu, compID);
      }
#endif
    }
	两个色度分量循环结束
#if !JVET_C0024_QTBT
  }
  else
  {
    UInt    uiSplitCbf[MAX_NUM_COMPONENT] = {0,0,0};

    TComTURecurse tuRecurseChild(rTu, false);
    const UInt uiTrDepthChild   = tuRecurseChild.GetTransformDepthRel();
    do
    {
      DEBUG_STRING_NEW(sChild)

      xRecurIntraChromaCodingQT( pcOrgYuv, pcPredYuv, pcResiYuv, resiLuma, ruiDist, tuRecurseChild DEBUG_STRING_PASS_INTO(sChild) );

      DEBUG_STRING_APPEND(sDebug, sChild)
      const UInt uiAbsPartIdxSub=tuRecurseChild.GetAbsPartIdxTU();

      for(UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++)
      {
        uiSplitCbf[ch] |= pcCU->getCbf( uiAbsPartIdxSub, ComponentID(ch), uiTrDepthChild );
      }
    } while ( tuRecurseChild.nextSection(rTu) );


    UInt uiPartsDiv = rTu.GetAbsPartIdxNumParts();
    for(UInt ch=COMPONENT_Cb; ch<numberValidComponents; ch++)
    {
      if (uiSplitCbf[ch])
      {
        const UInt flag=1<<uiTrDepth;
        ComponentID compID=ComponentID(ch);
        UChar *pBase=pcCU->getCbf( compID );
        for( UInt uiOffs = 0; uiOffs < uiPartsDiv; uiOffs++ )
        {
          pBase[ uiAbsPartIdx + uiOffs ] |= flag;
        }
      }
    }
  }
#endif  //#if !JVET_C0024_QTBT
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值