HEVC学习之琐事(三):TEncCu::compressCU

来源:互联网 发布:淘宝生e经被替换了 编辑:程序博客网 时间:2024/05/18 00:11

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_SPEEDUPVoid TEncCu::xCompressCU( TComDataCU*& rpcBestCU, TComDataCU*& rpcTempCU, UInt uiDepth, PartSize eParentPartSize )#elseVoid 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.  }

5、xCompressCU's Structure







0 0
原创粉丝点击