碼率分配參數更新
幀之後的更新
void EncRCPic::updateAfterPicture( int actualHeaderBits, int actualTotalBits, double averageQP, double averageLambda, bool isIRAP)
{
m_picActualHeaderBits = actualHeaderBits;
m_picActualBits = actualTotalBits;
if ( averageQP > 0.0 )
{
m_picQP = int( averageQP + 0.5 );
}
else
{
m_picQP = g_RCInvalidQPValue;
}
m_picLambda = averageLambda;
double alpha = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;
double beta = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;
double skipRatio = 0;
int numOfSkipPixel = 0;
for (int LCUIdx = 0; LCUIdx < m_numberOfLCU; LCUIdx++)
{
numOfSkipPixel += int(m_encRCSeq->getLCUPara(m_frameLevel, LCUIdx).m_skipRatio*m_LCUs[LCUIdx].m_numberOfPixel);
}
skipRatio = (double)numOfSkipPixel / (double)m_numberOfPixel;
if (isIRAP)
{
updateAlphaBetaIntra(&alpha, &beta);
}
else
{
// update parameters
double picActualBits = ( double )m_picActualBits;
double picActualBpp = picActualBits / (double)m_validPixelsInPic;
double calLambda = alpha * pow( picActualBpp, beta );
double inputLambda = m_picLambda;
if ( inputLambda < 0.01 || calLambda < 0.01 || picActualBpp < 0.0001 )
{
alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );
beta *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );
alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
beta = Clip3( g_RCBetaMinValue, g_RCBetaMaxValue, beta );
TRCParameter rcPara;
rcPara.m_alpha = alpha;
rcPara.m_beta = beta;
rcPara.m_skipRatio = skipRatio;
double avgMSE = getPicMSE();
double updatedK = picActualBpp * averageLambda / avgMSE;
double updatedC = avgMSE / pow(picActualBpp, -updatedK);
if (m_frameLevel > 0) //only use for level > 0
{
rcPara.m_alpha = updatedC * updatedK;
rcPara.m_beta = -updatedK - 1.0;
}
rcPara.m_validPix = m_validPixelsInPic;
if (m_validPixelsInPic > 0)
{
m_encRCSeq->setPicPara(m_frameLevel, rcPara);
}
return;
}
calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );
alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;
double lnbpp = log( picActualBpp );
lnbpp = Clip3( -5.0, -0.1, lnbpp );
beta += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;
alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
beta = Clip3( g_RCBetaMinValue, g_RCBetaMaxValue, beta );
}
TRCParameter rcPara;
rcPara.m_alpha = alpha;
rcPara.m_beta = beta;
rcPara.m_skipRatio = skipRatio;
double picActualBpp = (double)m_picActualBits / (double)m_validPixelsInPic;
double avgMSE = getPicMSE();
double updatedK = picActualBpp * averageLambda / avgMSE;
double updatedC = avgMSE / pow(picActualBpp, -updatedK);
if (m_frameLevel > 0) //only use for level > 0
{
rcPara.m_alpha = updatedC * updatedK;
rcPara.m_beta = -updatedK - 1.0;
}
rcPara.m_validPix = m_validPixelsInPic;
if (m_validPixelsInPic > 0)
{
m_encRCSeq->setPicPara(m_frameLevel, rcPara);
}
if ( m_frameLevel == 1 )
{
double currLambda = Clip3( 0.1, 10000.0, m_picLambda );
double updateLastLambda = g_RCWeightHistoryLambda * m_encRCSeq->getLastLambda() + g_RCWeightCurrentLambda * currLambda;
m_encRCSeq->setLastLambda( updateLastLambda );
}
}
LCU後的更新
void EncRCPic::updateAfterCTU(int LCUIdx, int bits, int QP, double lambda, double skipRatio, bool updateLCUParameter)
{
m_LCUs[LCUIdx].m_actualBits = bits;
m_LCUs[LCUIdx].m_QP = QP;
m_LCUs[LCUIdx].m_lambda = lambda;
m_LCUs[LCUIdx].m_actualSSE = m_LCUs[LCUIdx].m_actualMSE * m_LCUs[LCUIdx].m_numberOfPixel;
m_LCULeft--;
m_bitsLeft -= bits;
m_pixelsLeft -= m_LCUs[LCUIdx].m_numberOfPixel;
if ( !updateLCUParameter )
{
return;
}
if ( !m_encRCSeq->getUseLCUSeparateModel() )
{
return;
}
double alpha = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_alpha;
double beta = m_encRCSeq->getLCUPara( m_frameLevel, LCUIdx ).m_beta;
int LCUActualBits = m_LCUs[LCUIdx].m_actualBits;
int LCUTotalPixels = m_LCUs[LCUIdx].m_numberOfPixel;
double bpp = ( double )LCUActualBits/( double )LCUTotalPixels;
double calLambda = alpha * pow( bpp, beta );
double inputLambda = m_LCUs[LCUIdx].m_lambda;
if( inputLambda < 0.01 || calLambda < 0.01 || bpp < 0.0001 )
{
alpha *= ( 1.0 - m_encRCSeq->getAlphaUpdate() / 2.0 );
beta *= ( 1.0 - m_encRCSeq->getBetaUpdate() / 2.0 );
alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
beta = Clip3( g_RCBetaMinValue, g_RCBetaMaxValue, beta );
TRCParameter rcPara;
rcPara.m_alpha = alpha;
rcPara.m_beta = beta;
rcPara.m_skipRatio = skipRatio;
if (QP == g_RCInvalidQPValue && m_encRCSeq->getAdaptiveBits() == 1)
{
rcPara.m_validPix = 0;
}
else
{
rcPara.m_validPix = LCUTotalPixels;
}
double MSE = m_LCUs[LCUIdx].m_actualMSE;
double updatedK = bpp * inputLambda / MSE;
double updatedC = MSE / pow(bpp, -updatedK);
rcPara.m_alpha = updatedC * updatedK;
rcPara.m_beta = -updatedK - 1.0;
if (bpp > 0 && updatedK > 0.0001)
{
m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara);
}
else
{
rcPara.m_alpha = Clip3(0.0001, g_RCAlphaMaxValue, rcPara.m_alpha);
m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara);
}
return;
}
calLambda = Clip3( inputLambda / 10.0, inputLambda * 10.0, calLambda );
alpha += m_encRCSeq->getAlphaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * alpha;
double lnbpp = log( bpp );
lnbpp = Clip3( -5.0, -0.1, lnbpp );
beta += m_encRCSeq->getBetaUpdate() * ( log( inputLambda ) - log( calLambda ) ) * lnbpp;
alpha = Clip3( g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha );
beta = Clip3( g_RCBetaMinValue, g_RCBetaMaxValue, beta );
TRCParameter rcPara;
rcPara.m_alpha = alpha;
rcPara.m_beta = beta;
rcPara.m_skipRatio = skipRatio;
if (QP == g_RCInvalidQPValue && m_encRCSeq->getAdaptiveBits() == 1)
{
rcPara.m_validPix = 0;
}
else
{
rcPara.m_validPix = LCUTotalPixels;
}
double MSE = m_LCUs[LCUIdx].m_actualMSE;
double updatedK = bpp * inputLambda / MSE;
double updatedC = MSE / pow(bpp, -updatedK);
rcPara.m_alpha = updatedC * updatedK;
rcPara.m_beta = -updatedK - 1.0;
if (bpp > 0 && updatedK > 0.0001)
{
m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara);
}
else
{
rcPara.m_alpha = Clip3(0.0001, g_RCAlphaMaxValue, rcPara.m_alpha);
m_encRCSeq->setLCUPara(m_frameLevel, LCUIdx, rcPara);
}
}