X265码率控制——ABR算法基本原理

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;

        }

    }

}


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值