码率控制
介绍
码率控制
码率控制也叫速率控制,主要是控制编码后的比特率。
存在码率控制模块的原因是,有时候解码器处理的速度不够快、网络带宽不行,这些情况的存在要求我们必须减少数据的发送量(即比特率要变小),减少数据的发送量
意味着我们要对数据进行更近一步的压缩,在编码器中就表现为量化参数QP的变化。
当满足一定码率要求的情况下,我们还需要让编码的失真尽量小。
码率控制的核心就是要确定量化参数QP。
如果不使用码率控制,那么量化参数QP就是自定义的或者根据需要选择
码率控制是一级一级进行控制的,先分配图像组级(GOP)的比特数,然后分配图像级的比特数,再分配CTU级别的比特数。利用已经分配的比特数来确定量化参数。
更多的细节请参考http://blog.csdn.net/nb_vol_1/article/details/53288902
码率控制在HEVC中的实现
码率控制流程
在TEncCfg中有个布尔类型的m_RCEnableRateControl成员,它表示是否使用码率控制
在HM中码率控制的流程是:
1、在TEncTop::create中,定义了编码序列级别的码率控制
if ( m_RCEnableRateControl )
{
// 码率控制器初始化
m_cRateCtrl.init( m_framesToBeEncoded, m_RCTargetBitrate, m_iFrameRate, m_iGOPSize, m_iSourceWidth, m_iSourceHeight,
g_uiMaxCUWidth, g_uiMaxCUHeight, m_RCKeepHierarchicalBit, m_RCUseLCUSeparateModel, m_GOPList );
}
2、在TEncTop::encode中,定义了图像组级别的码率控制
if ( m_RCEnableRateControl )
{
m_cRateCtrl.initRCGOP( m_iNumPicRcvd );
}
if ( m_RCEnableRateControl )
{
m_cRateCtrl.destroyRCGOP();
}
3、在TEncGOP::compressGOP,定义了图像级别的码率控制
m_pcRateCtrl->initRCPic( frameLevel );
4、在TEncSlice::compressSlice()中,设置CTU(LCU)级别的码率控制参数
if ( m_pcCfg->getUseRateCtrl() )
{
Int estQP = pcSlice->getSliceQp();
Double estLambda = -1.0;
Double bpp = -1.0;
if ( ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )
{
estQP = pcSlice->getSliceQp();
}
else
{
bpp = m_pcRateCtrl->getRCPic()->getLCUTargetBpp(pcSlice->getSliceType());
if ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE)
{
estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP);
}
else
{
estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );
estQP = m_pcRateCtrl->getRCPic()->getLCUEstQP ( estLambda, pcSlice->getSliceQp() );
}
estQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, estQP );
m_pcRdCost->setLambda(estLambda);
#if RDOQ_CHROMA_LAMBDA
// set lambda for RDOQ
Double weight=m_pcRdCost->getChromaWeight();
const Double lambdaArray[3] = { estLambda, (estLambda / weight), (estLambda / weight) };
m_pcTrQuant->setLambdas( lambdaArray );
#else
m_pcTrQuant->setLambda( estLambda );
#endif
}
m_pcRateCtrl->setRCQP( estQP );
#if ADAPTIVE_QP_SELECTION
pcCU->getSlice()->setSliceQpBase( estQP );
#endif
}
5、在TEncSlice::compressSlice中,编码完成一个CTU之后,需要更新剩余比特数等相关的参数
if ( m_pcCfg->getUseRateCtrl() )
{
Int actualQP = g_RCInvalidQPValue;
Double actualLambda = m_pcRdCost->getLambda();
Int actualBits = pcCU->getTotalBits();
Int numberOfEffectivePixels = 0;
for ( Int idx = 0; idx < rpcPic->getNumPartInCU(); idx++ )
{
if ( pcCU->getPredictionMode( idx ) != MODE_NONE && ( !pcCU->isSkipped( idx ) ) )
{
numberOfEffectivePixels = numberOfEffectivePixels + 16;
break;
}
}
if ( numberOfEffectivePixels == 0 )
{
actualQP = g_RCInvalidQPValue;
}
else
{
actualQP = pcCU->getQP( 0 );
}
m_pcRdCost->setLambda(oldLambda);
m_pcRateCtrl->getRCPic()->updateAfterLCU( m_pcRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda,
pcCU->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() );
}
6、在TEncGOP::compressGOP中,每编码完成一个图像,就更新剩余比特数等码率控制相关的参数
if ( m_pcCfg->getUseRateCtrl() )
{
Double avgQP = m_pcRateCtrl->getRCPic()->calAverageQP();
Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();
if ( avgLambda < 0.0 )
{
avgLambda = lambda;
}
m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType());
m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() );
m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits );
if ( pcSlice->getSliceType() != I_SLICE )
{
m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits );
}
else // for intra picture, the estimated bits are used to update the current status in the GOP
{
m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );
}
}
码率控制的相关结构
CTU(LCU)级别的码率控制结构
/*
** LCU(CTU)级别的码率控制信息
*/
struct TRCLCU
{
// 实际比特数
Int m_actualBits;
// 相应的QP
Int m_QP; // QP of skip mode is set to g_RCInvalidQPValue
// 目标比特数
Int m_targetBits;
// lambda参数
Double m_lambda;
// 比特权重
Double m_bitWeight;
// 像素的数量
Int m_numberOfPixel;
// 帧内的代价
Double m_costIntra;
// 剩余的比特数(目标的剩余比特数)
Int m_targetBitsLeft;
};
码率参数结构
/*
** 码率控制参数!
*/
struct TRCParameter
{
Double m_alpha; // alpha参数
Double m_beta; // beta参数
};
编码序列级别的码率控制结构
/*
** seq序列级别(级别比gop高)的码率控制
*/
class TEncRCSeq
{
public:
TEncRCSeq();
~TEncRCSeq();
public:
Void create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit );
Void destroy();
// 初始化比特率
Void initBitsRatio( Int bitsRatio[] );
// 初始化gop到level的映射
Void initGOPID2Level( Int GOPID2Level[] );
// 初始化pic的码率控制参数
Void initPicPara( TRCParameter* picPara = NULL ); // NULL to initial with default value
// 初始化LCU的码率控制参数
Void initLCUPara( TRCParameter** LCUPara = NULL ); // NULL to initial with default value
// 在处理完一帧之后更新
Void updateAfterPic ( Int bits );
// 设置总得比特率
Void setAllBitRatio( Double basicLambda, Double* equaCoeffA, Double* equaCoeffB );
public:
Int getTotalFrames() { return m_totalFrames; }
Int getTargetRate() { return m_targetRate; }
Int getFrameRate() { return m_frameRate; }
Int getGOPSize() { return m_GOPSize; }
Int getPicWidth() { return m_picWidth; }
Int getPicHeight() { return m_picHeight; }
Int getLCUWidth() { return m_LCUWidth; }
Int getLCUHeight() { return m_LCUHeight; }
Int getNumberOfLevel() { return m_numberOfLevel; }
Int getAverageBits() { return m_averageBits; }
Int getLeftAverageBits() { assert( m_framesLeft > 0 ); return (Int)(m_bitsLeft / m_framesLeft); }
Bool getUseLCUSeparateModel() { return m_useLCUSeparateModel; }
Int getNumPixel() { return m_numberOfPixel; }
Int64 getTargetBits() { return m_targetBits; }
Int getNumberOfLCU() { return m_numberOfLCU; }
Int* getBitRatio() { return m_bitsRatio; }
Int getBitRatio( Int idx ) { assert( idx<m_GOPSize); return m_bitsRatio[idx]; }
Int* getGOPID2Level() { return m_GOPID2Level; }
Int getGOPID2Level( Int ID ) { assert( ID < m_GOPSize ); return m_GOPID2Level[ID]; }
TRCParameter* getPicPara() { return m_picPara; }
TRCParameter getPicPara( Int level ) { assert( level < m_numberOfLevel ); return m_picPara[level]; }
Void setPicPara( Int level, TRCParameter para ) { assert( level < m_numberOfLevel ); m_picPara[level] = para; }
TRCParameter** getLCUPara() { return m_LCUPara; }
TRCParameter* getLCUPara( Int level ) { assert( level < m_numberOfLevel ); return m_LCUPara[level]; }
TRCParameter getLCUPara( Int level, Int LCUIdx ) { assert( LCUIdx < m_numberOfLCU ); return getLCUPara(level)[LCUIdx]; }
Void setLCUPara( Int level, Int LCUIdx, TRCParameter para ) { assert( level < m_numberOfLevel ); assert( LCUIdx < m_numberOfLCU ); m_LCUPara[level][LCUIdx] = para; }
Int getFramesLeft() { return m_framesLeft; }
Int64 getBitsLeft() { return m_bitsLeft; }
Double getSeqBpp() { return m_seqTargetBpp; }
Double getAlphaUpdate() { return m_alphaUpdate; }
Double getBetaUpdate() { return m_betaUpdate; }
Int getAdaptiveBits() { return m_adaptiveBit; }
Double getLastLambda() { return m_lastLambda; }
Void setLastLambda( Double lamdba ) { m_lastLambda = lamdba; }
private:
// 总的帧数
Int m_totalFrames;
// 目标码率
Int m_targetRate;
// 帧率
Int m_frameRate;
// gop的大小
Int m_GOPSize;
// 帧宽和高
Int m_picWidth;
Int m_picHeight;
// LCU的宽和高
Int m_LCUWidth;
Int m_LCUHeight;
// level的数量
Int m_numberOfLevel;
// 平均的比特数
Int m_averageBits;
// 像素的数量
Int m_numberOfPixel;
// 目标比特数
Int64 m_targetBits;
// LCU的数量
Int m_numberOfLCU;
// 比特率
Int* m_bitsRatio;
// gop的id到level的映射
Int* m_GOPID2Level;
// pic的码率控制参数
TRCParameter* m_picPara;
// LCU的码率控制参数
TRCParameter** m_LCUPara;
// 剩余的帧数
Int m_framesLeft;
// 剩余的比特数
Int64 m_bitsLeft;
Double m_seqTargetBpp;
// alpha参数的更新
Double m_alphaUpdate;
// beta参数的更新
Double m_betaUpdate;
// 是否使用LCU分开的模型
Bool m_useLCUSeparateModel;
// 自适应的比特
Int m_adaptiveBit;
// 最后的lambda参数
Double m_lastLambda;
};
图像组(gop)级别的码率控制
/*
** GOP级别的码率控制
*/
class TEncRCGOP
{
public:
TEncRCGOP();
~TEncRCGOP();
public:
Void create( TEncRCSeq* encRCSeq, Int numPic );
Void destroy();
// 在处理完一帧之后更新
Void updateAfterPicture( Int bitsCost );
private:
// 预估一个gop占用的比特数
Int xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize );
Void xCalEquaCoeff( TEncRCSeq* encRCSeq, Double* lambdaRatio, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize );
Double xSolveEqua( Double targetBpp, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize );
public:
TEncRCSeq* getEncRCSeq() { return m_encRCSeq; }
Int getNumPic() { return m_numPic;}
Int getTargetBits() { return m_targetBits; }
Int getPicLeft() { return m_picLeft; }
Int getBitsLeft() { return m_bitsLeft; }
Int getTargetBitInGOP( Int i ) { return m_picTargetBitInGOP[i]; }
private:
// 所属的码率控制序列
TEncRCSeq* m_encRCSeq;
// 该gop中,每一帧的目标比特数
Int* m_picTargetBitInGOP;
// 帧数量
Int m_numPic;
// gop总的目标比特数
Int m_targetBits;
// 还剩多少帧处理完成
Int m_picLeft;
// 还剩多少比特
Int m_bitsLeft;
};
图像级别的码率控制对象
/*
** 图像级别的码率控制
*/
class TEncRCPic
{
public:
TEncRCPic();
~TEncRCPic();
public:
Void create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures );
Void destroy();
Int estimatePicQP ( Double lambda, list<TEncRCPic*>& listPreviousPictures );
Int getRefineBitsForIntra(Int orgBits);
Double calculateLambdaIntra(double alpha, double beta, double MADPerPixel, double bitsPerPixel);
Double estimatePicLambda( list<TEncRCPic*>& listPreviousPictures, SliceType eSliceType);
Void updateAlphaBetaIntra(double *alpha, double *beta);
Double getLCUTargetBpp(SliceType eSliceType);
Double getLCUEstLambdaAndQP(Double bpp, Int clipPicQP, Int *estQP);
Double getLCUEstLambda( Double bpp );
Int getLCUEstQP( Double lambda, Int clipPicQP );
Void updateAfterLCU( Int LCUIdx, Int bits, Int QP, Double lambda, Bool updateLCUParameter = true );
Void updateAfterPicture( Int actualHeaderBits, Int actualTotalBits, Double averageQP, Double averageLambda, SliceType eSliceType);
Void addToPictureLsit( list<TEncRCPic*>& listPreviousPictures );
Double calAverageQP();
Double calAverageLambda();
private:
Int xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP );
Int xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel );
public:
TEncRCSeq* getRCSequence() { return m_encRCSeq; }
TEncRCGOP* getRCGOP() { return m_encRCGOP; }
Int getFrameLevel() { return m_frameLevel; }
Int getNumberOfPixel() { return m_numberOfPixel; }
Int getNumberOfLCU() { return m_numberOfLCU; }
Int getTargetBits() { return m_targetBits; }
Int getEstHeaderBits() { return m_estHeaderBits; }
Int getLCULeft() { return m_LCULeft; }
Int getBitsLeft() { return m_bitsLeft; }
Int getPixelsLeft() { return m_pixelsLeft; }
Int getBitsCoded() { return m_targetBits - m_estHeaderBits - m_bitsLeft; }
Int getLCUCoded() { return m_numberOfLCU - m_LCULeft; }
TRCLCU* getLCU() { return m_LCUs; }
TRCLCU& getLCU( Int LCUIdx ) { return m_LCUs[LCUIdx]; }
Int getPicActualHeaderBits() { return m_picActualHeaderBits; }
Void setTargetBits( Int bits ) { m_targetBits = bits; m_bitsLeft = bits;}
Void setTotalIntraCost(Double cost) { m_totalCostIntra = cost; }
Void getLCUInitTargetBits();
Int getPicActualBits() { return m_picActualBits; }
Int getPicActualQP() { return m_picQP; }
Double getPicActualLambda() { return m_picLambda; }
Int getPicEstQP() { return m_estPicQP; }
Void setPicEstQP( Int QP ) { m_estPicQP = QP; }
Double getPicEstLambda() { return m_estPicLambda; }
Void setPicEstLambda( Double lambda ) { m_picLambda = lambda; }
private:
// 所属的码率控制序列
TEncRCSeq* m_encRCSeq;
// 所属的码率控制gop
TEncRCGOP* m_encRCGOP;
// 帧的level
Int m_frameLevel;
// 像素的数量
Int m_numberOfPixel;
// LCU的数量
Int m_numberOfLCU;
// 目标比特数
Int m_targetBits;
// 帧头部/slice头部等占用的比特数
Int m_estHeaderBits;
// 预估的帧的qp
Int m_estPicQP;
// 预估的lambda
Double m_estPicLambda;
// 剩下的LCU的数量
Int m_LCULeft;
// 剩下的比特数量
Int m_bitsLeft;
// 剩下的像素数量
Int m_pixelsLeft;
// 该帧对应的LCU码率控制对象
TRCLCU* m_LCUs;
// 真实的头部占用的比特数
Int m_picActualHeaderBits; // only SH and potential APS
// 帧内模式消耗的比特数
Double m_totalCostIntra;
// 帧内模式还剩余的比特数
Double m_remainingCostIntra;
// 帧真实占用的比特数
Int m_picActualBits; // the whole picture, including header
// 帧的qp
Int m_picQP; // in integer form
// 帧的lambda参数
Double m_picLambda;
};
码率控制对象
/*
** 码率控制管理器
** 管理了TEncRCSeq TEncRCGOP TEncRCPic等对象
*/
class TEncRateCtrl
{
public:
TEncRateCtrl();
~TEncRateCtrl();
public:
Void init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int keepHierBits, Bool useLCUSeparateModel, GOPEntry GOPList[MAX_GOP] );
Void destroy();
Void initRCPic( Int frameLevel );
Void initRCGOP( Int numberOfPictures );
Void destroyRCGOP();
public:
Void setRCQP ( Int QP ) { m_RCQP = QP; }
Int getRCQP () { return m_RCQP; }
TEncRCSeq* getRCSeq() { assert ( m_encRCSeq != NULL ); return m_encRCSeq; }
TEncRCGOP* getRCGOP() { assert ( m_encRCGOP != NULL ); return m_encRCGOP; }
TEncRCPic* getRCPic() { assert ( m_encRCPic != NULL ); return m_encRCPic; }
list<TEncRCPic*>& getPicList() { return m_listRCPictures; }
private:
// 当前的码率控制序列
TEncRCSeq* m_encRCSeq;
// 当前码率控制gop
TEncRCGOP* m_encRCGOP;
// 当前对应的码率控制pic
TEncRCPic* m_encRCPic;
// TEncRCPic列表(应该是一个gop中/或者一个序列中的所有帧)
list<TEncRCPic*> m_listRCPictures;
// qp参数
Int m_RCQP;
};
码率控制是怎么样控制比特率的
首先我们找到码率控制初始化函数TEncRateCtrl::init
TEncRateCtrl::initRCGOP用于图像组级别的码率控制的初始化,实际初始化在TEncRCGOP::create中,其中调用了一个比较重要的函数是xEstGOPTargetBits,用于估计GOP占用的比特数
TEncRateCtrl::initRCPic,图像级别的码率控制的初始化,实际调用TEncRCGOP::create
这几个初始化函数的大致功能都是比特率分配,即每一帧多少比特、每一个CTU多少个比特之类的
这些都没有什么看头,最重要的是看码率控制在HEVC中怎么样和编码器结合起来的
重点1——计算QP:
在TEncSlice::compressSlice中
(1)获取bpp(bits per pixel),通过getLCUTargetBpp得到
(2)获取Lambda参数,通过bpp等参数调用getLCUEstLambda得到
(3)获取码率控制对象计算出的QP,通过Lambda和slice的QP等参数调用getLCUEstQP得到
(4)把计算出来的QP保存起来,调用setRCQP
if ( m_pcCfg->getUseRateCtrl() )
{
Int estQP = pcSlice->getSliceQp();
Double estLambda = -1.0;
Double bpp = -1.0;
if ( ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE && m_pcCfg->getForceIntraQP() ) || !m_pcCfg->getLCULevelRC() )
{
estQP = pcSlice->getSliceQp();
}
else
{
bpp = m_pcRateCtrl->getRCPic()->getLCUTargetBpp(pcSlice->getSliceType());
if ( rpcPic->getSlice( 0 )->getSliceType() == I_SLICE)
{
estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambdaAndQP(bpp, pcSlice->getSliceQp(), &estQP);
}
else
{
estLambda = m_pcRateCtrl->getRCPic()->getLCUEstLambda( bpp );
estQP = m_pcRateCtrl->getRCPic()->getLCUEstQP ( estLambda, pcSlice->getSliceQp() );
}
estQP = Clip3( -pcSlice->getSPS()->getQpBDOffsetY(), MAX_QP, estQP );
m_pcRdCost->setLambda(estLambda);
#if RDOQ_CHROMA_LAMBDA
// set lambda for RDOQ
Double weight=m_pcRdCost->getChromaWeight();
const Double lambdaArray[3] = { estLambda, (estLambda / weight), (estLambda / weight) };
m_pcTrQuant->setLambdas( lambdaArray );
#else
m_pcTrQuant->setLambda( estLambda );
#endif
}
m_pcRateCtrl->setRCQP( estQP );
#if ADAPTIVE_QP_SELECTION
pcCU->getSlice()->setSliceQpBase( estQP );
#endif
}
重点2——把计算出来的QP应用到编码上:
在TEncCu::xCompressCU中
(1)把iMinQP设置为通过码率控制计算出来的QP(调用getRCQP)
(2)把iMaxQP设置为通过码率控制计算出来的QP(调用getRCQP)
(3)然后利用iMinQP和iMaxQP进行编码
// 使用码率控制
// 注意这里的QP使用了,码率控制对象计算出来的QP
// 通过QP,码率控制对象控制了编码器的比特率
if ( m_pcEncCfg->getUseRateCtrl() )
{
iMinQP = m_pcRateCtrl->getRCQP();
iMaxQP = m_pcRateCtrl->getRCQP();
}
重点3——根据比特率动态调整:
(1)编码一个CTU或者图像之后,可以得到它占用的比特数
(2)调用updateAfterLCU/updateAfterPicture,更新剩余比特数、Lambda等相关参数下一次计算QP的时候就利用这些参数重新计算,就能够自适应的改变比特率
if ( m_pcCfg->getUseRateCtrl() )
{
Int actualQP = g_RCInvalidQPValue;
Double actualLambda = m_pcRdCost->getLambda();
Int actualBits = pcCU->getTotalBits();
Int numberOfEffectivePixels = 0;
for ( Int idx = 0; idx < rpcPic->getNumPartInCU(); idx++ )
{
if ( pcCU->getPredictionMode( idx ) != MODE_NONE && ( !pcCU->isSkipped( idx ) ) )
{
numberOfEffectivePixels = numberOfEffectivePixels + 16;
break;
}
}
if ( numberOfEffectivePixels == 0 )
{
actualQP = g_RCInvalidQPValue;
}
else
{
actualQP = pcCU->getQP( 0 );
}
m_pcRdCost->setLambda(oldLambda);
m_pcRateCtrl->getRCPic()->updateAfterLCU( m_pcRateCtrl->getRCPic()->getLCUCoded(), actualBits, actualQP, actualLambda,
pcCU->getSlice()->getSliceType() == I_SLICE ? 0 : m_pcCfg->getLCULevelRC() );
}
if ( m_pcCfg->getUseRateCtrl() )
{
Double avgQP = m_pcRateCtrl->getRCPic()->calAverageQP();
Double avgLambda = m_pcRateCtrl->getRCPic()->calAverageLambda();
if ( avgLambda < 0.0 )
{
avgLambda = lambda;
}
m_pcRateCtrl->getRCPic()->updateAfterPicture( actualHeadBits, actualTotalBits, avgQP, avgLambda, pcSlice->getSliceType());
m_pcRateCtrl->getRCPic()->addToPictureLsit( m_pcRateCtrl->getPicList() );
m_pcRateCtrl->getRCSeq()->updateAfterPic( actualTotalBits );
if ( pcSlice->getSliceType() != I_SLICE )
{
m_pcRateCtrl->getRCGOP()->updateAfterPicture( actualTotalBits );
}
else // for intra picture, the estimated bits are used to update the current status in the GOP
{
m_pcRateCtrl->getRCGOP()->updateAfterPicture( estimatedBits );
}
}