TEncCu::compressCU分析
TEncCu::compressCU对应的代码如下:
Void TEncCu::compressCU( TComDataCU*& rpcCU )
{
// initialize CU data
m_ppcBestCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
m_ppcTempCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
// analysis of CU
xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 );
#if ADAPTIVE_QP_SELECTION
if( m_pcEncCfg->getUseAdaptQpSelect() )
{
if(rpcCU->getSlice()->getSliceType()!=I_SLICE) //IIII
{
xLcuCollectARLStats( rpcCU);
}
}
#endif
}
此段代码主要包括三个部分:
一是Input:
TComDataCU*& rpcCU
指向CU的参数。
二是initialize CU data:
m_ppcBestCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
m_ppcTempCU[0]->initCU( rpcCU->getPic(), rpcCU->getAddr() );
TempCU表示当前CU的切法,BestCU表示前面算出的最好的CU切法。
m_ppcBestCU / m_ppcTempCU:存储最好的/当前的QP和在每一个深度的预测模式决策。
下面进入initCU:TComDataCU::initCU,对应的代码如下:
Void TComDataCU::initCU( TComPic* pcPic, UInt iCUAddr )
{
m_pcPic = pcPic;
m_pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx());
m_uiCUAddr = iCUAddr;
m_uiCUPelX = ( iCUAddr % pcPic->getFrameWidthInCU() ) * g_uiMaxCUWidth;
m_uiCUPelY = ( iCUAddr / pcPic->getFrameWidthInCU() ) * g_uiMaxCUHeight;
m_uiAbsIdxInLCU = 0;
m_dTotalCost = MAX_DOUBLE;
m_uiTotalDistortion = 0;
m_uiTotalBits = 0;
m_uiTotalBins = 0;
m_uiNumPartition = pcPic->getNumPartInCU();
for(Int i=0; i<pcPic->getNumPartInCU(); i++)
{
if(pcPic->getPicSym()->getInverseCUOrderMap(iCUAddr)*pcPic->getNumPartInCU()+i>=getSlice()->getSliceCurStartCUAddr())
{
m_sliceStartCU[i]=getSlice()->getSliceCurStartCUAddr();
}
else
{
m_sliceStartCU[i]=pcPic->getCU(getAddr())->m_sliceStartCU[i];
}
}
for(Int i=0; i<pcPic->getNumPartInCU(); i++)
{
if(pcPic->getPicSym()->getInverseCUOrderMap(iCUAddr)*pcPic->getNumPartInCU()+i>=getSlice()->getSliceSegmentCurStartCUAddr())
{
m_sliceSegmentStartCU[i]=getSlice()->getSliceSegmentCurStartCUAddr();
}
else
{
m_sliceSegmentStartCU[i]=pcPic->getCU(getAddr())->m_sliceSegmentStartCU[i];
}
}
Int partStartIdx = getSlice()->getSliceSegmentCurStartCUAddr() - pcPic->getPicSym()->getInverseCUOrderMap(iCUAddr) * pcPic->getNumPartInCU();
Int numElements = min<Int>( partStartIdx, m_uiNumPartition );
for ( Int ui = 0; ui < numElements; ui++ )
{
TComDataCU * pcFrom = pcPic->getCU(getAddr());
m_skipFlag[ui] = pcFrom->getSkipFlag(ui);
m_pePartSize[ui] = pcFrom->getPartitionSize(ui);
m_pePredMode[ui] = pcFrom->getPredictionMode(ui);
m_CUTransquantBypass[ui] = pcFrom->getCUTransquantBypass(ui);
m_puhDepth[ui] = pcFrom->getDepth(ui);
m_puhWidth [ui] = pcFrom->getWidth(ui);
m_puhHeight [ui] = pcFrom->getHeight(ui);
m_puhTrIdx [ui] = pcFrom->getTransformIdx(ui);
m_puhTransformSkip[0][ui] = pcFrom->getTransformSkip(ui,TEXT_LUMA);
m_puhTransformSkip[1][ui] = pcFrom->getTransformSkip(ui,TEXT_CHROMA_U);
m_puhTransformSkip[2][ui] = pcFrom->getTransformSkip(ui,TEXT_CHROMA_V);
m_apiMVPIdx[0][ui] = pcFrom->m_apiMVPIdx[0][ui];;
m_apiMVPIdx[1][ui] = pcFrom->m_apiMVPIdx[1][ui];
m_apiMVPNum[0][ui] = pcFrom->m_apiMVPNum[0][ui];
m_apiMVPNum[1][ui] = pcFrom->m_apiMVPNum[1][ui];
m_phQP[ui]=pcFrom->m_phQP[ui];
m_pbMergeFlag[ui]=pcFrom->m_pbMergeFlag[ui];
m_puhMergeIndex[ui]=pcFrom->m_puhMergeIndex[ui];
m_puhLumaIntraDir[ui]=pcFrom->m_puhLumaIntraDir[ui];
m_puhChromaIntraDir[ui]=pcFrom->m_puhChromaIntraDir[ui];
m_puhInterDir[ui]=pcFrom->m_puhInterDir[ui];
m_puhCbf[0][ui]=pcFrom->m_puhCbf[0][ui];
m_puhCbf[1][ui]=pcFrom->m_puhCbf[1][ui];
m_puhCbf[2][ui]=pcFrom->m_puhCbf[2][ui];
m_pbIPCMFlag[ui] = pcFrom->m_pbIPCMFlag[ui];
}
Int firstElement = max<Int>( partStartIdx, 0 );
numElements = m_uiNumPartition - firstElement;
if ( numElements > 0 )
{
memset( m_skipFlag + firstElement, false, numElements * sizeof( *m_skipFlag ) );
memset( m_pePartSize + firstElement, SIZE_NONE, numElements * sizeof( *m_pePartSize ) );
memset( m_pePredMode + firstElement, MODE_NONE, numElements * sizeof( *m_pePredMode ) );
memset( m_CUTransquantBypass+ firstElement, false, numElements * sizeof( *m_CUTransquantBypass) );
memset( m_puhDepth + firstElement, 0, numElements * sizeof( *m_puhDepth ) );
memset( m_puhTrIdx + firstElement, 0, numElements * sizeof( *m_puhTrIdx ) );
memset( m_puhTransformSkip[0] + firstElement, 0, numElements * sizeof( *m_puhTransformSkip[0]) );
memset( m_puhTransformSkip[1] + firstElement, 0, numElements * sizeof( *m_puhTransformSkip[1]) );
memset( m_puhTransformSkip[2] + firstElement, 0, numElements * sizeof( *m_puhTransformSkip[2]) );
memset( m_puhWidth + firstElement, g_uiMaxCUWidth, numElements * sizeof( *m_puhWidth ) );
memset( m_puhHeight + firstElement, g_uiMaxCUHeight, numElements * sizeof( *m_puhHeight ) );
memset( m_apiMVPIdx[0] + firstElement, -1, numElements * sizeof( *m_apiMVPIdx[0] ) );
memset( m_apiMVPIdx[1] + firstElement, -1, numElements * sizeof( *m_apiMVPIdx[1] ) );
memset( m_apiMVPNum[0] + firstElement, -1, numElements * sizeof( *m_apiMVPNum[0] ) );
memset( m_apiMVPNum[1] + firstElement, -1, numElements * sizeof( *m_apiMVPNum[1] ) );
memset( m_phQP + firstElement, getSlice()->getSliceQp(), numElements * sizeof( *m_phQP ) );
memset( m_pbMergeFlag + firstElement, false, numElements * sizeof( *m_pbMergeFlag ) );
memset( m_puhMergeIndex + firstElement, 0, numElements * sizeof( *m_puhMergeIndex ) );
memset( m_puhLumaIntraDir + firstElement, DC_IDX, numElements * sizeof( *m_puhLumaIntraDir ) );
memset( m_puhChromaIntraDir + firstElement, 0, numElements * sizeof( *m_puhChromaIntraDir ) );
memset( m_puhInterDir + firstElement, 0, numElements * sizeof( *m_puhInterDir ) );
memset( m_puhCbf[0] + firstElement, 0, numElements * sizeof( *m_puhCbf[0] ) );
memset( m_puhCbf[1] + firstElement, 0, numElements * sizeof( *m_puhCbf[1] ) );
memset( m_puhCbf[2] + firstElement, 0, numElements * sizeof( *m_puhCbf[2] ) );
memset( m_pbIPCMFlag + firstElement, false, numElements * sizeof( *m_pbIPCMFlag ) );
}
UInt uiTmp = g_uiMaxCUWidth*g_uiMaxCUHeight;
if ( 0 >= partStartIdx )
{
m_acCUMvField[0].clearMvField();
m_acCUMvField[1].clearMvField();
memset( m_pcTrCoeffY , 0, sizeof( TCoeff ) * uiTmp );
#if ADAPTIVE_QP_SELECTION
memset( m_pcArlCoeffY , 0, sizeof( Int ) * uiTmp );
#endif
memset( m_pcIPCMSampleY , 0, sizeof( Pel ) * uiTmp );
uiTmp >>= 2;
memset( m_pcTrCoeffCb, 0, sizeof( TCoeff ) * uiTmp );
memset( m_pcTrCoeffCr, 0, sizeof( TCoeff ) * uiTmp );
#if ADAPTIVE_QP_SELECTION
memset( m_pcArlCoeffCb, 0, sizeof( Int ) * uiTmp );
memset( m_pcArlCoeffCr, 0, sizeof( Int ) * uiTmp );
#endif
memset( m_pcIPCMSampleCb , 0, sizeof( Pel ) * uiTmp );
memset( m_pcIPCMSampleCr , 0, sizeof( Pel ) * uiTmp );
}
else
{
TComDataCU * pcFrom = pcPic->getCU(getAddr());
m_acCUMvField[0].copyFrom(&pcFrom->m_acCUMvField[0],m_uiNumPartition,0);
m_acCUMvField[1].copyFrom(&pcFrom->m_acCUMvField[1],m_uiNumPartition,0);
for(Int i=0; i<uiTmp; i++)
{
m_pcTrCoeffY[i]=pcFrom->m_pcTrCoeffY[i];
#if ADAPTIVE_QP_SELECTION
m_pcArlCoeffY[i]=pcFrom->m_pcArlCoeffY[i];
#endif
m_pcIPCMSampleY[i]=pcFrom->m_pcIPCMSampleY[i];
}
for(Int i=0; i<(uiTmp>>2); i++)
{
m_pcTrCoeffCb[i]=pcFrom->m_pcTrCoeffCb[i];
m_pcTrCoeffCr[i]=pcFrom->m_pcTrCoeffCr[i];
#if ADAPTIVE_QP_SELECTION
m_pcArlCoeffCb[i]=pcFrom->m_pcArlCoeffCb[i];
m_pcArlCoeffCr[i]=pcFrom->m_pcArlCoeffCr[i];
#endif
m_pcIPCMSampleCb[i]=pcFrom->m_pcIPCMSampleCb[i];
m_pcIPCMSampleCr[i]=pcFrom->m_pcIPCMSampleCr[i];
}
}
// Setting neighbor CU
m_pcCULeft = NULL;
m_pcCUAbove = NULL;
m_pcCUAboveLeft = NULL;
m_pcCUAboveRight = NULL;
m_apcCUColocated[0] = NULL;
m_apcCUColocated[1] = NULL;
UInt uiWidthInCU = pcPic->getFrameWidthInCU();
if ( m_uiCUAddr % uiWidthInCU )
{
m_pcCULeft = pcPic->getCU( m_uiCUAddr - 1 );
}
if ( m_uiCUAddr / uiWidthInCU )
{
m_pcCUAbove = pcPic->getCU( m_uiCUAddr - uiWidthInCU );
}
if ( m_pcCULeft && m_pcCUAbove )
{
m_pcCUAboveLeft = pcPic->getCU( m_uiCUAddr - uiWidthInCU - 1 );
}
if ( m_pcCUAbove && ( (m_uiCUAddr%uiWidthInCU) < (uiWidthInCU-1) ) )
{
m_pcCUAboveRight = pcPic->getCU( m_uiCUAddr - uiWidthInCU + 1 );
}
if ( getSlice()->getNumRefIdx( REF_PIC_LIST_0 ) > 0 )
{
m_apcCUColocated[0] = getSlice()->getRefPic( REF_PIC_LIST_0, 0)->getCU( m_uiCUAddr );
}
if ( getSlice()->getNumRefIdx( REF_PIC_LIST_1 ) > 0 )
{
m_apcCUColocated[1] = getSlice()->getRefPic( REF_PIC_LIST_1, 0)->getCU( m_uiCUAddr );
}
}
此函数传入的是Pic和CU的参数,此段程序主要完成以下几个任务:
1、Initialize top-level CU
m_pcPic = pcPic;
m_pcSlice = pcPic->getSlice(pcPic->getCurrSliceIdx());
m_uiCUAddr = iCUAddr;
m_uiCUPelX = ( iCUAddr % pcPic->getFrameWid