1.首先是在gop层面,每组gop的初始时都分配了一个目标的gop码率以及gop内的每帧图像的目标码率。其中每帧图像的目标码率是通过递归收敛的方式先找到一个baselamda,通过这个baselamda以及已经定义好的alpha以及beta得到每一帧的bits数,然后将当前gop中所有的帧的bits数求和,就能求出每一帧应该占有的比特数的比例了。主要是求出这个比例,然后利用这个比例对gop的目标码率进行分配,从而得出了gop内每帧图像的目标码率。
2.在pic层。也就是帧一级的层面,首先根据gop的剩余比特数,再对当前帧的比特数做重新预测,获得一个新的目标比特数。利用这个目标比特数以及在gop层面算出来的每帧图像的目标码率做一个结合,算出一个当前帧的目标比特数。这个结合的比例为1:9,也就是说主要是利用在gop层算出来的每帧比特数,次要是利用在pic层算出来的比特数来做微调。
3.计算lamda。上一步预测出来的目标码率,计算每个像素的目标码率数。Lambda由下式计算所得:
λ=α*bppβ
其中bpp就是每个像素的目标码率数。
当然,这个lambda还要做一个处理。首先是用上一个相同层级的帧的lambda做约束。另外是用上一张编码图片的lambda做约束。
4.计算QP。使用以下公式计算得出:
qp=int(4.2005*logλ+13.7122+0.5)
其中λ是上一步计算出来的。
计算出来的QP值跟lambda一样,也要利用上一个相同层级的帧的QP以及上一帧编码图片的QP来做约束。
5.在每一帧的图像编码结束后,还要做一个重要的步骤——数据更新。更新的包括gop的比特剩余数量、整个序列的比特剩余数量以及当前帧所在时间层级的帧的alpha以及beta值。其中比特数量的更新很好理解,也就是减去当前帧已编码的比特数。下面具体讲讲alpha以及beta的更新。
-
//对于I帧的更新: double lnbpp = log(pow(m_picCfg.totalCostIntra / (double)m_seqCfg.numberOfPixel, HM_BETA1)); double diffLambda = beta*(log((double)totalBits) - log((double)m_picCfg.targetBits)); diffLambda = x265_clip3(-0.125, 0.125, 0.25*diffLambda); alpha = alpha * exp(diffLambda); beta = beta + diffLambda / lnbpp; 对于非I帧的更新: // update parameters double picActualBpp = totalBits / (double)m_seqCfg.numberOfPixel; double calLambda = alpha * pow(picActualBpp, beta); double inputLambda = averageLambda; double lnbpp = log(picActualBpp); //当lambda很小或者当前帧用的bit数很少时,减小alpha以及beta if (inputLambda < 0.01 || calLambda < 0.01 || picActualBpp < 0.0001) { alpha *= (1.0 - m_seqCfg.alphaUpdate / 2.0); beta *= (1.0 - m_seqCfg.betaUpdate / 2.0); m_seqCfg.picPara[m_picCfg.frameLevel].alpha = x265_clip3(g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha); m_seqCfg.picPara[m_picCfg.frameLevel].beta = x265_clip3(g_RCBetaMinValue, g_RCBetaMaxValue, beta); return; } //正常情况的话,就是对alpha以及beta增大 calLambda = x265_clip3(inputLambda / 10.0, inputLambda * 10.0, calLambda); alpha += m_seqCfg.alphaUpdate * (log(inputLambda) - log(calLambda)) * alpha; lnbpp = x265_clip3(-5.0, -0.1, lnbpp); beta += m_seqCfg.betaUpdate * (log(inputLambda) - log(calLambda)) * lnbpp; alpha = x265_clip3(g_RCAlphaMinValue, g_RCAlphaMaxValue, alpha); beta = x265_clip3(g_RCBetaMinValue, g_RCBetaMaxValue, beta);