Void
TDecCu::xIntraRecBlk( TComYuv* pcRecoYuv,
TComYuv* pcPredYuv,
TComYuv* pcResiYuv,
const ComponentID compID,
TComTU &rTu)
{
if (!rTu.ProcessComponentSection(compID))
{
return;
}
const Bool bIsLuma = isLuma(compID);
TComDataCU *pcCU = rTu.getCU();
#if COM16_C983_RSAF || !JVET_D0033_ADAPTIVE_CLIPPING
const TComSPS &sps=*(pcCU->getSlice()->getSPS());
#endif
const UInt uiAbsPartIdx=rTu.GetAbsPartIdxTU();
const TComRectangle &tuRect =rTu.getRect(compID);
const UInt uiWidth = tuRect.width;
const UInt uiHeight = tuRect.height;
const UInt uiStride = pcRecoYuv->getStride (compID);
Pel* piPred = pcPredYuv->getAddr( compID, uiAbsPartIdx );
const ChromaFormat chFmt = rTu.GetChromaFormat();
#if !JVET_C0024_QTBT
if (uiWidth != uiHeight)
{
//------------------------------------------------
//split at current level if dividing into square sub-TUs
TComTURecurse subTURecurse(rTu, false, TComTU::VERTICAL_SPLIT, true, compID);
//recurse further
do
{
xIntraRecBlk(pcRecoYuv, pcPredYuv, pcResiYuv, compID, subTURecurse);
} while (subTURecurse.nextSection(rTu));
//------------------------------------------------
return;
}
#endif
const UInt uiChPredMode = pcCU->getIntraDir( toChannelType(compID), uiAbsPartIdx );//得到预测模式;
#if JVET_C0024_QTBT
#if JVET_E0062_MULTI_DMS
const UInt uiChCodedMode = uiChPredMode;
#else
const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, uiAbsPartIdx) : uiChPredMode;
#endif
#else
const UInt partsPerMinCU = 1<<(2*(sps.getMaxTotalCUDepth() - sps.getLog2DiffMaxMinCodingBlockSize()));
const UInt uiChCodedMode = (uiChPredMode==DM_CHROMA_IDX && !bIsLuma) ? pcCU->getIntraDir(CHANNEL_TYPE_LUMA, getChromasCorrespondingPULumaIdx(uiAbsPartIdx, chFmt, partsPerMinCU)) : uiChPredMode;
#endif
const UInt uiChFinalMode = ((chFmt == CHROMA_422) && !bIsLuma) ? g_chroma422IntraAngleMappingTable[uiChCodedMode] : uiChCodedMode;
//===== init availability pattern ,初始化可获得pattern=====
#if !COM16_C983_RSAF
const
#endif //是否使用滤波的参考像素,与编码端一致
Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID,
uiChFinalMode,
uiWidth,
uiHeight,
chFmt,
pcCU->getSlice()->getSPS()->getSpsRangeExtension().getIntraSmoothingDisabledFlag()
#if COM16_C983_RSAF_PREVENT_OVERSMOOTHING
, sps.getUseRSAF()
#endif
);
#if DEBUG_STRING
std::ostream &ss(std::cout);
#endif
#if COM16_C983_RSAF
Bool bFilter = false;
#if COM16_C1046_PDPC_RSAF_HARMONIZATION
if (compID == COMPONENT_Y && sps.getUseRSAF() && pcCU->getPDPCIdx(uiAbsPartIdx) == 0)
#else
if (compID==COMPONENT_Y && sps.getUseRSAF())
#endif
{
bFilter = (pcCU->getLumaIntraFilter( uiAbsPartIdx )) != 0;
#if JVET_C0024_QTBT
bFilter &= !(pcCU->getWidth(0)*pcCU->getHeight(0)>1024);
#else
bFilter &= !(pcCU->getWidth(0)>32);
#endif
}
#endif
DEBUG_STRING_NEW(sTemp)
m_pcPrediction->initIntraPatternChType( rTu, compID, bUseFilteredPredictions
#if COM16_C983_RSAF
, (compID==COMPONENT_Y) ? bFilter : false
#endif
DEBUG_STRING_PASS_INTO(sTemp) );//初始化参考像素
//===== get prediction signal,得到预测信号,过程跟编码端也一致=====
#if COM16_C806_LMCHROMA
if( uiChFinalMode == LM_CHROMA_IDX
#if JVET_E0077_ENHANCED_LM
|| IsLMMode(uiChFinalMode)
#endif
)//是CCLM模式
{
m_pcPrediction->getLumaRecPixels( rTu, uiWidth, uiHeight );//对相邻亮度色度和当前亮度进行下采样;
#if JVET_E0077_ENHANCED_LM
Int iLMType = uiChFinalMode;
m_pcPrediction->predLMIntraChroma(rTu, compID, piPred, uiStride, uiWidth, uiHeight, iLMType);//用亮度预测色度
#else
m_pcPrediction->predLMIntraChroma( rTu, compID, piPred, uiStride, uiWidth, uiHeight );
#endif
}
else//普通角度模式
{
#endif
#if COM16_C983_RSAF
if (compID==COMPONENT_Y && sps.getUseRSAF())
{
bUseFilteredPredictions = (bFilter != false);
}
#endif//这个也是和编码时一样的函数
m_pcPrediction->predIntraAng( compID, uiChFinalMode, 0 /* Decoder does not have an original image */, 0, piPred, uiStride, rTu, bUseFilteredPredictions );
#if COM16_C806_LMCHROMA
if( compID == COMPONENT_Cr && pcCU->getSlice()->getSPS()->getUseLMChroma() )
{
//std::cout << "传统预测模式是 " << uiChFinalMode << std::endl;
m_pcPrediction->addCrossColorResi( rTu, compID, piPred, uiStride, uiWidth, uiHeight, pcResiYuv->getAddr( COMPONENT_Cb, uiAbsPartIdx ), pcResiYuv->getStride(COMPONENT_Cb) );
}
}
#endif
#if DEBUG_STRING
ss << sTemp;
#endif
//===== inverse transform ,反变换和反量化=====
Pel* piResi = pcResiYuv->getAddr( compID, uiAbsPartIdx );//残差YUV
TCoeff* pcCoeff = pcCU->getCoeff(compID) + rTu.getCoefficientOffset(compID);//( uiNumCoeffInc * uiAbsPartIdx );
const QpParam cQP(*pcCU, compID);
DEBUG_STRING_NEW(sDebug);
#if DEBUG_STRING
const Int debugPredModeMask=DebugStringGetPredModeMask(MODE_INTRA);
std::string *psDebug=(DebugOptionList::DebugString_InvTran.getInt()&debugPredModeMask) ? &sDebug : 0;
#endif
if (pcCU->getCbf(uiAbsPartIdx, compID, rTu.GetTransformDepthRel()) != 0)//如果cbf!=0,则对残差进行反量化和反变换
{
m_pcTrQuant->invTransformNxN( rTu, compID, piResi, uiStride, pcCoeff, cQP DEBUG_STRING_PASS_INTO(psDebug) );
}
else//如果cbf=0,则直接令残差数据为0
{
for (UInt y = 0; y < uiHeight; y++)
{
for (UInt x = 0; x < uiWidth; x++)
{
piResi[(y * uiStride) + x] = 0;
}
}
}
#if DEBUG_STRING
if (psDebug)
{
ss << (*psDebug);
}
#endif
//===== reconstruction ,重建=预测加残差=====
const UInt uiRecIPredStride = pcCU->getPic()->getPicYuvRec()->getStride(compID);
const Bool useCrossComponentPrediction = isChroma(compID) && (pcCU->getCrossComponentPredictionAlpha(uiAbsPartIdx, compID) != 0);
const Pel* pResiLuma = pcResiYuv->getAddr( COMPONENT_Y, uiAbsPartIdx );
const Int strideLuma = pcResiYuv->getStride( COMPONENT_Y );
Pel* pPred = piPred;
Pel* pResi = piResi;
Pel* pReco = pcRecoYuv->getAddr( compID, uiAbsPartIdx );
Pel* pRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx );
#if DEBUG_STRING
const Bool bDebugPred=((DebugOptionList::DebugString_Pred.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
const Bool bDebugResi=((DebugOptionList::DebugString_Resi.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
const Bool bDebugReco=((DebugOptionList::DebugString_Reco.getInt()&debugPredModeMask) && DEBUG_STRING_CHANNEL_CONDITION(compID));
if (bDebugPred || bDebugResi || bDebugReco)
{
ss << "###: " << "CompID: " << compID << " pred mode (ch/fin): " << uiChPredMode << "/" << uiChFinalMode << " absPartIdx: " << rTu.GetAbsPartIdxTU() << std::endl;
}
#endif
#if !JVET_D0033_ADAPTIVE_CLIPPING
const Int clipbd = sps.getBitDepth(toChannelType(compID));
#endif
#if O0043_BEST_EFFORT_DECODING
const Int bitDepthDelta = sps.getStreamBitDepth(toChannelType(compID)) - clipbd;
#endif
if( useCrossComponentPrediction )
{
TComTrQuant::crossComponentPrediction( rTu, compID, pResiLuma, piResi, piResi, uiWidth, uiHeight, strideLuma, uiStride, uiStride, true );
}
//if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67)
//{
// std::cout << "cr分量的重建残差: " << std::endl;
//}
for( UInt uiY = 0; uiY < uiHeight; uiY++ )
{
#if DEBUG_STRING
if (bDebugPred || bDebugResi || bDebugReco)
{
ss << "###: ";
}
if (bDebugPred)
{
ss << " - pred: ";
for( UInt uiX = 0; uiX < uiWidth; uiX++ )
{
ss << pPred[ uiX ] << ", ";
}
}
if (bDebugResi)
{
ss << " - resi: ";
}
#endif
for( UInt uiX = 0; uiX < uiWidth; uiX++ )
{
#if DEBUG_STRING
if (bDebugResi)
{
ss << pResi[ uiX ] << ", ";
}
#endif
#if O0043_BEST_EFFORT_DECODING
#if JVET_D0033_ADAPTIVE_CLIPPING
pReco [ uiX ] = ClipA( rightShiftEvenRounding<Pel>(pPred[ uiX ] + pResi[ uiX ], bitDepthDelta), compID);
#else
pReco [ uiX ] = ClipBD( rightShiftEvenRounding<Pel>(pPred[ uiX ] + pResi[ uiX ], bitDepthDelta), clipbd );
#endif
#else
#if JVET_D0033_ADAPTIVE_CLIPPING // decoder intra rec
pReco [ uiX ] = ClipA(pPred[ uiX ] + pResi[ uiX ], compID);//重建值等于预测值加残差;
#else
pReco [ uiX ] = ClipBD( pPred[ uiX ] + pResi[ uiX ], clipbd );
#endif
#endif
pRecIPred[ uiX ] = pReco[ uiX ];//保存重建值,用于下一帧的预测;
//if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67)
// printf("M", pResi[uiX]);
}
//if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67)
//std::cout << std::endl;
#if DEBUG_STRING
if (bDebugReco)
{
ss << " - reco: ";
for( UInt uiX = 0; uiX < uiWidth; uiX++ )
{
ss << pReco[ uiX ] << ", ";
}
}
if (bDebugPred || bDebugResi || bDebugReco)
{
ss << "\n";
}
#endif
pPred += uiStride;
pResi += uiStride;
pReco += uiStride;
pRecIPred += uiRecIPredStride;
}
//if (compID == 2 && uiChFinalMode >= 0 && uiChFinalMode < 67)
//{
// std::cout << std::endl;
// std::cout << std::endl;
//}
#if JVET_F0096_BILATERAL_FILTER
if(pcCU->getSlice()->getSPS()->getUseBilateralFilter()) //重建完使用双边滤波,和编码端一致,只对亮度分量使用
{
Pel* piReco = pcRecoYuv->getAddr( compID, uiAbsPartIdx );
Pel* piRecIPred = pcCU->getPic()->getPicYuvRec()->getAddr( compID, pcCU->getCtuRsAddr(), pcCU->getZorderIdxInCtu() + uiAbsPartIdx );
if (isLuma(compID))
{
if ((pcCU->getCbf(uiAbsPartIdx, compID, rTu.GetTransformDepthRel()) != 0) && (pcCU->getQP(COMPONENT_Y) > 17))
{//双边滤波器即重建CU中的每一个亮度采样都用其自身及其邻近采样的加权平均替代
TComBilateralFilter::instance()->bilateralFilterIntra(pcCU, uiWidth, uiHeight, piReco, uiStride, pcCU->getQP(COMPONENT_Y));
for( UInt uiY = 0; uiY < uiHeight; uiY++ )
{
memcpy(piRecIPred + uiY * uiRecIPredStride, piReco + uiY * uiStride , uiWidth * sizeof(Short));
uiY++;
memcpy(piRecIPred + uiY * uiRecIPredStride, piReco + uiY * uiStride , uiWidth * sizeof(Short));
}
}
}
}
#endif
}