本文转载自http://blog.csdn.net/nonmarking/article/details/47357657

在前两篇文章中,首先介绍了HEVC标准和编码流程,然后介绍了在HEVC中采用的全新的R-λ模型,本文将基于前面的内容和相应代码对码率控制算法进行详细的分析。

下面基于JCTVC-K0103提案详细介绍一下HEVC中基于R-λ模型的码率控制方法。同时基于HM-10对码率控制部分的代码做一个简要分析,相比于JM,HM中更多的使用了面向对象技术,结构更加清楚明了,码率控制相关代码的基本调用层次如下,纵向上即层层调用的关系,横向上是对几个比较重要的函数的内部调用情况列了出来。

HEVC:码率控制K0103提案学习(二)

跟以前的方法类似,码率控制方法还是分为两大步骤:比特分配以及调整编码参数来达到目标码率,在第二步中才会用到R-λ模型。

下面先看比特分配。分为三个级别,GOP层、图片层和基本编码单元层。
首先计算每幅图片的目标比特数,f为帧率,Rtar为目标码率
HEVC:码率控制K0103提案学习(二)

设已编码图片的数量为Ncoded,这些图片用掉的比特数为Rcoded,当前GOP中的图片数量为NGOP ,SW是平滑比特分配的滑动窗口的大小,用于使得比特消耗变化和编码图片的质量更加平缓,在这里设为40,则GOP级别的比特分配

HEVC:码率控制K0103提案学习(二)

我们希望能在SW帧之后达到目标码率,如果SW帧图片可以正好做到每一帧消耗TAvgPic 比特,则上式可以改写为

HEVC:码率控制K0103提案学习(二)

式子的第一部分代表目标码率,第二部分则代表buffer的状态
对应代码如下

[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode  
  4. TEncRateCtrl::initRCGOP  
  5. TEncRCGOP::create  
  6. TEncRCGOP:: xEstGOPTargetBits  
  7.   
  8. 事先定义有 const Int g_RCSmoothWindowSize = 40;  
  9. Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize )  
  10. {  
  11.   Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() );  
  12.   
  13.   Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() );  
  14.   Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture );  
  15.   Int targetBits = currentTargetBitsPerPic * GOPSize;  
  16.   
  17.   if ( targetBits < 200 )  
  18.   {  
  19.     targetBits = 200;   // at least allocate 200 bits for one GOP  
  20.   }  
  21.   
  22.   return targetBits;  
  23. }  

然后是图片级别的比特分配
设当前GOP已经用掉的比特数为CodedGOP ,ω 是每幅图片的比特分配权重,则当前图片的目标比特率为
HEVC:码率控制K0103提案学习(二)

[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode(先initRCGOP再compressGOP)  
  4. TEncGOP::compressGOP  
  5. TEncRateCtrl::initRCPic  
  6. TEncRCPic::create  
  7. TEncRCPic::xEstPicTargetBits  
  8. Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )  
  9. {  
  10.   Int targetBits        = 0;  
  11.   Int GOPbitsLeft       = encRCGOP->getBitsLeft();  
  12.   
  13.   Int i;  
  14.   Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();  
  15.   Int currPicRatio    = encRCSeq->getBitRatio( currPicPosition );  
  16.   Int totalPicRatio   = 0;  
  17.   for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )  
  18.   {  
  19.     totalPicRatio += encRCSeq->getBitRatio( i );  
  20.   }  
  21.   
  22.   targetBits  = Int( GOPbitsLeft * currPicRatio / totalPicRatio );  
  23.   
  24.   if ( targetBits < 100 )  
  25.   {  
  26.     targetBits = 100;   // at least allocate 100 bits for one picture  
  27.   }  
  28.   
  29.   if ( m_encRCSeq->getFramesLeft() > 16 )  
  30.   {  
  31.     targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );  
  32.   }  
  33.   
  34.   return targetBits;  
  35. }  
  36.   
  37. 同时有  
  38. if ( targetBits < estHeaderBits + 100 )  
  39.   {  
  40.     targetBits = estHeaderBits + 100;   // at least allocate 100 bits for picture data  
  41.   }  

上式可以根据不同图片的权重分配剩余的比特,ω 的值如下

HEVC:码率控制K0103提案学习(二)

HEVC:码率控制K0103提案学习(二)

在实际的应用中,所有图片均使用相同的ω是一种选择(即Equal allocation),这样设置会导致每幅图片消耗的比特差别不大。图片之间分级分配比特是另一种不错的选择(Hierarchical allocation),因为图片之间分级的分配比特可以对编码性能带来不小的提升。K0103的码率控制算法支持均匀分配比特和分级分配比特。

[cpp] view plain copy
  1. Main  
  2. TAppEncTop::encode  
  3. TAppEncTop::xCreateLib  
  4. TEncTop::create  
  5. TEncRateCtrl::init  
  6.   
  7. Int* bitsRatio;  
  8.   bitsRatio = new Int[ GOPSize ];  
  9.   for ( Int i=0; i<GOPSize; i++ )  
  10.   {  
  11.     bitsRatio[i] = 10;  
  12.     if ( !GOPList[i].m_refPic )  
  13.     {  
  14.       bitsRatio[i] = 2;  
  15.     }  
  16.   }  
  17. if ( keepHierBits )  
  18.   {  
  19.     Double bpp = (Double)( targetBitrate / (Double)( frameRate*picWidth*picHeight ) );  
  20.     if ( GOPSize == 4 && isLowdelay )  
  21.     {  
  22.       if ( bpp > 0.2 )  
  23.       {  
  24.         bitsRatio[0] = 2;  
  25.         bitsRatio[1] = 3;  
  26.         bitsRatio[2] = 2;  
  27.         bitsRatio[3] = 6;  
  28.       }  
  29.       else if( bpp > 0.1 )  
  30.       {  
  31.         bitsRatio[0] = 2;  
  32.         bitsRatio[1] = 3;  
  33.         bitsRatio[2] = 2;  
  34.         bitsRatio[3] = 10;  
  35.       }  
  36.       else if ( bpp > 0.05 )  
  37.       {  
  38.         bitsRatio[0] = 2;  
  39.         bitsRatio[1] = 3;  
  40.         bitsRatio[2] = 2;  
  41.         bitsRatio[3] = 12;  
  42.       }  
  43.       else  
  44.       {  
  45.         bitsRatio[0] = 2;  
  46.         bitsRatio[1] = 3;  
  47.         bitsRatio[2] = 2;  
  48.         bitsRatio[3] = 14;  
  49.       }  
  50.     }  
  51.     else if ( GOPSize == 8 && !isLowdelay )  
  52.     {  
  53.       if ( bpp > 0.2 )  
  54.       {  
  55.         bitsRatio[0] = 15;  
  56.         bitsRatio[1] = 5;  
  57.         bitsRatio[2] = 4;  
  58.         bitsRatio[3] = 1;  
  59.         bitsRatio[4] = 1;  
  60.         bitsRatio[5] = 4;  
  61.         bitsRatio[6] = 1;  
  62.         bitsRatio[7] = 1;  
  63.       }  
  64.       else if ( bpp > 0.1 )  
  65.       {  
  66.         bitsRatio[0] = 20;  
  67.         bitsRatio[1] = 6;  
  68.         bitsRatio[2] = 4;  
  69.         bitsRatio[3] = 1;  
  70.         bitsRatio[4] = 1;  
  71.         bitsRatio[5] = 4;  
  72.         bitsRatio[6] = 1;  
  73.         bitsRatio[7] = 1;  
  74.       }  
  75.       else if ( bpp > 0.05 )  
  76.       {  
  77.         bitsRatio[0] = 25;  
  78.         bitsRatio[1] = 7;  
  79.         bitsRatio[2] = 4;  
  80.         bitsRatio[3] = 1;  
  81.         bitsRatio[4] = 1;  
  82.         bitsRatio[5] = 4;  
  83.         bitsRatio[6] = 1;  
  84.         bitsRatio[7] = 1;  
  85.       }  
  86.       else  
  87.       {  
  88.         bitsRatio[0] = 30;  
  89.         bitsRatio[1] = 8;  
  90.         bitsRatio[2] = 4;  
  91.         bitsRatio[3] = 1;  
  92.         bitsRatio[4] = 1;  
  93.         bitsRatio[5] = 4;  
  94.         bitsRatio[6] = 1;  
  95.         bitsRatio[7] = 1;  
  96.       }  
  97.     }  
  98.     else  
  99.     {  
  100.       printf( "\n hierarchical bit allocation is not support for the specified coding structure currently." );  
  101.     }  
  102.   }  

对于帧内编码图像,当QP和λ未指定时,分配给帧内编码图像的比特数(TCurrPic)修正如下

HEVC:码率控制K0103提案学习(二)

需要注意的是,该修正值只在更新Rcoded 时使用(整个序列消耗的比特数),而不会用于更新CodedGOP (当前GOP消耗的比特数),这是因为帧内编码帧消耗的比特数往往很高,甚至高于给GOP分配的比特数,用未经修正的TCurrPic值更新CodedGOP

[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode(先initRCGOP再compressGOP)  
  4. TEncGOP::compressGOP  
  5. TEncRCSeq::getRefineBitsForIntra  
  6.   
  7. Int TEncRCSeq::getRefineBitsForIntra( Int orgBits )  
  8. {  
  9.   Double bpp = ( (Double)orgBits ) / m_picHeight / m_picHeight;  
  10.   if ( bpp > 0.2 )  
  11.   {  
  12.     return orgBits * 5;  
  13.   }  
  14.   if ( bpp > 0.1 )  
  15.   {  
  16.     return orgBits * 7;  
  17.   }  
  18.   return orgBits * 10;  
  19. }  

LCU层的比特分配
在该提案中认为一个基本单元包含一个LCU,其目标比特数由下式决定
HEVC:码率控制K0103提案学习(二)

Bitheader 是所有头信息比特数的估计值,由同一层之前的已编码图片的实际头信息比特数估计得来。

[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode(先initRCGOP再compressGOP)  
  4. TEncGOP::compressGOP  
  5. TEncRateCtrl::initRCPic  
  6. TEncRCPic::create(先xEstPicTargetBits再xEstPicHeaderBits)  
  7. TEncRCPic:: xEstPicHeaderBits  
  8.   
  9. Int TEncRCPic::xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel )  
  10. {  
  11.   Int numPreviousPics   = 0;  
  12.   Int totalPreviousBits = 0;  
  13.   
  14.   list<TEncRCPic*>::iterator it;  
  15.   for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )  
  16.   {  
  17.     if ( (*it)->getFrameLevel() == frameLevel )  
  18.     {  
  19.       totalPreviousBits += (*it)->getPicActualHeaderBits();  
  20.       numPreviousPics++;  
  21.     }  
  22.   }  
  23.   
  24.   Int estHeaderBits = 0;  
  25.   if ( numPreviousPics > 0 )  
  26.   {  
  27.     estHeaderBits = totalPreviousBits / numPreviousPics;  
  28.   }  
  29.   
  30.   return estHeaderBits;  
  31. }  

ω 则是每个LCU的权重,根据根据之前编码的,在同一级别图片中处于同一位置的基本单元的预测误差(MAD)进行计算,如下

HEVC:码率控制K0103提案学习(二)

以上就是比特分配的过程。

[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode(先initRCGOP再compressGOP)  
  4. TEncGOP::compressGOP  
  5. TEncSlice::compressSlice  
  6. TEncRCPic::getLCUTargetBpp  
  7.   
  8. Double TEncRCPic::getLCUTargetBpp()  
  9. {  
  10.   Int   LCUIdx    = getLCUCoded();  
  11.   Double bpp      = -1.0;  
  12.   Int avgBits     = 0;  
  13.   Double totalMAD = -1.0;  
  14.   Double MAD      = -1.0;  
  15.   
  16.   if ( m_lastPicture == NULL )  
  17.   {  
  18.     avgBits = Int( m_bitsLeft / m_LCULeft );  
  19.   }  
  20.   else  
  21.   {  
  22.     MAD = m_lastPicture->getLCU(LCUIdx).m_MAD;  
  23.     totalMAD = m_lastPicture->getTotalMAD();  
  24.     for ( Int i=0; i<LCUIdx; i++ )  
  25.     {  
  26.       totalMAD -= m_lastPicture->getLCU(i).m_MAD;  
  27.     }  
  28.   
  29.     if ( totalMAD > 0.1 )  
  30.     {  
  31.       avgBits = Int( m_bitsLeft * MAD / totalMAD );  
  32.     }  
  33.     else  
  34.     {  
  35.       avgBits = Int( m_bitsLeft / m_LCULeft );  
  36.     }  
  37.   }  
  38.   
  39. #if L0033_RC_BUGFIX  
  40.   if ( avgBits < 1 )  
  41.   {  
  42.     avgBits = 1;  
  43.   }  
  44. #else  
  45.   if ( avgBits < 5 )  
  46.   {  
  47.     avgBits = 5;  
  48.   }  
  49. #endif  
  50.   
  51.   bpp = ( Double )avgBits/( Double )m_LCUs[ LCUIdx ].m_numberOfPixel;  
  52.   m_LCUs[ LCUIdx ].m_targetBits = avgBits;  
  53.   
  54.   return bpp;  
  55. }  

然后是第二步,即如何达到分配的目标比特数
首先将前面的R-λ模型变为如下形式
HEVC:码率控制K0103提案学习(二)

使用上式依据一幅图片或者一个LCU的目标码率尺推导得到当前图片或者当前LCU编码所需要使用的λ。现在唯一的问题是,在不同编码序列的情况下,模型可能会拥有完全不相同的α和β值。此外,即使对于同一序列,处于不同级别的图片也可能拥有完全不相同的α和β值。例如,当GOP大小为4时,图片共分为三个级别,这三个级别的图片的α和β值可能是不同的。另外,不同的基本编码单元也可能拥有不同的α和β值,在此,我们假设在同一级别图片中对应位置的基本编码单元的α和β值相同。
需要注意的是α和β值的初始值设置并不是很严重的问题,因为在编码过程中,α和β值会根据序列逐渐更新,并最终适应序列特性。
设α和β值的初始值分别为3.2003 和-1.367。

[cpp] view plain copy
  1. Main  
  2. TAppEncTop::encode  
  3. TAppEncTop::xCreateLib  
  4. TEncTop::create  
  5. TEncRateCtrl::init  
  6. TEncRCSeq::initPicPara  
  7.   
  8. Void TEncRCSeq::initPicPara( TRCParameter* picPara )  
  9. {  
  10.   assert( m_picPara != NULL );  
  11.   
  12.   if ( picPara == NULL )  
  13.   {  
  14.     for ( Int i=0; i<m_numberOfLevel; i++ )  
  15.     {  
  16.       m_picPara[i].m_alpha = 3.2003;  
  17.       m_picPara[i].m_beta  = -1.367;  
  18.     }  
  19.   }  
  20.   else  
  21.   {  
  22.     for ( Int i=0; i<m_numberOfLevel; i++ )  
  23.     {  
  24.       m_picPara[i] = picPara[i];  
  25.     }  
  26.   }  
  27. }  
  28.   
  29. 以及  
  30. Main  
  31. TAppEncTop::encode  
  32. TAppEncTop::xCreateLib  
  33. TEncTop::create  
  34. TEncRateCtrl::init  
  35. TEncRCSeq::initLCUPara  
  36.   
  37. Void TEncRCSeq::initLCUPara( TRCParameter** LCUPara )  
  38. {  
  39.   if ( m_LCUPara == NULL )  
  40.   {  
  41.     return;  
  42.   }  
  43.   if ( LCUPara == NULL )  
  44.   {  
  45.     for ( Int i=0; i<m_numberOfLevel; i++ )  
  46.     {  
  47.       for ( Int j=0; j<m_numberOfLCU; j++)  
  48.       {  
  49.         m_LCUPara[i][j].m_alpha = 3.2003;  
  50.         m_LCUPara[i][j].m_beta  = -1.367;  
  51.       }  
  52.     }  
  53.   }  
  54.   else  
  55.   {  
  56.     for ( Int i=0; i<m_numberOfLevel; i++ )  
  57.     {  
  58.       for ( Int j=0; j<m_numberOfLCU; j++)  
  59.       {  
  60.         m_LCUPara[i][j] = LCUPara[i][j];  
  61.       }  
  62.     }  
  63.   }  
  64. }  


确定λ之后,使用下式得到QP值

HEVC:码率控制K0103提案学习(二)

[cpp] view plain copy
  1. Int QP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 );  


最后是参数更新步骤
在编码完一个LCU或者一幅图像之后,需要使用真正的bpp值(bppreal)和λ值(λreal)来更新α和β值。需要注意的是,在一幅图像中,每一个LCU都有他自己的λ值,而整幅图像的λ为所有LCU的λ的几何平均值
HEVC:码率控制K0103提案学习(二)

[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode(先initRCGOP再compressGOP)  
  4. TEncGOP::compressGOP  
  5. TEncRCPic::calAverageLambda  
  6.   
  7. Double TEncRCPic::calAverageLambda()  
  8. {  
  9.   Double totalLambdas = 0.0;  
  10.   Int numTotalLCUs = 0;  
  11.   
  12.   Int i;  
  13.   for ( i=0; i<m_numberOfLCU; i++ )  
  14.   {  
  15.     if ( m_LCUs[i].m_lambda > 0.01 )  
  16.     {  
  17.       totalLambdas += log( m_LCUs[i].m_lambda );  
  18.       numTotalLCUs++;  
  19.     }  
  20.   }  
  21.   
  22.   Double avgLambda;   
  23.   if( numTotalLCUs == 0 )  
  24.   {  
  25.     avgLambda = -1.0;  
  26.   }  
  27.   else  
  28.   {  
  29.     avgLambda = pow( 2.7183, totalLambdas / numTotalLCUs );  
  30.   }  
  31.   return avgLambda;  
  32. }  

至于QP平均值的计算,就是用常见的算术平均值
[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode(先initRCGOP再compressGOP)  
  4. TEncGOP::compressGOP  
  5. TEncRCPic:: calAverageQP  
  6.   
  7. Double TEncRCPic::calAverageQP()  
  8. {  
  9.   Int totalQPs = 0;  
  10.   Int numTotalLCUs = 0;  
  11.   
  12.   Int i;  
  13.   for ( i=0; i<m_numberOfLCU; i++ )  
  14.   {  
  15.     if ( m_LCUs[i].m_QP > 0 )  
  16.     {  
  17.       totalQPs += m_LCUs[i].m_QP;  
  18.       numTotalLCUs++;  
  19.     }  
  20.   }  
  21.   
  22.   Double avgQP = 0.0;  
  23.   if ( numTotalLCUs == 0 )  
  24.   {  
  25.     avgQP = g_RCInvalidQPValue;  
  26.   }  
  27.   else  
  28.   {  
  29.     avgQP = ((Double)totalQPs) / ((Double)numTotalLCUs);  
  30.   }  
  31.   return avgQP;  
  32. }  

更新过程按下式进行

HEVC:码率控制K0103提案学习(二)

[cpp] view plain copy
  1. Double estLambda = alpha * pow( bpp, beta );  

HEVC:码率控制K0103提案学习(二)

[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode(先initRCGOP再compressGOP)  
  4. TEncGOP::compressGOP  
  5. TEncRCPic::updateAfterLCU  
  6.   
  7. Void TEncRCPic::updateAfterLCU( Int LCUIdx, Int bits, Int QP, Double lambda, Bool updateLCUParameter )  
  8. {  
  9.   m_LCUs[LCUIdx].m_actualBits = bits;  
  10.   m_LCUs[LCUIdx].m_QP         = QP;  
  11.   m_LCUs[LCUIdx].m_lambda     = lambda;  
  12.   
  13.   m_LCULeft--;  
  14.   m_bitsLeft   -= bits;  
  15.   m_pixelsLeft -= m_LCUs[LCUIdx].m_numberOfPixel;  
  16.   
  17.   if ( !updateLCUParameter )  
  18.   {  
  19.     return;  
  20.   }  
  21.   
  22.   if ( !m_encRCSeq->getUseLCUSeparateModel() )  
  23.   {  
  24.     return;  
  25.   }  
  26.   
  27.   Double alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha;  
  28.   Double beta  = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta;  
  29.   
  30.   Int LCUActualBits   = m_LCUs[LCUIdx].m_actualBits;  
  31.   Int LCUTotalPixels  = m_LCUs[LCUIdx].m_numberOfPixel;  
  32.   Double bpp         = ( Double )LCUActualBits/( Double )LCUTotalPixels;  
  33.   Double calLambda   = alpha * pow( bpp, beta );  
  34.   Double inputLambda = m_LCUs[LCUIdx].m_lambda;  
  35.   
  36.   if( inputLambda < 0.01 || calLambda < 0.01 || bpp < 0.0001 )  
  37.   {  
  38.     alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );  
  39.     beta  *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );  
  40.   
  41.     alpha = Clip3( 0.05, 20.0, alpha );  
  42.     beta  = Clip3( -3.0, -0.1, beta  );  
  43.   
  44.     TRCParameter rcPara;  
  45.     rcPara.m_alpha = alpha;  
  46.     rcPara.m_beta  = beta;  
  47.     m_encRCSeq->setLCUPara( m_frameLevel, LCUIdx, rcPara );  
  48.   
  49.     return;  
  50.   }  
  51.   
  52.   calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );  
  53.   alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;  
  54.   double lnbpp = log( bpp );  
  55.   lnbpp = Clip3( -5.0, 1.0, lnbpp );  
  56.   beta  += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;  
  57.   
  58.   alpha = Clip3( 0.05, 20.0, alpha );  
  59.   beta  = Clip3( -3.0, -0.1, beta  );  
  60.   TRCParameter rcPara;  
  61.   rcPara.m_alpha = alpha;  
  62.   rcPara.m_beta  = beta;  
  63.   m_encRCSeq->setLCUPara( m_frameLevel, LCUIdx, rcPara );  
  64.   
  65. }  
  66.   
  67. 以及  
  68. main  
  69. TAppEncTop::encode  
  70. TEncTop::encode(先initRCGOP再compressGOP)  
  71. TEncGOP::compressGOP  
  72. TEncRCPic:: updateAfterPicture  
  73.   
  74. Void TEncRCPic::updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, Double effectivePercentage )  
  75. {  
  76.   m_picActualHeaderBits = actualHeaderBits;  
  77.   m_picActualBits       = actualTotalBits;  
  78.   if ( averageQP > 0.0 )  
  79.   {  
  80.     m_picQP             = Int( averageQP + 0.5 );  
  81.   }  
  82.   else  
  83.   {  
  84.     m_picQP             = g_RCInvalidQPValue;  
  85.   }  
  86.   m_picLambda           = averageLambda;  
  87.   for ( Int i=0; i<m_numberOfLCU; i++ )  
  88.   {  
  89.     m_totalMAD += m_LCUs[i].m_MAD;  
  90.   }  
  91.   
  92.   Double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;  
  93.   Double beta  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;  
  94.   
  95.   // update parameters  
  96.   Double picActualBits = ( Double )m_picActualBits;  
  97.   Double picActualBpp  = picActualBits/(Double)m_numberOfPixel;  
  98.   Double calLambda     = alpha * pow( picActualBpp, beta );  
  99.   Double inputLambda   = m_picLambda;  
  100.   
  101.   if ( inputLambda < 0.01 || calLambda < 0.01 || picActualBpp < 0.0001 || effectivePercentage < 0.05 )  
  102.   {  
  103.     alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );  
  104.     beta  *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );  
  105.   
  106.     alpha = Clip3( 0.05, 20.0, alpha );  
  107.     beta  = Clip3( -3.0, -0.1, beta  );  
  108.     TRCParameter rcPara;  
  109.     rcPara.m_alpha = alpha;  
  110.     rcPara.m_beta  = beta;  
  111.     m_encRCSeq->setPicPara( m_frameLevel, rcPara );  
  112.   
  113.     return;  
  114.   }  
  115.   
  116.   calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );  
  117.   alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;  
  118.   double lnbpp = log( picActualBpp );  
  119.   lnbpp = Clip3( -5.0, 1.0, lnbpp );  
  120.   beta  += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;  
  121.   
  122.   alpha = Clip3( 0.05, 20.0, alpha );  
  123.   beta  = Clip3( -3.0, -0.1, beta  );  
  124.   
  125.   TRCParameter rcPara;  
  126.   rcPara.m_alpha = alpha;  
  127.   rcPara.m_beta  = beta;  
  128.   
  129.   m_encRCSeq->setPicPara( m_frameLevel, rcPara );  
  130. }  

δα 和δβ 设为0.1 和 0.05 

[cpp] view plain copy
  1.  Main  
  2. TAppEncTop::encode  
  3. TAppEncTop::xCreateLib  
  4. TEncTop::create  
  5. TEncRateCtrl::init  
  6. TEncRCSeq::create  
  7.   
  8.   m_numberOfPixel   = m_picWidth * m_picHeight;  
  9.   m_targetBits      = (Int64)m_totalFrames * (Int64)m_targetRate / (Int64)m_frameRate;  
  10.   m_seqTargetBpp = (Double)m_targetRate / (Double)m_frameRate / (Double)m_numberOfPixel;  
  11.   if ( m_seqTargetBpp < 0.03 )  
  12.   {  
  13.     m_alphaUpdate = 0.01;  
  14.     m_betaUpdate  = 0.005;  
  15.   }  
  16.   else if ( m_seqTargetBpp < 0.08 )  
  17.   {  
  18.     m_alphaUpdate = 0.05;  
  19.     m_betaUpdate  = 0.025;  
  20.   }  
  21.   else  
  22.   {  
  23.     m_alphaUpdate = 0.1;  
  24.     m_betaUpdate  = 0.05;  
  25.   }  

此外,在某些时候(如LCU使用了skip模式,或者一幅图片中有大量的skip模式的LCU)可能出现bpp过小的情况,此时用下式进行更新

HEVC:码率控制K0103提案学习(二)

当然,α和β也是有范围限定的。α 的值限定在 [0.05, 20] 而 β 的值限定在 [−3.0, −0.1].

[cpp] view plain copy
  1. alpha = Clip3( 0.05, 20.0, alpha );  
  2. beta  = Clip3( -3.0, -0.1, beta  );  

当然,λ和QP值将会被限定在一个范围内
在图像层,有
HEVC:码率控制K0103提案学习(二)

[cpp] view plain copy
  1. main  
  2. TAppEncTop::encode  
  3. TEncTop::encode(先initRCGOP再compressGOP)  
  4. TEncGOP::compressGOP  
  5.   
  6. Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures )  
  7. {  
  8.   Double alpha         = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;  
  9.   Double beta          = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;  
  10.   Double bpp       = (Double)m_targetBits/(Double)m_numberOfPixel;  
  11.   Double estLambda = alpha * pow( bpp, beta );  
  12.   Double lastLevelLambda = -1.0;  
  13.   Double lastPicLambda   = -1.0;  
  14.   Double lastValidLambda = -1.0;  
  15.   list<TEncRCPic*>::iterator it;  
  16.   for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )  
  17.   {  
  18.     if ( (*it)->getFrameLevel() == m_frameLevel )  
  19.     {  
  20.       lastLevelLambda = (*it)->getPicActualLambda();  
  21.     }  
  22.     lastPicLambda     = (*it)->getPicActualLambda();  
  23.   
  24.     if ( lastPicLambda > 0.0 )  
  25.     {  
  26.       lastValidLambda = lastPicLambda;  
  27.     }  
  28.   }  
  29.   
  30.   if ( lastLevelLambda > 0.0 )  
  31.   {  
  32.     lastLevelLambda = Clip3( 0.1, 10000.0, lastLevelLambda );  
  33.     estLambda = Clip3( lastLevelLambda * pow( 2.0, -3.0/3.0 ), lastLevelLambda * pow( 2.0, 3.0/3.0 ), estLambda );  
  34.   }  
  35.   
  36.   if ( lastPicLambda > 0.0 )  
  37.   {  
  38.     lastPicLambda = Clip3( 0.1, 2000.0, lastPicLambda );  
  39.     estLambda = Clip3( lastPicLambda * pow( 2.0, -10.0/3.0 ), lastPicLambda * pow( 2.0, 10.0/3.0 ), estLambda );  
  40.   }  
  41.   else if ( lastValidLambda > 0.0 )  
  42.   {  
  43.     lastValidLambda = Clip3( 0.1, 2000.0, lastValidLambda );  
  44.     estLambda = Clip3( lastValidLambda * pow(2.0, -10.0/3.0), lastValidLambda * pow(2.0, 10.0/3.0), estLambda );  
  45.   }  
  46.   else  
  47.   {  
  48.     estLambda = Clip3( 0.1, 10000.0, estLambda );  
  49.   }  
  50.   
  51.   if ( estLambda < 0.1 )  
  52.   {  
  53.     estLambda = 0.1;  
  54.   }  
  55.   
  56.   m_estPicLambda = estLambda;  
  57.   return estLambda;  
  58. }  
  59.   
  60. Int TEncRCPic::estimatePicQP( Double lambda, list<TEncRCPic*>& listPreviousPictures )  
  61. {  
  62.   Int QP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 );   
  63.   
  64.   Int lastLevelQP = g_RCInvalidQPValue;  
  65.   Int lastPicQP   = g_RCInvalidQPValue;  
  66.   Int lastValidQP = g_RCInvalidQPValue;  
  67.   list<TEncRCPic*>::iterator it;  
  68.   for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )  
  69.   {  
  70.     if ( (*it)->getFrameLevel() == m_frameLevel )  
  71.     {  
  72.       lastLevelQP = (*it)->getPicActualQP();  
  73.     }  
  74.     lastPicQP = (*it)->getPicActualQP();  
  75.     if ( lastPicQP > g_RCInvalidQPValue )  
  76.     {  
  77.       lastValidQP = lastPicQP;  
  78.     }  
  79.   }  
  80.   
  81.   if ( lastLevelQP > g_RCInvalidQPValue )  
  82.   {  
  83.     QP = Clip3( lastLevelQP - 3, lastLevelQP + 3, QP );  
  84.   }  
  85.   
  86.   if( lastPicQP > g_RCInvalidQPValue )  
  87.   {  
  88.     QP = Clip3( lastPicQP - 10, lastPicQP + 10, QP );  
  89.   }  
  90.   else if( lastValidQP > g_RCInvalidQPValue )  
  91.   {  
  92.     QP = Clip3( lastValidQP - 10, lastValidQP + 10, QP );  
  93.   }  
  94.   
  95.   return QP;  
  96. }  


在LCU层有

HEVC:码率控制K0103提案学习(二)

[cpp] view plain copy
  1. Double TEncRCPic::getLCUEstLambda( Double bpp )  
  2. {  
  3.   Int   LCUIdx = getLCUCoded();  
  4.   Double alpha;  
  5.   Double beta;  
  6.   if ( m_encRCSeq->getUseLCUSeparateModel() )  
  7.   {  
  8.     alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha;  
  9.     beta  = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta;  
  10.   }  
  11.   else  
  12.   {  
  13.     alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;  
  14.     beta  = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;  
  15.   }  
  16.   
  17.   Double estLambda = alpha * pow( bpp, beta );  
  18.   //for Lambda clip, picture level clip  
  19.   Double clipPicLambda = m_estPicLambda;  
  20.   
  21.   //for Lambda clip, LCU level clip  
  22.   Double clipNeighbourLambda = -1.0;  
  23.   for ( int i=LCUIdx - 1; i>=0; i-- )  
  24.   {  
  25.     if ( m_LCUs[i].m_lambda > 0 )  
  26.     {  
  27.       clipNeighbourLambda = m_LCUs[i].m_lambda;  
  28.       break;  
  29.     }  
  30.   }  
  31.   
  32.   if ( clipNeighbourLambda > 0.0 )  
  33.   {  
  34.     estLambda = Clip3( clipNeighbourLambda * pow( 2.0, -1.0/3.0 ), clipNeighbourLambda * pow( 2.0, 1.0/3.0 ), estLambda );  
  35.   }    
  36.   
  37.   if ( clipPicLambda > 0.0 )  
  38.   {  
  39.     estLambda = Clip3( clipPicLambda * pow( 2.0, -2.0/3.0 ), clipPicLambda * pow( 2.0, 2.0/3.0 ), estLambda );  
  40.   }  
  41.   else  
  42.   {  
  43.     estLambda = Clip3( 10.0, 1000.0, estLambda );  
  44.   }  
  45.   
  46.   if ( estLambda < 0.1 )  
  47.   {  
  48.     estLambda = 0.1;  
  49.   }  
  50.   
  51.   return estLambda;  
  52. }  
  53.   
  54. Int TEncRCPic::getLCUEstQP( Double lambda, Int clipPicQP )  
  55. {  
  56.   Int LCUIdx = getLCUCoded();  
  57.   Int estQP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 );  
  58.   
  59.   //for Lambda clip, LCU level clip  
  60.   Int clipNeighbourQP = g_RCInvalidQPValue;  
  61. #if L0033_RC_BUGFIX  
  62.   for ( int i=LCUIdx - 1; i>=0; i-- )  
  63. #else  
  64.   for ( int i=LCUIdx; i>=0; i-- )  
  65. #endif  
  66.   {  
  67.     if ( (getLCU(i)).m_QP > g_RCInvalidQPValue )  
  68.     {  
  69.       clipNeighbourQP = getLCU(i).m_QP;  
  70.       break;  
  71.     }  
  72.   }  
  73.   
  74.   if ( clipNeighbourQP > g_RCInvalidQPValue )  
  75.   {  
  76.     estQP = Clip3( clipNeighbourQP - 1, clipNeighbourQP + 1, estQP );  
  77.   }  
  78.   
  79.   estQP = Clip3( clipPicQP - 2, clipPicQP + 2, estQP );  
  80.   
  81.   return estQP;  
  82. }  

相关文章:

  • 2022-12-23
  • 2021-08-17
  • 2022-12-23
  • 2021-05-09
  • 2021-09-16
  • 2022-01-09
猜你喜欢
  • 2021-05-09
  • 2021-09-18
  • 2022-12-23
  • 2021-11-16
  • 2022-01-26
  • 2022-01-09
  • 2022-01-12
相关资源
相似解决方案