HEVC学习(六) —— 帧内预测系列之四

HEVC学习(六) —— 帧内预测系列之四

本文主要把实现亮度分量帧内预测的主函数的大体框架通过代码注释的方式介绍一下。

 

  1. Void   
  2. TEncSearch::estIntraPredQT( TComDataCU* pcCU,   
  3.                            TComYuv*    pcOrgYuv,   
  4.                            TComYuv*    pcPredYuv,   
  5.                            TComYuv*    pcResiYuv,   
  6.                            TComYuv*    pcRecoYuv,  
  7.                            UInt&       ruiDistC,  
  8.                            Bool        bLumaOnly )  
  9. {  
  10.   UInt    uiDepth        = pcCU->getDepth(0); //!< 当前CU的深度  
  11.   UInt    uiNumPU        = pcCU->getNumPartInter(); //!< 当前CU的分割模式,(SIZE_2Nx2N:1, SIZE_2NxN:2, SIZE_Nx2N:2, SIZE_NxN:4 ... )  
  12.   UInt    uiInitTrDepth  = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1; //!< 用于计算变换的深度,实际深度为该值+uiDepth  
  13.   UInt    uiWidth        = pcCU->getWidth (0) >> uiInitTrDepth; //!< 当前PU的宽度,如果又分成4个子块,则宽度除以2  
  14.   UInt    uiHeight       = pcCU->getHeight(0) >> uiInitTrDepth; //!< 当前PU的高度,如果又分成4个子块,则高度除以2  
  15.   UInt    uiQNumParts    = pcCU->getTotalNumPart() >> 2; // 最小的分区是4x4大小的块,这里计算出以该4x4块为单位的分割数,这么做便于计算当前CU的Zorder坐标  
  16.   UInt    uiWidthBit     = pcCU->getIntraSizeIdx(0);  
  17.   UInt    uiOverallDistY = 0;  
  18.   UInt    uiOverallDistC = 0;  
  19.   UInt    CandNum;  
  20.   Double  CandCostList[ FAST_UDI_MAX_RDMODE_NUM ];  
  21.     
  22.   //===== set QP and clear Cbf =====   
  23.   if ( pcCU->getSlice()->getPPS()->getUseDQP() == true)  
  24.   {  
  25.     pcCU->setQPSubParts( pcCU->getQP(0), 0, uiDepth );  
  26.   }  
  27.   else  
  28.   {  
  29.     pcCU->setQPSubParts( pcCU->getSlice()->getSliceQp(), 0, uiDepth );  
  30.   }  
  31.     
  32.   //===== loop over partitions =====   
  33.   UInt uiPartOffset = 0; //!< 用于记录当前PU的Zorder坐标  
  34.   for( UInt uiPU = 0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts ) //!< 对当前CU中的每个PU进行遍历  
  35.   {  
  36.     //===== init pattern for luma prediction =====  
  37.     Bool bAboveAvail = false;  
  38.     Bool bLeftAvail  = false;  
  39.     pcCU->getPattern()->initPattern   ( pcCU, uiInitTrDepth, uiPartOffset ); // set parameters from CU data for accessing neighbouring pixels  
  40.  // set luma parameters from CU data for accessing ADI data //!< 主要获取当前PU的邻域可用性,对参考样点进行设置及滤波  
  41.     pcCU->getPattern()->initAdiPattern( pcCU, uiPartOffset, uiInitTrDepth, m_piYuvExt, m_iYuvExtStride, m_iYuvExtHeight, bAboveAvail, bLeftAvail );  
  42.       
  43.     //===== determine set of modes to be tested (using prediction signal only) =====  
  44.     Int numModesAvailable     = 35; //total number of Intra modes  
  45.     Pel* piOrg         = pcOrgYuv ->getLumaAddr( uiPU, uiWidth );  
  46.     Pel* piPred        = pcPredYuv->getLumaAddr( uiPU, uiWidth );  
  47.     UInt uiStride      = pcPredYuv->getStride();  
  48.     UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];  
  49.     Int numModesForFullRD = g_aucIntraModeNumFast[ uiWidthBit ]; //!< MPM数目  
  50.     //!< g_aucIntraModeNumFast[] = {3, 8, 8, 3, 3, 3, 3}; 2x2, 4x4, 8x8, 16x16, 32x32, 64x64, 128x128  
  51.     Bool doFastSearch = (numModesForFullRD != numModesAvailable); //!< 此处doFastSearch恒为真  
  52.     if (doFastSearch)  
  53.     {  
  54.       assert(numModesForFullRD < numModesAvailable);  
  55.   
  56.       for( Int i=0; i < numModesForFullRD; i++ )   
  57.       {  
  58.         CandCostList[ i ] = MAX_DOUBLE;  
  59.       }  
  60.       CandNum = 0;  
  61.         
  62.       for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) //!< 遍历35种帧内预测模式  
  63.       {  
  64.         UInt uiMode = modeIdx;  
  65.   //! 调用亮度帧内预测函数   
  66.         predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, pcCU, bAboveAvail, bLeftAvail );  
  67.           
  68.         // use hadamard transform here   
  69.         UInt uiSad = m_pcRdCost->calcHAD( piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight );  
  70.           
  71.         UInt   iModeBits = xModeBitsIntra( pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth );  
  72.         Double cost      = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda();  
  73.           
  74.         CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );  
  75.       }  
  76.       
  77. #if FAST_UDI_USE_MPM // UDI---Unified Directional Intra  
  78.       Int uiPreds[3] = {-1, -1, -1};  
  79.       Int iMode = -1;  //!< 如果三个MPMs的前两个相同,则iMode=1,否则iMode=2  
  80.       Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode ); //!< 获取亮度帧内预测模式的三个MPMs  
  81.       if( iMode >= 0 ) //!< iMode = 1 or 2,因此,numCand会被重新赋值为iMode  
  82.       {  
  83.         numCand = iMode;  
  84.       }  
  85.         
  86.       for( Int j=0; j < numCand; j++)  
  87.   
  88.       {  
  89.         Bool mostProbableModeIncluded = false;  
  90.         Int mostProbableMode = uiPreds[j]; //!< 取出MPM  
  91.           
  92.         for( Int i=0; i < numModesForFullRD; i++)  
  93.         {  
  94.           mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); //!< 检查MPMs是否被uiRdModeList所包含  
  95.         }  
  96.         if (!mostProbableModeIncluded)  //!< 如果没被包含,则将该MPM包含到uiRdModeList里  
  97.         {  
  98.           uiRdModeList[numModesForFullRD++] = mostProbableMode;  
  99.         }  
  100.       }  
  101. #endif // FAST_UDI_USE_MPM  
  102.     } //!< if (doFastSearch)   
  103.     else  
  104.     {  
  105.       for( Int i=0; i < numModesForFullRD; i++)  
  106.       {  
  107.         uiRdModeList[i] = i;  
  108.       }  
  109.     }  
  110.       
  111.     //===== check modes (using r-d costs) =====  
  112.  //! 帧内预测模式最佳值的确定主要有以下几个步骤:1. 对numModesForFullRD种预测模式进行遍历,即对每种模式计算出  
  113.  //! 对应的RD costs,但该步骤中,并不会把一个CU的所有分割都算一遍,而仅仅对于至多深度为1的分割进行遍历,这么做  
  114.  //! 大大减少了运算量,提高速度;2. 在第1个步骤中,会粗略得到最佳预测模式(在HM9.0中会得到包括次优解在内的两个  
  115.  //! 预测模式),存储下来,以供第3步使用;3. 在第2步的基础上,对最佳(及次优)预测模式的所有分割模式遍历一遍,  
  116.  //! 得到最终的最佳结果   
  117. #if HHI_RQT_INTRA_SPEEDUP_MOD  
  118.     UInt   uiSecondBestMode  = MAX_UINT;  
  119.     Double dSecondBestPUCost = MAX_DOUBLE;  
  120. #endif   
  121.       
  122.     UInt    uiBestPUMode  = 0; //!< 存放最佳预测模式  
  123.     UInt    uiBestPUDistY = 0; //!< 存放最佳预测模式对应的亮度失真值  
  124.     UInt    uiBestPUDistC = 0; //!< 存放最佳预测模式对应的色度失真值  
  125.     Double  dBestPUCost   = MAX_DOUBLE;  //!< 存放最佳预测模式对应的总代价  
  126.     for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) //!< 遍历存储在uiRdModeList里的模式  
  127.     {  
  128.       // set luma prediction mode   
  129.       UInt uiOrgMode = uiRdModeList[uiMode];  
  130.         
  131.       pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );  
  132.         
  133.       // set context models   
  134.       if( m_bUseSBACRD )  
  135.       {  
  136.         m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );  
  137.       }  
  138.         
  139.       // determine residual for partition  
  140.       UInt   uiPUDistY = 0;  //!< 存放当前预测模式对应的亮度失真值  
  141.       UInt   uiPUDistC = 0;  //!< 存放当前预测模式对应的色度失真值  
  142.       Double dPUCost   = 0.0; //!< 存放当前预测模式对应的代价  
  143. #if HHI_RQT_INTRA_SPEEDUP //! 注意这个函数倒数第二个参数,此时为true  
  144.       xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, true, dPUCost );  
  145. #else   
  146.       xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, dPUCost );  
  147. #endif   
  148.         
  149.       // check r-d cost   
  150.       if( dPUCost < dBestPUCost ) //!< 更新最佳预测模式相关参数  
  151.       {  
  152. #if HHI_RQT_INTRA_SPEEDUP_MOD   
  153.         uiSecondBestMode  = uiBestPUMode;  
  154.         dSecondBestPUCost = dBestPUCost;  
  155. #endif   
  156.         uiBestPUMode  = uiOrgMode;  
  157.         uiBestPUDistY = uiPUDistY;  
  158.         uiBestPUDistC = uiPUDistC;  
  159.         dBestPUCost   = dPUCost;  
  160.           
  161.         xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv );  
  162.           
  163.         UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );  
  164.         ::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  165.         ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  166.         ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  167.         ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  168.         ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  169.         ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  170.         ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  171.       }  
  172. #if HHI_RQT_INTRA_SPEEDUP_MOD   
  173.       else if( dPUCost < dSecondBestPUCost )  
  174.       {  
  175.         uiSecondBestMode  = uiOrgMode;  
  176.         dSecondBestPUCost = dPUCost;  
  177.       }  
  178. #endif   
  179.     } // Mode loop   
  180.       
  181. #if HHI_RQT_INTRA_SPEEDUP  
  182. #if HHI_RQT_INTRA_SPEEDUP_MOD   
  183.     for( UInt ui =0; ui < 2; ++ui )  
  184. #endif   
  185.     {  
  186. #if HHI_RQT_INTRA_SPEEDUP_MOD   
  187.       UInt uiOrgMode   = ui ? uiSecondBestMode  : uiBestPUMode;  
  188.       if( uiOrgMode == MAX_UINT )  
  189.       {  
  190.         break;  
  191.       }  
  192. #else   
  193.       UInt uiOrgMode = uiBestPUMode; //!< 设置模式为最佳预测模式  
  194. #endif   
  195.         
  196.       pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );  
  197.         
  198.       // set context models   
  199.       if( m_bUseSBACRD )  
  200.       {  
  201.         m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );  
  202.       }  
  203.         
  204.       // determine residual for partition   
  205.       UInt   uiPUDistY = 0;  
  206.       UInt   uiPUDistC = 0;  
  207.       Double dPUCost   = 0.0;  
  208.    //! 注意该函数倒数第二个参数,此时为false   
  209.       xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, false, dPUCost );  
  210.         
  211.       // check r-d cost   
  212.       if( dPUCost < dBestPUCost )  
  213.       {  
  214.         uiBestPUMode  = uiOrgMode;  
  215.         uiBestPUDistY = uiPUDistY;  
  216.         uiBestPUDistC = uiPUDistC;  
  217.         dBestPUCost   = dPUCost;  
  218.           
  219.         xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv );  
  220.           
  221.         UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );  
  222.         ::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  223.         ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  224.         ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  225.         ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  226.         ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  227.         ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  228.         ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  229.       }  
  230.     } // Mode loop   
  231. #endif   
  232.       
  233.     //--- update overall distortion ---  
  234.     uiOverallDistY += uiBestPUDistY;  
  235.     uiOverallDistC += uiBestPUDistC;  
  236.       
  237.     //--- update transform index and cbf ---  
  238.     UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );  
  239.     ::memcpy( pcCU->getTransformIdx()       + uiPartOffset, m_puhQTTempTrIdx,  uiQPartNum * sizeof( UChar ) );  
  240.     ::memcpy( pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, m_puhQTTempCbf[0], uiQPartNum * sizeof( UChar ) );  
  241.     ::memcpy( pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, m_puhQTTempCbf[1], uiQPartNum * sizeof( UChar ) );  
  242.     ::memcpy( pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, m_puhQTTempCbf[2], uiQPartNum * sizeof( UChar ) );  
  243.     ::memcpy( pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, m_puhQTTempTransformSkipFlag[0], uiQPartNum * sizeof( UChar ) );  
  244.     ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, m_puhQTTempTransformSkipFlag[1], uiQPartNum * sizeof( UChar ) );  
  245.     ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, m_puhQTTempTransformSkipFlag[2], uiQPartNum * sizeof( UChar ) );  
  246.     //--- set reconstruction for next intra prediction blocks ---  
  247.     if( uiPU != uiNumPU - 1 )  
  248.     {  
  249.       Bool bSkipChroma  = false;  
  250.       Bool bChromaSame  = false;  
  251.       UInt uiLog2TrSize = g_aucConvertToBit[ pcCU->getSlice()->getSPS()->getMaxCUWidth() >> ( pcCU->getDepth(0) + uiInitTrDepth ) ] + 2;  
  252.       if( !bLumaOnly && uiLog2TrSize == 2 )  
  253.       {  
  254.         assert( uiInitTrDepth  > 0 );  
  255.         bSkipChroma  = ( uiPU != 0 );  
  256.         bChromaSame  = true;  
  257.       }  
  258.         
  259.       UInt    uiCompWidth   = pcCU->getWidth ( 0 ) >> uiInitTrDepth;  
  260.       UInt    uiCompHeight  = pcCU->getHeight( 0 ) >> uiInitTrDepth;  
  261.       UInt    uiZOrder      = pcCU->getZorderIdxInCU() + uiPartOffset;  
  262.       Pel*    piDes         = pcCU->getPic()->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), uiZOrder );  
  263.       UInt    uiDesStride   = pcCU->getPic()->getPicYuvRec()->getStride();  
  264.       Pel*    piSrc         = pcRecoYuv->getLumaAddr( uiPartOffset );  
  265.       UInt    uiSrcStride   = pcRecoYuv->getStride();  
  266.       for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )  
  267.       {  
  268.         for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )  
  269.         {  
  270.           piDes[ uiX ] = piSrc[ uiX ];  
  271.         }  
  272.       }  
  273.       if( !bLumaOnly && !bSkipChroma )  
  274.       {  
  275.         if( !bChromaSame )  
  276.         {  
  277.           uiCompWidth   >>= 1;  
  278.           uiCompHeight  >>= 1;  
  279.         }  
  280.         piDes         = pcCU->getPic()->getPicYuvRec()->getCbAddr( pcCU->getAddr(), uiZOrder );  
  281.         uiDesStride   = pcCU->getPic()->getPicYuvRec()->getCStride();  
  282.         piSrc         = pcRecoYuv->getCbAddr( uiPartOffset );  
  283.         uiSrcStride   = pcRecoYuv->getCStride();  
  284.         for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )  
  285.         {  
  286.           for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )  
  287.           {  
  288.             piDes[ uiX ] = piSrc[ uiX ];  
  289.           }  
  290.         }  
  291.         piDes         = pcCU->getPic()->getPicYuvRec()->getCrAddr( pcCU->getAddr(), uiZOrder );  
  292.         piSrc         = pcRecoYuv->getCrAddr( uiPartOffset );  
  293.         for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )  
  294.         {  
  295.           for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )  
  296.           {  
  297.             piDes[ uiX ] = piSrc[ uiX ];  
  298.           }  
  299.         }  
  300.       }  
  301.     }  
  302.       
  303.     //=== update PU data ====   
  304.     pcCU->setLumaIntraDirSubParts     ( uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth );  
  305.     pcCU->copyToPic                   ( uiDepth, uiPU, uiInitTrDepth );  
  306.   } // PU loop   
  307.     
  308.     
  309.   if( uiNumPU > 1 )  
  310.   { // set Cbf for all blocks   
  311.     UInt uiCombCbfY = 0;  
  312.     UInt uiCombCbfU = 0;  
  313.     UInt uiCombCbfV = 0;  
  314.     UInt uiPartIdx  = 0;  
  315.     for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts )  
  316.     {  
  317.       uiCombCbfY |= pcCU->getCbf( uiPartIdx, TEXT_LUMA,     1 );  
  318.       uiCombCbfU |= pcCU->getCbf( uiPartIdx, TEXT_CHROMA_U, 1 );  
  319.       uiCombCbfV |= pcCU->getCbf( uiPartIdx, TEXT_CHROMA_V, 1 );  
  320.     }  
  321.     for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ )  
  322.     {  
  323.       pcCU->getCbf( TEXT_LUMA     )[ uiOffs ] |= uiCombCbfY;  
  324.       pcCU->getCbf( TEXT_CHROMA_U )[ uiOffs ] |= uiCombCbfU;  
  325.       pcCU->getCbf( TEXT_CHROMA_V )[ uiOffs ] |= uiCombCbfV;  
  326.     }  
  327.   }  
  328.     
  329.   //===== reset context models =====  
  330.   if(m_bUseSBACRD)  
  331.   {  
  332.     m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);  
  333.   }  
  334.     
  335.   //===== set distortion (rate and r-d costs are determined later) =====  
  336.   ruiDistC                   = uiOverallDistC;  
  337.   pcCU->getTotalDistortion() = uiOverallDistY + uiOverallDistC;  
  338. }  
Void 
TEncSearch::estIntraPredQT( TComDataCU* pcCU, 
                           TComYuv*    pcOrgYuv, 
                           TComYuv*    pcPredYuv, 
                           TComYuv*    pcResiYuv, 
                           TComYuv*    pcRecoYuv,
                           UInt&       ruiDistC,
                           Bool        bLumaOnly )
{
  UInt    uiDepth        = pcCU->getDepth(0); //!< 当前CU的深度
  UInt    uiNumPU        = pcCU->getNumPartInter(); //!< 当前CU的分割模式,(SIZE_2Nx2N:1, SIZE_2NxN:2, SIZE_Nx2N:2, SIZE_NxN:4 ... )
  UInt    uiInitTrDepth  = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1; //!< 用于计算变换的深度,实际深度为该值+uiDepth
  UInt    uiWidth        = pcCU->getWidth (0) >> uiInitTrDepth; //!< 当前PU的宽度,如果又分成4个子块,则宽度除以2
  UInt    uiHeight       = pcCU->getHeight(0) >> uiInitTrDepth; //!< 当前PU的高度,如果又分成4个子块,则高度除以2
  UInt    uiQNumParts    = pcCU->getTotalNumPart() >> 2; // 最小的分区是4x4大小的块,这里计算出以该4x4块为单位的分割数,这么做便于计算当前CU的Zorder坐标
  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 ) //!< 对当前CU中的每个PU进行遍历
  {
    //===== init pattern for luma prediction =====
    Bool bAboveAvail = false;
    Bool bLeftAvail  = false;
    pcCU->getPattern()->initPattern   ( pcCU, uiInitTrDepth, uiPartOffset ); // set parameters from CU data for accessing neighbouring pixels
 // set luma parameters from CU data for accessing ADI data //!< 主要获取当前PU的邻域可用性,对参考样点进行设置及滤波
    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);

      for( Int i=0; i < numModesForFullRD; i++ ) 
      {
        CandCostList[ i ] = MAX_DOUBLE;
      }
      CandNum = 0;
      
      for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) //!< 遍历35种帧内预测模式
      {
        UInt uiMode = modeIdx;
  //! 调用亮度帧内预测函数
        predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, pcCU, bAboveAvail, bLeftAvail );
        
        // use hadamard transform here
        UInt uiSad = m_pcRdCost->calcHAD( piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight );
        
        UInt   iModeBits = xModeBitsIntra( pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth );
        Double cost      = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda();
        
        CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );
      }
    
#if FAST_UDI_USE_MPM // UDI---Unified Directional Intra
      Int uiPreds[3] = {-1, -1, -1};
      Int iMode = -1;  //!< 如果三个MPMs的前两个相同,则iMode=1,否则iMode=2
      Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode ); //!< 获取亮度帧内预测模式的三个MPMs
      if( iMode >= 0 ) //!< iMode = 1 or 2,因此,numCand会被重新赋值为iMode
      {
        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
    } //!< if (doFastSearch)
    else
    {
      for( Int i=0; i < numModesForFullRD; i++)
      {
        uiRdModeList[i] = i;
      }
    }
    
    //===== check modes (using r-d costs) =====
 //! 帧内预测模式最佳值的确定主要有以下几个步骤:1. 对numModesForFullRD种预测模式进行遍历,即对每种模式计算出
 //! 对应的RD costs,但该步骤中,并不会把一个CU的所有分割都算一遍,而仅仅对于至多深度为1的分割进行遍历,这么做
 //! 大大减少了运算量,提高速度;2. 在第1个步骤中,会粗略得到最佳预测模式(在HM9.0中会得到包括次优解在内的两个
 //! 预测模式),存储下来,以供第3步使用;3. 在第2步的基础上,对最佳(及次优)预测模式的所有分割模式遍历一遍,
 //! 得到最终的最佳结果
#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;  //!< 存放最佳预测模式对应的总代价
    for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) //!< 遍历存储在uiRdModeList里的模式
    {
      // set luma prediction mode
      UInt uiOrgMode = uiRdModeList[uiMode];
      
      pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );
      
      // set context models
      if( m_bUseSBACRD )
      {
        m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );
      }
      
      // determine residual for partition
      UInt   uiPUDistY = 0;  //!< 存放当前预测模式对应的亮度失真值
      UInt   uiPUDistC = 0;  //!< 存放当前预测模式对应的色度失真值
      Double dPUCost   = 0.0; //!< 存放当前预测模式对应的代价
#if HHI_RQT_INTRA_SPEEDUP //! 注意这个函数倒数第二个参数,此时为true
      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
      if( m_bUseSBACRD )
      {
        m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );
      }
      
      // determine residual for partition
      UInt   uiPUDistY = 0;
      UInt   uiPUDistC = 0;
      Double dPUCost   = 0.0;
   //! 注意该函数倒数第二个参数,此时为false
      xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, false, dPUCost );
      
      // 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 =====
  if(m_bUseSBACRD)
  {
    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;
}

(转载请注明出处http://blog.csdn.net/hevc_cjl/article/details/8200793#comments

本文主要把实现亮度分量帧内预测的主函数的大体框架通过代码注释的方式介绍一下。

 

  1. Void   
  2. TEncSearch::estIntraPredQT( TComDataCU* pcCU,   
  3.                            TComYuv*    pcOrgYuv,   
  4.                            TComYuv*    pcPredYuv,   
  5.                            TComYuv*    pcResiYuv,   
  6.                            TComYuv*    pcRecoYuv,  
  7.                            UInt&       ruiDistC,  
  8.                            Bool        bLumaOnly )  
  9. {  
  10.   UInt    uiDepth        = pcCU->getDepth(0); //!< 当前CU的深度  
  11.   UInt    uiNumPU        = pcCU->getNumPartInter(); //!< 当前CU的分割模式,(SIZE_2Nx2N:1, SIZE_2NxN:2, SIZE_Nx2N:2, SIZE_NxN:4 ... )  
  12.   UInt    uiInitTrDepth  = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1; //!< 用于计算变换的深度,实际深度为该值+uiDepth  
  13.   UInt    uiWidth        = pcCU->getWidth (0) >> uiInitTrDepth; //!< 当前PU的宽度,如果又分成4个子块,则宽度除以2  
  14.   UInt    uiHeight       = pcCU->getHeight(0) >> uiInitTrDepth; //!< 当前PU的高度,如果又分成4个子块,则高度除以2  
  15.   UInt    uiQNumParts    = pcCU->getTotalNumPart() >> 2; // 最小的分区是4x4大小的块,这里计算出以该4x4块为单位的分割数,这么做便于计算当前CU的Zorder坐标  
  16.   UInt    uiWidthBit     = pcCU->getIntraSizeIdx(0);  
  17.   UInt    uiOverallDistY = 0;  
  18.   UInt    uiOverallDistC = 0;  
  19.   UInt    CandNum;  
  20.   Double  CandCostList[ FAST_UDI_MAX_RDMODE_NUM ];  
  21.     
  22.   //===== set QP and clear Cbf =====   
  23.   if ( pcCU->getSlice()->getPPS()->getUseDQP() == true)  
  24.   {  
  25.     pcCU->setQPSubParts( pcCU->getQP(0), 0, uiDepth );  
  26.   }  
  27.   else  
  28.   {  
  29.     pcCU->setQPSubParts( pcCU->getSlice()->getSliceQp(), 0, uiDepth );  
  30.   }  
  31.     
  32.   //===== loop over partitions =====   
  33.   UInt uiPartOffset = 0; //!< 用于记录当前PU的Zorder坐标  
  34.   for( UInt uiPU = 0; uiPU < uiNumPU; uiPU++, uiPartOffset += uiQNumParts ) //!< 对当前CU中的每个PU进行遍历  
  35.   {  
  36.     //===== init pattern for luma prediction =====  
  37.     Bool bAboveAvail = false;  
  38.     Bool bLeftAvail  = false;  
  39.     pcCU->getPattern()->initPattern   ( pcCU, uiInitTrDepth, uiPartOffset ); // set parameters from CU data for accessing neighbouring pixels  
  40.  // set luma parameters from CU data for accessing ADI data //!< 主要获取当前PU的邻域可用性,对参考样点进行设置及滤波  
  41.     pcCU->getPattern()->initAdiPattern( pcCU, uiPartOffset, uiInitTrDepth, m_piYuvExt, m_iYuvExtStride, m_iYuvExtHeight, bAboveAvail, bLeftAvail );  
  42.       
  43.     //===== determine set of modes to be tested (using prediction signal only) =====  
  44.     Int numModesAvailable     = 35; //total number of Intra modes  
  45.     Pel* piOrg         = pcOrgYuv ->getLumaAddr( uiPU, uiWidth );  
  46.     Pel* piPred        = pcPredYuv->getLumaAddr( uiPU, uiWidth );  
  47.     UInt uiStride      = pcPredYuv->getStride();  
  48.     UInt uiRdModeList[FAST_UDI_MAX_RDMODE_NUM];  
  49.     Int numModesForFullRD = g_aucIntraModeNumFast[ uiWidthBit ]; //!< MPM数目  
  50.     //!< g_aucIntraModeNumFast[] = {3, 8, 8, 3, 3, 3, 3}; 2x2, 4x4, 8x8, 16x16, 32x32, 64x64, 128x128  
  51.     Bool doFastSearch = (numModesForFullRD != numModesAvailable); //!< 此处doFastSearch恒为真  
  52.     if (doFastSearch)  
  53.     {  
  54.       assert(numModesForFullRD < numModesAvailable);  
  55.   
  56.       for( Int i=0; i < numModesForFullRD; i++ )   
  57.       {  
  58.         CandCostList[ i ] = MAX_DOUBLE;  
  59.       }  
  60.       CandNum = 0;  
  61.         
  62.       for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) //!< 遍历35种帧内预测模式  
  63.       {  
  64.         UInt uiMode = modeIdx;  
  65.   //! 调用亮度帧内预测函数   
  66.         predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, pcCU, bAboveAvail, bLeftAvail );  
  67.           
  68.         // use hadamard transform here   
  69.         UInt uiSad = m_pcRdCost->calcHAD( piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight );  
  70.           
  71.         UInt   iModeBits = xModeBitsIntra( pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth );  
  72.         Double cost      = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda();  
  73.           
  74.         CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );  
  75.       }  
  76.       
  77. #if FAST_UDI_USE_MPM // UDI---Unified Directional Intra  
  78.       Int uiPreds[3] = {-1, -1, -1};  
  79.       Int iMode = -1;  //!< 如果三个MPMs的前两个相同,则iMode=1,否则iMode=2  
  80.       Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode ); //!< 获取亮度帧内预测模式的三个MPMs  
  81.       if( iMode >= 0 ) //!< iMode = 1 or 2,因此,numCand会被重新赋值为iMode  
  82.       {  
  83.         numCand = iMode;  
  84.       }  
  85.         
  86.       for( Int j=0; j < numCand; j++)  
  87.   
  88.       {  
  89.         Bool mostProbableModeIncluded = false;  
  90.         Int mostProbableMode = uiPreds[j]; //!< 取出MPM  
  91.           
  92.         for( Int i=0; i < numModesForFullRD; i++)  
  93.         {  
  94.           mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]); //!< 检查MPMs是否被uiRdModeList所包含  
  95.         }  
  96.         if (!mostProbableModeIncluded)  //!< 如果没被包含,则将该MPM包含到uiRdModeList里  
  97.         {  
  98.           uiRdModeList[numModesForFullRD++] = mostProbableMode;  
  99.         }  
  100.       }  
  101. #endif // FAST_UDI_USE_MPM  
  102.     } //!< if (doFastSearch)   
  103.     else  
  104.     {  
  105.       for( Int i=0; i < numModesForFullRD; i++)  
  106.       {  
  107.         uiRdModeList[i] = i;  
  108.       }  
  109.     }  
  110.       
  111.     //===== check modes (using r-d costs) =====  
  112.  //! 帧内预测模式最佳值的确定主要有以下几个步骤:1. 对numModesForFullRD种预测模式进行遍历,即对每种模式计算出  
  113.  //! 对应的RD costs,但该步骤中,并不会把一个CU的所有分割都算一遍,而仅仅对于至多深度为1的分割进行遍历,这么做  
  114.  //! 大大减少了运算量,提高速度;2. 在第1个步骤中,会粗略得到最佳预测模式(在HM9.0中会得到包括次优解在内的两个  
  115.  //! 预测模式),存储下来,以供第3步使用;3. 在第2步的基础上,对最佳(及次优)预测模式的所有分割模式遍历一遍,  
  116.  //! 得到最终的最佳结果   
  117. #if HHI_RQT_INTRA_SPEEDUP_MOD  
  118.     UInt   uiSecondBestMode  = MAX_UINT;  
  119.     Double dSecondBestPUCost = MAX_DOUBLE;  
  120. #endif   
  121.       
  122.     UInt    uiBestPUMode  = 0; //!< 存放最佳预测模式  
  123.     UInt    uiBestPUDistY = 0; //!< 存放最佳预测模式对应的亮度失真值  
  124.     UInt    uiBestPUDistC = 0; //!< 存放最佳预测模式对应的色度失真值  
  125.     Double  dBestPUCost   = MAX_DOUBLE;  //!< 存放最佳预测模式对应的总代价  
  126.     for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) //!< 遍历存储在uiRdModeList里的模式  
  127.     {  
  128.       // set luma prediction mode   
  129.       UInt uiOrgMode = uiRdModeList[uiMode];  
  130.         
  131.       pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );  
  132.         
  133.       // set context models   
  134.       if( m_bUseSBACRD )  
  135.       {  
  136.         m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );  
  137.       }  
  138.         
  139.       // determine residual for partition  
  140.       UInt   uiPUDistY = 0;  //!< 存放当前预测模式对应的亮度失真值  
  141.       UInt   uiPUDistC = 0;  //!< 存放当前预测模式对应的色度失真值  
  142.       Double dPUCost   = 0.0; //!< 存放当前预测模式对应的代价  
  143. #if HHI_RQT_INTRA_SPEEDUP //! 注意这个函数倒数第二个参数,此时为true  
  144.       xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, true, dPUCost );  
  145. #else   
  146.       xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, dPUCost );  
  147. #endif   
  148.         
  149.       // check r-d cost   
  150.       if( dPUCost < dBestPUCost ) //!< 更新最佳预测模式相关参数  
  151.       {  
  152. #if HHI_RQT_INTRA_SPEEDUP_MOD   
  153.         uiSecondBestMode  = uiBestPUMode;  
  154.         dSecondBestPUCost = dBestPUCost;  
  155. #endif   
  156.         uiBestPUMode  = uiOrgMode;  
  157.         uiBestPUDistY = uiPUDistY;  
  158.         uiBestPUDistC = uiPUDistC;  
  159.         dBestPUCost   = dPUCost;  
  160.           
  161.         xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv );  
  162.           
  163.         UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );  
  164.         ::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  165.         ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  166.         ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  167.         ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  168.         ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  169.         ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  170.         ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  171.       }  
  172. #if HHI_RQT_INTRA_SPEEDUP_MOD   
  173.       else if( dPUCost < dSecondBestPUCost )  
  174.       {  
  175.         uiSecondBestMode  = uiOrgMode;  
  176.         dSecondBestPUCost = dPUCost;  
  177.       }  
  178. #endif   
  179.     } // Mode loop   
  180.       
  181. #if HHI_RQT_INTRA_SPEEDUP  
  182. #if HHI_RQT_INTRA_SPEEDUP_MOD   
  183.     for( UInt ui =0; ui < 2; ++ui )  
  184. #endif   
  185.     {  
  186. #if HHI_RQT_INTRA_SPEEDUP_MOD   
  187.       UInt uiOrgMode   = ui ? uiSecondBestMode  : uiBestPUMode;  
  188.       if( uiOrgMode == MAX_UINT )  
  189.       {  
  190.         break;  
  191.       }  
  192. #else   
  193.       UInt uiOrgMode = uiBestPUMode; //!< 设置模式为最佳预测模式  
  194. #endif   
  195.         
  196.       pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );  
  197.         
  198.       // set context models   
  199.       if( m_bUseSBACRD )  
  200.       {  
  201.         m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );  
  202.       }  
  203.         
  204.       // determine residual for partition   
  205.       UInt   uiPUDistY = 0;  
  206.       UInt   uiPUDistC = 0;  
  207.       Double dPUCost   = 0.0;  
  208.    //! 注意该函数倒数第二个参数,此时为false   
  209.       xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, false, dPUCost );  
  210.         
  211.       // check r-d cost   
  212.       if( dPUCost < dBestPUCost )  
  213.       {  
  214.         uiBestPUMode  = uiOrgMode;  
  215.         uiBestPUDistY = uiPUDistY;  
  216.         uiBestPUDistC = uiPUDistC;  
  217.         dBestPUCost   = dPUCost;  
  218.           
  219.         xSetIntraResultQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcRecoYuv );  
  220.           
  221.         UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );  
  222.         ::memcpy( m_puhQTTempTrIdx,  pcCU->getTransformIdx()       + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  223.         ::memcpy( m_puhQTTempCbf[0], pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  224.         ::memcpy( m_puhQTTempCbf[1], pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  225.         ::memcpy( m_puhQTTempCbf[2], pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  226.         ::memcpy( m_puhQTTempTransformSkipFlag[0], pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  227.         ::memcpy( m_puhQTTempTransformSkipFlag[1], pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  228.         ::memcpy( m_puhQTTempTransformSkipFlag[2], pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, uiQPartNum * sizeof( UChar ) );  
  229.       }  
  230.     } // Mode loop   
  231. #endif   
  232.       
  233.     //--- update overall distortion ---  
  234.     uiOverallDistY += uiBestPUDistY;  
  235.     uiOverallDistC += uiBestPUDistC;  
  236.       
  237.     //--- update transform index and cbf ---  
  238.     UInt uiQPartNum = pcCU->getPic()->getNumPartInCU() >> ( ( pcCU->getDepth(0) + uiInitTrDepth ) << 1 );  
  239.     ::memcpy( pcCU->getTransformIdx()       + uiPartOffset, m_puhQTTempTrIdx,  uiQPartNum * sizeof( UChar ) );  
  240.     ::memcpy( pcCU->getCbf( TEXT_LUMA     ) + uiPartOffset, m_puhQTTempCbf[0], uiQPartNum * sizeof( UChar ) );  
  241.     ::memcpy( pcCU->getCbf( TEXT_CHROMA_U ) + uiPartOffset, m_puhQTTempCbf[1], uiQPartNum * sizeof( UChar ) );  
  242.     ::memcpy( pcCU->getCbf( TEXT_CHROMA_V ) + uiPartOffset, m_puhQTTempCbf[2], uiQPartNum * sizeof( UChar ) );  
  243.     ::memcpy( pcCU->getTransformSkip(TEXT_LUMA)     + uiPartOffset, m_puhQTTempTransformSkipFlag[0], uiQPartNum * sizeof( UChar ) );  
  244.     ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_U) + uiPartOffset, m_puhQTTempTransformSkipFlag[1], uiQPartNum * sizeof( UChar ) );  
  245.     ::memcpy( pcCU->getTransformSkip(TEXT_CHROMA_V) + uiPartOffset, m_puhQTTempTransformSkipFlag[2], uiQPartNum * sizeof( UChar ) );  
  246.     //--- set reconstruction for next intra prediction blocks ---  
  247.     if( uiPU != uiNumPU - 1 )  
  248.     {  
  249.       Bool bSkipChroma  = false;  
  250.       Bool bChromaSame  = false;  
  251.       UInt uiLog2TrSize = g_aucConvertToBit[ pcCU->getSlice()->getSPS()->getMaxCUWidth() >> ( pcCU->getDepth(0) + uiInitTrDepth ) ] + 2;  
  252.       if( !bLumaOnly && uiLog2TrSize == 2 )  
  253.       {  
  254.         assert( uiInitTrDepth  > 0 );  
  255.         bSkipChroma  = ( uiPU != 0 );  
  256.         bChromaSame  = true;  
  257.       }  
  258.         
  259.       UInt    uiCompWidth   = pcCU->getWidth ( 0 ) >> uiInitTrDepth;  
  260.       UInt    uiCompHeight  = pcCU->getHeight( 0 ) >> uiInitTrDepth;  
  261.       UInt    uiZOrder      = pcCU->getZorderIdxInCU() + uiPartOffset;  
  262.       Pel*    piDes         = pcCU->getPic()->getPicYuvRec()->getLumaAddr( pcCU->getAddr(), uiZOrder );  
  263.       UInt    uiDesStride   = pcCU->getPic()->getPicYuvRec()->getStride();  
  264.       Pel*    piSrc         = pcRecoYuv->getLumaAddr( uiPartOffset );  
  265.       UInt    uiSrcStride   = pcRecoYuv->getStride();  
  266.       for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )  
  267.       {  
  268.         for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )  
  269.         {  
  270.           piDes[ uiX ] = piSrc[ uiX ];  
  271.         }  
  272.       }  
  273.       if( !bLumaOnly && !bSkipChroma )  
  274.       {  
  275.         if( !bChromaSame )  
  276.         {  
  277.           uiCompWidth   >>= 1;  
  278.           uiCompHeight  >>= 1;  
  279.         }  
  280.         piDes         = pcCU->getPic()->getPicYuvRec()->getCbAddr( pcCU->getAddr(), uiZOrder );  
  281.         uiDesStride   = pcCU->getPic()->getPicYuvRec()->getCStride();  
  282.         piSrc         = pcRecoYuv->getCbAddr( uiPartOffset );  
  283.         uiSrcStride   = pcRecoYuv->getCStride();  
  284.         for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )  
  285.         {  
  286.           for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )  
  287.           {  
  288.             piDes[ uiX ] = piSrc[ uiX ];  
  289.           }  
  290.         }  
  291.         piDes         = pcCU->getPic()->getPicYuvRec()->getCrAddr( pcCU->getAddr(), uiZOrder );  
  292.         piSrc         = pcRecoYuv->getCrAddr( uiPartOffset );  
  293.         for( UInt uiY = 0; uiY < uiCompHeight; uiY++, piSrc += uiSrcStride, piDes += uiDesStride )  
  294.         {  
  295.           for( UInt uiX = 0; uiX < uiCompWidth; uiX++ )  
  296.           {  
  297.             piDes[ uiX ] = piSrc[ uiX ];  
  298.           }  
  299.         }  
  300.       }  
  301.     }  
  302.       
  303.     //=== update PU data ====   
  304.     pcCU->setLumaIntraDirSubParts     ( uiBestPUMode, uiPartOffset, uiDepth + uiInitTrDepth );  
  305.     pcCU->copyToPic                   ( uiDepth, uiPU, uiInitTrDepth );  
  306.   } // PU loop   
  307.     
  308.     
  309.   if( uiNumPU > 1 )  
  310.   { // set Cbf for all blocks   
  311.     UInt uiCombCbfY = 0;  
  312.     UInt uiCombCbfU = 0;  
  313.     UInt uiCombCbfV = 0;  
  314.     UInt uiPartIdx  = 0;  
  315.     for( UInt uiPart = 0; uiPart < 4; uiPart++, uiPartIdx += uiQNumParts )  
  316.     {  
  317.       uiCombCbfY |= pcCU->getCbf( uiPartIdx, TEXT_LUMA,     1 );  
  318.       uiCombCbfU |= pcCU->getCbf( uiPartIdx, TEXT_CHROMA_U, 1 );  
  319.       uiCombCbfV |= pcCU->getCbf( uiPartIdx, TEXT_CHROMA_V, 1 );  
  320.     }  
  321.     for( UInt uiOffs = 0; uiOffs < 4 * uiQNumParts; uiOffs++ )  
  322.     {  
  323.       pcCU->getCbf( TEXT_LUMA     )[ uiOffs ] |= uiCombCbfY;  
  324.       pcCU->getCbf( TEXT_CHROMA_U )[ uiOffs ] |= uiCombCbfU;  
  325.       pcCU->getCbf( TEXT_CHROMA_V )[ uiOffs ] |= uiCombCbfV;  
  326.     }  
  327.   }  
  328.     
  329.   //===== reset context models =====  
  330.   if(m_bUseSBACRD)  
  331.   {  
  332.     m_pcRDGoOnSbacCoder->load(m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST]);  
  333.   }  
  334.     
  335.   //===== set distortion (rate and r-d costs are determined later) =====  
  336.   ruiDistC                   = uiOverallDistC;  
  337.   pcCU->getTotalDistortion() = uiOverallDistY + uiOverallDistC;  
  338. }  
Void 
TEncSearch::estIntraPredQT( TComDataCU* pcCU, 
                           TComYuv*    pcOrgYuv, 
                           TComYuv*    pcPredYuv, 
                           TComYuv*    pcResiYuv, 
                           TComYuv*    pcRecoYuv,
                           UInt&       ruiDistC,
                           Bool        bLumaOnly )
{
  UInt    uiDepth        = pcCU->getDepth(0); //!< 当前CU的深度
  UInt    uiNumPU        = pcCU->getNumPartInter(); //!< 当前CU的分割模式,(SIZE_2Nx2N:1, SIZE_2NxN:2, SIZE_Nx2N:2, SIZE_NxN:4 ... )
  UInt    uiInitTrDepth  = pcCU->getPartitionSize(0) == SIZE_2Nx2N ? 0 : 1; //!< 用于计算变换的深度,实际深度为该值+uiDepth
  UInt    uiWidth        = pcCU->getWidth (0) >> uiInitTrDepth; //!< 当前PU的宽度,如果又分成4个子块,则宽度除以2
  UInt    uiHeight       = pcCU->getHeight(0) >> uiInitTrDepth; //!< 当前PU的高度,如果又分成4个子块,则高度除以2
  UInt    uiQNumParts    = pcCU->getTotalNumPart() >> 2; // 最小的分区是4x4大小的块,这里计算出以该4x4块为单位的分割数,这么做便于计算当前CU的Zorder坐标
  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 ) //!< 对当前CU中的每个PU进行遍历
  {
    //===== init pattern for luma prediction =====
    Bool bAboveAvail = false;
    Bool bLeftAvail  = false;
    pcCU->getPattern()->initPattern   ( pcCU, uiInitTrDepth, uiPartOffset ); // set parameters from CU data for accessing neighbouring pixels
 // set luma parameters from CU data for accessing ADI data //!< 主要获取当前PU的邻域可用性,对参考样点进行设置及滤波
    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);

      for( Int i=0; i < numModesForFullRD; i++ ) 
      {
        CandCostList[ i ] = MAX_DOUBLE;
      }
      CandNum = 0;
      
      for( Int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++ ) //!< 遍历35种帧内预测模式
      {
        UInt uiMode = modeIdx;
  //! 调用亮度帧内预测函数
        predIntraLumaAng( pcCU->getPattern(), uiMode, piPred, uiStride, uiWidth, uiHeight, pcCU, bAboveAvail, bLeftAvail );
        
        // use hadamard transform here
        UInt uiSad = m_pcRdCost->calcHAD( piOrg, uiStride, piPred, uiStride, uiWidth, uiHeight );
        
        UInt   iModeBits = xModeBitsIntra( pcCU, uiMode, uiPU, uiPartOffset, uiDepth, uiInitTrDepth );
        Double cost      = (Double)uiSad + (Double)iModeBits * m_pcRdCost->getSqrtLambda();
        
        CandNum += xUpdateCandList( uiMode, cost, numModesForFullRD, uiRdModeList, CandCostList );
      }
    
#if FAST_UDI_USE_MPM // UDI---Unified Directional Intra
      Int uiPreds[3] = {-1, -1, -1};
      Int iMode = -1;  //!< 如果三个MPMs的前两个相同,则iMode=1,否则iMode=2
      Int numCand = pcCU->getIntraDirLumaPredictor( uiPartOffset, uiPreds, &iMode ); //!< 获取亮度帧内预测模式的三个MPMs
      if( iMode >= 0 ) //!< iMode = 1 or 2,因此,numCand会被重新赋值为iMode
      {
        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
    } //!< if (doFastSearch)
    else
    {
      for( Int i=0; i < numModesForFullRD; i++)
      {
        uiRdModeList[i] = i;
      }
    }
    
    //===== check modes (using r-d costs) =====
 //! 帧内预测模式最佳值的确定主要有以下几个步骤:1. 对numModesForFullRD种预测模式进行遍历,即对每种模式计算出
 //! 对应的RD costs,但该步骤中,并不会把一个CU的所有分割都算一遍,而仅仅对于至多深度为1的分割进行遍历,这么做
 //! 大大减少了运算量,提高速度;2. 在第1个步骤中,会粗略得到最佳预测模式(在HM9.0中会得到包括次优解在内的两个
 //! 预测模式),存储下来,以供第3步使用;3. 在第2步的基础上,对最佳(及次优)预测模式的所有分割模式遍历一遍,
 //! 得到最终的最佳结果
#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;  //!< 存放最佳预测模式对应的总代价
    for( UInt uiMode = 0; uiMode < numModesForFullRD; uiMode++ ) //!< 遍历存储在uiRdModeList里的模式
    {
      // set luma prediction mode
      UInt uiOrgMode = uiRdModeList[uiMode];
      
      pcCU->setLumaIntraDirSubParts ( uiOrgMode, uiPartOffset, uiDepth + uiInitTrDepth );
      
      // set context models
      if( m_bUseSBACRD )
      {
        m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );
      }
      
      // determine residual for partition
      UInt   uiPUDistY = 0;  //!< 存放当前预测模式对应的亮度失真值
      UInt   uiPUDistC = 0;  //!< 存放当前预测模式对应的色度失真值
      Double dPUCost   = 0.0; //!< 存放当前预测模式对应的代价
#if HHI_RQT_INTRA_SPEEDUP //! 注意这个函数倒数第二个参数,此时为true
      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
      if( m_bUseSBACRD )
      {
        m_pcRDGoOnSbacCoder->load( m_pppcRDSbacCoder[uiDepth][CI_CURR_BEST] );
      }
      
      // determine residual for partition
      UInt   uiPUDistY = 0;
      UInt   uiPUDistC = 0;
      Double dPUCost   = 0.0;
   //! 注意该函数倒数第二个参数,此时为false
      xRecurIntraCodingQT( pcCU, uiInitTrDepth, uiPartOffset, bLumaOnly, pcOrgYuv, pcPredYuv, pcResiYuv, uiPUDistY, uiPUDistC, false, dPUCost );
      
      // 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 =====
  if(m_bUseSBACRD)
  {
    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;
}

(转载请注明出处http://blog.csdn.net/hevc_cjl/article/details/8200793#comments

猜你喜欢

转载自blog.csdn.net/chenxiuli0810/article/details/8493165
今日推荐