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 );
}
}