HEVC码率控制浅析——HM代码阅读之三

续上文继续分析

m_pcRateCtrl->initRCPic( )

[cpp]  view plain copy
  1. Void TEncRateCtrl::initRCPic( Int frameLevel )  
  2. {  
  3.   m_encRCPic = new TEncRCPic;  
  4.   m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures );  
  5. }  


m_encRCPic->create

[cpp]  view plain copy
  1. Void TEncRCPic::create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures )  
  2. {  
  3.   destroy();  
  4.   m_encRCSeq = encRCSeq;  
  5.   m_encRCGOP = encRCGOP;  
  6.   
  7.   Int targetBits    = xEstPicTargetBits( encRCSeq, encRCGOP );  //!< K0103式子(9)  
  8.   Int estHeaderBits = xEstPicHeaderBits( listPreviousPictures, frameLevel ); //!< header bits estimation  
  9.   
  10.   if ( targetBits < estHeaderBits + 100 )  
  11.   {  
  12.     targetBits = estHeaderBits + 100;   // at least allocate 100 bits for picture data  
  13.   }  
  14.   //!< 以下为RC相关参数的初始化,根据变量名很容易就能判断其用途,故不罗嗦~  
  15.   m_frameLevel       = frameLevel;  
  16.   m_numberOfPixel    = encRCSeq->getNumPixel();  
  17.   m_numberOfLCU      = encRCSeq->getNumberOfLCU();  
  18.   m_estPicLambda     = 100.0;  
  19.   m_targetBits       = targetBits;  
  20.   m_estHeaderBits    = estHeaderBits;  
  21.   m_bitsLeft         = m_targetBits;  
  22.   Int picWidth       = encRCSeq->getPicWidth();  
  23.   Int picHeight      = encRCSeq->getPicHeight();  
  24.   Int LCUWidth       = encRCSeq->getLCUWidth();  
  25.   Int LCUHeight      = encRCSeq->getLCUHeight();  
  26.   Int picWidthInLCU  = ( picWidth  % LCUWidth  ) == 0 ? picWidth  / LCUWidth  : picWidth  / LCUWidth  + 1;  
  27.   Int picHeightInLCU = ( picHeight % LCUHeight ) == 0 ? picHeight / LCUHeight : picHeight / LCUHeight + 1;  
  28.   
  29.   m_LCULeft         = m_numberOfLCU;  
  30.   m_bitsLeft       -= m_estHeaderBits; //!< 考虑header bits后的剩余比特数  
  31.   m_pixelsLeft      = m_numberOfPixel;  
  32.   
  33.   m_LCUs           = new TRCLCU[m_numberOfLCU];  
  34.   Int i, j;  
  35.   Int LCUIdx;  
  36.   for ( i=0; i<picWidthInLCU; i++ )  
  37.   {  
  38.     for ( j=0; j<picHeightInLCU; j++ )  
  39.     {  
  40.       LCUIdx = j*picWidthInLCU + i;  
  41.       m_LCUs[LCUIdx].m_actualBits = 0;  
  42.       m_LCUs[LCUIdx].m_QP         = 0;  
  43.       m_LCUs[LCUIdx].m_lambda     = 0.0;  
  44.       m_LCUs[LCUIdx].m_targetBits = 0;  
  45. #if M0036_RC_IMPROVEMENT  
  46.       m_LCUs[LCUIdx].m_bitWeight  = 1.0;  
  47. #else  
  48.       m_LCUs[LCUIdx].m_MAD        = 0.0;  
  49. #endif  
  50.       Int currWidth  = ( (i == picWidthInLCU -1) ? picWidth  - LCUWidth *(picWidthInLCU -1) : LCUWidth  );  
  51.       Int currHeight = ( (j == picHeightInLCU-1) ? picHeight - LCUHeight*(picHeightInLCU-1) : LCUHeight );  
  52.       m_LCUs[LCUIdx].m_numberOfPixel = currWidth * currHeight;  
  53.     }  
  54.   }  
  55.   m_picActualHeaderBits = 0;  
  56. #if !M0036_RC_IMPROVEMENT  
  57.   m_totalMAD            = 0.0;  
  58. #endif  
  59.   m_picActualBits       = 0;  
  60.   m_picQP               = 0;  
  61.   m_picLambda           = 0.0;  
  62.   
  63. #if !M0036_RC_IMPROVEMENT  
  64.   m_lastPicture = NULL;  
  65.   list<TEncRCPic*>::reverse_iterator it;  
  66.   for ( it = listPreviousPictures.rbegin(); it != listPreviousPictures.rend(); it++ )  
  67.   {  
  68.     if ( (*it)->getFrameLevel() == m_frameLevel ) //!< 保存跟当前帧同一层的前一帧  
  69.     {  
  70.       m_lastPicture = (*it);  
  71.       break;  
  72.     }  
  73.   }  
  74. #endif  
  75. }  


m_encRCPic->create子函数xEstPicTargetBits()

[cpp]  view plain copy
  1. <span style="font-size:12px;">Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )  
  2. {  
  3.   Int targetBits        = 0;  
  4.   Int GOPbitsLeft       = encRCGOP->getBitsLeft(); //!< TGOP - CodedGOP  
  5.   
  6.   Int i;  
  7.   Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();  
  8.   Int currPicRatio    = encRCSeq->getBitRatio( currPicPosition );    //!< 当前picture的权值  
  9.   Int totalPicRatio   = 0;  
  10.   for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )  
  11.   {  
  12.     totalPicRatio += encRCSeq->getBitRatio( i ); //!< 总权值  
  13.   }  
  14.   
  15. #if M0036_RC_IMPROVEMENT  
  16.   targetBits  = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio );  
  17. #else  
  18.   targetBits  = Int( GOPbitsLeft * currPicRatio / totalPicRatio );  
  19. #endif  
  20.   
  21.   if ( targetBits < 100 )  
  22.   {  
  23.     targetBits = 100;   // at least allocate 100 bits for one picture  
  24.   }  
  25.   
  26.   //!< 在此之前targetBits是基于K0103式子(9)计算的结果,而m_encRCGOP->getTargetBitInGOP( currPicPosition )得到的  
  27.   //!< bits为NotCodedPictures=0通过式子(9)得到的  
  28.   if ( m_encRCSeq->getFramesLeft() > 16 )  
  29.   {  
  30.     targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );  
  31.   }  
  32.   
  33.   return targetBits;  
  34. }</span>  

m_encRCPic->create子函数xEstPicHeaderBits()

[cpp]  view plain copy
  1. <span style="font-size:12px;">Int TEncRCPic::xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel )  
  2. {  
  3.   Int numPreviousPics   = 0;  
  4.   Int totalPreviousBits = 0;  
  5.   
  6.   list<TEncRCPic*>::iterator it;  
  7.   for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ ) //!< 求出当前帧之前所有与其在同一层的帧的header bits之和  
  8.   {  
  9.     if ( (*it)->getFrameLevel() == frameLevel )  
  10.     {  
  11.       totalPreviousBits += (*it)->getPicActualHeaderBits();  
  12.       numPreviousPics++;  
  13.     }  
  14.   }  
  15.   
  16.   Int estHeaderBits = 0;  
  17.   if ( numPreviousPics > 0 ) //!< 取平均值  
  18.   {  
  19.     estHeaderBits = totalPreviousBits / numPreviousPics;  
  20.   }  
  21.   
  22.   return estHeaderBits;  
  23. }</span>  

分析第一篇提到的compressGOP中的RC初始化代码片段:

[cpp]  view plain copy
  1. <span style="font-size:12px;">#if RATE_CONTROL_LAMBDA_DOMAIN  
  2.     Double lambda            = 0.0;  
  3.     Int actualHeadBits       = 0;  
  4.     Int actualTotalBits      = 0;  
  5.     Int estimatedBits        = 0;  
  6.     Int tmpBitsBeforeWriting = 0;  
  7.     if ( m_pcCfg->getUseRateCtrl() )  
  8.     {  
  9.       Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );  
  10.       if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )  
  11.       {  
  12.         frameLevel = 0;  
  13.       }  
  14.       m_pcRateCtrl->initRCPic( frameLevel ); //!< picture level 初始化  
  15.       estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits(); //!< 在initRCPic中已经计算出了targetBits  
  16.         
  17.       Int sliceQP = m_pcCfg->getInitialQP(); //!< 对应于配置文件中的InitalQP  
  18.       if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified  
  19.       {//!< 如果配置文件对序列第一帧指定了初始QP,则基于这个QP计算出lamda  
  20.         Int    NumberBFrames = ( m_pcCfg->getGOPSize() - 1 );  
  21.         Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames );  
  22.         Double dQPFactor     = 0.57*dLambda_scale;  
  23.         Int    SHIFT_QP      = 12;  
  24.         Int    bitdepth_luma_qp_scale = 0;  
  25.         Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP;  
  26.         lambda = dQPFactor*pow( 2.0, qp_temp/3.0 );  
  27.       }  
  28.       else if ( frameLevel == 0 )   // intra case, but use the model  
  29.       { //!< 对I slice的情况,需要做些特殊处理,如targetBits的修正等  
  30. #if RATE_CONTROL_INTRA  
  31.         m_pcSliceEncoder->calCostSliceI(pcPic);  
  32. #endif  
  33.         if ( m_pcCfg->getIntraPeriod() != 1 )   // do not refine allocated bits for all intra case  
  34.         {  
  35.           Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits();  
  36. #if RATE_CONTROL_INTRA  
  37.           bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits );  
  38. #else  
  39.           bits = m_pcRateCtrl->getRCSeq()->getRefineBitsForIntra( bits ); //!< K0103 Table 3  
  40. #endif  
  41.           if ( bits < 200 )  
  42.           {  
  43.             bits = 200;  
  44.           }  
  45.           m_pcRateCtrl->getRCPic()->setTargetBits( bits );  
  46.         }  
  47.           
  48.         list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();  
  49. #if RATE_CONTROL_INTRA  
  50.         m_pcRateCtrl->getRCPic()->getLCUInitTargetBits();  
  51.         lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());  
  52. #else  
  53.         lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture );  
  54. #endif  
  55.         sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );  
  56.       }  
  57.       else    // normal case  
  58.       {  
  59.         list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();  
  60. #if RATE_CONTROL_INTRA  
  61.         lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());  
  62. #else  
  63.         lambda  = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture );  
  64. #endif  
  65.         sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );  
  66.       }  
  67.         
  68.       sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, sliceQP );  
  69.       m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP );  
  70.         
  71.       m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda ); //!< 设置当前slice使用的QP, lambda,编码时用到  
  72.     }  
  73. #endif</span>  

compressGOP子函数getRefineBitsForIntra()

[cpp]  view plain copy
  1. <span style="font-size:12px;">#if !RATE_CONTROL_INTRA  
  2. Int TEncRCSeq::getRefineBitsForIntra( Int orgBits ) //!< K0103 Table 3  
  3. {  
  4.   Double bpp = ( (Double)orgBits ) / m_picHeight / m_picHeight;  
  5.   if ( bpp > 0.2 )  
  6.   {  
  7.     return orgBits * 5;  
  8.   }  
  9.   if ( bpp > 0.1 )  
  10.   {  
  11.     return orgBits * 7;  
  12.   }  
  13.   return orgBits * 10;  
  14. }  
  15. #endif</span>  

compressGOP子函数estimatePicLambda()
[cpp]  view plain copy
  1. <span style="font-size:12px;">#if RATE_CONTROL_INTRA  
  2. Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures, SliceType eSliceType)  
  3. #else  
  4. Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures )  
  5. #endif  
  6. {  
  7.   Double alpha         = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;  
  8.   Double beta          = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;  
  9.   Double bpp       = (Double)m_targetBits/(Double)m_numberOfPixel;  
  10. #if RATE_CONTROL_INTRA  
  11.   Double estLambda;  
  12.   if (eSliceType == I_SLICE)  
  13.   {  
  14.     estLambda = calculateLambdaIntra(alpha, beta, pow(m_totalCostIntra/(Double)m_numberOfPixel, BETA1), bpp);   
  15.   }  
  16.   else  
  17.   {  
  18.     estLambda = alpha * pow( bpp, beta );  
  19.   }  
  20. #else  
  21.   Double estLambda = alpha * pow( bpp, beta ); //!< K0103 式子(10)  
  22. #endif    
  23.     
  24.   Double lastLevelLambda = -1.0;  
  25.   Double lastPicLambda   = -1.0;  
  26.   Double lastValidLambda = -1.0;  
  27.   list<TEncRCPic*>::iterator it;  
  28.   for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )  
  29.   {  
  30.     if ( (*it)->getFrameLevel() == m_frameLevel )  
  31.     {  
  32.       lastLevelLambda = (*it)->getPicActualLambda();  
  33.     }  
  34.     lastPicLambda     = (*it)->getPicActualLambda();  
  35.   
  36.     if ( lastPicLambda > 0.0 )  
  37.     {  
  38.       lastValidLambda = lastPicLambda;  
  39.     }  
  40.   }  
  41.   //!< 以下对lastLevelLambda和estLambda进行clip,范围在K0103的section 3.2中进行了定义  
  42.   if ( lastLevelLambda > 0.0 )  
  43.   {  
  44.     lastLevelLambda = Clip3( 0.1, 10000.0, lastLevelLambda );  
  45.     estLambda = Clip3( lastLevelLambda * pow( 2.0, -3.0/3.0 ), lastLevelLambda * pow( 2.0, 3.0/3.0 ), estLambda );  
  46.   }  
  47.   
  48.   if ( lastPicLambda > 0.0 )  
  49.   {  
  50.     lastPicLambda = Clip3( 0.1, 2000.0, lastPicLambda );  
  51.     estLambda = Clip3( lastPicLambda * pow( 2.0, -10.0/3.0 ), lastPicLambda * pow( 2.0, 10.0/3.0 ), estLambda );  
  52.   }  
  53.   else if ( lastValidLambda > 0.0 )  
  54.   {  
  55.     lastValidLambda = Clip3( 0.1, 2000.0, lastValidLambda );  
  56.     estLambda = Clip3( lastValidLambda * pow(2.0, -10.0/3.0), lastValidLambda * pow(2.0, 10.0/3.0), estLambda );  
  57.   }  
  58.   else  
  59.   {  
  60.     estLambda = Clip3( 0.1, 10000.0, estLambda );  
  61.   }  
  62.   
  63.   if ( estLambda < 0.1 )  
  64.   {  
  65.     estLambda = 0.1;  
  66.   }  
  67.   
  68.   m_estPicLambda = estLambda;  
  69.   
  70. #if M0036_RC_IMPROVEMENT  
  71.   Double totalWeight = 0.0;  
  72.   // initial BU bit allocation weight  
  73.   for ( Int i=0; i<m_numberOfLCU; i++ )  
  74.   {  
  75. #if RC_FIX  
  76.     Double alphaLCU, betaLCU;  
  77.     if ( m_encRCSeq->getUseLCUSeparateModel() )  
  78.     {  
  79.       alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha;  
  80.       betaLCU  = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta;  
  81.     }  
  82.     else  
  83.     {  
  84.       alphaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;  
  85.       betaLCU  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;  
  86.     }  
  87. #else  
  88.     Double alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha;  
  89.     Double betaLCU  = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta;  
  90. #endif  
  91.   
  92.     m_LCUs[i].m_bitWeight =  m_LCUs[i].m_numberOfPixel * pow( estLambda/alphaLCU, 1.0/betaLCU );  
  93.   
  94.     if ( m_LCUs[i].m_bitWeight < 0.01 )  
  95.     {  
  96.       m_LCUs[i].m_bitWeight = 0.01;  
  97.     }  
  98.     totalWeight += m_LCUs[i].m_bitWeight;  
  99.   }  
  100.   for ( Int i=0; i<m_numberOfLCU; i++ )  
  101.   {  
  102.     Double BUTargetBits = m_targetBits * m_LCUs[i].m_bitWeight / totalWeight;  
  103.     m_LCUs[i].m_bitWeight = BUTargetBits;  
  104.   }  
  105. #endif  
  106.   
  107.   return estLambda;  
  108. }</span>  

 compressGOP子函数estimatePicQP()

[cpp]  view plain copy
  1. <span style="font-size:12px;">Int TEncRCPic::estimatePicQP( Double lambda, list<TEncRCPic*>& listPreviousPictures )  
  2. {  
  3.   Int QP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 ); //!< 通过lambda求QP  
  4.   
  5.   Int lastLevelQP = g_RCInvalidQPValue;  
  6.   Int lastPicQP   = g_RCInvalidQPValue;  
  7.   Int lastValidQP = g_RCInvalidQPValue;  
  8.   list<TEncRCPic*>::iterator it;  
  9.   for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )  
  10.   {  
  11.     if ( (*it)->getFrameLevel() == m_frameLevel )  
  12.     {  
  13.       lastLevelQP = (*it)->getPicActualQP();  
  14.     }  
  15.     lastPicQP = (*it)->getPicActualQP();  
  16.     if ( lastPicQP > g_RCInvalidQPValue )  
  17.     {  
  18.       lastValidQP = lastPicQP;  
  19.     }  
  20.   }  
  21.   //!< 以下对QP进行clip,范围在K0103的section 3.2进行了定义  
  22.   if ( lastLevelQP > g_RCInvalidQPValue )  
  23.   {  
  24.     QP = Clip3( lastLevelQP - 3, lastLevelQP + 3, QP );  
  25.   }  
  26.   
  27.   if( lastPicQP > g_RCInvalidQPValue )  
  28.   {  
  29.     QP = Clip3( lastPicQP - 10, lastPicQP + 10, QP );  
  30.   }  
  31.   else if( lastValidQP > g_RCInvalidQPValue )  
  32.   {  
  33.     QP = Clip3( lastValidQP - 10, lastValidQP + 10, QP );  
  34.   }  
  35.   
  36.   return QP;  
  37. }</span>  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值