HEVC码率控制代码追踪(二)

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 )//默认的目标比特大于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块的比重值为MADif (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帧的两种情况,都不是我想要的那种代码。

上面是大致的关于帧层和单元层的目标比特代码分析。还有没看懂的地方,后续弄清楚了,再纠正。

海内存知已,天涯若比邻。

HEVC码率控制代码追踪(二)

相关文章:

你感兴趣的文章:

标签云: