文章目錄
- 碼率控制的各級初始化函數
-
- 碼率控制子產品初始化
- GOP碼率控制初始化
- 幀級碼率控制初始化
碼率控制的各級初始化函數
碼率控制子產品初始化
void RateCtrl::init(int totalFrames, int targetBitrate, int frameRate, int GOPSize, int picWidth, int picHeight, int LCUWidth, int LCUHeight, int bitDepth, int keepHierBits, bool useLCUSeparateModel, GOPEntry GOPList[MAX_GOP])
{
destroy();
bool isLowdelay = true;
for ( int i=0; i<GOPSize-1; i++ )
{
if ( GOPList[i].m_POC > GOPList[i+1].m_POC )
{
isLowdelay = false;
break;
}
}
int numberOfLevel = 1;
int adaptiveBit = 0;
if ( keepHierBits > 0 )
{
numberOfLevel = int( log((double)GOPSize)/log(2.0) + 0.5 ) + 1;
}
if (!isLowdelay && (GOPSize == 16 || GOPSize == 8))
{
numberOfLevel = int( log((double)GOPSize)/log(2.0) + 0.5 ) + 1;
}
numberOfLevel++; // intra picture
numberOfLevel++; // non-reference picture
int* bitsRatio;
bitsRatio = new int[ GOPSize ];
for ( int i=0; i<GOPSize; i++ )
{
bitsRatio[i] = 10;
if ( !GOPList[i].m_refPic )
{
bitsRatio[i] = 2;
}
}
if ( keepHierBits > 0 )
{
double bpp = (double)( targetBitrate / (double)( frameRate*picWidth*picHeight ) );
if ( GOPSize == 4 && isLowdelay )
{
if ( bpp > 0.2 )
{
bitsRatio[0] = 2;
bitsRatio[1] = 3;
bitsRatio[2] = 2;
bitsRatio[3] = 6;
}
else if( bpp > 0.1 )
{
bitsRatio[0] = 2;
bitsRatio[1] = 3;
bitsRatio[2] = 2;
bitsRatio[3] = 10;
}
else if ( bpp > 0.05 )
{
bitsRatio[0] = 2;
bitsRatio[1] = 3;
bitsRatio[2] = 2;
bitsRatio[3] = 12;
}
else
{
bitsRatio[0] = 2;
bitsRatio[1] = 3;
bitsRatio[2] = 2;
bitsRatio[3] = 14;
}
if ( keepHierBits == 2 )
{
adaptiveBit = 1;
}
}
else if ( GOPSize == 8 && !isLowdelay )
{
if ( bpp > 0.2 )
{
bitsRatio[0] = 15;
bitsRatio[1] = 5;
bitsRatio[2] = 4;
bitsRatio[3] = 1;
bitsRatio[4] = 1;
bitsRatio[5] = 4;
bitsRatio[6] = 1;
bitsRatio[7] = 1;
}
else if ( bpp > 0.1 )
{
bitsRatio[0] = 20;
bitsRatio[1] = 6;
bitsRatio[2] = 4;
bitsRatio[3] = 1;
bitsRatio[4] = 1;
bitsRatio[5] = 4;
bitsRatio[6] = 1;
bitsRatio[7] = 1;
}
else if ( bpp > 0.05 )
{
bitsRatio[0] = 25;
bitsRatio[1] = 7;
bitsRatio[2] = 4;
bitsRatio[3] = 1;
bitsRatio[4] = 1;
bitsRatio[5] = 4;
bitsRatio[6] = 1;
bitsRatio[7] = 1;
}
else
{
bitsRatio[0] = 30;
bitsRatio[1] = 8;
bitsRatio[2] = 4;
bitsRatio[3] = 1;
bitsRatio[4] = 1;
bitsRatio[5] = 4;
bitsRatio[6] = 1;
bitsRatio[7] = 1;
}
if ( keepHierBits == 2 )
{
adaptiveBit = 2;
}
}
else if (GOPSize == 16 && !isLowdelay)
{
if (bpp > 0.2)
{
bitsRatio[0] = 10;
bitsRatio[1] = 8;
bitsRatio[2] = 4;
bitsRatio[3] = 2;
bitsRatio[4] = 1;
bitsRatio[5] = 1;
bitsRatio[6] = 2;
bitsRatio[7] = 1;
bitsRatio[8] = 1;
bitsRatio[9] = 4;
bitsRatio[10] = 2;
bitsRatio[11] = 1;
bitsRatio[12] = 1;
bitsRatio[13] = 2;
bitsRatio[14] = 1;
bitsRatio[15] = 1;
}
else if (bpp > 0.1)
{
bitsRatio[0] = 15;
bitsRatio[1] = 9;
bitsRatio[2] = 4;
bitsRatio[3] = 2;
bitsRatio[4] = 1;
bitsRatio[5] = 1;
bitsRatio[6] = 2;
bitsRatio[7] = 1;
bitsRatio[8] = 1;
bitsRatio[9] = 4;
bitsRatio[10] = 2;
bitsRatio[11] = 1;
bitsRatio[12] = 1;
bitsRatio[13] = 2;
bitsRatio[14] = 1;
bitsRatio[15] = 1;
}
else if (bpp > 0.05)
{
bitsRatio[0] = 40;
bitsRatio[1] = 17;
bitsRatio[2] = 7;
bitsRatio[3] = 2;
bitsRatio[4] = 1;
bitsRatio[5] = 1;
bitsRatio[6] = 2;
bitsRatio[7] = 1;
bitsRatio[8] = 1;
bitsRatio[9] = 7;
bitsRatio[10] = 2;
bitsRatio[11] = 1;
bitsRatio[12] = 1;
bitsRatio[13] = 2;
bitsRatio[14] = 1;
bitsRatio[15] = 1;
}
else
{
bitsRatio[0] = 40;
bitsRatio[1] = 15;
bitsRatio[2] = 6;
bitsRatio[3] = 3;
bitsRatio[4] = 1;
bitsRatio[5] = 1;
bitsRatio[6] = 3;
bitsRatio[7] = 1;
bitsRatio[8] = 1;
bitsRatio[9] = 6;
bitsRatio[10] = 3;
bitsRatio[11] = 1;
bitsRatio[12] = 1;
bitsRatio[13] = 3;
bitsRatio[14] = 1;
bitsRatio[15] = 1;
}
if (keepHierBits == 2)
{
adaptiveBit = 3;
}
}
else
{
msg( WARNING, "\n hierarchical bit allocation is not support for the specified coding structure currently.\n" );
}
}
int* GOPID2Level = new int[ GOPSize ];
for ( int i=0; i<GOPSize; i++ )
{
GOPID2Level[i] = 1;
if ( !GOPList[i].m_refPic )
{
GOPID2Level[i] = 2;
}
}
if ( keepHierBits > 0 )
{
if ( GOPSize == 4 && isLowdelay )
{
GOPID2Level[0] = 3;
GOPID2Level[1] = 2;
GOPID2Level[2] = 3;
GOPID2Level[3] = 1;
}
else if ( GOPSize == 8 && !isLowdelay )
{
GOPID2Level[0] = 1;
GOPID2Level[1] = 2;
GOPID2Level[2] = 3;
GOPID2Level[3] = 4;
GOPID2Level[4] = 4;
GOPID2Level[5] = 3;
GOPID2Level[6] = 4;
GOPID2Level[7] = 4;
}
else if (GOPSize == 16 && !isLowdelay)
{
GOPID2Level[0] = 1;
GOPID2Level[1] = 2;
GOPID2Level[2] = 3;
GOPID2Level[3] = 4;
GOPID2Level[4] = 5;
GOPID2Level[5] = 5;
GOPID2Level[6] = 4;
GOPID2Level[7] = 5;
GOPID2Level[8] = 5;
GOPID2Level[9] = 3;
GOPID2Level[10] = 4;
GOPID2Level[11] = 5;
GOPID2Level[12] = 5;
GOPID2Level[13] = 4;
GOPID2Level[14] = 5;
GOPID2Level[15] = 5;
}
}
if ( !isLowdelay && GOPSize == 8 )
{
GOPID2Level[0] = 1;
GOPID2Level[1] = 2;
GOPID2Level[2] = 3;
GOPID2Level[3] = 4;
GOPID2Level[4] = 4;
GOPID2Level[5] = 3;
GOPID2Level[6] = 4;
GOPID2Level[7] = 4;
}
else if (GOPSize == 16 && !isLowdelay)
{
GOPID2Level[0] = 1;
GOPID2Level[1] = 2;
GOPID2Level[2] = 3;
GOPID2Level[3] = 4;
GOPID2Level[4] = 5;
GOPID2Level[5] = 5;
GOPID2Level[6] = 4;
GOPID2Level[7] = 5;
GOPID2Level[8] = 5;
GOPID2Level[9] = 3;
GOPID2Level[10] = 4;
GOPID2Level[11] = 5;
GOPID2Level[12] = 5;
GOPID2Level[13] = 4;
GOPID2Level[14] = 5;
GOPID2Level[15] = 5;
}
m_encRCSeq = new EncRCSeq;
m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel, adaptiveBit );
m_encRCSeq->initBitsRatio( bitsRatio );
m_encRCSeq->initGOPID2Level( GOPID2Level );
m_encRCSeq->setBitDepth(bitDepth);
m_encRCSeq->initPicPara();
if ( useLCUSeparateModel )
{
m_encRCSeq->initLCUPara();
}
#if U0132_TARGET_BITS_SATURATION
m_CpbSaturationEnabled = false;
m_cpbSize = targetBitrate;
m_cpbState = (uint32_t)(m_cpbSize*0.5f);
m_bufferingRate = (int)(targetBitrate / frameRate);
#endif
delete[] bitsRatio;
delete[] GOPID2Level;
}
GOP碼率控制初始化
void EncRCGOP::create( EncRCSeq* encRCSeq, int numPic )
{
destroy();
int targetBits = xEstGOPTargetBits( encRCSeq, numPic );
if ( encRCSeq->getAdaptiveBits() > 0 && encRCSeq->getLastLambda() > 0.1 )
{
double targetBpp = (double)targetBits / encRCSeq->getNumPixel();
double basicLambda = 0.0;
double* lambdaRatio = new double[encRCSeq->getGOPSize()];
double* equaCoeffA = new double[encRCSeq->getGOPSize()];
double* equaCoeffB = new double[encRCSeq->getGOPSize()];
if ( encRCSeq->getAdaptiveBits() == 1 ) // for GOP size =4, low delay case
{
if ( encRCSeq->getLastLambda() < 120.0 )
{
lambdaRatio[1] = 0.725 * log( encRCSeq->getLastLambda() ) + 0.5793;
lambdaRatio[0] = 1.3 * lambdaRatio[1];
lambdaRatio[2] = 1.3 * lambdaRatio[1];
lambdaRatio[3] = 1.0;
}
else
{
lambdaRatio[0] = 5.0;
lambdaRatio[1] = 4.0;
lambdaRatio[2] = 5.0;
lambdaRatio[3] = 1.0;
}
}
else if ( encRCSeq->getAdaptiveBits() == 2 ) // for GOP size = 8, random access case
{
if ( encRCSeq->getLastLambda() < 90.0 )
{
lambdaRatio[0] = 1.0;
lambdaRatio[1] = 0.725 * log( encRCSeq->getLastLambda() ) + 0.7963;
lambdaRatio[2] = 1.3 * lambdaRatio[1];
lambdaRatio[3] = 3.25 * lambdaRatio[1];
lambdaRatio[4] = 3.25 * lambdaRatio[1];
lambdaRatio[5] = 1.3 * lambdaRatio[1];
lambdaRatio[6] = 3.25 * lambdaRatio[1];
lambdaRatio[7] = 3.25 * lambdaRatio[1];
}
else
{
lambdaRatio[0] = 1.0;
lambdaRatio[1] = 4.0;
lambdaRatio[2] = 5.0;
lambdaRatio[3] = 12.3;
lambdaRatio[4] = 12.3;
lambdaRatio[5] = 5.0;
lambdaRatio[6] = 12.3;
lambdaRatio[7] = 12.3;
}
}
else if (encRCSeq->getAdaptiveBits() == 3) // for GOP size = 16, random access case
{
{
int bitdepth_luma_scale =
2
* (encRCSeq->getbitDepth() - 8
- DISTORTION_PRECISION_ADJUSTMENT(encRCSeq->getbitDepth()));
double hierarQp = 4.2005 * log(encRCSeq->getLastLambda() / pow(2.0, bitdepth_luma_scale)) + 13.7122; // the qp of POC16
double qpLev2 = (hierarQp + 0.0) + 0.2016 * (hierarQp + 0.0) - 4.8848;
double qpLev3 = (hierarQp + 3.0) + 0.22286 * (hierarQp + 3.0) - 5.7476;
double qpLev4 = (hierarQp + 4.0) + 0.2333 * (hierarQp + 4.0) - 5.9;
double qpLev5 = (hierarQp + 5.0) + 0.3 * (hierarQp + 5.0) - 7.1444;
double lambdaLev1 = exp((hierarQp - 13.7122) / 4.2005) *pow(2.0, bitdepth_luma_scale);
double lambdaLev2 = exp((qpLev2 - 13.7122) / 4.2005) * pow(2.0, bitdepth_luma_scale);
double lambdaLev3 = exp((qpLev3 - 13.7122) / 4.2005) * pow(2.0, bitdepth_luma_scale);
double lambdaLev4 = exp((qpLev4 - 13.7122) / 4.2005) * pow(2.0, bitdepth_luma_scale);
double lambdaLev5 = exp((qpLev5 - 13.7122) / 4.2005) * pow(2.0, bitdepth_luma_scale);
lambdaRatio[0] = 1.0;
lambdaRatio[1] = lambdaLev2 / lambdaLev1;
lambdaRatio[2] = lambdaLev3 / lambdaLev1;
lambdaRatio[3] = lambdaLev4 / lambdaLev1;
lambdaRatio[4] = lambdaLev5 / lambdaLev1;
lambdaRatio[5] = lambdaLev5 / lambdaLev1;
lambdaRatio[6] = lambdaLev4 / lambdaLev1;
lambdaRatio[7] = lambdaLev5 / lambdaLev1;
lambdaRatio[8] = lambdaLev5 / lambdaLev1;
lambdaRatio[9] = lambdaLev3 / lambdaLev1;
lambdaRatio[10] = lambdaLev4 / lambdaLev1;
lambdaRatio[11] = lambdaLev5 / lambdaLev1;
lambdaRatio[12] = lambdaLev5 / lambdaLev1;
lambdaRatio[13] = lambdaLev4 / lambdaLev1;
lambdaRatio[14] = lambdaLev5 / lambdaLev1;
lambdaRatio[15] = lambdaLev5 / lambdaLev1;
const double qdfParaLev2A = 0.5847;
const double qdfParaLev2B = -0.0782;
const double qdfParaLev3A = 0.5468;
const double qdfParaLev3B = -0.1364;
const double qdfParaLev4A = 0.6539;
const double qdfParaLev4B = -0.203;
const double qdfParaLev5A = 0.8623;
const double qdfParaLev5B = -0.4676;
double qdfLev1Lev2 = Clip3(0.12, 0.9, qdfParaLev2A * encRCSeq->getPicPara(2).m_skipRatio + qdfParaLev2B);
double qdfLev1Lev3 = Clip3(0.13, 0.9, qdfParaLev3A * encRCSeq->getPicPara(3).m_skipRatio + qdfParaLev3B);
double qdfLev1Lev4 = Clip3(0.15, 0.9, qdfParaLev4A * encRCSeq->getPicPara(4).m_skipRatio + qdfParaLev4B);
double qdfLev1Lev5 = Clip3(0.20, 0.9, qdfParaLev5A * encRCSeq->getPicPara(5).m_skipRatio + qdfParaLev5B);
double qdfLev2Lev3 = Clip3(0.09, 0.9, qdfLev1Lev3 * (1 - qdfLev1Lev2));
double qdfLev2Lev4 = Clip3(0.12, 0.9, qdfLev1Lev4 * (1 - qdfLev1Lev2));
double qdfLev2Lev5 = Clip3(0.14, 0.9, qdfLev1Lev5 * (1 - qdfLev1Lev2));
double qdfLev3Lev4 = Clip3(0.06, 0.9, qdfLev1Lev4 * (1 - qdfLev1Lev3));
double qdfLev3Lev5 = Clip3(0.09, 0.9, qdfLev1Lev5 * (1 - qdfLev1Lev3));
double qdfLev4Lev5 = Clip3(0.10, 0.9, qdfLev1Lev5 * (1 - qdfLev1Lev4));
lambdaLev1 = 1 / (1 + 2 * (qdfLev1Lev2 + 2 * qdfLev1Lev3 + 4 * qdfLev1Lev4 + 8 * qdfLev1Lev5));
lambdaLev2 = 1 / (1 + (3 * qdfLev2Lev3 + 5 * qdfLev2Lev4 + 8 * qdfLev2Lev5));
lambdaLev3 = 1 / (1 + 2 * qdfLev3Lev4 + 4 * qdfLev3Lev5);
lambdaLev4 = 1 / (1 + 2 * qdfLev4Lev5);
lambdaLev5 = 1 / (1.0);
lambdaRatio[0] = 1.0;
lambdaRatio[1] = lambdaLev2 / lambdaLev1;
lambdaRatio[2] = lambdaLev3 / lambdaLev1;
lambdaRatio[3] = lambdaLev4 / lambdaLev1;
lambdaRatio[4] = lambdaLev5 / lambdaLev1;
lambdaRatio[5] = lambdaLev5 / lambdaLev1;
lambdaRatio[6] = lambdaLev4 / lambdaLev1;
lambdaRatio[7] = lambdaLev5 / lambdaLev1;
lambdaRatio[8] = lambdaLev5 / lambdaLev1;
lambdaRatio[9] = lambdaLev3 / lambdaLev1;
lambdaRatio[10] = lambdaLev4 / lambdaLev1;
lambdaRatio[11] = lambdaLev5 / lambdaLev1;
lambdaRatio[12] = lambdaLev5 / lambdaLev1;
lambdaRatio[13] = lambdaLev4 / lambdaLev1;
lambdaRatio[14] = lambdaLev5 / lambdaLev1;
lambdaRatio[15] = lambdaLev5 / lambdaLev1;
}
}
xCalEquaCoeff( encRCSeq, lambdaRatio, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() );
basicLambda = xSolveEqua(encRCSeq, targetBpp, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize());
encRCSeq->setAllBitRatio( basicLambda, equaCoeffA, equaCoeffB );
delete []lambdaRatio;
delete []equaCoeffA;
delete []equaCoeffB;
}
m_picTargetBitInGOP = new int[numPic];
int i;
int totalPicRatio = 0;
int currPicRatio = 0;
for ( i=0; i<numPic; i++ )
{
totalPicRatio += encRCSeq->getBitRatio( i );
}
for ( i=0; i<numPic; i++ )
{
currPicRatio = encRCSeq->getBitRatio( i );
m_picTargetBitInGOP[i] = (int)( ((double)targetBits) * currPicRatio / totalPicRatio );
}
m_encRCSeq = encRCSeq;
m_numPic = numPic;
m_targetBits = targetBits;
m_picLeft = m_numPic;
m_bitsLeft = m_targetBits;
}
幀級碼率控制初始化
void EncRCPic::create( EncRCSeq* encRCSeq, EncRCGOP* encRCGOP, int frameLevel, list<EncRCPic*>& listPreviousPictures )
{
destroy();
m_encRCSeq = encRCSeq;
m_encRCGOP = encRCGOP;
int targetBits = xEstPicTargetBits( encRCSeq, encRCGOP );
int estHeaderBits = xEstPicHeaderBits( listPreviousPictures, frameLevel );
if ( targetBits < estHeaderBits + 100 )
{
targetBits = estHeaderBits + 100; // at least allocate 100 bits for picture data
}
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;
#if V0078_ADAPTIVE_LOWER_BOUND
m_lowerBound = xEstPicLowerBound( encRCSeq, encRCGOP );
#endif
m_LCULeft = m_numberOfLCU;
m_bitsLeft -= m_estHeaderBits;
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_actualSSE = 0.0;
m_LCUs[LCUIdx].m_actualMSE = 0.0;
m_LCUs[LCUIdx].m_QP = 0;
m_LCUs[LCUIdx].m_lambda = 0.0;
m_LCUs[LCUIdx].m_targetBits = 0;
m_LCUs[LCUIdx].m_bitWeight = 1.0;
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;
m_picActualBits = 0;
m_picQP = 0;
m_picLambda = 0.0;
m_validPixelsInPic = 0;
m_picMSE = 0.0;
}