今天来继续学习帧内编码的重要函数xIntraCodingTUBlock
,上次 H.266代码学习:xRecurIntraCodingLumaQT函数 学习中提到,xIntraCodingTUBlock
中完成了亮度信号的帧内预测、计算残差并进行变换、量化,生成重构信号。实际色度信号帧内预测xRecurIntraChromaCodingQT
也会调用xIntraCodingTUBlock
来完成这些操作。
也就是说,xRecurIntraCodingLumaQT
亮度预测和xRecurIntraChromaCodingQT
色度预测最终都会调用xIntraCodingTUBlock
来完成帧内预测、计算残差并进行变换量化,并最终生成重构信号。
JEM与HM主要区别有:
1.JEM中色度帧内预测增加了CCLM模式,因此xIntraCodingTUBlock
多了CCLM的帧内预测部分。
2.JEM中增加了smoothResidual
对残差进行平滑。
3.JEM中增加了对重构信号进行双边滤波。
流程如下:
一、初始化各种参数和可获取的临近像素,不详细说了。
二、生成预测信号。
1.如果是CCLM模式,调用predLMIntraChroma
完成色度信号的CCLM模式预测,生成预测信号。
2.其他情况调用predIntraAng
完成亮度或色度的帧内预测,生成预测信号。
三、计算残差。
四、变换量化。
1.设置lambda。
2.调用smoothResidual
进行残差平滑滤波。
3.调用transformNxN
进行变换量化。
五、调用invTransformNxN
反变换量化。
六、用预测信号+残差生成重构信号,然后进行双边滤波。
七、更新失真信息。
代码分析:
Void TEncSearch::xIntraCodingTUBlock( 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
const Bool checkCrossCPrediction,
Distortion& ruiDist,
const ComponentID compID,
TComTU& rTu
DEBUG_STRING_FN_DECLARE(sDebug)
, Int default0Save1Load2
#if COM16_C806_EMT
, UInt* puiSigNum
#endif
)
{
/******************* 一、初始化,删除了此部分代码,不详细说了*******************/
/******************* 二、生成预测信号 *******************/
#if !DEBUG_STRING
if( default0Save1Load2 != 2 )
#endif
{
#if COM16_C983_RSAF
//删除默认不开启的代码
#else
const Bool bUseFilteredPredictions=TComPrediction::filteringIntraReferenceSamples(compID, uiChFinalMode, uiWidth, uiHeight, chFmt, sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag());
//判断相邻像素是否可用并根据一定规则获取像素值,进行参考像素滤波
initIntraPatternChType( rTu, compID, bUseFilteredPredictions DEBUG_STRING_PASS_INTO(sDebug) );
#endif
#if COM16_C983_RSAF
#if JVET_E0077_ENHANCED_LM && JVET_C0024_QTBT
}
#endif
#endif
//===== get prediction signal =====
#if COM16_C806_LMCHROMA
if( uiChFinalMode == LM_CHROMA_IDX
#if JVET_E0077_ENHANCED_LM
|| IsLMMode(uiChFinalMode)
#end