ABR算法
刘小杰(QQ:472249968)
(主要针对P,B帧和连续I帧)
1首先图像半精度的残差STAD之和,利用J=SATD+λR进行模式选择
2利用当前帧的SATD计算图像的模糊复杂度(Blurred Complexity), 设当前帧的SATD为SATD(i),累积复杂度为cplx_sum(i),
cplx_sum(i)=0.5cplx_sum(i-1)+SATD(i),
X265中
{
rateControlUpdateStats
m_cplxrSum += rce->rowCplxrSum;
rateControlEnd函数中
if (rce->sliceType != B_SLICE)
{
/* The factor 1.5is to tune up the actual bits, otherwise the cplxrSum is scaled too low
* to improve short termcompensation for next frame. */
m_cplxrSum +=(bits * x265_qp2qScale(rce->qpaRc) / rce->qRceq) - (rce->rowCplxrSum);
}
else
{
/* Depends on thefact that B-frame's QP is an offset from the following P-frame's.
* Not perfectly accurate withB-refs, but good enough. */
m_cplxrSum +=(bits * x265_qp2qScale(rce->qpaRc) / (rce->qRceq *fabs(m_param->rc.pbFactor))) - (rce->rowCplxrSum);
}
}
第二次修正,利用溢出判断因子overflow来修正,它可以表示出总目标比特和实际
产生的总比特的之间的偏差,修正公式如下:
qscale(i)= qscale_adjust(i)*overflow(i).
overflow限定在0.5到2之间。
预估bits的计算
在RateControl类中有
Predictor m_pred[4]; /* Slice predictors to preidct bits for each Slice type -I,P,Bref and B */ 用于估计当前帧的bits
在RateControlEntry结构体中有
Predictor rowPreds[3][2];
Predictor* rowPred[2];
rce->rowPred[0] =&rce->rowPreds[m_sliceType][0];
rce->rowPred[1] = &rce->rowPreds[m_sliceType][1];
struct Predictor
{
doublecoeffMin;
doublecoeff;
doublecount;
doubledecay;
doubleoffset;
};
Bit=(coeff*satd*+offset)/(qScale*count);
updatePredictor(rce->rowPred[0], qScaleVbv, (double)rowSatdCost,encodedBits);
updatePredictor(Predictor *p, doubleq, double var, double bits)
{
if(var < 10)
return;
const double range = 2;
double old_coeff = p->coeff / p->count;
double old_offset = p->offset / p->count;
double new_coeff = X265_MAX((bits * q - old_offset) / var,p->coeffMin );
double new_coeff_clipped = x265_clip3(old_coeff / range, old_coeff *range, new_coeff);
double new_offset = bits * q - new_coeff_clipped * var;
if (new_offset >= 0)
new_coeff = new_coeff_clipped;
else
new_offset = 0;
p->count *= p->decay;
p->coeff *= p->decay;
p->offset *= p->decay;
p->count++;
p->coeff += new_coeff;
p->offset += new_offset;
}
Predictor的更新
1:在rowVbvRateControl()更新
{
所有帧情况下
updatePredictor(rce->rowPred[0], qScaleVbv, (double)rowSatdCost,encodedBits);
在非I帧情况下
当前行的qp小于参考qp
predictSize(rce->rowPred[1],qScale, intraCostForPendingCus);
}
2:在updateVbv()更新(rateControlEnd调用updateVbv)
updatePredictor(&m_pred[predType],x265_qp2qScale(rce->qpaRc), (double)rce->lastSatd, (double)bits);
其他参数的更新1
I帧qp调整
1 m_accumPNorm 初始化 m_accumPNorm = .01; //init函数调用
2 m_accumPQp 初始化 (m_param->rc.rateControlMode== X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN) * m_accumPNorm;//init函数调用
这两个参数的更新在函数中accumPQpUpdate()(在rateControlStart函数中调用)
void RateControl::accumPQpUpdate()
{
m_accumPQp *= .95;
m_accumPNorm *= .95;
m_accumPNorm += 1;
if(m_sliceType == I_SLICE)
m_accumPQp += m_qp + m_ipOffset;
else
m_accumPQp += m_qp;
}
在影响I帧qp的调整(在函数rateEstimateQscale调用中)
if((m_sliceType == I_SLICE && m_param->keyframeMax > 1
&& m_lastNonBPictType!= I_SLICE && !m_isAbrReset) || (m_isNextGop && !m_framesDone))
{
if (!m_param->rc.bStrictCbr)
q =x265_qp2qScale(m_accumPQp / m_accumPNorm);
q/= fabs(m_param->rc.ipFactor);
m_avgPFrameQp = 0;
}
其他参数的更新2
m_bufferFillFinal, m_bufferFillActual和 m_bufferExcess
1初始化
m_bufferFillFinal = m_bufferSize *m_param->rc.vbvBufferInit;
m_bufferFillActual = m_bufferFillFinal;
m_bufferExcess = 0;
2更新updateVbv函数中(在rateControlEnd函数中调用)
updateVbv(int64_t bits, RateControlEntry* rce)
{
m_bufferFillFinal -= bits;
m_bufferFillFinal =X265_MAX(m_bufferFillFinal, 0);
m_bufferFillFinal += m_bufferRate;
if(m_param->rc.bStrictCbr)
{
if(m_bufferFillFinal > m_bufferSize)
{
filler = (int)(m_bufferFillFinal- m_bufferSize);
filler += FILLER_OVERHEAD * 8;
}
m_bufferFillFinal -= filler;
bufferBits = X265_MIN(bits + filler +m_bufferExcess, m_bufferRate);
m_bufferExcess = X265_MAX(m_bufferExcess- bufferBits + bits + filler, 0);
m_bufferFillActual += bufferBits - bits- filler;
}
else
{
m_bufferFillFinal =X265_MIN(m_bufferFillFinal, m_bufferSize);
bufferBits = X265_MIN(bits +m_bufferExcess, m_bufferRate);
m_bufferExcess =X265_MAX(m_bufferExcess - bufferBits + bits, 0);
m_bufferFillActual += bufferBits -bits;
m_bufferFillActual =X265_MIN(m_bufferFillActual, m_bufferSize);
}
}
3 在updateVbvPlan(Encoder* enc)中更新(由rateControlStart调用)
{
m_bufferFill = m_bufferFillFinal;
for (int i = 0; i <m_param->frameNumThreads; i++)
{
FrameEncoder *encoder = m_frameEncoder[i];
if (encoder->m_rce.isActive &&encoder->m_rce.poc != rc->m_curSlice->m_poc)
{
int64_t bits = m_param->rc.bEnableConstVbv? (int64_t)encoder->m_rce.frameSizePlanned :(int64_t)X265_MAX(encoder->m_rce.frameSizeEstimated,encoder->m_rce.frameSizePlanned);
rc->m_bufferFill -= bits;
rc->m_bufferFill =X265_MAX(rc->m_bufferFill, 0);
rc->m_bufferFill += encoder->m_rce.bufferRate;
rc->m_bufferFill = X265_MIN(rc->m_bufferFill,rc->m_bufferSize);
if(rc->m_2pass)
rc->m_predictedBits += bits;
}
}
}