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

关于图像级别和单元级别的lambda和qp预测计算 这两个级别各两个参数的计算主要考虑的是计算和计算后的平滑参数的设置。都有现成的公式可以参考。同样用到的是HEVC提案JCTVC-K0103(码率控制提案) (一)Double TEncRCPic::estimatePicLambda

Double TEncRCPic::estimatePicLambda( list<TEncRCPic*>& listPreviousPictures, SliceType eSliceType)//估计图片级别的lambda{ Double alpha= m_encRCSeq->getPicPara( m_frameLevel ).m_alpha; Double beta= m_encRCSeq->getPicPara( m_frameLevel ).m_beta; Double bpp= (Double)m_targetBits/(Double)m_numberOfPixel;//前面求得的bpp用于这里来获得lambda Double estLambda; if (eSliceType == I_SLICE)//I片有自己的lambda算法 {estLambda = calculateLambdaIntra(alpha, beta, pow(m_totalCostIntra/(Double)m_numberOfPixel, BETA1), bpp); } else {estLambda = alpha * pow( bpp, beta );//非I帧的计算公式,提案中常用的公式 } /*到这里当前帧的lambda已经求得,但是还需要对数据进行处理才能正式用于编码当中,用约束条件进行约束,,使其值有限定范围*/ //下面这段程序是对Lambda的平滑,保证前后帧之间的参数不变化太大。 Double lastLevelLambda = -1.0;//上一个级别??? Double lastPicLambda = -1.0;//上一帧的lambda Double lastValidLambda = -1.0; list<TEncRCPic*>::iterator it; for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ ) {if ( (*it)->getFrameLevel() == m_frameLevel ){lastLevelLambda = (*it)->getPicActualLambda();}lastPicLambda= (*it)->getPicActualLambda();if ( lastPicLambda > 0.0 ){lastValidLambda = lastPicLambda;} } if ( lastLevelLambda > 0.0 ) {lastLevelLambda = Clip3( 0.1, 10000.0, lastLevelLambda );estLambda = Clip3( lastLevelLambda * pow( 2.0, -3.0/3.0 ), lastLevelLambda * pow( 2.0, 3.0/3.0 ), estLambda ); } if ( lastPicLambda > 0.0 ) {lastPicLambda = Clip3( 0.1, 2000.0, lastPicLambda );estLambda = Clip3( lastPicLambda * pow( 2.0, -10.0/3.0 ), lastPicLambda * pow( 2.0, 10.0/3.0 ), estLambda ); } else if ( lastValidLambda > 0.0 ) {lastValidLambda = Clip3( 0.1, 2000.0, lastValidLambda );estLambda = Clip3( lastValidLambda * pow(2.0, -10.0/3.0), lastValidLambda * pow(2.0, 10.0/3.0), estLambda ); } else {estLambda = Clip3( 0.1, 10000.0, estLambda ); } if ( estLambda < 0.1 )//最终的预测lambda不能小于0.1 {estLambda = 0.1; } m_estPicLambda = estLambda; Double totalWeight = 0.0; // initial BU bit allocation weight初始化BU比特分配比重 for ( Int i=0; i<m_numberOfLCU; i++ )//遍历整个LCU的数目 {Double alphaLCU, betaLCU;if ( m_encRCSeq->getUseLCUSeparateModel() )//启用LCU的分层模式,同一个图片层的不同LCU的参数是不同的,所以要遍历整个图像层的所有LCU ,分配不同的参数。。{alphaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_alpha;betaLCU = m_encRCSeq->getLCUPara( m_frameLevel, i ).m_beta;}else//如果没有启用LCU的层的不同模式,则整个picture使用个相同的参数,就不需要分各个不同的LCU考虑了{alphaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_alpha;betaLCU = m_encRCSeq->getPicPara( m_frameLevel ).m_beta;}m_LCUs[i].m_bitWeight = m_LCUs[i].m_numberOfPixel * pow( estLambda/alphaLCU, 1.0/betaLCU );if ( m_LCUs[i].m_bitWeight < 0.01 ){m_LCUs[i].m_bitWeight = 0.01;}totalWeight += m_LCUs[i].m_bitWeight; } for ( Int i=0; i<m_numberOfLCU; i++ ) {Double BUTargetBits = m_targetBits * m_LCUs[i].m_bitWeight / totalWeight;m_LCUs[i].m_bitWeight = BUTargetBits; } return estLambda;}

(二)TEncRCPic::estimatePicQP

Int TEncRCPic::estimatePicQP( Double lambda, list<TEncRCPic*>& listPreviousPictures ){ Int QP = Int( 4.2005 * log( lambda ) + 13.7122 + 0.5 );//加0.5为了四舍五入(上面一个函数已经给出了lambda的计算,所以由公式可以知道,直接计算出QP的值) /*将下面三个参数都赋值相同,什么意思?*/ Int lastLevelQP = g_RCInvalidQPValue;//上一层? Int lastPicQP = g_RCInvalidQPValue; Int lastValidQP = g_RCInvalidQPValue;//前一帧的有效的合法的QP,也就是经过平滑之后的QP list<TEncRCPic*>::iterator it; for ( it = listPreviousPictures.begin(); it != listPreviousPictures.end(); it++ ) {if ( (*it)->getFrameLevel() == m_frameLevel ){lastLevelQP = (*it)->getPicActualQP();}lastPicQP = (*it)->getPicActualQP();if ( lastPicQP > g_RCInvalidQPValue ){lastValidQP = lastPicQP;} } if ( lastLevelQP > g_RCInvalidQPValue ) {QP = Clip3( lastLevelQP – 3, lastLevelQP + 3, QP ); } if( lastPicQP > g_RCInvalidQPValue ) {QP = Clip3( lastPicQP – 10, lastPicQP + 10, QP ); } else if( lastValidQP > g_RCInvalidQPValue ) {QP = Clip3(lastValidQP – 10, lastValidQP + 10, QP);//当前的QP受限于前一帧的合法QP值 } return QP;}没有行李,没有背包,不带电脑更不要手机,

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

相关文章:

你感兴趣的文章:

标签云: