HEVC帧内预测参考相邻帧代码解析

12 篇文章 4 订阅
3 篇文章 4 订阅

作者:66

(转载请注明出处)

参考链接:http://blog.csdn.net/hevc_cjl/article/details/8200793

亮度分量的帧内预测涉及到的模块比较多,CU->PU的划分,参考像素的填充,哈达玛变换计算STAD(代替率失真),参考预测模式的选择,最佳模式的选择等。

先了解相关的知识:1.CU->PU的划分,在帧内预测中,2Nx2NCU有两种PU划分方式:2Nx2NNxN。帧间预测模式有八种:分别为:2Nx2NNxN2NxNNx2NnRx2N(左右3:1),nLx2N(左右1:3),2NxnU(上下1:3),2NxnD(上下3:1)。

2. 参考像素的填充:前面说过,HEVC较后h.264增加了左下边界,配合增加的角度模式。

3. 哈达玛变换,WHTWalsh-Hadamard Transform),广义傅里叶变换的一种,变换矩阵Hm是个大小为2的次幂的矩阵,如下:

 


 

图一、hadamard矩阵

这种矩阵的特性主要有,元素+1-1,计算方便;正交对称;奇行(列)偶对称,偶行(列)奇对称;变换前后能量守恒;因残差信号经WHT后的求绝对值和与DCT之后系数绝对值之和接近,可以作为视频编码中的快速模式选择。

4. 参考预测模式的选择:

 

图二、参考PU与当前PU的位置关系

HEVC中共35种亮度预测模式,包括planar0)、DC1)和33种角度模式(2~34)。

如上图,帧内预测参考其他PU,并建立候选列表candModeList[3],三个备选项。

选择的规则如下:

①modeA预测模式与modeB相同

1. 同为planar或DC

candModeList[3] = {planar, DC, 角度26(垂直)}

2. 同为角度模式

candModeList[3] = {modeA, modeA-1, modeA+1}

注:mode2相邻为3和32,mode34相邻为33和3。

②modeA与modeB不同

candModeList = {modeA, modeB, choice}

关于choice的选择:

1. modeA与modeB都不为planar

choice = planar

2. modeA与modeB都不为DC

choice = DC

3. 当前两个都不符合时,

choice = 26

candModelist建立后,对当前PU信息进行编码,经过率失真遍历计算后,

最优预测模式modeC在列表中,仅编码模式在列表中的位置

②若不在,依次进行如下步骤:

1. candModeList中的候选模式从小到大重排

2. 比较最优预测模式modeC与列表中每个的标号大小,若modeC >= candModeList[i],则令modeC = modeC - 1,遍历结束后,对modeC最终值进行编码。

整体上看,思路为:

当前CU划分为PU ->遍历每个PU ->对每个PU计算35个模式中的最优模式,与预测对比,最后确定最佳预测模式。

详细情况见代码,目前对代码还存有疑问,之后搞清楚了来修改:

//亮度分量帧内预测

Void

TEncSearch::estIntraPredQT( TComDataCU* pcCU,

                           TComYuv*    pcOrgYuv,

                           TComYuv*    pcPredYuv,

                           TComYuv*    pcResiYuv,

                           TComYuv*    pcRecoYuv,

                           UInt&       ruiDistC,

                           Bool        bLumaOnly )

{

  UInt    uiDepth        = pcCU->getDepth(0);//当前CU的深度

 

  //uiNumPU,划分后pu的个数,PU的划分模式,帧内有2种:2NX2N,NxN;帧间有8种:4种对称模式:2Nx2N,2NxN,Nx2N,NxN,四种非对称模式,2NxnU(上下1:3),2NxnD(上下3:1),nLx2N(左右1:3),nRx2N(左右3:1)。帧间还有一种skip模式,即不需要编码残差信息时。

  UInt    uiNumPU        = pcCU->getNumPartitions();//当前cu划分为pu的数目

  UInt    uiInitTrDepth  = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1;//计算变换深度,实际为uiDepth

  UInt    uiWidth        = pcCU->getWidth (0) >> uiInitTrDepth;//当前cu的宽度

  UInt    uiHeight       = pcCU->getHeight(0) >> uiInitTrDepth;//当前cu的长度

  UInt    uiQNumParts    = pcCU->getTotalNumPart() >> 2;//当前cu包含的最小分区4x4的数目。

  UInt    uiWidthBit     = pcCU->getIntraSizeIdx(0);

  UInt    uiOverallDistY = 0;

  UInt    uiOverallDistC = 0;

  UInt    CandNum;

  Double  CandCostList[ FAST_UDI_MAX_RDMODE_NUM ];

  

  //===== set QP and clear Cbf =====

  if ( pcCU->getSlice()->getPPS()->getUseDQP() == true)

  {

    pcCU->setQPSubParts( pcCU->getQP(0), 0, uiDepth );

  }

  else

  {

    pcCU->setQPSubParts( pcCU->getSlice()->getSliceQp(), 0, uiDepth );

  }

  

  //===== loop over partitions =====遍历

  UInt uiPartOffset = 0;//记录当前pu的Zorder坐标

  for( UInt uiPU = 0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts )

  {

    //===== init pattern for luma prediction =====

    Bool bAboveAvail = false;//

    Bool bLeftAvail  = false;

    pcCU->getPattern()->initPattern   ( pcCU, uiInitTrDepth, uiPartOffset );

    //获取当前PU邻域的可用性,对参考像素进行滤波,代码里的宽长都为当前cu的宽长,但是pu与tu的划分是以depth为基础的隐式划分,名字上仍以Cu表示,实际此Cu已经代表了PU或TU V

    pcCU->getPattern()->initAdiPattern( pcCU, uiPartOffset, uiInitTrDepth, m_piYuvExt, m_iYuvExtStride, m_iYuvExtHeight, bAboveAvail, bLeftAvail );

    

    //===== determine set of modes to be tested (using prediction signal only) =====

    Int numModesAvailable     = 35; //total number of Intra modes

    Pel* piOrg         = pcOrgYuv ->getLumaAddr( uiPU, uiWidth );

    Pel* piPred        = pcPredYuv->getLumaAddr( uiPU, uiWidth );

    UInt uiStride      = pcPredYuv->getStride();

    UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];

   Int numModesForFullRD = g_aucIntraModeNumFast[ uiWidthBit ];//MPM的数目,像是候选预测模式数目

    //  g_aucIntraModeNumFast[]={3,8,8,3,3,3,3};2x2,4x4,8x8,16x16,32x32,64x64,128x128

    Bool doFastSearch = (numModesForFullRD != numModesAvailable);//这里doFastSearch恒为真

    if (doFastSearch)//此时是肯定会进入

    {

      assert(numModesForFullRD < numModesAvailable);//确定numModesForFullRD < numModesAvailable

       

      for( Int i=0; i < numModesForFullRD; i++ )

      {

        CandCostList[ i ] = MAX_DOUBLE;//初始化率失真表,全部为最大值,方便后面比较。

      }

      CandNum = 0;

      

      for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ )//遍历35中预测模式

      {

        UInt uiMode = modeIdx;

        //调用亮度帧内预测函数 V

        predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, bAboveAvail, bLeftAvail );

        

        // use hadamard transform here哈达玛矩阵计算率失真

        UInt uiSad = m_pcRdCost->calcHAD(g_bitDepthY, piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight );//计算SATD(残差经HAD后的绝对值总和)

        

        UInt   iModeBits = xModeBitsIntra( pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth );//计算编码当面所需的bits

        Double cost      = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda();//率失真代价

        //iModeBits编码当前模式需要的bits,

 

        CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );//帧内预测模式候选列表

      }

    

#if FAST_UDI_USE_MPM

      Int uiPreds[3] = {-1, -1, -1};

      Int iMode = -1;//分两种情况,如果前两个相同iMode=1,否则iMode=2

      Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode );//获取亮度预测的前三个MPMs

      if( iMode >= 0 )

      {

        numCand = iMode;

      }

      

      for( Int j=0; j < numCand; j++)

      {

        Bool mostProbableModeIncluded = false;

        Int mostProbableMode = uiPreds[j];//取出预测的MPM

        

        for( Int i=0; i < numModesForFullRD; i++)

        {

          mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]);//检查MPMs,是否被uiRdModeList包含

        }

        if (!mostProbableModeIncluded)//若没被包含,则将该MPM包含进uiRdModeList里

        {

          uiRdModeList[numModesForFullRD++] = mostProbableMode;//计算率失真的备选模式表

        }

      }

#endif // FAST_UDI_USE_MPM

    }

    else

    {

      for( Int i=0; i < numModesForFullRD; i++)

      {

        uiRdModeList[i] = i;

      }

    }

    

    //check modes 确定帧内预测模式的最佳值主要有以下几个步骤:

    //1. 对numModesForFullRD中预测模式进行遍历,算出RDcosts,但至多对depth=1的CU进行遍历,提高了速度。

    //2.得到最优,有可能包括次优的两个。

    //3.最佳模式下的分割模式遍历,以得最优结果。

    //===== check modes (using r-d costs) =====

#if HHI_RQT_INTRA_SPEEDUP_MOD

    UInt   uiSecondBestMode  = MAX_UINT;

    Double dSecondBestPUCost = MAX_DOUBLE;

#endif

    

    UInt    uiBestPUMode  = 0;//最佳预测模式

    UInt    uiBestPUDistY = 0;//最佳预测模式对应的亮度失真

    UInt    uiBestPUDistC = 0;//最佳预测模式色度失真

    Double  dBestPUCost   = MAX_DOUBLE;//RDcosts

    for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ )

    {

      // set luma prediction mode

      UInt uiOrgMode = uiRdModeList[uiMode];

      

      pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );

      

      // set context models

      m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );

      

      // determine residual for partition

      UInt   uiPUDistY = 0;//当前预测模式的亮度失真

      UInt   uiPUDistC = 0;//当前色度失真

      Double dPUCost   = 0.0;//当前预测RDcost

#if HHI_RQT_INTRA_SPEEDUP

      xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, true, dPUCost );

#else

      xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, dPUCost );

#endif

      

      // check r-d cost

      if( dPUCost < dBestPUCost )//更新最佳预测模式相关参数

      {

#if HHI_RQT_INTRA_SPEEDUP_MOD//次优模式

        uiSecondBestMode  = uiBestPUMode;

        dSecondBestPUCost = dBestPUCost;

#endif

        uiBestPUMode  = uiOrgMode;

        uiBestPUDistY = uiPUDistY;

        uiBestPUDistC = uiPUDistC;

        dBestPUCost   = dPUCost;

        

        xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv );

        

        UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );

        ::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

      }

#if HHI_RQT_INTRA_SPEEDUP_MOD

      else if( dPUCost < dSecondBestPUCost )

      {

        uiSecondBestMode  = uiOrgMode;

        dSecondBestPUCost = dPUCost;

      }

#endif

    } // Mode loop

    

#if HHI_RQT_INTRA_SPEEDUP

#if HHI_RQT_INTRA_SPEEDUP_MOD

    for( UInt ui =0; ui < 2; ++ui )

#endif

    {

#if HHI_RQT_INTRA_SPEEDUP_MOD

      UInt uiOrgMode   = ui ? uiSecondBestMode  : uiBestPUMode;

      if( uiOrgMode == MAX_UINT )

      {

        break;

      }

#else

      UInt uiOrgMode = uiBestPUMode;//设置为最佳模式

#endif

      

      pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );

      

      // set context models

      m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );

      

      // determine residual for partition

      UInt   uiPUDistY = 0;

      UInt   uiPUDistC = 0;

      Double dPUCost   = 0.0;

      xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, false, dPUCost );

      //此时倒数第二个参数为false

      // check r-d cost

      if( dPUCost < dBestPUCost )

      {

        uiBestPUMode  = uiOrgMode;

        uiBestPUDistY = uiPUDistY;

        uiBestPUDistC = uiPUDistC;

        dBestPUCost   = dPUCost;

        

        xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv );

        

        UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );

        ::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

        ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) );

      }

    } // Mode loop

#endif

    

    //--- update overall distortion ---

    uiOverallDistY += uiBestPUDistY;

    uiOverallDistC += uiBestPUDistC;

    

    //--- update transform index and cbf ---

    UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );

    ::memcpy( pcCU->getTransformIdx()       + uiPartOffset, m_puhQTTempTrIdx,  uiQPartNum * sizeof( UChar ) );

    ::memcpy( pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, m_puhQTTempCbf[0], uiQPartNum * sizeof( UChar ) );

    ::memcpy( pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, m_puhQTTempCbf[1], uiQPartNum * sizeof( UChar ) );

    ::memcpy( pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, m_puhQTTempCbf[2], uiQPartNum * sizeof( UChar ) );

    ::memcpy( pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, m_puhQTTempTransformSkipFlag[0], uiQPartNum * sizeof( UChar ) );

    ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, m_puhQTTempTransformSkipFlag[1], uiQPartNum * sizeof( UChar ) );

    ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, m_puhQTTempTransformSkipFlag[2], uiQPartNum * sizeof( UChar ) );

    //--- set reconstruction for next intra prediction blocks ---

    if( uiPU != uiNumPU - 1 )

    {

      Bool bSkipChroma  = false;

      Bool bChromaSame  = false;

      UInt uiLog2TrSize = g_aucConvertToBit[ pcCU->getSlice()->getSPS()->getMaxCUWidth() >> ( pcCU->getDepth(0) + uiInitTrDepth ) ] + 2;

      if( !bLumaOnly && uiLog2TrSize == 2 )

      {

        assert( uiInitTrDepth  > 0 );

        bSkipChroma  = ( uiPU != 0 );

        bChromaSame  = true;

      }

      

      UInt    uiCompWidth   = pcCU->getWidth ( 0 ) >> uiInitTrDepth;

      UInt    uiCompHeight  = pcCU->getHeight( 0 ) >> uiInitTrDepth;

      UInt    uiZOrder      = pcCU->getZorderIdxInCU() + uiPartOffset;

      Pel*    piDes         = pcCU->getPic()->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), uiZOrder );

      UInt    uiDesStride   = pcCU->getPic()->getPicYuvRec()->getStride();

      Pel*    piSrc         = pcRecoYuv->getLumaAddr( uiPartOffset );

      UInt    uiSrcStride   = pcRecoYuv->getStride();

      for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )

      {

        for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )

        {

          piDes[ uiX ] = piSrc[ uiX ];

        }

      }

      if( !bLumaOnly && !bSkipChroma )

      {

        if( !bChromaSame )

        {

          uiCompWidth   >>= 1;

          uiCompHeight  >>= 1;

        }

        piDes         = pcCU->getPic()->getPicYuvRec()->getCbAddr( pcCU->getAddr(), uiZOrder );

        uiDesStride   = pcCU->getPic()->getPicYuvRec()->getCStride();

        piSrc         = pcRecoYuv->getCbAddr( uiPartOffset );

        uiSrcStride   = pcRecoYuv->getCStride();

        for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )

        {

          for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )

          {

            piDes[ uiX ] = piSrc[ uiX ];

          }

        }

        piDes         = pcCU->getPic()->getPicYuvRec()->getCrAddr( pcCU->getAddr(), uiZOrder );

        piSrc         = pcRecoYuv->getCrAddr( uiPartOffset );

        for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )

        {

          for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )

          {

            piDes[ uiX ] = piSrc[ uiX ];

          }

        }

      }

    }

    

    //=== update PU data ====

    pcCU->setLumaIntraDirSubParts     ( uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth );

    pcCU->copyToPic                   ( uiDepth, uiPU, uiInitTrDepth );

  } // PU loop

  

  

  if( uiNumPU > 1 )

  { // set Cbf for all blocks

    UInt uiCombCbfY = 0;

    UInt uiCombCbfU = 0;

    UInt uiCombCbfV = 0;

    UInt uiPartIdx  = 0;

    for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts )

    {

      uiCombCbfY |= pcCU->getCbf( uiPartIdx, TEXT_LUMA,     1 );

      uiCombCbfU |= pcCU->getCbf( uiPartIdx, TEXT_CHROMA_U, 1 );

      uiCombCbfV |= pcCU->getCbf( uiPartIdx, TEXT_CHROMA_V, 1 );

    }

    for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ )

    {

      pcCU->getCbf( TEXT_LUMA     )[ uiOffs ] |= uiCombCbfY;

      pcCU->getCbf( TEXT_CHROMA_U )[ uiOffs ] |= uiCombCbfU;

      pcCU->getCbf( TEXT_CHROMA_V )[ uiOffs ] |= uiCombCbfV;

    }

  }

  

  //===== reset context models =====

  m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);

  

  //===== set distortion (rate and r-d costs are determined later) =====

  ruiDistC                   = uiOverallDistC;

  pcCU->getTotalDistortion() = uiOverallDistY + uiOverallDistC;

}

 

 

 

Void

TEncSearch::estIntraPredChromaQT( TComDataCU* pcCU,

                                 TComYuv*    pcOrgYuv,

                                 TComYuv*    pcPredYuv,

                                 TComYuv*    pcResiYuv,

                                 TComYuv*    pcRecoYuv,

                                 UInt        uiPreCalcDistC )

{

  UInt    uiDepth     = pcCU->getDepth(0);

  UInt    uiBestMode  = 0;

  UInt    uiBestDist  = 0;

  Double  dBestCost   = MAX_DOUBLE;

  

  //----- init mode list -----

  UInt  uiMinMode = 0;

  UInt  uiModeList[ NUM_CHROMA_MODE ];

  pcCU->getAllowedChromaDir( 0, uiModeList );

  UInt  uiMaxMode = NUM_CHROMA_MODE;

 

  //----- check chroma modes -----

  for( UInt uiMode = uiMinMode; uiMode < uiMaxMode; uiMode++ )

  {

    //----- restore context models -----

    m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );

    

    //----- chroma coding -----

    UInt    uiDist = 0;

    pcCU->setChromIntraDirSubParts  ( uiModeList[uiMode], 0, uiDepth );

    xRecurIntraChromaCodingQT       ( pcCU,   0, 0, pcOrgYuv, pcPredYuv, pcResiYuv, uiDist );

    if( pcCU->getSlice()->getPPS()->getUseTransformSkip() )

    {

      m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );

    }

    UInt    uiBits = xGetIntraBitsQT( pcCU,   0, 0, false, true, false );

    Double  dCost  = m_pcRdCost->calcRdCost( uiBits, uiDist );

    

    //----- compare -----

    if( dCost < dBestCost )

    {

      dBestCost   = dCost;

      uiBestDist  = uiDist;

      uiBestMode  = uiModeList[uiMode];

      UInt  uiQPN = pcCU->getPic()->getNumPartInCU() >> ( uiDepth << 1 );

      xSetIntraResultChromaQT( pcCU, 0, 0, pcRecoYuv );

      ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ), uiQPN * sizeof( UChar ) );

      ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ), uiQPN * sizeof( UChar ) );

      ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip( TEXT_CHROMA_U ), uiQPN * sizeof( UChar ) );

      ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip( TEXT_CHROMA_V ), uiQPN * sizeof( UChar ) );

    }

  }

  

  //----- set data -----

  UInt  uiQPN = pcCU->getPic()->getNumPartInCU() >> ( uiDepth << 1 );

  ::memcpy( pcCU->getCbf( TEXT_CHROMA_U ), m_puhQTTempCbf[1], uiQPN * sizeof( UChar ) );

  ::memcpy( pcCU->getCbf( TEXT_CHROMA_V ), m_puhQTTempCbf[2], uiQPN * sizeof( UChar ) );

  ::memcpy( pcCU->getTransformSkip( TEXT_CHROMA_U ), m_puhQTTempTransformSkipFlag[1], uiQPN * sizeof( UChar ) );

  ::memcpy( pcCU->getTransformSkip( TEXT_CHROMA_V ), m_puhQTTempTransformSkipFlag[2], uiQPN * sizeof( UChar ) );

  pcCU->setChromIntraDirSubParts( uiBestMode, 0, uiDepth );

  pcCU->getTotalDistortion      () += uiBestDist - uiPreCalcDistC;

  

  //----- restore context models -----

  m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );

}


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值