前面我们讲的都是预测,下面开始变换的实现。
本文参考http://blog.csdn.net/shaqoneal/article/details/44856469
1、HM中Intra模式的主要实现逻辑
以Intra的亮度模式为例。主要实现代码实现于TEncSearch::estIntraPredQT方法中。TEncSearch::estIntraPredQT实现时,首先获取当前CU的分割子块的个数,并且对每个子块分别进行预测、变换量化操作(代码中称之为PU Loop)。在每一次的PU Loop中,编码器首先遍历35种预测模式,对每一种模式进行参考像素配置、预测和率失真代价判断,并选择出某几个最优的候选模式。对这几个选取出的最优模式,递归地进行变换、量化、熵编码操作(代码中称之为Mode loop)。以下伪代码可以作为参考:
Void
TEncSearch::estIntraPredQT( TComDataCU* pcCU, TComYuv* pcOrgYuv, TComYuv* pcPredYuv, TComYuv* pcResiYuv, TComYuv* pcRecoYuv, UInt& ruiDistC, Bool bLumaOnly )
{
UInt uiNumPU = pcCU->getNumPartInter();//当前CU的分割模式下,子块的个数
for( UInt uiPU = 0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts )
{
// 获取参考像素,对参考像素进行滤波
pcCU->getPattern()->initAdiPattern();
for( Int modeIdx = 0; modeIdx < 35; modeIdx++ )
{
predIntraLumaAng();//获取各个预测模式的结果
//计算预测模式的代价
UInt uiSad = m_pcRdCost->calcHAD();
UInt iModeBits = xModeBitsIntra();
xUpdateCandList();//更新候选模式的cost值
}//Mode loop
//递归编码Intra CU,包括变换、量化等
xRecurIntraCodingQT();
}// PU loop
}
这里就不放原代码了,直接放的原博主写的伪代码。
2、xRecurIntraCodingQT以及变换量化的实现
本段主要通过代码注释讨论变换和量化的方法(由于过长删除了一部分):
Void
TEncSearch::xRecurIntraCodingLumaQT(TComYuv* pcOrgYuv,
TComYuv* pcPredYuv,
TComYuv* pcResiYuv,
Pel resiLuma[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE],
Distortion& ruiDistY,
#if HHI_RQT_INTRA_SPEEDUP
Bool bCheckFirst,
#endif
Double& dRDCost,
TComTU& rTu
DEBUG_STRING_FN_DECLARE(sDebug))
{
TComDataCU *pcCU = rTu.getCU();
const UInt uiAbsPartIdx = rTu.GetAbsPartIdxTU();
const UInt uiFullDepth = rTu.GetTransformDepthTotal();
const UInt uiTrDepth = rTu.GetTransformDepthRel();
const UInt uiLog2TrSize = rTu.GetLog2LumaTrSize();
Bool bCheckFull = ( uiLog2TrSize <= pcCU->getSlice()->getSPS()->getQuadtreeTULog2MaxSize() );
Bool bCheckSplit = ( uiLog2TrSize > pcCU->getQuadtreeTULog2MinSizeInCU(uiAbsPartIdx) );
Pel resiLumaSplit [NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];
Pel resiLumaSingle[NUMBER_OF_STORED_RESIDUAL_TYPES][MAX_CU_SIZE * MAX_CU_SIZE];
Bool bMaintainResidual[NUMBER_OF_STORED_RESIDUAL_TYPES];
for (UInt residualTypeIndex = 0; residualTypeIndex < NUMBER_OF_STORED_RESIDUAL_TYPES; residualTypeIndex++)
{
bMaintainResidual[residualTypeIndex] = true; //assume true unless specified otherwise
}
bMaintainResidual[RESIDUAL_ENCODER_SIDE] = !(m_pcEncCfg->getUseReconBasedCrossCPredictionEstimate());
#if HHI_RQT_INTRA_SPEEDUP
Int