HEVC:函数xEstimateInterResidualQT()注释

这个函数主要包括TU单元的变化量化,反变换反量化,熵编码
其中transformNxN函数为变化量化主函数
其中invtransformNxN函数为反变换反量化主函数
/*
** 估计残差的编码代价
** 主要是进行变换量化以及熵编码,然后选出最优的模式
*/
Void TEncSearch::xEstimateInterResidualQT(TComYuv    *pcResi,
       Double     &rdCost,
       UInt       &ruiBits,
       Distortion &ruiDist,
       Distortion *puiZeroDist,
       TComTU     &rTu
       DEBUG_STRING_FN_DECLARE(sDebug))
{
       TComDataCU *pcCU = rTu.getCU();
       const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU();
       const UInt uiDepth = rTu.GetTransformDepthTotal();//变换块的总深度,可直接得出块的尺寸
       const UInt uiTrMode = rTu.GetTransformDepthRel();//TU相对CU的深度(TrIdx)
       const UInt subTUDepth = uiTrMode + 1;
       const UInt numValidComp = pcCU->getPic()->getNumberValidComponents();//有效分量
       DEBUG_STRING_NEW(sSingleStringComp[MAX_NUM_COMPONENT])
              assert(pcCU->getDepth(0) == pcCU->getDepth(uiAbsPartIdx));
       const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize();//块尺寸
       UInt SplitFlag = ((pcCU->getSlice()->getSPS()->getQuadtreeTUMaxDepthInter() == 1) && pcCU->isInter(uiAbsPartIdx) && (pcCU->getPartitionSize(uiAbsPartIdx) != SIZE_2Nx2N));
#if DEBUG_STRING
       const Int debugPredModeMask = DebugStringGetPredModeMask(pcCU->getPredictionMode(uiAbsPartIdx));
#endif
       Bool bCheckFull;//TU大小从32x32开始
       if (SplitFlag && uiDepth == pcCU->getDepth(uiAbsPartIdx) && (uiLog2TrSize >  pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx)))
       {//若划分,且当前总深度与CU深度相等(即TU还未进行划分),且当前TU尺寸较大;认为当前TU需要划分,则无需check当前层的TU而直接划分
              bCheckFull = false;//无需check当前层TU
       }
       else
       {//否则,若当前TU尺寸小于最大TU尺寸,则可check当前层TU
              bCheckFull = (uiLog2TrSize <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize());
       }
       const Bool bCheckSplit = (uiLog2TrSize >  pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx));
//QuadtreeTULog2MinSizeInCU:不同尺寸的CU有不同的最小TU尺寸(64x64的CU最小TU为16x16;32x32的CU最小TU为8x8;16x16的CU最小TU为4x4)
//所以64x64的CU中TU深度(TrIdx)为1,2(也存在为0的情况,当ZeroCost<nonZeroCost时);32x32和16x16的CU中TU深度为0,1,2;
 assert(bCheckFull || bCheckSplit);//检查当前层或划分至少有一项
Double dSingleCost = MAX_DOUBLE;
  UInt       uiSingleBits                                                                                                        = 0;
  Distortion uiSingleDistComp            [MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {
  {0,0},{0,0},{0,0}};
  Distortion uiSingleDist                                                                                                        = 0;
  TCoeff     uiAbsSum                    [MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {
  {0,0},{0,0},{0,0}};
  UInt       uiBestTransformMode         [MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {
  {0,0},{0,0},{0,0}};
  //  Stores the best explicit RDPCM mode for a TU encoded without split
  UInt       bestExplicitRdpcmModeUnSplit[MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {
  {3,3}, {3,3}, {3,3}};
  SChar      bestCrossCPredictionAlpha   [MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/] = {
  {0,0},{0,0},{0,0}};
#if RQTET_ATTRIBUTE
  Int		 uinonZeroCoeff				 [MAX_NUM_COMPONENT][2];
#endif

  m_pcRDGoOnSbacCoder->store( m_pppcRDSbacCoder[ uiDepth ][ CI_QT_TRAFO_ROOT ] );

  if( bCheckFull )
  {
    Double minCost[MAX_NUM_COMPONENT][2/*0 = top (or whole TU for non-4:2:2) sub-TU, 1 = bottom sub-TU*/];
    Bool checkTransformSkip[MAX_NUM_COMPONENT];
    pcCU->setTrIdxSubParts( uiTrMode, uiAbsPartIdx, uiDepth );

    m_pcEntropyCoder->resetBits();//重置熵编码比特数

    memset( m_pTempPel, 0, sizeof( Pel ) * rTu.getRect(COMPONENT_Y).width * rTu.getRect(COMPONENT_Y).height ); // not necessary needed for inside of recursion (only at the beginning)

    const UInt uiQTTempAccessLayer = pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() - uiLog2TrSize;
    TCoeff *pcCoeffCurr[MAX_NUM_COMPONENT];//YUV分量的系数
#if ADAPTIVE_QP_SELECTION
    TCoeff *pcArlCoeffCurr[MAX_NUM_COMPONENT];
#endif

    for(UInt i=0; i<numValidComp; i++)
    {
      minCost[i][0] = MAX_DOUBLE;//初始化最小cost
      minCost[i][1] = MAX_DOUBLE;
    }

    Pel crossCPredictedResidualBuffer[ MAX_TU_SIZE * MAX_TU_SIZE ];

    for(UInt i=0; i<numValidComp; i++)//有效分量循环
    {
      checkTransformSkip[i]=false;//初始化transformSkip为false
      const ComponentID compID=ComponentID(i);
      const Int channelBitDepth=pcCU->getSlice()->getSPS()->getBitDepth(toChannelType(compID));
      pcCoeffCurr[compID]    = m_ppcQTTempCoeff[compID][uiQTTempAccessLayer] + rTu.getCoefficientOffset(compID);//当前分量系数存储数组
#if ADAPTIVE_QP_SELECTION
      pcArlCoeffCurr[compID] = m_ppcQTTempArlCoeff[compID ][uiQTTempAccessLayer] +  rTu.getCoefficientOffset(compID);
#endif

      if(rTu.ProcessComponentSection(compID))//当前分量是否存在(Width是否大于0)
      {
        const QpParam cQP(*pcCU, compID);

        checkTransformSkip[compID] = pcCU->getSlice()->getPPS()->getUseTransformSkip() &&
                                     TUCompRectHasAssociatedTransformSkipFlag(rTu.getRect(compID), pcCU->getSlice()->getPPS()->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize()) &&
                                     (!pcCU->isLosslessCoded(0));//获取TransformSkip标志位(使用TrSkip、且Rect可以TrSkip、且不使用无损编码的情况下,进行TrSkip模式)

        const Bool splitIntoSubTUs = rTu.getRect(compID).width != rTu.getRect(compID).height;//若当前TU为矩形,则分为两部分

        TComTURecurse TUIterator(rTu, false, (splitIntoSubTUs ? TComTU::VERTICAL_SPLIT : TComTU::DONT_SPLIT), true, compID);//创建矩形TU分割的子TU

        const UInt partIdxesPerSubTU = TUIterator.GetAbsPartIdxNumParts(compID);

        do//矩形TU分割得到的子TU循环编码
        {//初始化矩形分割得到的子TU的信息
          const UInt           subTUIndex             = TUIterator.GetSectionNumber();
          const UInt           subTUAbsPartIdx        = TUIterator.GetAbsPartIdxTU(compID);
          const TComRectangle &tuCompRect             = TUIterator.getRect(compID);
          const UInt           subTUBufferOffset      = tuCompRect.width * tuCompRect.height * subTUIndex;//子TU的offset

                TCoeff        *currentCoefficients    = pcCoeffCurr[compID] + subTUBufferOffset;//获取当前分量的子TU系数
#if ADAPTIVE_QP_SELECTION
                TCoeff        *currentARLCoefficients = pcArlCoeffCurr[compID] + subTUBufferOffset;
#endif
          const Bool isCrossCPredictionAvailable      =    isChroma(compID)
                                                         && pcCU->getSlice()->getPPS()->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag()
                                                         && (pcCU->getCbf(subTUAbsPartIdx, COMPONENT_Y, uiTrMode) != 0);//是否使用交叉预测编码?色度编码可利用亮度编码的信息
		  //若当前分量为色度,且使用CrossCPred,且Y亮度分量的残差系数绝对值和大于0(cbf不为0)

          SChar preCalcAlpha = 0;
          const Pel *pLumaResi = m_pcQTTempTComYuv[uiQTTempAccessLayer].getAddrPix( COMPONENT_Y, rTu.getRect( COMPONENT_Y ).x0, rTu.getRect( COMPONENT_Y ).y0 );//亮度残差

          if (isCrossCPredictionAvailable)
          {
            const Bool bUseReconstructedResidualForEstimate = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate();
            const Pel  *const lumaResidualForEstimate       = bUseReconstructedResidualForEstimate ? pLumaResi                                                     : pcResi->getAddrPix(COMPONENT_Y, tuCompRect.x0, tuCompRect.y0);
            const UInt        lumaResidualStrideForEstimate = bUseReconst
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值