HEVC码率控制浅析——HM代码阅读之三
2013-10-20 10:19
337 查看
续上文继续分析
m_pcRateCtrl->initRCPic( )
[cpp] view
plaincopy
Void TEncRateCtrl::initRCPic( Int frameLevel )
{
m_encRCPic = new TEncRCPic;
m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures );
}
m_encRCPic->create
[cpp] view
plaincopy
Void TEncRCPic::create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures )
{
destroy();
m_encRCSeq = encRCSeq;
m_encRCGOP = encRCGOP;
Int targetBits = xEstPicTargetBits( encRCSeq, encRCGOP ); //!< K0103式子(9)
Int estHeaderBits = xEstPicHeaderBits( listPreviousPictures, frameLevel ); //!< header bits estimation
if ( targetBits < estHeaderBits + 100 )
{
targetBits = estHeaderBits + 100; // at least allocate 100 bits for picture data
}
//!< 以下为RC相关参数的初始化,根据变量名很容易就能判断其用途,故不罗嗦~
m_frameLevel = frameLevel;
m_numberOfPixel = encRCSeq->getNumPixel();
m_numberOfLCU = encRCSeq->getNumberOfLCU();
m_estPicLambda = 100.0;
m_targetBits = targetBits;
m_estHeaderBits = estHeaderBits;
m_bitsLeft = m_targetBits;
Int picWidth = encRCSeq->getPicWidth();
Int picHeight = encRCSeq->getPicHeight();
Int LCUWidth = encRCSeq->getLCUWidth();
Int LCUHeight = encRCSeq->getLCUHeight();
Int picWidthInLCU = ( picWidth % LCUWidth ) == 0 ? picWidth / LCUWidth : picWidth / LCUWidth + 1;
Int picHeightInLCU = ( picHeight % LCUHeight ) == 0 ? picHeight / LCUHeight : picHeight / LCUHeight + 1;
m_LCULeft = m_numberOfLCU;
m_bitsLeft -= m_estHeaderBits; //!< 考虑header bits后的剩余比特数
m_pixelsLeft = m_numberOfPixel;
m_LCUs = new TRCLCU[m_numberOfLCU];
Int i, j;
Int LCUIdx;
for ( i=0; i<picWidthInLCU; i++ )
{
for ( j=0; j<picHeightInLCU; j++ )
{
LCUIdx = j*picWidthInLCU + i;
m_LCUs[LCUIdx].m_actualBits = 0;
m_LCUs[LCUIdx].m_QP = 0;
m_LCUs[LCUIdx].m_lambda = 0.0;
m_LCUs[LCUIdx].m_targetBits = 0;
#if M0036_RC_IMPROVEMENT
m_LCUs[LCUIdx].m_bitWeight = 1.0;
#else
m_LCUs[LCUIdx].m_MAD = 0.0;
#endif
Int currWidth = ( (i == picWidthInLCU -1) ? picWidth - LCUWidth *(picWidthInLCU -1) : LCUWidth );
Int currHeight = ( (j == picHeightInLCU-1) ? picHeight - LCUHeight*(picHeightInLCU-1) : LCUHeight );
m_LCUs[LCUIdx].m_numberOfPixel = currWidth * currHeight;
}
}
m_picActualHeaderBits = 0;
#if !M0036_RC_IMPROVEMENT
m_totalMAD = 0.0;
#endif
m_picActualBits = 0;
m_picQP = 0;
m_picLambda = 0.0;
#if !M0036_RC_IMPROVEMENT
m_lastPicture = NULL;
list<TEncRCPic*>::reverse_iterator it;
for ( it = listPreviousPictures.rbegin(); it != listPreviousPictures.rend(); it++ )
{
if ( (*it)->getFrameLevel() == m_frameLevel ) //!< 保存跟当前帧同一层的前一帧
{
m_lastPicture = (*it);
break;
}
}
#endif
}
m_encRCPic->create子函数xEstPicTargetBits()
[cpp] view
plaincopy
<span style="font-size:12px;">Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )
{
Int targetBits = 0;
Int GOPbitsLeft = encRCGOP->getBitsLeft(); //!< TGOP - CodedGOP
Int i;
Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();
Int currPicRatio = encRCSeq->getBitRatio( currPicPosition ); //!< 当前picture的权值
Int totalPicRatio = 0;
for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )
{
totalPicRatio += encRCSeq->getBitRatio( i ); //!< 总权值
}
#if M0036_RC_IMPROVEMENT
targetBits = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio );
#else
targetBits = Int( GOPbitsLeft * currPicRatio / totalPicRatio );
#endif
if ( targetBits < 100 )
{
targetBits = 100; // at least allocate 100 bits for one picture
}
//!< 在此之前targetBits是基于K0103式子(9)计算的结果,而m_encRCGOP->getTargetBitInGOP( currPicPosition )得到的
//!< bits为NotCodedPictures=0通过式子(9)得到的
if ( m_encRCSeq->getFramesLeft() > 16 )
{
targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );
}
return targetBits;
}</span>
m_encRCPic->create子函数xEstPicHeaderBits()
[cpp] view
plaincopy
<span style="font-size:12px;">Int TEncRCPic::xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel )
{
Int numPreviousPics = 0;
Int totalPreviousBits = 0;
list<TEncRCPic*>::iterator it;
for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ ) //!< 求出当前帧之前所有与其在同一层的帧的header bits之和
{
if ( (*it)->getFrameLevel() == frameLevel )
{
totalPreviousBits += (*it)->getPicActualHeaderBits();
numPreviousPics++;
}
}
Int estHeaderBits = 0;
if ( numPreviousPics > 0 ) //!< 取平均值
{
estHeaderBits = totalPreviousBits / numPreviousPics;
}
return estHeaderBits;
}</span>
分析第一篇提到的compressGOP中的RC初始化代码片段:
[cpp] view
plaincopy
<span style="font-size:12px;">#if RATE_CONTROL_LAMBDA_DOMAIN
Double lambda = 0.0;
Int actualHeadBits = 0;
Int actualTotalBits = 0;
Int estimatedBits = 0;
Int tmpBitsBeforeWriting = 0;
if ( m_pcCfg->getUseRateCtrl() )
{
Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );
if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )
{
frameLevel = 0;
}
m_pcRateCtrl->initRCPic( frameLevel ); //!< picture level 初始化
estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits(); //!< 在initRCPic中已经计算出了targetBits
Int sliceQP = m_pcCfg->getInitialQP(); //!< 对应于配置文件中的InitalQP
if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified
{//!< 如果配置文件对序列第一帧指定了初始QP,则基于这个QP计算出lamda
Int NumberBFrames = ( m_pcCfg->getGOPSize() - 1 );
Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames );
Double dQPFactor = 0.57*dLambda_scale;
Int SHIFT_QP = 12;
Int bitdepth_luma_qp_scale = 0;
Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP;
lambda = dQPFactor*pow( 2.0, qp_temp/3.0 );
}
else if ( frameLevel == 0 ) // intra case, but use the model
{ //!< 对I slice的情况,需要做些特殊处理,如targetBits的修正等
#if RATE_CONTROL_INTRA
m_pcSliceEncoder->calCostSliceI(pcPic);
#endif
if ( m_pcCfg->getIntraPeriod() != 1 ) // do not refine allocated bits for all intra case
{
Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits();
#if RATE_CONTROL_INTRA
bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits );
#else
bits = m_pcRateCtrl->getRCSeq()->getRefineBitsForIntra( bits ); //!< K0103 Table 3
#endif
if ( bits < 200 )
{
bits = 200;
}
m_pcRateCtrl->getRCPic()->setTargetBits( bits );
}
list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
#if RATE_CONTROL_INTRA
m_pcRateCtrl->getRCPic()->getLCUInitTargetBits();
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
#else
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture );
#endif
sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
}
else // normal case
{
list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
#if RATE_CONTROL_INTRA
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
#else
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture );
#endif
sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
}
sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, sliceQP );
m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP );
m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda ); //!< 设置当前slice使用的QP, lambda,编码时用到
}
#endif</span>
compressGOP子函数getRefineBitsForIntra()
[cpp] view
plaincopy
<span style="font-size:12px;">#if !RATE_CONTROL_INTRA
Int TEncRCSeq::getRefineBitsForIntra( Int orgBits ) //!< K0103 Table 3
{
Double bpp = ( (Double)orgBits ) / m_picHeight / m_picHeight;
if ( bpp > 0.2 )
{
return orgBits * 5;
}
if ( bpp > 0.1 )
{
return orgBits * 7;
}
return orgBits * 10;
}
#endif</span>
compressGOP子函数estimatePicLambda()
[cpp] view
plaincopy
<span style="font-size:12px;">#if RATE_CONTROL_INTRA
Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures, SliceType eSliceType)
#else
Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures )
#endif
{
Double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
Double beta = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
Double bpp = (Double)m_targetBits/(Double)m_numberOfPixel;
#if RATE_CONTROL_INTRA
Double estLambda;
if (eSliceType == I_SLICE)
{
estLambda = calculateLambdaIntra(alpha, beta, pow(m_totalCostIntra/(Double)m_numberOfPixel, BETA1), bpp);
}
else
{
estLambda = alpha * pow( bpp, beta );
}
#else
Double estLambda = alpha * pow( bpp, beta ); //!< K0103 式子(10)
#endif
Double lastLevelLambda = -1.0;
Double lastPicLambda = -1.0;
Double lastValidLambda = -1.0;
list<TEncRCPic*>::iterator it;
for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )
{
if ( (*it)->getFrameLevel() == m_frameLevel )
{
lastLevelLambda = (*it)->getPicActualLambda();
}
lastPicLambda = (*it)->getPicActualLambda();
if ( lastPicLambda > 0.0 )
{
lastValidLambda = lastPicLambda;
}
}
//!< 以下对lastLevelLambda和estLambda进行clip,范围在K0103的section 3.2中进行了定义
if ( lastLevelLambda > 0.0 )
{
lastLevelLambda = Clip3( 0.1, 10000.0, lastLevelLambda );
estLambda = Clip3( lastLevelLambda * pow( 2.0, -3.0/3.0 ), lastLevelLambda * pow( 2.0, 3.0/3.0 ), estLambda );
}
if ( lastPicLambda > 0.0 )
{
lastPicLambda = Clip3( 0.1, 2000.0, lastPicLambda );
estLambda = Clip3( lastPicLambda * pow( 2.0, -10.0/3.0 ), lastPicLambda * pow( 2.0, 10.0/3.0 ), estLambda );
}
else if ( lastValidLambda > 0.0 )
{
lastValidLambda = Clip3( 0.1, 2000.0, lastValidLambda );
estLambda = Clip3( lastValidLambda * pow(2.0, -10.0/3.0), lastValidLambda * pow(2.0, 10.0/3.0), estLambda );
}
else
{
estLambda = Clip3( 0.1, 10000.0, estLambda );
}
if ( estLambda < 0.1 )
{
estLambda = 0.1;
}
m_estPicLambda = estLambda;
#if M0036_RC_IMPROVEMENT
Double totalWeight = 0.0;
// initial BU bit allocation weight
for ( Int i=0; i<m_numberOfLCU; i++ )
{
#if RC_FIX
Double alphaLCU, betaLCU;
if ( m_encRCSeq->getUseLCUSeparateModel() )
{
alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha;
betaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta;
}
else
{
alphaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
betaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
}
#else
Double alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha;
Double betaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta;
#endif
m_LCUs[i].m_bitWeight = m_LCUs[i].m_numberOfPixel * pow( estLambda/alphaLCU, 1.0/betaLCU );
if ( m_LCUs[i].m_bitWeight < 0.01 )
{
m_LCUs[i].m_bitWeight = 0.01;
}
totalWeight += m_LCUs[i].m_bitWeight;
}
for ( Int i=0; i<m_numberOfLCU; i++ )
{
Double BUTargetBits = m_targetBits * m_LCUs[i].m_bitWeight / totalWeight;
m_LCUs[i].m_bitWeight = BUTargetBits;
}
#endif
return estLambda;
}</span>
compressGOP子函数estimatePicQP()
[cpp] view
plaincopy
<span style="font-size:12px;">Int TEncRCPic::estimatePicQP( Double lambda, list<TEncRCPic*>& listPreviousPictures )
{
Int QP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 ); //!< 通过lambda求QP
Int lastLevelQP = g_RCInvalidQPValue;
Int lastPicQP = g_RCInvalidQPValue;
Int lastValidQP = g_RCInvalidQPValue;
list<TEncRCPic*>::iterator it;
for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )
{
if ( (*it)->getFrameLevel() == m_frameLevel )
{
lastLevelQP = (*it)->getPicActualQP();
}
lastPicQP = (*it)->getPicActualQP();
if ( lastPicQP > g_RCInvalidQPValue )
{
lastValidQP = lastPicQP;
}
}
//!< 以下对QP进行clip,范围在K0103的section 3.2进行了定义
if ( lastLevelQP > g_RCInvalidQPValue )
{
QP = Clip3( lastLevelQP - 3, lastLevelQP + 3, QP );
}
if( lastPicQP > g_RCInvalidQPValue )
{
QP = Clip3( lastPicQP - 10, lastPicQP + 10, QP );
}
else if( lastValidQP > g_RCInvalidQPValue )
{
QP = Clip3( lastValidQP - 10, lastValidQP + 10, QP );
}
return QP;
}</span>
m_pcRateCtrl->initRCPic( )
[cpp] view
plaincopy
Void TEncRateCtrl::initRCPic( Int frameLevel )
{
m_encRCPic = new TEncRCPic;
m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures );
}
m_encRCPic->create
[cpp] view
plaincopy
Void TEncRCPic::create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures )
{
destroy();
m_encRCSeq = encRCSeq;
m_encRCGOP = encRCGOP;
Int targetBits = xEstPicTargetBits( encRCSeq, encRCGOP ); //!< K0103式子(9)
Int estHeaderBits = xEstPicHeaderBits( listPreviousPictures, frameLevel ); //!< header bits estimation
if ( targetBits < estHeaderBits + 100 )
{
targetBits = estHeaderBits + 100; // at least allocate 100 bits for picture data
}
//!< 以下为RC相关参数的初始化,根据变量名很容易就能判断其用途,故不罗嗦~
m_frameLevel = frameLevel;
m_numberOfPixel = encRCSeq->getNumPixel();
m_numberOfLCU = encRCSeq->getNumberOfLCU();
m_estPicLambda = 100.0;
m_targetBits = targetBits;
m_estHeaderBits = estHeaderBits;
m_bitsLeft = m_targetBits;
Int picWidth = encRCSeq->getPicWidth();
Int picHeight = encRCSeq->getPicHeight();
Int LCUWidth = encRCSeq->getLCUWidth();
Int LCUHeight = encRCSeq->getLCUHeight();
Int picWidthInLCU = ( picWidth % LCUWidth ) == 0 ? picWidth / LCUWidth : picWidth / LCUWidth + 1;
Int picHeightInLCU = ( picHeight % LCUHeight ) == 0 ? picHeight / LCUHeight : picHeight / LCUHeight + 1;
m_LCULeft = m_numberOfLCU;
m_bitsLeft -= m_estHeaderBits; //!< 考虑header bits后的剩余比特数
m_pixelsLeft = m_numberOfPixel;
m_LCUs = new TRCLCU[m_numberOfLCU];
Int i, j;
Int LCUIdx;
for ( i=0; i<picWidthInLCU; i++ )
{
for ( j=0; j<picHeightInLCU; j++ )
{
LCUIdx = j*picWidthInLCU + i;
m_LCUs[LCUIdx].m_actualBits = 0;
m_LCUs[LCUIdx].m_QP = 0;
m_LCUs[LCUIdx].m_lambda = 0.0;
m_LCUs[LCUIdx].m_targetBits = 0;
#if M0036_RC_IMPROVEMENT
m_LCUs[LCUIdx].m_bitWeight = 1.0;
#else
m_LCUs[LCUIdx].m_MAD = 0.0;
#endif
Int currWidth = ( (i == picWidthInLCU -1) ? picWidth - LCUWidth *(picWidthInLCU -1) : LCUWidth );
Int currHeight = ( (j == picHeightInLCU-1) ? picHeight - LCUHeight*(picHeightInLCU-1) : LCUHeight );
m_LCUs[LCUIdx].m_numberOfPixel = currWidth * currHeight;
}
}
m_picActualHeaderBits = 0;
#if !M0036_RC_IMPROVEMENT
m_totalMAD = 0.0;
#endif
m_picActualBits = 0;
m_picQP = 0;
m_picLambda = 0.0;
#if !M0036_RC_IMPROVEMENT
m_lastPicture = NULL;
list<TEncRCPic*>::reverse_iterator it;
for ( it = listPreviousPictures.rbegin(); it != listPreviousPictures.rend(); it++ )
{
if ( (*it)->getFrameLevel() == m_frameLevel ) //!< 保存跟当前帧同一层的前一帧
{
m_lastPicture = (*it);
break;
}
}
#endif
}
m_encRCPic->create子函数xEstPicTargetBits()
[cpp] view
plaincopy
<span style="font-size:12px;">Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )
{
Int targetBits = 0;
Int GOPbitsLeft = encRCGOP->getBitsLeft(); //!< TGOP - CodedGOP
Int i;
Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();
Int currPicRatio = encRCSeq->getBitRatio( currPicPosition ); //!< 当前picture的权值
Int totalPicRatio = 0;
for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )
{
totalPicRatio += encRCSeq->getBitRatio( i ); //!< 总权值
}
#if M0036_RC_IMPROVEMENT
targetBits = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio );
#else
targetBits = Int( GOPbitsLeft * currPicRatio / totalPicRatio );
#endif
if ( targetBits < 100 )
{
targetBits = 100; // at least allocate 100 bits for one picture
}
//!< 在此之前targetBits是基于K0103式子(9)计算的结果,而m_encRCGOP->getTargetBitInGOP( currPicPosition )得到的
//!< bits为NotCodedPictures=0通过式子(9)得到的
if ( m_encRCSeq->getFramesLeft() > 16 )
{
targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );
}
return targetBits;
}</span>
m_encRCPic->create子函数xEstPicHeaderBits()
[cpp] view
plaincopy
<span style="font-size:12px;">Int TEncRCPic::xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel )
{
Int numPreviousPics = 0;
Int totalPreviousBits = 0;
list<TEncRCPic*>::iterator it;
for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ ) //!< 求出当前帧之前所有与其在同一层的帧的header bits之和
{
if ( (*it)->getFrameLevel() == frameLevel )
{
totalPreviousBits += (*it)->getPicActualHeaderBits();
numPreviousPics++;
}
}
Int estHeaderBits = 0;
if ( numPreviousPics > 0 ) //!< 取平均值
{
estHeaderBits = totalPreviousBits / numPreviousPics;
}
return estHeaderBits;
}</span>
分析第一篇提到的compressGOP中的RC初始化代码片段:
[cpp] view
plaincopy
<span style="font-size:12px;">#if RATE_CONTROL_LAMBDA_DOMAIN
Double lambda = 0.0;
Int actualHeadBits = 0;
Int actualTotalBits = 0;
Int estimatedBits = 0;
Int tmpBitsBeforeWriting = 0;
if ( m_pcCfg->getUseRateCtrl() )
{
Int frameLevel = m_pcRateCtrl->getRCSeq()->getGOPID2Level( iGOPid );
if ( pcPic->getSlice(0)->getSliceType() == I_SLICE )
{
frameLevel = 0;
}
m_pcRateCtrl->initRCPic( frameLevel ); //!< picture level 初始化
estimatedBits = m_pcRateCtrl->getRCPic()->getTargetBits(); //!< 在initRCPic中已经计算出了targetBits
Int sliceQP = m_pcCfg->getInitialQP(); //!< 对应于配置文件中的InitalQP
if ( ( pcSlice->getPOC() == 0 && m_pcCfg->getInitialQP() > 0 ) || ( frameLevel == 0 && m_pcCfg->getForceIntraQP() ) ) // QP is specified
{//!< 如果配置文件对序列第一帧指定了初始QP,则基于这个QP计算出lamda
Int NumberBFrames = ( m_pcCfg->getGOPSize() - 1 );
Double dLambda_scale = 1.0 - Clip3( 0.0, 0.5, 0.05*(Double)NumberBFrames );
Double dQPFactor = 0.57*dLambda_scale;
Int SHIFT_QP = 12;
Int bitdepth_luma_qp_scale = 0;
Double qp_temp = (Double) sliceQP + bitdepth_luma_qp_scale - SHIFT_QP;
lambda = dQPFactor*pow( 2.0, qp_temp/3.0 );
}
else if ( frameLevel == 0 ) // intra case, but use the model
{ //!< 对I slice的情况,需要做些特殊处理,如targetBits的修正等
#if RATE_CONTROL_INTRA
m_pcSliceEncoder->calCostSliceI(pcPic);
#endif
if ( m_pcCfg->getIntraPeriod() != 1 ) // do not refine allocated bits for all intra case
{
Int bits = m_pcRateCtrl->getRCSeq()->getLeftAverageBits();
#if RATE_CONTROL_INTRA
bits = m_pcRateCtrl->getRCPic()->getRefineBitsForIntra( bits );
#else
bits = m_pcRateCtrl->getRCSeq()->getRefineBitsForIntra( bits ); //!< K0103 Table 3
#endif
if ( bits < 200 )
{
bits = 200;
}
m_pcRateCtrl->getRCPic()->setTargetBits( bits );
}
list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
#if RATE_CONTROL_INTRA
m_pcRateCtrl->getRCPic()->getLCUInitTargetBits();
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
#else
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture );
#endif
sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
}
else // normal case
{
list<TEncRCPic*> listPreviousPicture = m_pcRateCtrl->getPicList();
#if RATE_CONTROL_INTRA
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture, pcSlice->getSliceType());
#else
lambda = m_pcRateCtrl->getRCPic()->estimatePicLambda( listPreviousPicture );
#endif
sliceQP = m_pcRateCtrl->getRCPic()->estimatePicQP( lambda, listPreviousPicture );
}
sliceQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, sliceQP );
m_pcRateCtrl->getRCPic()->setPicEstQP( sliceQP );
m_pcSliceEncoder->resetQP( pcPic, sliceQP, lambda ); //!< 设置当前slice使用的QP, lambda,编码时用到
}
#endif</span>
compressGOP子函数getRefineBitsForIntra()
[cpp] view
plaincopy
<span style="font-size:12px;">#if !RATE_CONTROL_INTRA
Int TEncRCSeq::getRefineBitsForIntra( Int orgBits ) //!< K0103 Table 3
{
Double bpp = ( (Double)orgBits ) / m_picHeight / m_picHeight;
if ( bpp > 0.2 )
{
return orgBits * 5;
}
if ( bpp > 0.1 )
{
return orgBits * 7;
}
return orgBits * 10;
}
#endif</span>
compressGOP子函数estimatePicLambda()
[cpp] view
plaincopy
<span style="font-size:12px;">#if RATE_CONTROL_INTRA
Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures, SliceType eSliceType)
#else
Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures )
#endif
{
Double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
Double beta = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
Double bpp = (Double)m_targetBits/(Double)m_numberOfPixel;
#if RATE_CONTROL_INTRA
Double estLambda;
if (eSliceType == I_SLICE)
{
estLambda = calculateLambdaIntra(alpha, beta, pow(m_totalCostIntra/(Double)m_numberOfPixel, BETA1), bpp);
}
else
{
estLambda = alpha * pow( bpp, beta );
}
#else
Double estLambda = alpha * pow( bpp, beta ); //!< K0103 式子(10)
#endif
Double lastLevelLambda = -1.0;
Double lastPicLambda = -1.0;
Double lastValidLambda = -1.0;
list<TEncRCPic*>::iterator it;
for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )
{
if ( (*it)->getFrameLevel() == m_frameLevel )
{
lastLevelLambda = (*it)->getPicActualLambda();
}
lastPicLambda = (*it)->getPicActualLambda();
if ( lastPicLambda > 0.0 )
{
lastValidLambda = lastPicLambda;
}
}
//!< 以下对lastLevelLambda和estLambda进行clip,范围在K0103的section 3.2中进行了定义
if ( lastLevelLambda > 0.0 )
{
lastLevelLambda = Clip3( 0.1, 10000.0, lastLevelLambda );
estLambda = Clip3( lastLevelLambda * pow( 2.0, -3.0/3.0 ), lastLevelLambda * pow( 2.0, 3.0/3.0 ), estLambda );
}
if ( lastPicLambda > 0.0 )
{
lastPicLambda = Clip3( 0.1, 2000.0, lastPicLambda );
estLambda = Clip3( lastPicLambda * pow( 2.0, -10.0/3.0 ), lastPicLambda * pow( 2.0, 10.0/3.0 ), estLambda );
}
else if ( lastValidLambda > 0.0 )
{
lastValidLambda = Clip3( 0.1, 2000.0, lastValidLambda );
estLambda = Clip3( lastValidLambda * pow(2.0, -10.0/3.0), lastValidLambda * pow(2.0, 10.0/3.0), estLambda );
}
else
{
estLambda = Clip3( 0.1, 10000.0, estLambda );
}
if ( estLambda < 0.1 )
{
estLambda = 0.1;
}
m_estPicLambda = estLambda;
#if M0036_RC_IMPROVEMENT
Double totalWeight = 0.0;
// initial BU bit allocation weight
for ( Int i=0; i<m_numberOfLCU; i++ )
{
#if RC_FIX
Double alphaLCU, betaLCU;
if ( m_encRCSeq->getUseLCUSeparateModel() )
{
alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha;
betaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta;
}
else
{
alphaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
betaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
}
#else
Double alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha;
Double betaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta;
#endif
m_LCUs[i].m_bitWeight = m_LCUs[i].m_numberOfPixel * pow( estLambda/alphaLCU, 1.0/betaLCU );
if ( m_LCUs[i].m_bitWeight < 0.01 )
{
m_LCUs[i].m_bitWeight = 0.01;
}
totalWeight += m_LCUs[i].m_bitWeight;
}
for ( Int i=0; i<m_numberOfLCU; i++ )
{
Double BUTargetBits = m_targetBits * m_LCUs[i].m_bitWeight / totalWeight;
m_LCUs[i].m_bitWeight = BUTargetBits;
}
#endif
return estLambda;
}</span>
compressGOP子函数estimatePicQP()
[cpp] view
plaincopy
<span style="font-size:12px;">Int TEncRCPic::estimatePicQP( Double lambda, list<TEncRCPic*>& listPreviousPictures )
{
Int QP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 ); //!< 通过lambda求QP
Int lastLevelQP = g_RCInvalidQPValue;
Int lastPicQP = g_RCInvalidQPValue;
Int lastValidQP = g_RCInvalidQPValue;
list<TEncRCPic*>::iterator it;
for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )
{
if ( (*it)->getFrameLevel() == m_frameLevel )
{
lastLevelQP = (*it)->getPicActualQP();
}
lastPicQP = (*it)->getPicActualQP();
if ( lastPicQP > g_RCInvalidQPValue )
{
lastValidQP = lastPicQP;
}
}
//!< 以下对QP进行clip,范围在K0103的section 3.2进行了定义
if ( lastLevelQP > g_RCInvalidQPValue )
{
QP = Clip3( lastLevelQP - 3, lastLevelQP + 3, QP );
}
if( lastPicQP > g_RCInvalidQPValue )
{
QP = Clip3( lastPicQP - 10, lastPicQP + 10, QP );
}
else if( lastValidQP > g_RCInvalidQPValue )
{
QP = Clip3( lastValidQP - 10, lastValidQP + 10, QP );
}
return QP;
}</span>
相关文章推荐
- HEVC码率控制浅析——HM代码阅读之二
- HEVC码率控制浅析——HM代码阅读之四
- HEVC码率控制浅析——HM代码阅读之一
- HEVC码率控制浅析——HM代码阅读之四
- HEVC码率控制浅析——HM代码阅读之二
- HEVC码率控制浅析——HM代码阅读之四
- HEVC码率控制浅析——HM代码阅读之三
- HEVC码率控制浅析——HM代码阅读之一
- HEVC码率控制浅析——HM代码阅读之一
- HEVC码率控制算法研究与HM相应代码分析(三)——算法及代码分析
- HEVC码率控制浅析——HM代码阅读之二
- HEVC码率控制算法研究与HM相应代码分析(二)——新的码率控制模型
- 最近调试HEVC中码率控制, 发现HM里面一个重大bug
- H.265/HEVC码率控制总体框架与代码解读(中)
- x265代码阅读:码率控制(二)
- HM/JEM CTU级码率控制相关代码
- HM编码器代码阅读(29)——码率控制
- x265代码阅读:码率控制(一)
- HEVC参考软件(HM)代码阅读之帧内预测:Void TComPrediction::xPredIntraAng
- HM编码器代码阅读(41)——码率控制(二)