参考大神传送门:
https://blog.csdn.net/NB_vol_1/article/details/55096464
https://blog.csdn.net/s1314_JHC/article/details/78113416
https://blog.csdn.net/HEVC_CJL/article/details/11115721
一、m_cRateCtrl.init()
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] )
{
destroy();
Bool isLowdelay = true;//lowdelay的判断标志位
for ( Int i=0; i<GOPSize-1; i++ )//GOPList[MAX_GOP]GOP列表,MAX_GOP是GOP分层结构大小的最大值,为64
{
if ( GOPList[i].m_POC > GOPList[i+1].m_POC )//.m_POC是GOPEntry结构体的成员。如果编码顺序对应的播放顺序大于下一帧的播放顺序,就不是lowdelay模式
{
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 == 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 ) );//计算bpp
if ( GOPSize == 4 && isLowdelay )//如果GOPSize==4并且是lowdelay模式,按照358页表12.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 ( keepHierBits == 2 )//若keepHierBits==2,adaptiveBit赋值为1
{
adaptiveBit = 1;
}
}
else if ( GOPSize == 8 && !isLowdelay )//如果GOPSize==8并且不是lowdelay模式,按照358页表12.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 ( keepHierBits == 2 )//若keepHierBits==2,adaptiveBit赋值为1
{
adaptiveBit = 2;
}
}
else
{
printf( "\n hierarchical bit allocation is not support for the specified coding structure currently.\n" );
}
}
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 ( 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;
}
}
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;
m_encRCSeq->create( totalFrames, targetBitrate, frameRate, GOPSize, picWidth, picHeight, LCUWidth, LCUHeight, numberOfLevel, useLCUSeparateModel, adaptiveBit );
//!< 序列级RC参数的初始化
m_encRCSeq->initBitsRatio( bitsRatio );//!< 每幅picture的权值
m_encRCSeq->initGOPID2Level( GOPID2Level );//设置GOP的Id到Level的映射
m_encRCSeq->initPicPara();//帧级别的alpha,beta的参数设置
if ( useLCUSeparateModel )
{
m_encRCSeq->initLCUPara();//LCU级别的alpha,beta的参数设置
}
delete[] bitsRatio;
delete[] GOPID2Level;
}
其中有两个比较重要的函数
(1)m_encRCSeq->create()** 序列级RC参数的初始化**
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 )
{
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_alphaUpdata和m_betaUpdate这两个变量用于在接下来更新lamda的参数值
if ( m_seqTargetBpp < 0.03 )
{
m_alphaUpdate = 0.01;
m_betaUpdate = 0.005;
}
else if ( m_seqTargetBpp < 0.08 )
{
m_alphaUpdate = 0.05;
m_betaUpdate = 0.025;
}
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;
}
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];//TRCParameter结构体中包含.m_alpha和.m_beta两个成员
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;//!< 剩余可用的比特数
m_adaptiveBit = adaptiveBit;
m_lastLambda = 0.0;
}
(2)m_encRCSeq->initPicPara()帧级别的alpha,beta的参数设置
Void TEncRCSeq::initPicPara( TRCParameter* picPara )
{
assert( m_picPara != NULL );
if ( picPara == NULL )
{
for ( Int i=0; i<m_numberOfLevel; i++ )
{
if (i>0)
{
m_picPara[i].m_alpha = 3.2003;
m_picPara[i].m_beta = -1.367;
}
else
{
m_picPara[i].m_alpha = ALPHA;//i=0时,赋给初始值
m_picPara[i].m_beta = BETA2;
}
}
}
else
{
for ( Int i=0; i<m_numberOfLevel; i++ )
{
m_picPara[i] = picPara[i];
}
}
}
二、Void TEncRateCtrl::initRCGOP( Int numberOfPictures )
Void TEncRateCtrl::initRCGOP( Int numberOfPictures )
{
m_encRCGOP = new TEncRCGOP;
m_encRCGOP->create( m_encRCSeq, numberOfPictures );//创建新的GOP层的类,传递序列层和一个GOP中的帧数
}
(1)其中调用了一个m_encRCGOP->create()函数
Void TEncRCGOP::create( TEncRCSeq* encRCSeq, Int numPic )
{
destroy();
Int targetBits = xEstGOPTargetBits( encRCSeq, numPic );//获得GOP层的目标总比特数;
if ( encRCSeq->getAdaptiveBits() > 0 && encRCSeq->getLastLambda() > 0.1 )//采用自适应比特分配并且序列的最后一个lambda的值大于0.1
{
Double targetBpp = (Double)targetBits / encRCSeq->getNumPixel();//得到目标bpp
Double basicLambda = 0.0;
Double* lambdaRatio = new Double[encRCSeq->getGOPSize()];//分别新建存储lambda、alpha、beta 的值
Double* equaCoeffA = new Double[encRCSeq->getGOPSize()];
Double* equaCoeffB = new Double[encRCSeq->getGOPSize()];
if ( encRCSeq->getAdaptiveBits() == 1 ) // for GOP size =4, low delay case在lowdelay模式下, encRCSeq->getAdaptiveBits() == 1
{
if ( encRCSeq->getLastLambda() < 120.0 )//对每一帧的lambda的权值进行赋值
{
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在random access模式下, encRCSeq->getAdaptiveBits() == 2
{
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;
}
m_picTargetBitInGOP = new Int[numPic];//GOP中的图片目标比特
Int i;
Int totalPicRatio = 0;
Int currPicRatio = 0;
for ( i=0; i<numPic; i++ )//遍历整个GOP
{
totalPicRatio += encRCSeq->getBitRatio( i );//得到整个GOP所有图片的比特数
}
for ( i=0; i<numPic; i++ )
{
currPicRatio = encRCSeq->getBitRatio( i );//得到当前图像的比特率
m_picTargetBitInGOP[i] = (Int)( ((Double)targetBits) * currPicRatio / totalPicRatio );//得到当前GOP中的每一帧的目标比特
}
m_encRCSeq = encRCSeq;
m_numPic = numPic;
m_targetBits = targetBits;
m_picLeft = m_numPic;
m_bitsLeft = m_targetBits;
}
①其中调用了xEstGOPTargetBits( encRCSeq, numPic )函数对GOP的目标比特进行预测,返回预测的目标比特数。
Int TEncRCGOP::xEstGOPTargetBits( TEncRCSeq* encRCSeq, Int GOPSize )//传递进来码控序列和GOP的大小即一个GOP中的帧数
{
Int realInfluencePicture = min( g_RCSmoothWindowSize, encRCSeq->getFramesLeft() );//获得实际的平滑窗口大小
Int averageTargetBitsPerPic = (Int)( encRCSeq->getTargetBits() / encRCSeq->getTotalFrames() );//获得平均每帧的目标比特
Int currentTargetBitsPerPic = (Int)( ( encRCSeq->getBitsLeft() - averageTargetBitsPerPic * (encRCSeq->getFramesLeft() - realInfluencePicture) ) / realInfluencePicture );
//当前每帧的目标比特=(视频序列剩余比特数-平均每帧目标比特*(未编码帧数-平滑窗口SW))/平滑窗口SW
Int targetBits = currentTargetBitsPerPic * GOPSize;//当前GOP的目标比特数=当前每帧的目标比特数*一个GOP中的帧数
if ( targetBits < 200 )
{
targetBits = 200; // at least allocate 200 bits for one GOP每个GOP至少分配200个比特
}
return targetBits;
}
②其中调用了xCalEquaCoeff( encRCSeq, lambdaRatio, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() )来计算系数A和B
Void TEncRCGOP::xCalEquaCoeff( TEncRCSeq* encRCSeq, Double* lambdaRatio, Double* equaCoeffA, Double* equaCoeffB, Int GOPSize )
{
for ( Int i=0; i<GOPSize; i++ )//遍历整个GOP
{
Int frameLevel = encRCSeq->getGOPID2Level(i);//调用映射函数得到帧所对应的level
Double alpha = encRCSeq->getPicPara(frameLevel).m_alpha;//根据framelevel调用getPicPara()函数来得到对应的alpha和beta
Double beta = encRCSeq->getPicPara(frameLevel).m_beta;
equaCoeffA[i] = pow( 1.0/alpha, 1.0/beta ) * pow( lambdaRatio[i], 1.0/beta );//根据alpha和beta计算系数A和B
equaCoeffB[i] = 1.0/beta;
}
}
③然后调用xSolveEqua( targetBpp, equaCoeffA, equaCoeffB, encRCSeq->getGOPSize() )计算初始λ的值
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++ )//const Int g_RCIterationNum = 20;循环20次
{
Double fx = 0.0;//新建变量fx作为计算的bpp,并且初始化
for ( Int j=0; j<GOPSize; j++ )//遍历整个GOP
{
fx += equaCoeffA[j] * pow( solution, equaCoeffB[j] );//fx+=系数A*lambda的系数B次方,累加过后为一个GOP的计算Bpp
}
if ( fabs( fx - targetBpp ) < 0.000001 )//若fx - targetBpp的绝对值小于0.000001,满足精度跳出循环
{
break;
}
if ( fx > targetBpp )//若fx大于targetBpp,将solution赋给min,并从solution—max进行二分赋给solution
{
minNumber = solution;
solution = ( solution + maxNumber ) / 2.0;
}
else//若fx小于targetBpp,将solution赋给max,并从min—solution进行二分赋给solution
{
maxNumber = solution;
solution = ( solution + minNumber ) / 2.0;
}
}
solution = Clip3( 0.1, 10000.0, solution );//最后结果为min(10000,max(0.1,solution))
return solution;//返回solution作为lambda的起始值
}
fbas(x)为求浮点数的绝对值
clip3(A,B.C)=min(B,max(A,C))
④最后调用setAllBitRatio( basicLambda, equaCoeffA, equaCoeffB )计算比特率并且将得到的比特率赋值给m_bitsRatio[i],对它进行初始化
Void TEncRCSeq::setAllBitRatio( Double basicLambda, Double* equaCoeffA, Double* equaCoeffB )
{
Int* bitsRatio = new Int[m_GOPSize];//新建数组计算最终的比特率
for ( Int i=0; i<m_GOPSize; i++ )
{
bitsRatio[i] = (Int)( equaCoeffA[i] * pow( basicLambda, equaCoeffB[i] ) * m_numberOfPixel );//第i帧的比特率=Bpp*总像素数
}
initBitsRatio( bitsRatio );//遍历整个GOP,利用 m_bitsRatio[i] = bitsRatio[i]对 m_bitsRatio进行初始化
delete[] bitsRatio;
}
三、Void TEncRateCtrl::initRCPic( Int frameLevel )
Void TEncRateCtrl::initRCPic( Int frameLevel )
{
m_encRCPic = new TEncRCPic;
m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures );//创建新的PIC层的类,传递序列、GOP、framelevel和m_listRCPictures
}
(1)其中调用了m_encRCPic->create( m_encRCSeq, m_encRCGOP, frameLevel, m_listRCPictures );来进行帧层的码控初始化
Void TEncRCPic::create( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP, Int frameLevel, list<TEncRCPic*>& listPreviousPictures )
{
destroy();
m_encRCSeq = encRCSeq;//首先对序列层和GOP层进行赋值初始化
m_encRCGOP = encRCGOP;
Int targetBits = xEstPicTargetBits( encRCSeq, encRCGOP );//调用函数对帧层的目标比特进行预测并赋值给变量targetBits
Int estHeaderBits = xEstPicHeaderBits( listPreviousPictures, frameLevel );//调用函数对帧层的头文件比特进行预测并赋值给变量estHeaderBits
if ( targetBits < estHeaderBits + 100 )
{
targetBits = estHeaderBits + 100; // at least allocate 100 bits for picture data每帧至少分配100个比特
}
m_frameLevel = frameLevel;//帧的level初始化
m_numberOfPixel = encRCSeq->getNumPixel();//像素的数目
m_numberOfLCU = encRCSeq->getNumberOfLCU();//LCU的个数
m_estPicLambda = 100.0;//预测图片的初始lambda为100
m_targetBits = targetBits;//将目标比特和头文件比特初始化
m_estHeaderBits = estHeaderBits;
m_bitsLeft = m_targetBits;//剩余比特,即和目标比特相等
Int picWidth = encRCSeq->getPicWidth();//得到图片的宽高
Int picHeight = encRCSeq->getPicHeight();
Int LCUWidth = encRCSeq->getLCUWidth();//得到LCU的宽高
Int LCUHeight = encRCSeq->getLCUHeight();
Int picWidthInLCU = ( picWidth % LCUWidth ) == 0 ? picWidth / LCUWidth : picWidth / LCUWidth + 1;//宽上面的LCU个数
Int picHeightInLCU = ( picHeight % LCUHeight ) == 0 ? picHeight / LCUHeight : picHeight / LCUHeight + 1;//高上面的LCU个数
m_LCULeft = m_numberOfLCU;//剩余的LCU个数
m_bitsLeft -= m_estHeaderBits;//剩余比特数目=m_bitsLeft-m_estHeaderBits
m_pixelsLeft = m_numberOfPixel;//剩余像素个数
m_LCUs = new TRCLCU[m_numberOfLCU];//新建结构体TRCLCU存储LCU的信息
Int i, j;
Int LCUIdx;
for ( i=0; i<picWidthInLCU; i++ )
{
for ( j=0; j<picHeightInLCU; j++ )
{
LCUIdx = j*picWidthInLCU + i;//确定一个LCU在帧的位置,LCUIdx为索引,对每个LCU的成员进行初始化
m_LCUs[LCUIdx].m_actualBits = 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;
}
①其中调用了xEstPicTargetBits( encRCSeq, encRCGOP )来计算帧层的目标比特
Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )
{
Int targetBits = 0;//定义目标比特并且初始化
Int GOPbitsLeft = encRCGOP->getBitsLeft();//获得当前的剩余比特
Int i;
Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();//总的帧数-剩余未编码的帧数=当前帧在序列中的位置
Int currPicRatio = encRCSeq->getBitRatio( currPicPosition );//利用当前帧的位置求得当前帧的比特率
Int totalPicRatio = 0;//定义全部图片比特率并初始化
for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )//从当前帧位置进行遍历
{
totalPicRatio += encRCSeq->getBitRatio( i );//所有帧的比特率之和等于剩余未编码帧的比特率之和
}
targetBits = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio );//求出当前帧的目标比特=GOP剩余比特*(当前帧比特率/全部帧比特率)
if ( targetBits < 100 )
{
targetBits = 100; // at least allocate 100 bits for one picture一帧的目标比特至少为100
}
if ( m_encRCSeq->getFramesLeft() > 16 )//如果剩余未编码帧的数目大于16
{
targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );
//目标比特=0.1*目标比特+0.9*当前帧在GOP中的目标比特
}
return targetBits;//返回目标比特
}
②调用了xEstPicHeaderBits( listPreviousPictures, frameLevel )对头文件比特进行估计
Int TEncRCPic::xEstPicHeaderBits( list<TEncRCPic*>& listPreviousPictures, Int frameLevel )
{
Int numPreviousPics = 0;
Int totalPreviousBits = 0;
list<TEncRCPic*>::iterator it;
for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ )//遍历已经编码的帧
{
if ( (*it)->getFrameLevel() == frameLevel )//如果已编码帧和当前帧为同一个level
{
totalPreviousBits += (*it)->getPicActualHeaderBits();//将已编码帧的实际头文件比特数进行累加得到totalPreviousBits
numPreviousPics++;
}
}
Int estHeaderBits = 0;
if ( numPreviousPics > 0 )//如果不是第一帧
{
estHeaderBits = totalPreviousBits / numPreviousPics;//当前帧的头文件预测比特=已经编码帧的头文件比特总数/已经编码的帧数
}
return estHeaderBits;//返回头文件预测比特
}
本博文仅作小白学习记录使用,所有文章出处均在开头链接处可见,所有疑惑点均作了标注。欢迎各位大佬交流批评指正,侵删。