R-lambda码率控制模型中的关于帧层,单元层的目标比特分配代码部分。求出各层的目标比特再除以该层的总像素数,得到Bpp用于后续的lambda和Qp的求解。
(1)帧层的目标比特代码部分
Int TEncRCPic::xEstPicTargetBits( TEncRCSeq* encRCSeq, TEncRCGOP* encRCGOP )//估计图像的目标比特数//类中的私有函数的定义
{
Int targetBits = 0;
Int GOPbitsLeft = encRCGOP->getBitsLeft();//GOP剩余比特数
Int i;
Int currPicPosition = encRCGOP->getNumPic()-encRCGOP->getPicLeft();//当前图片的位置
Int currPicRatio = encRCSeq->getBitRatio( currPicPosition );//当前图片的比重(当前图像的比重的分配在Void TEncRateCtrl::init中有详细的介绍)
Int totalPicRatio = 0;//定义总比重,初始值为0
for ( i=currPicPosition; i<encRCGOP->getNumPic(); i++ )//for循环累加,求出总比重
{
totalPicRatio += encRCSeq->getBitRatio( i );//第一步
}
targetBits = Int( ((Double)GOPbitsLeft) * currPicRatio / totalPicRatio );//图像层的目标比特数(13)第二步
if ( targetBits < 100 )//默认的目标比特大于100,当比特小于100的时候系统默认分配100比特
{
targetBits = 100; // at least allocate 100 bits for one picture
}
if ( m_encRCSeq->getFramesLeft() > 16 )//剩余帧数大于16帧
{
targetBits = Int( g_RCWeightPicRargetBitInBuffer * targetBits + g_RCWeightPicTargetBitInGOP * m_encRCGOP->getTargetBitInGOP( currPicPosition ) );//
}
return targetBits;
}
这段代码中有几个值得指出的地方
①currPicRatio :这个整型变量相当于提案JCTVC-K0103中的公式(9)中的W,表示当前帧的复杂度(就是一种衡量的标准,可以理解为纹理复杂度)。currPicRatio / totalPicRatio表示当前帧在整个GOP中的比重。
②if ( targetBits < 100 ):就是人为规定了个帧的目标比特数不能小于100。
(2)单元层的目标比特分配
/*
下面这段程序的目的是为了获得LCU层的目标比特数Bpp,那么说先要获得图片层的各单元的总的目标比特数,再除以整个LCU层的总像素数。
分两种情况:I帧和非I帧。
(1)当为I帧时,考虑getLCU(LCUIdx).m_costIntra这个变量,他是表征各索引LCU块的costIntra(我的理解是帧内比重的意思),
在帧内又有两种情况,剩余的总的costIntra>0.1时,就要考虑各个LCU块的比重,并根据比重对各个LCU块分配比特。当剩余的比重小于0.1时,就对
剩余的块平均分配剩余的比特数。
(2)当为非I帧时,使用bitWeight表示各个LCU块的比重,求出各个块的分配到的比特数avgBits 。
两种情况的Bpp都是通过下面的公式求得:bpp = ( Double )avgBits/( Double )m_LCUs[ LCUIdx ].m_numberOfPixel;
*/
Double TEncRCPic::getLCUTargetBpp(SliceType eSliceType)//获得单元层的目标比特分配
{
Int LCUIdx = getLCUCoded();//获得已经编码的单元数
Double bpp = -1.0;//为什么初始值为这个?
Int avgBits = 0;//平均比特
if (eSliceType == I_SLICE)//如果编码帧为I帧
{
Int noOfLCUsLeft = m_numberOfLCU - LCUIdx + 1;//总单元数-已经编码的单元数+1 =剩余单元数
Int bitrateWindow = min(4,noOfLCUsLeft);//比特率窗,最小为四,不能小于GOP的值
Double MAD = getLCU(LCUIdx).m_costIntra;//编号为LCUIdx的LCU块的比重值为MAD
if (m_remainingCostIntra > 0.1 )//剩余帧内消耗比重
{
Double weightedBitsLeft = (m_bitsLeft*bitrateWindow+(m_bitsLeft-getLCU(LCUIdx).m_targetBitsLeft)*noOfLCUsLeft)/(Double)bitrateWindow;//剩余比特数
avgBits = Int( MAD*weightedBitsLeft/m_remainingCostIntra );//就是剩余的比特数*当前块在总块中的比重
}
else//如果剩余的比重小于0.1
{
avgBits = Int( m_bitsLeft / m_LCULeft );//剩余的比特数/剩余的单元数作为当前编码块的平均比特数
}
m_remainingCostIntra -= MAD;//每一块的MAD相等,也就是没块的目标比特数相等了,所以剩余的比重就是总的减去上一块的,都相等(都为MAD)。
}
else//下面讨论不是帧内的情况
{
Double totalWeight = 0;
for ( Int i=LCUIdx; i<m_numberOfLCU; i++ )
{
totalWeight += m_LCUs[i].m_bitWeight;
}
Int realInfluenceLCU = min( g_RCLCUSmoothWindowSize, getLCULeft() );//真正有影响的LCU块(平滑窗和剩余块数目的最小值)
avgBits = (Int)( m_LCUs[LCUIdx].m_bitWeight - ( totalWeight - m_bitsLeft ) / realInfluenceLCU + 0.5 );
}
if ( avgBits < 1 )
{
avgBits = 1;
}
bpp = ( Double )avgBits/( Double )m_LCUs[ LCUIdx ].m_numberOfPixel;//总的比特数/总的像素数(bpp用于后面求lambda)
m_LCUs[ LCUIdx ].m_targetBits = avgBits;
return bpp;
}
这段代码中有几个值得指出的地方
①if (eSliceType == I_SLICE)
else//下面讨论不是帧内的情况
首先将整个过程分为两种情况:帧内和非帧内
②MAD = getLCU(LCUIdx).m_costIntra
这是提案JCTVC-K0103中单元层比特分配时用到的一个变量。用MAD的平方来表征当前快的复杂度。但是在代码中我并没有看到相应的MAD的平方用于求目标比特数:
avgBits = Int( MAD*weightedBitsLeft/m_remainingCostIntra );
avgBits = Int( m_bitsLeft / m_LCULeft );
这是I帧的两种情况,都不是我想要的那种代码。
上面是大致的关于帧层和单元层的目标比特代码分析。还有没看懂的地方,后续弄清楚了,再纠正。
时间: 2024-12-27 04:29:19