1. 程式人生 > >率失真優化——程式碼

率失真優化——程式碼

轉載https://blog.csdn.net/nb_vol_1/article/details/56036991

程式碼實現

某個模式下的率失真代價,是通過該模式下編碼的失真和佔用的位元位元數來計算的

TComDataCU中有三個成員以及函式和率失真相關:

  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,平方誤差和)。

  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.     cDtParam.bApplyWeight = false;  
  13.     cDtParam.uiComp       = 255;    // just for assert: to be sure it was set before use, since only values 0,1 or 2 are allowed.
  14.     cDtParam.bitDepth = bitDepth;  
  15.     if (eText == TEXT_CHROMA_U)  
  16.     {  
  17.         return ((Int) (m_cbDistortionWeight * cDtParam.DistFunc( &cDtParam )));  
  18.     }  
  19.     elseif (eText == TEXT_CHROMA_V)  
  20.     {  
  21.         return ((Int) (m_crDistortionWeight * cDtParam.DistFunc( &cDtParam )));  
  22.     }  
  23.     else
  24.     {  
  25.         return cDtParam.DistFunc( &cDtParam );  
  26.     }  
  27. }  
  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.     UInt uiSum = 0;  
  17.     UInt uiShift = DISTORTION_PRECISION_ADJUSTMENT((pcDtParam->bitDepth-8) << 1);  
  18.     Int iTemp;  
  19.     for( ; iRows != 0; iRows-- )  
  20.     {  
  21.         for (Int n = 0; n < iCols; n++ )  
  22.         {  
  23.             iTemp = piOrg[n  ] - piCur[n  ];  
  24.             uiSum += ( iTemp * iTemp ) >> uiShift;  
  25.         }  
  26.         piOrg += iStrideOrg;  
  27.         piCur += iStrideCur;  
  28.     }  
  29.     return ( uiSum );  
  30. }  

位元總數的計算

    這個就比較簡單了,熵編碼之後統計位元數就可以了,具體的就是呼叫TEncEntropy::getNumberOfWrittenBits()函式得到位元數

率失真代價的計算

    計算完成失真與位元數之後,就可以利用失真與位元數來計算代價了,計算代價是通過TComRdCost::calcRdCost函式來進行的

  1. Double TComRdCost::calcRdCost( UInt uiBits, UInt uiDistortion, Bool bFlag, DFunc eDFunc )  
  2. {  
  3.     Double dRdCost = 0.0;  
  4.     Double dLambda = 0.0;  
  5.     // 根據率失真計算函式的型別來確定lambda引數
  6.     switch ( eDFunc )  
  7.     {  
  8.     case DF_SSE:  
  9.         assert(0);  
  10.         break;  
  11.     case DF_SAD:  
  12.         dLambda = (Double)m_uiLambdaMotionSAD;  
  13.         break;  
  14.     case DF_DEFAULT:  
  15.         dLambda =         m_dLambda;  
  16.         break;  
  17.     case DF_SSE_FRAME:  
  18.         dLambda =         m_dFrameLambda;  
  19.         break;  
  20.     default:  
  21.         assert (0);  
  22.         break;  
  23.     }  
  24.     // 根據失真和位元數來計算代價
  25.     // 是否選用某種模式,要根據代價來決定,代價要在失真和位元數之間達到平衡
  26.     // 既要讓失真小,也要讓位元數少
  27.     if (bFlag)  
  28.     {  
  29.         // Intra8x8, Intra4x4 Block only...
  30. #if SEQUENCE_LEVEL_LOSSLESS
  31.         dRdCost = (Double)(uiBits);  
  32. #else
  33.         dRdCost = (((Double)uiDistortion) + ((Double)uiBits * dLambda));  
  34. #endif
  35.     }  
  36.     else
  37.     {  
  38.         if (eDFunc == DF_SAD)  
  39.         {  
  40.             dRdCost = ((Double)uiDistortion + (Double)((Int)(uiBits * dLambda+.5)>>16));  
  41.             dRdCost = (Double)(UInt)floor(dRdCost);  
  42.         }  
  43.         else
  44.         {  
  45. #if SEQUENCE_LEVEL_LOSSLESS
  46.             dRdCost = (Double)(uiBits);  
  47. #else
  48.             dRdCost = ((Double)uiDistortion + (Double)((Int)(uiBits * dLambda+.5)));  
  49.             dRdCost = (Double)(UInt)floor(dRdCost);  
  50. #endif
  51.         }  
  52.     }  
  53.     return dRdCost;  
  54. }