在执行色度分量的预测时,对色度分量的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
}