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->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();
指明了当前CU属于哪一个Pic,属于哪一个Slice以及CU的地址。
2、Set neighbor CU
m_pcCULeft = NULL; m_pcCUAbove = NULL; m_pcCUAboveLeft = NULL; m_pcCUAboveRight = NULL;
左方、上方、左上和右上的位置和值,接下来的也可以参考这一块的值。
三是analysis of CU:
xCompressCU( m_ppcBestCU[0], m_ppcTempCU[0], 0 );
从深度0开始一直往上加,选择最好的预测模式和QP
xCompressCU的函数位于TEncCu::xCompressCU,对应的代码如下:
#if AMP_ENC_SPEEDUP Void TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, UInt uiDepth, PartSize eParentPartSize ) #else Void TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, UInt uiDepth ) #endif { TComPic* pcPic = rpcBestCU->getPic(); // get Original YUV data from picture m_ppcOrigYuv[uiDepth]->copyFromPicYuv( pcPic->getPicYuvOrg(), rpcBestCU->getAddr(), rpcBestCU->getZorderIdxInCU() ); // variable for Early CU determination Bool bSubBranch = true; // variable for Cbf fast mode PU decision Bool doNotBlockPu = true; Bool earlyDetectionSkipMode = false; Bool bBoundary = false; UInt uiLPelX = rpcBestCU->getCUPelX(); UInt uiRPelX = uiLPelX + rpcBestCU->getWidth(0) - 1; UInt uiTPelY = rpcBestCU->getCUPelY(); UInt uiBPelY = uiTPelY + rpcBestCU->getHeight(0) - 1; Int iBaseQP = xComputeQP( rpcBestCU, uiDepth ); Int iMinQP; Int iMaxQP; Bool isAddLowestQP = false; if( (g_uiMaxCUWidth>>uiDepth) >= rpcTempCU->getSlice()->getPPS()->getMinCuDQPSize() ) { Int idQP = m_pcEncCfg->getMaxDeltaQP(); iMinQP = Clip3( -rpcTempCU->getSlice()->getSPS()->getQpBDOffsetY(), MAX_QP, iBaseQP-idQP ); iMaxQP = Clip3( -rpcTempCU->getSlice()->getSPS()->getQpBDOffsetY(), MAX_QP, iBaseQP+idQP ); } else { iMinQP = rpcTempCU->getQP(0); iMaxQP = rpcTempCU->getQP(0); } if ( m_pcEncCfg->getUseRateCtrl() ) { iMinQP = m_pcRateCtrl->getRCQP(); iMaxQP = m_pcRateCtrl->getRCQP(); } // transquant-bypass (TQB) processing loop variable initialisation --- const Int lowestQP = iMinQP; // For TQB, use this QP which is the lowest non TQB QP tested (rather than QP'=0) - that way delta QPs are smaller, and TQB can be tested at all CU levels. if ( (rpcTempCU->getSlice()->getPPS()->getTransquantBypassEnableFlag()) ) { isAddLowestQP = true; // mark that the first iteration is to cost TQB mode. iMinQP = iMinQP - 1; // increase loop variable range by 1, to allow testing of TQB mode along with other QPs if ( m_pcEncCfg->getCUTransquantBypassFlagForceValue() ) { iMaxQP = iMinQP; } } // If slice start or slice end is within this cu... TComSlice * pcSlice = rpcTempCU->getPic()->getSlice(rpcTempCU->getPic()->getCurrSliceIdx()); Bool bSliceStart = pcSlice->getSliceSegmentCurStartCUAddr()>rpcTempCU->getSCUAddr()&&pcSlice->getSliceSegmentCurStartCUAddr()<rpcTempCU->getSCUAddr()+rpcTempCU->getTotalNumPart(); Bool bSliceEnd = (pcSlice->getSliceSegmentCurEndCUAddr()>rpcTempCU->getSCUAddr()&&pcSlice->getSliceSegmentCurEndCUAddr()<rpcTempCU->getSCUAddr()+rpcTempCU->getTotalNumPart()); Bool bInsidePicture = ( uiRPelX < rpcBestCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiBPelY < rpcBestCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ); // We need to split, so don't try these modes. if(!bSliceEnd && !bSliceStart && bInsidePicture ) { for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP); if (bIsLosslessMode) { iQP = lowestQP; } rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // do inter modes, SKIP and 2Nx2N if( rpcBestCU->getSlice()->getSliceType() != I_SLICE ) { // 2Nx2N if(m_pcEncCfg->getUseEarlySkipDetection()) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );//by Competition for inter_2Nx2N } // SKIP xCheckRDCostMerge2Nx2N( rpcBestCU, rpcTempCU, &earlyDetectionSkipMode );//by Merge for inter_2Nx2N rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(!m_pcEncCfg->getUseEarlySkipDetection()) { // 2Nx2N, NxN xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode()) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } if (bIsLosslessMode) { iQP = iMinQP; } } if(!earlyDetectionSkipMode) { for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP); if (bIsLosslessMode) { iQP = lowestQP; } rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // do inter modes, NxN, 2NxN, and Nx2N if( rpcBestCU->getSlice()->getSliceType() != I_SLICE ) { // 2Nx2N, NxN if(!( (rpcBestCU->getWidth(0)==8) && (rpcBestCU->getHeight(0)==8) )) { if( uiDepth == g_uiMaxCUDepth - g_uiAddCUDepth && doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_NxN ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } // 2NxN, Nx2N if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_Nx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_Nx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter ( rpcBestCU, rpcTempCU, SIZE_2NxN ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxN) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } #if 1 //! Try AMP (SIZE_2NxnU, SIZE_2NxnD, SIZE_nLx2N, SIZE_nRx2N) if( pcPic->getSlice(0)->getSPS()->getAMPAcc(uiDepth) ) { #if AMP_ENC_SPEEDUP Bool bTestAMP_Hor = false, bTestAMP_Ver = false; #if AMP_MRG Bool bTestMergeAMP_Hor = false, bTestMergeAMP_Ver = false; deriveTestModeAMP (rpcBestCU, eParentPartSize, bTestAMP_Hor, bTestAMP_Ver, bTestMergeAMP_Hor, bTestMergeAMP_Ver); #else deriveTestModeAMP (rpcBestCU, eParentPartSize, bTestAMP_Hor, bTestAMP_Ver); #endif //! Do horizontal AMP if ( bTestAMP_Hor ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnU ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnD ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } #if AMP_MRG else if ( bTestMergeAMP_Hor ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU, true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnU ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD, true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnD ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } #endif //! Do horizontal AMP if ( bTestAMP_Ver ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_nLx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } #if AMP_MRG else if ( bTestMergeAMP_Ver ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N, true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_nLx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N, true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } #endif #else xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); #endif } #endif } // do normal intra modes // speedup for inter frames if( rpcBestCU->getSlice()->getSliceType() == I_SLICE || rpcBestCU->getCbf( 0, TEXT_LUMA ) != 0 || rpcBestCU->getCbf( 0, TEXT_CHROMA_U ) != 0 || rpcBestCU->getCbf( 0, TEXT_CHROMA_V ) != 0 ) // avoid very complex intra if it is unlikely { xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_2Nx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if( uiDepth == g_uiMaxCUDepth - g_uiAddCUDepth ) { if( rpcTempCU->getWidth(0) > ( 1 << rpcTempCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) ) { xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_NxN ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } } // test PCM if(pcPic->getSlice(0)->getSPS()->getUsePCM() && rpcTempCU->getWidth(0) <= (1<<pcPic->getSlice(0)->getSPS()->getPCMLog2MaxSize()) && rpcTempCU->getWidth(0) >= (1<<pcPic->getSlice(0)->getSPS()->getPCMLog2MinSize()) ) { UInt uiRawBits = (2 * g_bitDepthY + g_bitDepthC) * rpcBestCU->getWidth(0) * rpcBestCU->getHeight(0) / 2; UInt uiBestBits = rpcBestCU->getTotalBits(); if((uiBestBits > uiRawBits) || (rpcBestCU->getTotalCost() > m_pcRdCost->calcRdCost(uiRawBits, 0))) { xCheckIntraPCM (rpcBestCU, rpcTempCU); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } if (bIsLosslessMode) { iQP = iMinQP; } } } m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeSplitFlag( rpcBestCU, 0, uiDepth, true ); rpcBestCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // split bits rpcBestCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcBestCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcBestCU->getTotalBits(), rpcBestCU->getTotalDistortion() ); // Early CU determination if( m_pcEncCfg->getUseEarlyCU() && rpcBestCU->isSkipped(0) ) { bSubBranch = false; } else { bSubBranch = true; } } else if(!(bSliceEnd && bInsidePicture)) { bBoundary = true; } // copy orginal YUV samples to PCM buffer if( rpcBestCU->isLosslessCoded(0) && (rpcBestCU->getIPCMFlag(0) == false)) { xFillPCMBuffer(rpcBestCU, m_ppcOrigYuv[uiDepth]); } if( (g_uiMaxCUWidth>>uiDepth) == rpcTempCU->getSlice()->getPPS()->getMinCuDQPSize() ) { Int idQP = m_pcEncCfg->getMaxDeltaQP(); iMinQP = Clip3( -rpcTempCU->getSlice()->getSPS()->getQpBDOffsetY(), MAX_QP, iBaseQP-idQP ); iMaxQP = Clip3( -rpcTempCU->getSlice()->getSPS()->getQpBDOffsetY(), MAX_QP, iBaseQP+idQP ); } else if( (g_uiMaxCUWidth>>uiDepth) > rpcTempCU->getSlice()->getPPS()->getMinCuDQPSize() ) { iMinQP = iBaseQP; iMaxQP = iBaseQP; } else { Int iStartQP; if( pcPic->getCU( rpcTempCU->getAddr() )->getSliceSegmentStartCU(rpcTempCU->getZorderIdxInCU()) == pcSlice->getSliceSegmentCurStartCUAddr()) { iStartQP = rpcTempCU->getQP(0); } else { UInt uiCurSliceStartPartIdx = pcSlice->getSliceSegmentCurStartCUAddr() % pcPic->getNumPartInCU() - rpcTempCU->getZorderIdxInCU(); iStartQP = rpcTempCU->getQP(uiCurSliceStartPartIdx); } iMinQP = iStartQP; iMaxQP = iStartQP; } if ( m_pcEncCfg->getUseRateCtrl() ) { iMinQP = m_pcRateCtrl->getRCQP(); iMaxQP = m_pcRateCtrl->getRCQP(); } if ( m_pcEncCfg->getCUTransquantBypassFlagForceValue() ) { iMaxQP = iMinQP; // If all blocks are forced into using transquant bypass, do not loop here. } for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = false; // False at this level. Next level down may set it to true. rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // further split if( bSubBranch && uiDepth < g_uiMaxCUDepth - g_uiAddCUDepth ) { UChar uhNextDepth = uiDepth+1; TComDataCU* pcSubBestPartCU = m_ppcBestCU[uhNextDepth]; TComDataCU* pcSubTempPartCU = m_ppcTempCU[uhNextDepth]; for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ ) { pcSubBestPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP ); // clear sub partition datas or init. pcSubTempPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP ); // clear sub partition datas or init. Bool bInSlice = pcSubBestPartCU->getSCUAddr()+pcSubBestPartCU->getTotalNumPart()>pcSlice->getSliceSegmentCurStartCUAddr()&&pcSubBestPartCU->getSCUAddr()<pcSlice->getSliceSegmentCurEndCUAddr(); if(bInSlice && ( pcSubBestPartCU->getCUPelX() < pcSlice->getSPS()->getPicWidthInLumaSamples() ) && ( pcSubBestPartCU->getCUPelY() < pcSlice->getSPS()->getPicHeightInLumaSamples() ) ) { if ( 0 == uiPartUnitIdx) //initialize RD with previous depth buffer { m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); } else { m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); } #if AMP_ENC_SPEEDUP if ( rpcBestCU->isIntra(0) ) { xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, SIZE_NONE ); } else { xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, rpcBestCU->getPartitionSize(0) ); } #else xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth ); #endif rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth ); // Keep best part data to current temporary data. xCopyYuv2Tmp( pcSubBestPartCU->getTotalNumPart()*uiPartUnitIdx, uhNextDepth ); } else if (bInSlice) { pcSubBestPartCU->copyToPic( uhNextDepth ); rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth ); } } if( !bBoundary ) { m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeSplitFlag( rpcTempCU, 0, uiDepth, true ); rpcTempCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // split bits rpcTempCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); } rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); if( (g_uiMaxCUWidth>>uiDepth) == rpcTempCU->getSlice()->getPPS()->getMinCuDQPSize() && rpcTempCU->getSlice()->getPPS()->getUseDQP()) { Bool hasResidual = false; for( UInt uiBlkIdx = 0; uiBlkIdx < rpcTempCU->getTotalNumPart(); uiBlkIdx ++) { if( ( pcPic->getCU( rpcTempCU->getAddr() )->getSliceSegmentStartCU(uiBlkIdx+rpcTempCU->getZorderIdxInCU()) == rpcTempCU->getSlice()->getSliceSegmentCurStartCUAddr() ) && ( rpcTempCU->getCbf( uiBlkIdx, TEXT_LUMA ) || rpcTempCU->getCbf( uiBlkIdx, TEXT_CHROMA_U ) || rpcTempCU->getCbf( uiBlkIdx, TEXT_CHROMA_V ) ) ) { hasResidual = true; break; } } UInt uiTargetPartIdx; if ( pcPic->getCU( rpcTempCU->getAddr() )->getSliceSegmentStartCU(rpcTempCU->getZorderIdxInCU()) != pcSlice->getSliceSegmentCurStartCUAddr() ) { uiTargetPartIdx = pcSlice->getSliceSegmentCurStartCUAddr() % pcPic->getNumPartInCU() - rpcTempCU->getZorderIdxInCU(); } else { uiTargetPartIdx = 0; } if ( hasResidual ) { #if !RDO_WITHOUT_DQP_BITS m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeQP( rpcTempCU, uiTargetPartIdx, false ); rpcTempCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // dQP bits rpcTempCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); #endif Bool foundNonZeroCbf = false; rpcTempCU->setQPSubCUs( rpcTempCU->getRefQP( uiTargetPartIdx ), rpcTempCU, 0, uiDepth, foundNonZeroCbf ); assert( foundNonZeroCbf ); } else { rpcTempCU->setQPSubParts( rpcTempCU->getRefQP( uiTargetPartIdx ), 0, uiDepth ); // set QP to default QP } } m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); Bool isEndOfSlice = rpcBestCU->getSlice()->getSliceMode()==FIXED_NUMBER_OF_BYTES && (rpcBestCU->getTotalBits()>rpcBestCU->getSlice()->getSliceArgument()<<3); Bool isEndOfSliceSegment = rpcBestCU->getSlice()->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && (rpcBestCU->getTotalBits()>rpcBestCU->getSlice()->getSliceSegmentArgument()<<3); if(isEndOfSlice||isEndOfSliceSegment) { rpcBestCU->getTotalCost()=rpcTempCU->getTotalCost()+1; } xCheckBestMode( rpcBestCU, rpcTempCU, uiDepth); // RD compare current larger prediction } // with sub partitioned prediction. } rpcBestCU->copyToPic(uiDepth); // Copy Best data to Picture for next partition prediction. xCopyYuv2Pic( rpcBestCU->getPic(), rpcBestCU->getAddr(), rpcBestCU->getZorderIdxInCU(), uiDepth, uiDepth, rpcBestCU, uiLPelX, uiTPelY ); // Copy Yuv data to picture Yuv if( bBoundary ||(bSliceEnd && bInsidePicture)) { return; } // Assert if Best prediction mode is NONE // Selected mode's RD-cost must be not MAX_DOUBLE. assert( rpcBestCU->getPartitionSize ( 0 ) != SIZE_NONE ); assert( rpcBestCU->getPredictionMode( 0 ) != MODE_NONE ); assert( rpcBestCU->getTotalCost ( ) != MAX_DOUBLE ); }
xCompressCU是主要做切割的地方,传入的参数是BestCU,TempCU和Depth,主要完成以下几个任务:
1、Get picture YUV data
TComPic* pcPic = rpcBestCU->getPic(); // get Original YUV data from picture m_ppcOrigYuv[uiDepth]->copyFromPicYuv( pcPic->getPicYuvOrg(), rpcBestCU->getAddr(), rpcBestCU->getZorderIdxInCU() );
2、Compute BaseQP
通过iBaseQP计算iMinQP和iMaxQP,对应的函数是:
Int iBaseQP = xComputeQP( rpcBestCU, uiDepth );
3、Check every possible QP
在一个for循环中完成,主要功能为:尝试每一个可能的QP对应的每一种预测模式,得到QP和预测模式。
其基本模型为:
for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++)
{
try all kinds of prediction modes for every possible QP
}
对应的代码如下:
// If slice start or slice end is within this cu... TComSlice * pcSlice = rpcTempCU->getPic()->getSlice(rpcTempCU->getPic()->getCurrSliceIdx()); Bool bSliceStart = pcSlice->getSliceSegmentCurStartCUAddr()>rpcTempCU->getSCUAddr()&&pcSlice->getSliceSegmentCurStartCUAddr()<rpcTempCU->getSCUAddr()+rpcTempCU->getTotalNumPart(); Bool bSliceEnd = (pcSlice->getSliceSegmentCurEndCUAddr()>rpcTempCU->getSCUAddr()&&pcSlice->getSliceSegmentCurEndCUAddr()<rpcTempCU->getSCUAddr()+rpcTempCU->getTotalNumPart()); Bool bInsidePicture = ( uiRPelX < rpcBestCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiBPelY < rpcBestCU->getSlice()->getSPS()->getPicHeightInLumaSamples() ); // We need to split, so don't try these modes. <span style="color:#cc0000;"> <strong>if(!bSliceEnd && !bSliceStart && bInsidePicture )</strong></span> { for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP); if (bIsLosslessMode) { iQP = lowestQP; } rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // do inter modes, SKIP and 2Nx2N if( rpcBestCU->getSlice()->getSliceType() != I_SLICE ) { // 2Nx2N if(m_pcEncCfg->getUseEarlySkipDetection()) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode );//by Competition for inter_2Nx2N } // SKIP xCheckRDCostMerge2Nx2N( rpcBestCU, rpcTempCU, &earlyDetectionSkipMode );//by Merge for inter_2Nx2N rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(!m_pcEncCfg->getUseEarlySkipDetection()) { // 2Nx2N, NxN xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2Nx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode()) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } if (bIsLosslessMode) { iQP = iMinQP; } } if(!earlyDetectionSkipMode) { for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = isAddLowestQP && (iQP == iMinQP); if (bIsLosslessMode) { iQP = lowestQP; } rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // do inter modes, NxN, 2NxN, and Nx2N if( rpcBestCU->getSlice()->getSliceType() != I_SLICE ) { // 2Nx2N, NxN if(!( (rpcBestCU->getWidth(0)==8) && (rpcBestCU->getHeight(0)==8) )) { if( uiDepth == g_uiMaxCUDepth - g_uiAddCUDepth && doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_NxN ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } // 2NxN, Nx2N if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_Nx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_Nx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter ( rpcBestCU, rpcTempCU, SIZE_2NxN ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxN) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } #if 1 //! Try AMP (SIZE_2NxnU, SIZE_2NxnD, SIZE_nLx2N, SIZE_nRx2N) if( pcPic->getSlice(0)->getSPS()->getAMPAcc(uiDepth) ) { #if AMP_ENC_SPEEDUP Bool bTestAMP_Hor = false, bTestAMP_Ver = false; #if AMP_MRG Bool bTestMergeAMP_Hor = false, bTestMergeAMP_Ver = false; deriveTestModeAMP (rpcBestCU, eParentPartSize, bTestAMP_Hor, bTestAMP_Ver, bTestMergeAMP_Hor, bTestMergeAMP_Ver); #else deriveTestModeAMP (rpcBestCU, eParentPartSize, bTestAMP_Hor, bTestAMP_Ver); #endif //! Do horizontal AMP if ( bTestAMP_Hor ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnU ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnD ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } #if AMP_MRG else if ( bTestMergeAMP_Hor ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU, true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnU ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD, true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_2NxnD ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } } #endif //! Do horizontal AMP if ( bTestAMP_Ver ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_nLx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } #if AMP_MRG else if ( bTestMergeAMP_Ver ) { if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N, true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if(m_pcEncCfg->getUseCbfFastMode() && rpcBestCU->getPartitionSize(0) == SIZE_nLx2N ) { doNotBlockPu = rpcBestCU->getQtRootCbf( 0 ) != 0; } } if(doNotBlockPu) { xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N, true ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } #endif #else xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnU ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_2NxnD ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nLx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); xCheckRDCostInter( rpcBestCU, rpcTempCU, SIZE_nRx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); #endif } #endif } // do normal intra modes // speedup for inter frames if( rpcBestCU->getSlice()->getSliceType() == I_SLICE || rpcBestCU->getCbf( 0, TEXT_LUMA ) != 0 || rpcBestCU->getCbf( 0, TEXT_CHROMA_U ) != 0 || rpcBestCU->getCbf( 0, TEXT_CHROMA_V ) != 0 ) // avoid very complex intra if it is unlikely { xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_2Nx2N ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); if( uiDepth == g_uiMaxCUDepth - g_uiAddCUDepth ) { if( rpcTempCU->getWidth(0) > ( 1 << rpcTempCU->getSlice()->getSPS()->getQuadtreeTULog2MinSize() ) ) { xCheckRDCostIntra( rpcBestCU, rpcTempCU, SIZE_NxN ); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } } // test PCM if(pcPic->getSlice(0)->getSPS()->getUsePCM() && rpcTempCU->getWidth(0) <= (1<<pcPic->getSlice(0)->getSPS()->getPCMLog2MaxSize()) && rpcTempCU->getWidth(0) >= (1<<pcPic->getSlice(0)->getSPS()->getPCMLog2MinSize()) ) { UInt uiRawBits = (2 * g_bitDepthY + g_bitDepthC) * rpcBestCU->getWidth(0) * rpcBestCU->getHeight(0) / 2; UInt uiBestBits = rpcBestCU->getTotalBits(); if((uiBestBits > uiRawBits) || (rpcBestCU->getTotalCost() > m_pcRdCost->calcRdCost(uiRawBits, 0))) { xCheckIntraPCM (rpcBestCU, rpcTempCU); rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); } } if (bIsLosslessMode) { iQP = iMinQP; } } } m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeSplitFlag( rpcBestCU, 0, uiDepth, true ); rpcBestCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // split bits rpcBestCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcBestCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcBestCU->getTotalBits(), rpcBestCU->getTotalDistortion() ); // Early CU determination if( m_pcEncCfg->getUseEarlyCU() && rpcBestCU->isSkipped(0) ) { bSubBranch = false; } else { bSubBranch = true; } } <span style="color:#cc0000;"> <strong>else if(!(bSliceEnd && bInsidePicture))</strong></span> { bBoundary = true; }
4、Check if Slice starts or Slice ends within this CU
对应的函数功能代码如下:
Bool bInsidePicture = ( uiRPelX < rpcBestCU->getSlice()->getSPS()->getPicWidthInLumaSamples() ) && ( uiBPelY < rpcBestCU->getSlice()->getSPS()->getPicHeightInLumaSamples() );
True:try every prediction mode
False:further split
//try every prediction mode
for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++)
{
try all kinds of prediction modes for every possible QP
}
//further split在此函数的功能:即检查当前CU是否在当前Slice的头或尾,若没有跨越Slice,则尝试每一种预测模式;若跨越Slice,则进一步分割。
对应的代码如下:
for (Int iQP=iMinQP; iQP<=iMaxQP; iQP++) { const Bool bIsLosslessMode = false; // False at this level. Next level down may set it to true. rpcTempCU->initEstData( uiDepth, iQP, bIsLosslessMode ); // further split if( bSubBranch && uiDepth < g_uiMaxCUDepth - g_uiAddCUDepth ) { UChar uhNextDepth = uiDepth+1; TComDataCU* pcSubBestPartCU = m_ppcBestCU[uhNextDepth]; TComDataCU* pcSubTempPartCU = m_ppcTempCU[uhNextDepth]; for ( UInt uiPartUnitIdx = 0; uiPartUnitIdx < 4; uiPartUnitIdx++ ) { pcSubBestPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP ); // clear sub partition datas or init. pcSubTempPartCU->initSubCU( rpcTempCU, uiPartUnitIdx, uhNextDepth, iQP ); // clear sub partition datas or init. Bool bInSlice = pcSubBestPartCU->getSCUAddr()+pcSubBestPartCU->getTotalNumPart()>pcSlice->getSliceSegmentCurStartCUAddr()&&pcSubBestPartCU->getSCUAddr()<pcSlice->getSliceSegmentCurEndCUAddr(); if(bInSlice && ( pcSubBestPartCU->getCUPelX() < pcSlice->getSPS()->getPicWidthInLumaSamples() ) && ( pcSubBestPartCU->getCUPelY() < pcSlice->getSPS()->getPicHeightInLumaSamples() ) ) { if ( 0 == uiPartUnitIdx) //initialize RD with previous depth buffer { m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]); } else { m_pppcRDSbacCoder[uhNextDepth][CI_CURR_BEST]->load(m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]); } #if AMP_ENC_SPEEDUP if ( rpcBestCU->isIntra(0) ) { xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, SIZE_NONE ); } else { xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth, rpcBestCU->getPartitionSize(0) ); } #else xCompressCU( pcSubBestPartCU, pcSubTempPartCU, uhNextDepth ); #endif rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth ); // Keep best part data to current temporary data. xCopyYuv2Tmp( pcSubBestPartCU->getTotalNumPart()*uiPartUnitIdx, uhNextDepth ); } else if (bInSlice) { pcSubBestPartCU->copyToPic( uhNextDepth ); rpcTempCU->copyPartFrom( pcSubBestPartCU, uiPartUnitIdx, uhNextDepth ); } } if( !bBoundary ) { m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeSplitFlag( rpcTempCU, 0, uiDepth, true ); rpcTempCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // split bits rpcTempCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); } rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); if( (g_uiMaxCUWidth>>uiDepth) == rpcTempCU->getSlice()->getPPS()->getMinCuDQPSize() && rpcTempCU->getSlice()->getPPS()->getUseDQP()) { Bool hasResidual = false; for( UInt uiBlkIdx = 0; uiBlkIdx < rpcTempCU->getTotalNumPart(); uiBlkIdx ++) { if( ( pcPic->getCU( rpcTempCU->getAddr() )->getSliceSegmentStartCU(uiBlkIdx+rpcTempCU->getZorderIdxInCU()) == rpcTempCU->getSlice()->getSliceSegmentCurStartCUAddr() ) && ( rpcTempCU->getCbf( uiBlkIdx, TEXT_LUMA ) || rpcTempCU->getCbf( uiBlkIdx, TEXT_CHROMA_U ) || rpcTempCU->getCbf( uiBlkIdx, TEXT_CHROMA_V ) ) ) { hasResidual = true; break; } } UInt uiTargetPartIdx; if ( pcPic->getCU( rpcTempCU->getAddr() )->getSliceSegmentStartCU(rpcTempCU->getZorderIdxInCU()) != pcSlice->getSliceSegmentCurStartCUAddr() ) { uiTargetPartIdx = pcSlice->getSliceSegmentCurStartCUAddr() % pcPic->getNumPartInCU() - rpcTempCU->getZorderIdxInCU(); } else { uiTargetPartIdx = 0; } if ( hasResidual ) { #if !RDO_WITHOUT_DQP_BITS m_pcEntropyCoder->resetBits(); m_pcEntropyCoder->encodeQP( rpcTempCU, uiTargetPartIdx, false ); rpcTempCU->getTotalBits() += m_pcEntropyCoder->getNumberOfWrittenBits(); // dQP bits rpcTempCU->getTotalBins() += ((TEncBinCABAC *)((TEncSbac*)m_pcEntropyCoder->m_pcEntropyCoderIf)->getEncBinIf())->getBinsCoded(); rpcTempCU->getTotalCost() = m_pcRdCost->calcRdCost( rpcTempCU->getTotalBits(), rpcTempCU->getTotalDistortion() ); #endif Bool foundNonZeroCbf = false; rpcTempCU->setQPSubCUs( rpcTempCU->getRefQP( uiTargetPartIdx ), rpcTempCU, 0, uiDepth, foundNonZeroCbf ); assert( foundNonZeroCbf ); } else { rpcTempCU->setQPSubParts( rpcTempCU->getRefQP( uiTargetPartIdx ), 0, uiDepth ); // set QP to default QP } } m_pppcRDSbacCoder[uhNextDepth][CI_NEXT_BEST]->store(m_pppcRDSbacCoder[uiDepth][CI_TEMP_BEST]); Bool isEndOfSlice = rpcBestCU->getSlice()->getSliceMode()==FIXED_NUMBER_OF_BYTES && (rpcBestCU->getTotalBits()>rpcBestCU->getSlice()->getSliceArgument()<<3); Bool isEndOfSliceSegment = rpcBestCU->getSlice()->getSliceSegmentMode()==FIXED_NUMBER_OF_BYTES && (rpcBestCU->getTotalBits()>rpcBestCU->getSlice()->getSliceSegmentArgument()<<3); if(isEndOfSlice||isEndOfSliceSegment) { rpcBestCU->getTotalCost()=rpcTempCU->getTotalCost()+1; } xCheckBestMode( rpcBestCU, rpcTempCU, uiDepth); // RD compare current larger prediction } // with sub partitioned prediction. }