上一篇文章主要讨论了RC的总体框架,本文开始分析具体的代码实现细节。分析的顺序按照总体框架来,即初始化-->更新。
(1)m_cRateCtrl.init()
#if M0036_RC_IMPROVEMENT Void TEncRateCtrl::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] ) #else Void TEncRateCtrl::init( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Bool keepHierBits, Bool useLCUSeparateModel, GOPEntry GOPList[MAX_GOP] ) #endif { destroy(); Bool isLowdelay = true; for ( Int i=0; i<GOPSize-1; i++ ) { if ( GOPList[i].m_POC > GOPList[i+1].m_POC ) //!< 判断是否为lowdelay配置 { isLowdelay = false; break; } } Int numberOfLevel = 1; #if M0036_RC_IMPROVEMENT Int adaptiveBit = 0; if ( keepHierBits > 0 ) #else if ( keepHierBits ) //!< hierarchical structure #endif { numberOfLevel = Int( log((Double)GOPSize)/log(2.0) + 0.5 ) + 1; } if ( !isLowdelay && GOPSize == 8 ) { numberOfLevel = Int( log((Double)GOPSize)/log(2.0) + 0.5 ) + 1; } numberOfLevel++; // intra picture numberOfLevel++; // non-reference picture Int* bitsRatio; //!< 每一幅picture的权值 bitsRatio = new Int[ GOPSize ]; for ( Int i=0; i<GOPSize; i++ ) { bitsRatio[i] = 10; if ( !GOPList[i].m_refPic ) { bitsRatio[i] = 2; } } #if M0036_RC_IMPROVEMENT if ( keepHierBits > 0 ) #else if ( keepHierBits ) #endif { Double bpp = (Double)( targetBitrate / (Double)( frameRate*picWidth*picHeight ) ); //!< K0103 式子(3) if ( GOPSize == 4 && isLowdelay ) //!< K0103 Table 1 { 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 M0036_RC_IMPROVEMENT if ( keepHierBits == 2 ) { adaptiveBit = 1; } #endif } else if ( GOPSize == 8 && !isLowdelay ) //!< K0103 Table 2 { 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 M0036_RC_IMPROVEMENT if ( keepHierBits == 2 ) { adaptiveBit = 2; } #endif } else { #if M0036_RC_IMPROVEMENT printf( "\n hierarchical bit allocation is not support for the specified coding structure currently.\n" ); #else printf( "\n hierarchical bit allocation is not support for the specified coding structure currently." ); #endif } } Int* GOPID2Level = new int[ GOPSize ]; //!< 根据在GOP中的id确定所属的分层 for ( int i=0; i<GOPSize; i++ ) { GOPID2Level[i] = 1; if ( !GOPList[i].m_refPic ) { GOPID2Level[i] = 2; } } #if M0036_RC_IMPROVEMENT if ( keepHierBits > 0 ) #else if ( keepHierBits ) #endif { 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; } } 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; } m_encRCSeq = new TEncRCSeq; #if M0036_RC_IMPROVEMENT m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel, adaptiveBit ); #else //!< 序列级RC参数的初始化 m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel ); #endif m_encRCSeq->initBitsRatio( bitsRatio ); //!< 每幅picture的权值 m_encRCSeq->initGOPID2Level( GOPID2Level ); m_encRCSeq->initPicPara(/*TRCParameter* picPara = NULL*/); //!< alpha, beta if ( useLCUSeparateModel ) { m_encRCSeq->initLCUPara(); //!< alpha,beta初始化 } delete[] bitsRatio; delete[] GOPID2Level; }
分析该函数中调用的比较重要的若干个子函数:
m_encRCSeq->create()
#if M0036_RC_IMPROVEMENT Void TEncRCSeq::create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel, Int adaptiveBit ) #else Void TEncRCSeq::create( Int totalFrames, Int targetBitrate, Int frameRate, Int GOPSize, Int picWidth, Int picHeight, Int LCUWidth, Int LCUHeight, Int numberOfLevel, Bool useLCUSeparateModel ) #endif { destroy(); m_totalFrames = totalFrames; m_targetRate = targetBitrate; m_frameRate = frameRate; m_GOPSize = GOPSize; m_picWidth = picWidth; m_picHeight = picHeight; m_LCUWidth = LCUWidth; m_LCUHeight = LCUHeight; m_numberOfLevel = numberOfLevel; m_useLCUSeparateModel = useLCUSeparateModel; m_numberOfPixel = m_picWidth * m_picHeight; m_targetBits = (Int64)m_totalFrames * (Int64)m_targetRate / (Int64)m_frameRate; //!< 序列总码率(输出码流总大小) m_seqTargetBpp = (Double)m_targetRate / (Double)m_frameRate / (Double)m_numberOfPixel; //!< m_targetRate--bps //!< m_alphaUpdata和m_betaUpdate这两个变量用于在接下来更新lamda的参数值 if ( m_seqTargetBpp < 0.03 ) //!< (..., 0.03) { m_alphaUpdate = 0.01; m_betaUpdate = 0.005; } else if ( m_seqTargetBpp < 0.08 ) //!< [0.03, 0.08) { m_alphaUpdate = 0.05; m_betaUpdate = 0.025; } #if M0036_RC_IMPROVEMENT else if ( m_seqTargetBpp < 0.2 ) { m_alphaUpdate = 0.1; m_betaUpdate = 0.05; } else if ( m_seqTargetBpp < 0.5 ) { m_alphaUpdate = 0.2; m_betaUpdate = 0.1; } else { m_alphaUpdate = 0.4; m_betaUpdate = 0.2; } #else else //!< [0.08, ...] { m_alphaUpdate = 0.1; m_betaUpdate = 0.05; } #endif m_averageBits = (Int)(m_targetBits / totalFrames); //!< 平均每帧占用的比特数 Int picWidthInBU = ( m_picWidth % m_LCUWidth ) == 0 ? m_picWidth / m_LCUWidth : m_picWidth / m_LCUWidth + 1; Int picHeightInBU = ( m_picHeight % m_LCUHeight ) == 0 ? m_picHeight / m_LCUHeight : m_picHeight / m_LCUHeight + 1; m_numberOfLCU = picWidthInBU * picHeightInBU; //!< 一帧picture中包含的LCU数目 m_bitsRatio = new Int[m_GOPSize]; for ( Int i=0; i<m_GOPSize; i++ ) { m_bitsRatio[i] = 1; } m_GOPID2Level = new Int[m_GOPSize]; for ( Int i=0; i<m_GOPSize; i++ ) { m_GOPID2Level[i] = 1; } m_picPara = new TRCParameter[m_numberOfLevel]; for ( Int i=0; i<m_numberOfLevel; i++ ) { m_picPara[i].m_alpha = 0.0; m_picPara[i].m_beta = 0.0; } if ( m_useLCUSeparateModel ) //!< 每个LCU的alpha和beta都有各自的值 { m_LCUPara = new TRCParameter*[m_numberOfLevel]; for ( Int i=0; i<m_numberOfLevel; i++ ) { m_LCUPara[i] = new TRCParameter[m_numberOfLCU]; for ( Int j=0; j<m_numberOfLCU; j++) { m_LCUPara[i][j].m_alpha = 0.0; m_LCUPara[i][j].m_beta = 0.0; } } } m_framesLeft = m_totalFrames; //!< 剩余的待编码帧数 m_bitsLeft = m_targetBits; //!< 剩余可用的比特数 #if M0036_RC_IMPROVEMENT m_adaptiveBit = adaptiveBit; m_lastLambda = 0.0; #endif }
m_encRCSeq->initPicPara()
Void TEncRCSeq::initPicPara( TRCParameter* picPara ) { assert( m_picPara != NULL ); if ( picPara == NULL ) //!< K0103 式子(10) { for ( Int i=0; i<m_numberOfLevel; i++ ) { #if RATE_CONTROL_INTRA if (i>0) { m_picPara[i].m_alpha = 3.2003; m_picPara[i].m_beta = -1.367; } else { m_picPara[i].m_alpha = ALPHA; m_picPara[i].m_beta = BETA2; } #else //!< 第一帧图像的参数初始化 m_picPara[i].m_alpha = 3.2003; m_picPara[i].m_beta = -1.367; #endif } } else { for ( Int i=0; i<m_numberOfLevel; i++ ) { m_picPara[i] = picPara[i]; } } }
(2)m_cRateCtrl.initRCGOP()
Void TEncRateCtrl::initRCGOP( Int numberOfPictures ) { m_encRCGOP = new TEncRCGOP; m_encRCGOP->create( m_encRCSeq, numberOfPictures ); }
Void TEncRCGOP::create( TEncRCSeq* encRCSeq, Int numPic ) { destroy(); Int targetBits = xEstGOPTargetBits( encRCSeq, numPic ); //!< GOP level bit allocation #if M0036_RC_IMPROVEMENT 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() ); basicLambda = xSolveEqua( targetBpp, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() ); encRCSeq->setAllBitRatio( basicLambda, equaCoeffA, equaCoeffB ); delete []lambdaRatio; delete []equaCoeffA; delete []equaCoeffB; } #endif m_picTargetBitInGOP = new Int[numPic]; //!< 用于保存当前GOP中每幅picture对应的目标码率 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 ); //!< 当前picture的权值 #if M0036_RC_IMPROVEMENT m_picTargetBitInGOP[i] = (Int)( ((Double)targetBits) * currPicRatio / totalPicRatio ); #else m_picTargetBitInGOP[i] = targetBits * currPicRatio / totalPicRatio; //!< K0103 式子(9),注意:由于是初始化,式子中的CodedGOP等于0 #endif } m_encRCSeq = encRCSeq; m_numPic = numPic; m_targetBits = targetBits; m_picLeft = m_numPic; m_bitsLeft = m_targetBits; }
Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize ) { Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() ); //!< 获得实际的平滑窗口大小 Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() ); //!< RPicArg Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture ); //!< TAvgPic,计算方法跟K0103不同,这里利用left的思路计算,而K0103利用coded的思路计算,但结果是一样的 Int targetBits = currentTargetBitsPerPic * GOPSize; //!< TGOP if ( targetBits < 200 ) { targetBits = 200; // at least allocate 200 bits for one GOP } return targetBits; }
(未完待续...)