每个picture的比特分配权重,跟GOP级别的Lagrangian multiplier lambda有关。已知GOP内每个picture的alpha和beta,在保证所有Picture的target bit加起来等于GOP的target bit的前提下,通过二分法,迭代求出GOP的拉格朗日乘子。
在 TEncTop:encode()函数中,执行compress GOP( )之前,还执行了一句对每个GOP的初始化:
Void TEncTop:encode) { ... if ( m_RCEnableRateControl ) { m_cRateCtrl.initRCGOP( m_iNumPicRcvd ); } // compress GOP m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, false, false, snrCSC, m_printFrameMSE); } 在initRCGOP()函数中,完成了对每个picture的比特分配权重的确定 Void TEncRateCtrl::initRCGOP( Int numberOfPictures ) { m_encRCGOP = new TEncRCGOP; m_encRCGOP->create( m_encRCSeq, numberOfPictures ); } 在create()函数中,通过二分法完成了对GOP level 的lambda求解 Void TEncRCGOP::create( TEncRCSeq* encRCSeq, Int numPic ) { destroy(); Int targetBits = xEstGOPTargetBits( encRCSeq, numPic );//GOP level bit allocation 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; } } xCalEquaCoeff( encRCSeq, lambdaRatio, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() ); //根据每个picture的alpha和beta,初始化系数数组A和B basicLambda = xSolveEqua( 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;//一个GOP内不同PIC的权重 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; }二分法实现lambda求解的代码:
Double TEncRCGOP::xSolveEqua( Double targetBpp, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize ) { Double solution = 100.0; Double minNumber = 0.1; Double maxNumber = 10000.0; for ( Int i=0; i<g_RCIterationNum; i++ ) { Double fx = 0.0; for ( Int j=0; j<GOPSize; j++ ) { fx += equaCoeffA[j] * pow( solution, equaCoeffB[j] ); } if ( fabs( fx - targetBpp ) < 0.000001 ) { break; } if ( fx > targetBpp ) { minNumber = solution; solution = ( solution + maxNumber ) / 2.0; } else { maxNumber = solution; solution = ( solution + minNumber ) / 2.0; } } solution = Clip3( 0.1, 10000.0, solution ); return solution; }