HM编码器代码阅读(34)——帧内预测(一)

帧内预测


原理


    帧内预测,利用当前图像内已经编码的像素生成预测值,生成预测值之后,和原始的值相减,得到残差,后续的变换量化等操作就是基于残差进行处理的。具体细节参考  HEVC/H.265理论知识(3)——帧内预测

流程


帧内预测的大致流程是这样的
(1)遍历所有的预测模式,得到每种模式下的残差信号,再对残差信号进行Hadamard变换计算SATD值
(2)利用SATD值计算每种预测模式的率失真代价,选取率失真代价最小的几种模式(与PU大小相关)为预测模式集
(3)将已编码相邻块的预测模式补充到预测模式集中
(4)遍历模式集合中的所有模式,并对残差信号进行正常编码(熵编码),计算率失真代价
(5)选取最优的预测模式作为该PU的最优模式
(6)当亮度块的模式确定之后,把该模式以及DC、planar、水平方向模式、垂直方向模式作为色度块的候选模式,选取最优的模式即可

帧内预测的入口函数

入口函数是TEncCu::xCheckRDCostIntra,流程如下:
1、对亮度块进行帧内预测、变换量化,选取出最优的预测模式、并且计算出变换系数
2、对色度块(U、V分量)进行帧内预测、变换量化,选出最优的预测模式,并且计算出量化变换系数
3、对步骤1、2得到的模式和变换系数进行熵编码,得到比特代价
4、最后更新最优模式信息和数据
/*
** 帧内预测入口函数
*/
Void TEncCu::xCheckRDCostIntra( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, PartSize eSize )
{
	// 获取当前CU所处的深度
	UInt uiDepth = rpcTempCU->getDepth( 0 );

	// 跳过模式,设置为false
	rpcTempCU->setSkipFlagSubParts( false, 0, uiDepth );

	// 设置尺寸
	rpcTempCU->setPartSizeSubParts( eSize, 0, uiDepth );

	// 设置预测模式(帧内)
	rpcTempCU->setPredModeSubParts( MODE_INTRA, 0, uiDepth );

	// 是否区分亮度和色度
	Bool bSeparateLumaChroma = true; // choose estimation mode
	UInt uiPreCalcDistC      = 0;

	// !bSeparateLumaChroma总是false,所以不会进到该条件判断
	if( !bSeparateLumaChroma )
	{
		m_pcPredSearch->preestChromaPredMode( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth] );
	}

	// 这里进行实际的帧内预测(亮度)
	m_pcPredSearch  ->estIntraPredQT      ( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], uiPreCalcDistC, bSeparateLumaChroma );

	m_ppcRecoYuvTemp[uiDepth]->copyToPicLuma(rpcTempCU->getPic()->getPicYuvRec(), rpcTempCU->getAddr(), rpcTempCU->getZorderIdxInCU() );

	// 这里进行实际的帧内预测(色度)
	m_pcPredSearch  ->estIntraPredChromaQT( rpcTempCU, m_ppcOrigYuv[uiDepth], m_ppcPredYuvTemp[uiDepth], m_ppcResiYuvTemp[uiDepth], m_ppcRecoYuvTemp[uiDepth], uiPreCalcDistC );

	// 重置熵编码器的比特数量
	m_pcEntropyCoder->resetBits();
	if ( rpcTempCU->getSlice()->getPPS()->getTransquantBypassEnableFlag())
	{
		m_pcEntropyCoder->encodeCUTransquantBypassFlag( rpcTempCU, 0,          true );
	}

	// 进行熵编码,得到最优模式下的比特代价等信息
	m_pcEntropyCoder->encodeSkipFlag ( rpcTempCU, 0,          true );
	m_pcEntropyCoder->encodePredMode( rpcTempCU, 0,          true );
	m_pcEntropyCoder->encodePartSize( rpcTempCU, 0, uiDepth, true );
	m_pcEntropyCoder->encodePredInfo( rpcTempCU, 0,          true );
	// 编码IPCM信息
	m_pcEntropyCoder->encodeIPCMInfo(rpcTempCU, 0, true );

	// Encode Coefficients
	Bool bCodeDQP = getdQPFlag();

	// 对系数进编码
	m_pcEntropyCoder->encodeCoeff( rpcTempCU, 0, uiDepth, rpcTempCU->getWidth (0), rpcTempCU->getHeight(0), bCodeDQP );

	setdQPFlag( bCodeDQP );

	m_pcRDGoOnSbacCoder->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]);

	rpcTempCU->getTotalBits() = m_pcEntropyCoder->getNumberOfWrittenBits();
	rpcTempCU->getTotalBins() = ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded();
	rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() );

	xCheckDQP( rpcTempCU );

	// 更新最优模式信息和数据
	xCheckBestMode(rpcBestCU, rpcTempCU, uiDepth);
}




你可能感兴趣的:(HEVC编码器HM源码阅读)