VTM1.0代码阅读:xIntraCodingTUBlock函数

xIntraCodingTUBlock在xRecurIntraCodingLumaQT函数和xRecurIntraChromaCodingQT函数中均会被调用,该进行给定变换模式和帧内预测模式下的一系列操作。
调用xIntraCodingTUBlock函数的目的,就是对tu在给定变换模式和帧内模式的情况下,求得解码端reco像素和orig的失真。
函数流程:
对pu进行帧内预测得到pred像素,由pred像素和orig像素得到残差像素resi,将resi通过调用transformNxN和invTransformNxN函数,得到解码端得到的resi像素,其与pred求和即的reco像素。最后通过reco像素和orig像素,求得失真,返回。
具体的会有很多种情况,函数中都有注释

Void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &compID, const Bool &checkCrossCPrediction, Distortion& ruiDist, const Int &default0Save1Load2, UInt* numSig )
{
  if (!tu.blocks[compID].valid())
  {
    return;
  }

  CodingStructure &cs                       = *tu.cs;

  const CompArea      &area                 = tu.blocks[compID];	//tu的area
  const SPS           &sps                  = *cs.sps;
  const PPS           &pps                  = *cs.pps;

  const ChannelType    chType               = toChannelType(compID);
  const Int            bitDepth             = sps.getBitDepth(chType);

  PelBuf         piOrg                      = cs.getOrgBuf    (area);	//原始像素
  PelBuf         piPred                     = cs.getPredBuf   (area);	//预测像素
  PelBuf         piResi                     = cs.getResiBuf   (area);	//残差像素
  PelBuf         piOrgResi                  = cs.getOrgResiBuf(area);	//编码端pred和orig的残差像素
  PelBuf         piReco                     = cs.getRecoBuf   (area);	//重建像素

  const PredictionUnit &pu                  = *cs.getPU(area.pos(), chType);	//pu,方便帧内预测等操作
#if ENABLE_TRACING
  const UInt           uiChFinalMode        = PU::getFinalIntraMode(pu, chType);
#endif
									//chromaIntra预测时,是否可以进行跨组件预测
  const Bool           bUseCrossCPrediction = pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isChroma( compID ) && PU::isChromaIntraModeCrossCheckMode( pu ) && checkCrossCPrediction;
  const Bool           ccUseRecoResi        = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate();


  //===== init availability pattern =====
  PelBuf sharedPredTS( m_pSharedPredTransformSkip[compID], area );
  if( default0Save1Load2 != 2 )		//当前tu的变换模式是DCT2
  {
    const bool bUseFilteredPredictions = IntraPrediction::useFilteredIntraRefSamples( compID, pu, true, tu );	//参考像素是否滤波
    initIntraPatternChType( *tu.cu, area, bUseFilteredPredictions );		//帧内预测参考像素的初始化,准备好

    //===== get prediction signal =====
    {
      predIntraAng( compID, piPred, pu, bUseFilteredPredictions );	//帧内角度预测,得到pred像素
    }


    // save prediction
    if( default0Save1Load2 == 1 )		//当前变换模式为DCT2,并且之后还有变换模式
    {
      sharedPredTS.copyFrom( piPred );	//sharedPredTS拷贝此时角度预测的pred像素
    }
  }
  else			//当前tu的变换模式不是DCT2
  {
    // load prediction
    piPred.copyFrom( sharedPredTS );	//直接拷贝sharedPredTS得到pred像素,即DCT2时角度预测的pred
  }


  DTRACE( g_trace_ctx, D_PRED, "@(%4d,%4d) [%2dx%2d] IMode=%d\n", tu.lx(), tu.ly(), tu.lwidth(), tu.lheight(), uiChFinalMode );
  //DTRACE_PEL_BUF( D_PRED, piPred, tu, tu.cu->predMode, COMPONENT_Y );

  //===== get residual signal =====
  piResi.copyFrom( piOrg  );
  piResi.subtract( piPred );		//orig减去pred像素得到resi像素

  if (pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isLuma(compID))
  {
    piOrgResi.copyFrom (piResi);
  }

  if (bUseCrossCPrediction)			//色度预测时,跨组件预测
  {
    if (xCalcCrossComponentPredictionAlpha(tu, compID, ccUseRecoResi) == 0)
    {
      return;
    }
    CrossComponentPrediction::crossComponentPrediction(tu, compID, cs.getResiBuf(tu.Y()), piResi, piResi, false);
  }

  //===== transform and quantization =====
  //--- init rate estimation arrays for RDOQ ---
  //--- transform and quantization           ---
  TCoeff uiAbsSum = 0;

  const QpParam cQP(tu, compID);	//量化参数qp

#if RDOQ_CHROMA_LAMBDA
  m_pcTrQuant->selectLambda(compID);
#endif
									//对resi进行变换量化
  m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx());


  DTRACE( g_trace_ctx, D_TU_ABS_SUM, "%d: comp=%d, abssum=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_TU_ABS_SUM ), compID, uiAbsSum );


  //--- inverse transform ---
  if (uiAbsSum > 0)					//反变换反量化,得到解码端解码的resi
  {
    m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP);
  }
  else
  {
    piResi.fill(0);
  }

  //===== reconstruction =====
  if (bUseCrossCPrediction)		//色度预测时,跨组件预测
  {
    CrossComponentPrediction::crossComponentPrediction(tu, compID, cs.getResiBuf(tu.Y()), piResi, piResi, true);
  }
								//resi加pred得到reco像素
  piReco.reconstruct(piPred, piResi, cs.slice->clpRng( compID ));

  //===== update distortion =====
#if WCG_EXT
  if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
  {
    const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
    ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma );
  }
  else
#endif
  {								//由orig和reco像素求得失真
    ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
  }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值