RC代码一些不明白的地方,网上参考

1、RC总体框架

参考http://blog.csdn.net/hevc_cjl/article/details/10982699

2、 码率控制的一个大致流程图:

来自于http://blog.csdn.net/cpp12341234/article/details/46043615

RC代码一些不明白的地方,网上参考_第1张图片

3、copressGOP函数:HM16.0中TEncGop类中compressGop函数RC部分在1447-1543行(初始化相关参数),1838-1864行(每编码完一张图片更新参数)。

参考http://blog.csdn.net/cpp12341234/article/details/45766687

和http://blog.csdn.net/hevc_cjl/article/details/11115721

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

compressSlice函数:参考http://blog.csdn.net/hevc_cjl/article/details/11128745。在TEncSlice中的第698行,涉及到的RC部分为第834-876行(初始化相关参数),第931-957行(每编码完一个CTU后进行参数更新)。

  1. #if RATE_CONTROL_LAMBDA_DOMAIN  
  2.       Double oldLambda = m_pcRdCost->getLambda();  
  3.       if ( m_pcCfg->getUseRateCtrl() )  
  4.       {  
  5.         Int estQP        = pcSlice->getSliceQp();  
  6.         Double estLambda = -1.0;  
  7.         Double bpp       = -1.0;  
  8.   
  9. #if M0036_RC_IMPROVEMENT  
  10.         if ( ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )  
  11. #else  
  12.         if ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE || !m_pcCfg->getLCULevelRC() )  
  13. #endif  
  14.         { //!< 如果当前slice为I slice或者不进行LCU level RC,则LCU直接使用当前slice的QP  
  15.           estQP = pcSlice->getSliceQp();  
  16.         }  
  17.         else  
  18.         {  
  19. #if RATE_CONTROL_INTRA  
  20.           bpp = m_pcRateCtrl->getRCPic()->getLCUTargetBpp(pcSlice->getSliceType());  
  21.           if ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE)  
  22.           {  
  23.             estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP);  
  24.           }  
  25.           else  
  26.           {  
  27.             estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );  
  28.             estQP     = m_pcRateCtrl->getRCPic()->getLCUEstQP    ( estLambda, pcSlice->getSliceQp() );  
  29.           }  
  30. #else  
  31.           bpp       = m_pcRateCtrl->getRCPic()->getLCUTargetBpp();  
  32.           estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );  
  33.           estQP     = m_pcRateCtrl->getRCPic()->getLCUEstQP    ( estLambda, pcSlice->getSliceQp() );  
  34. #endif  
  35.   
  36.           estQP     = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, estQP );  
  37.   
  38.           m_pcRdCost->setLambda(estLambda);  
  39. #if M0036_RC_IMPROVEMENT  
  40. #if RDOQ_CHROMA_LAMBDA  
  41.           // set lambda for RDOQ  
  42.           Double weight=m_pcRdCost->getChromaWeight();  
  43.           m_pcTrQuant->setLambda( estLambda, estLambda / weight );  
  44. #else  
  45.           m_pcTrQuant->setLambda( estLambda );  
  46. #endif  
  47. #endif  
  48.         }  
  49.   
  50.         m_pcRateCtrl->setRCQP( estQP );  
  51.         pcCU->getSlice()->setSliceQpBase( estQP ); //!< 设置编码时使用的QP值  
  52.       }  
  53. #endif  

4、CTU目标比特分配(CTU bpp的计算)

参考http://blog.csdn.net/cpp12341234/article/details/45851175

5、RC涉及到的关键函数

可以看看http://blog.csdn.net/hevc_cjl/article/category/1283611系列博客

6、对RC整体概括、写的不错的一篇博客,详细介绍了RC涉及到的一些类内成员变量的含义

http://blog.csdn.net/nb_vol_1/article/details/55096464

比如:

  1.     // 帧内模式消耗的比特数  
  2.     Double m_totalCostIntra;  
  3.     // 帧内模式还剩余的比特数  
  4.     Double m_remainingCostIntra; 
  5.     // gop的id到level的映射  
  6.     Int* m_GOPID2Level;
  7.     // 自适应的比特  
  8.     Int m_adaptiveBit; 
  9.     // 最后的lambda参数
  10.     Double m_lastLambda;
  11.     // 帧内的代价  
  12.     Double m_costIntra; 

该博主的另外一篇介绍码率控制的博客:http://blog.csdn.net/nb_vol_1/article/details/56022073(结合原理分析代码)

你可能感兴趣的:(HEVC学习,码率控制)