VTM3.0代码阅读:xIntraCodingTUBlock函数

xIntraCodingTUBlock函数在xRecurIntraCodingLumaQT和xRecurIntraChromaCodingQT中扮演关键角色,负责基于给定的变换模式和帧内预测模式计算像素失真。函数首先进行帧内预测得到pred像素,然后计算残差,通过变换和逆变换得到解码端的reco像素,最终确定失真。相较于VTM1,主要增加了局部运动(LM)预测。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &compID, const bool &checkCrossCPrediction, Distortion& ruiDist, const int &default0Save1Load2, uint32_t* 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,方便帧内预测等操作
  const uint32_t       uiChFinalMode        = PU::getFinalIntraMode(pu, chType);
														//chromaIntra预测时,是否可以进行跨组件预测
  const bool           bUseCrossCPrediction = pps.getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && isChroma( compID ) && PU::isChromaIntraModeCrossCheckMode( pu ) && checkCrossCPrediction;
  const bool           ccUseRecoResi        = m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate();

#if !JVET_L0059_MTS_SIMP
  const uint8_t          transformIndex       = tu.cu->emtFlag && compID == COMPONENT_Y ? tu.emtIdx : DCT2_EMT ;
#endif

  //===== 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 =====
    if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) )
    {
      {
        xGetLumaRecPixels( pu, area );		//获取色度块对应的亮度块的重建像素
      }
      predIntraChromaLM( compID, piPred, pu, area, uiChFinalMode );		//色度帧内LM模式预测
    }
    else
    {
      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;
    }												//跨组件预测,CCLM
    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)
  {
    m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP);	//反变换反量化,得到解码端解码的resi
  }
  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 ));	//reconstruct

  //===== update distortion =====
  {									//由orig和reco像素求得失真
    ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
  }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值