率失真优化——代码

转载https://blog.csdn.net/nb_vol_1/article/details/56036991

代码实现

某个模式下的率失真代价,是通过该模式下编码的失真和占用的比特比特数来计算的

TComDataCU中有三个成员以及函数和率失真相关:

[cpp]  view plain  copy
  1. UInt&         getTotalDistortion()            { return m_uiTotalDistortion; }  //总的失真,某一种模式下总的失真  
  2. Double&       getTotalCost()                  { return m_dTotalCost;        }  //总的代价,某一种模式下总的代价  
  3. UInt&         getTotalBits()                  { return m_uiTotalBits;       }  //总得比特数,按照某一种模式进行编码之后的总比特数  

失真的计算

    一个像素块的总的失真就是该像素块中三个分量的失真之和。失真是通过TComRdCost::getDistPart函数进行计算的,DistParam是失真参数结构体,用于存放计算失真的参数,以及处理计算过程的函数指针,至于使用哪个具体的率失真计算函数,可以通过DFunc枚举来指定,默认使用DF_SSE(即xGetSSE,平方误差和)。

[cpp]  view plain  copy
  1. UInt TComRdCost::getDistPart(Int bitDepth, Pel* piCur, Int iCurStride,  Pel* piOrg, Int iOrgStride, UInt uiBlkWidth, UInt uiBlkHeight, TextType eText, DFunc eDFunc)  
  2. {  
  3.     // DistParam是失真参数结构体,用于存放计算失真的参数,以及处理计算过程的函数指针  
  4.     DistParam cDtParam;  
  5.     // eDFunc指定了使用哪个失真计算函数(默认使用SSE的方式计算)  
  6.     setDistParam( uiBlkWidth, uiBlkHeight, eDFunc, cDtParam );  
  7.     cDtParam.pOrg       = piOrg;  
  8.     cDtParam.pCur       = piCur;  
  9.     cDtParam.iStrideOrg = iOrgStride;  
  10.     cDtParam.iStrideCur = iCurStride;  
  11.     cDtParam.iStep      = 1;  
  12.   
  13.     cDtParam.bApplyWeight = false;  
  14.     cDtParam.uiComp       = 255;    // just for assert: to be sure it was set before use, since only values 0,1 or 2 are allowed.  
  15.     cDtParam.bitDepth = bitDepth;  
  16.   
  17.     if (eText == TEXT_CHROMA_U)  
  18.     {  
  19.         return ((Int) (m_cbDistortionWeight * cDtParam.DistFunc( &cDtParam )));  
  20.     }  
  21.     else if (eText == TEXT_CHROMA_V)  
  22.     {  
  23.         return ((Int) (m_crDistortionWeight * cDtParam.DistFunc( &cDtParam )));  
  24.     }  
  25.     else  
  26.     {  
  27.         return cDtParam.DistFunc( &cDtParam );  
  28.     }  
  29. }  
[cpp]  view plain  copy
  1. /* 
  2. ** 默认的失真计算函数(使用SSE的方法) 
  3. */  
  4. UInt TComRdCost::xGetSSE( DistParam* pcDtParam )  
  5. {  
  6.     if ( pcDtParam->bApplyWeight )  
  7.     {  
  8.         return xGetSSEw( pcDtParam );  
  9.     }  
  10.     Pel* piOrg   = pcDtParam->pOrg;  
  11.     Pel* piCur   = pcDtParam->pCur;  
  12.     Int  iRows   = pcDtParam->iRows;  
  13.     Int  iCols   = pcDtParam->iCols;  
  14.     Int  iStrideOrg = pcDtParam->iStrideOrg;  
  15.     Int  iStrideCur = pcDtParam->iStrideCur;  
  16.   
  17.     UInt uiSum = 0;  
  18.     UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1);  
  19.   
  20.     Int iTemp;  
  21.   
  22.     for( ; iRows != 0; iRows-- )  
  23.     {  
  24.         for (Int n = 0; n < iCols; n++ )  
  25.         {  
  26.             iTemp = piOrg[n  ] - piCur[n  ];  
  27.             uiSum += ( iTemp * iTemp ) >> uiShift;  
  28.         }  
  29.         piOrg += iStrideOrg;  
  30.         piCur += iStrideCur;  
  31.     }  
  32.   
  33.     return ( uiSum );  
  34. }  

比特总数的计算

    这个就比较简单了,熵编码之后统计比特数就可以了,具体的就是调用TEncEntropy::getNumberOfWrittenBits()函数得到比特数


率失真代价的计算

    计算完成失真与比特数之后,就可以利用失真与比特数来计算代价了,计算代价是通过TComRdCost::calcRdCost函数来进行的

[cpp]  view plain  copy
  1. Double TComRdCost::calcRdCost( UInt uiBits, UInt uiDistortion, Bool bFlag, DFunc eDFunc )  
  2. {  
  3.     Double dRdCost = 0.0;  
  4.     Double dLambda = 0.0;  
  5.   
  6.     // 根据率失真计算函数的类型来确定lambda参数  
  7.     switch ( eDFunc )  
  8.     {  
  9.     case DF_SSE:  
  10.         assert(0);  
  11.         break;  
  12.     case DF_SAD:  
  13.         dLambda = (Double)m_uiLambdaMotionSAD;  
  14.         break;  
  15.     case DF_DEFAULT:  
  16.         dLambda =         m_dLambda;  
  17.         break;  
  18.     case DF_SSE_FRAME:  
  19.         dLambda =         m_dFrameLambda;  
  20.         break;  
  21.     default:  
  22.         assert (0);  
  23.         break;  
  24.     }  
  25.   
  26.     // 根据失真和比特数来计算代价  
  27.     // 是否选用某种模式,要根据代价来决定,代价要在失真和比特数之间达到平衡  
  28.     // 既要让失真小,也要让比特数少  
  29.     if (bFlag)  
  30.     {  
  31.         // Intra8x8, Intra4x4 Block only...  
  32. #if SEQUENCE_LEVEL_LOSSLESS  
  33.         dRdCost = (Double)(uiBits);  
  34. #else  
  35.         dRdCost = (((Double)uiDistortion) + ((Double)uiBits * dLambda));  
  36. #endif  
  37.     }  
  38.     else  
  39.     {  
  40.         if (eDFunc == DF_SAD)  
  41.         {  
  42.             dRdCost = ((Double)uiDistortion + (Double)((Int)(uiBits * dLambda+.5)>>16));  
  43.             dRdCost = (Double)(UInt)floor(dRdCost);  
  44.         }  
  45.         else  
  46.         {  
  47. #if SEQUENCE_LEVEL_LOSSLESS  
  48.             dRdCost = (Double)(uiBits);  
  49. #else  
  50.             dRdCost = ((Double)uiDistortion + (Double)((Int)(uiBits * dLambda+.5)));  
  51.             dRdCost = (Double)(UInt)floor(dRdCost);  
  52. #endif  
  53.         }  
  54.     }  
  55.   
  56.     return dRdCost;  
  57. }  

你可能感兴趣的:(HEVC)