[x265] [PATCH] abr: reset ABR to prevent high bitrate peaks in single pass ABR

Steve Borho steve at borho.org
Sun Feb 2 19:38:34 CET 2014


On Sun, Feb 2, 2014 at 6:37 AM, Aarthi Priya Thirumalai <
aarthi at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Aarthi Thirumalai
> # Date 1391343895 -19800
> #      Sun Feb 02 17:54:55 2014 +0530
> # Node ID bf00f495951eb882e34225740c43540311bf51cb
> # Parent  bb33ab0f4ef933315cedf388d70443bc97fefeea
> abr: reset ABR to prevent high bitrate peaks in single pass ABR .
>
> Long series of blank frames in video followed by detailed content causes
> heavy ABR underflow and overall bitrates surges high for a long while.
> patch detects this condition in Single pass ABR mode and resets ABR - to
> not consider history from blank frames and continue from following
> scene-cut.
>

The patch behavior seems reasonable, given what was documented in another
email, however lots of coding style nits.


>
> diff -r bb33ab0f4ef9 -r bf00f495951e source/encoder/ratecontrol.cpp
> --- a/source/encoder/ratecontrol.cpp Sat Feb 01 16:39:12 2014 -0600
> +++ b/source/encoder/ratecontrol.cpp Sun Feb 02 17:54:55 2014 +0530
> @@ -240,7 +240,7 @@
>      shortTermCplxCount = 0;
>      framesDone = 0;
>      lastNonBPictType = I_SLICE;
> -
> +    isAbrReset = false;
>      // vbv initialization
>      cfg->param.rc.vbvBufferSize = Clip3(0, 2000000,
> cfg->param.rc.vbvBufferSize);
>      cfg->param.rc.vbvMaxBitrate = Clip3(0, 2000000,
> cfg->param.rc.vbvMaxBitrate);
> @@ -375,12 +375,12 @@
>      if (isAbr) //ABR,CRF
>      {
>          lastSatd = l->getEstimatedPictureCost(pic);
> +        rce->lastSatd = lastSatd;
>          double q = qScale2qp(rateEstimateQscale(rce));
>          qp = Clip3(MIN_QP, MAX_MAX_QP, (int)(q + 0.5));
>          rce->qpaRc = q;
>          /* copy value of lastRceq into thread local rce struct *to be
> used in RateControlEnd() */
>          rce->qRceq = lastRceq;
> -        rce->lastSatd = lastSatd;
>          accumPQpUpdate();
>      }
>      else //CQP
> @@ -464,6 +464,7 @@
>           * tolerances, the bit distribution approaches that of 2pass. */
>
>          double wantedBits, overflow = 1;
> +        rce->movingAvgSum = shortTermCplxSum;
>          shortTermCplxSum *= 0.5;
>          shortTermCplxCount *= 0.5;
>          shortTermCplxSum += lastSatd / (CLIP_DURATION(frameDuration) /
> BASE_FRAME_DURATION);
> @@ -479,6 +480,8 @@
>          }
>          else
>          {
> +            if (!isVbv)
> +                checkAndResetABR(rce);
>              q = getQScale(rce, wantedBitsWindow / cplxrSum);
>
>              /* ABR code can potentially be counterproductive in CBR, so
> just don't bother.
> @@ -498,7 +501,7 @@
>          }
>
>          if (sliceType == I_SLICE && cfg->param.keyframeMax > 1
> -            && lastNonBPictType != I_SLICE)
> +            && lastNonBPictType != I_SLICE &&  !isAbrReset)
>          {
>              q = qp2qScale(accumPQp / accumPNorm);
>              q /= fabs(cfg->param.rc.ipFactor);
> @@ -539,7 +542,7 @@
>
>          lastQScaleFor[sliceType] = q;
>
> -        if (curSlice->getPOC() == 0)
> +        if (curSlice->getPOC() == 0 || (isAbrReset && sliceType ==
> I_SLICE))
>              lastQScaleFor[P_SLICE] = q * fabs(cfg->param.rc.ipFactor);
>
>          rce->frameSizePlanned = predictSize(&pred[sliceType], q,
> (double)lastSatd);
> @@ -548,6 +551,35 @@
>      }
>  }
>
> +void RateControl::checkAndResetABR( RateControlEntry* rce )
>

white-space


> +{
> +    double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;
> +    // Check if current SLice is a scene cut that follow low
> detailed/blank frames
>

'slice' can be all lower case, `follow` should be follows


> +    if (rce->lastSatd > 4 * rce->movingAvgSum)
> +    {
> +        if (!isAbrReset && rce->movingAvgSum > 0 )
>

ws


> +        {
> +            // Reset ABR if prev frames are blank to prevent further
> sudden overflows/ high bit rate spikes.
> +            double underflow = 1.0 + (totalBits - wantedBitsWindow) /
> abrBuffer;
> +            if (underflow < 1 && curSlice->m_avgQpRc==0)
>

ws


> +            {
> +                totalBits = 0;
> +                framesDone = 0;
> +                cplxrSum = .01 * pow(7.0e5, qCompress) * pow(ncu, 0.5);
> +                wantedBitsWindow = bitrate * frameDuration;
> +                accumPNorm = .01;
> +                accumPQp = (ABR_INIT_QP_MIN)*accumPNorm;
> +                isAbrReset = true;
> +            }
> +        }
> +        // Clear flag to reset ABR and continue as usual.
>

we generally place else comments within the else braces


> +       else
> +       {
> +           isAbrReset = false;
> +       }
> +    }
> +}
> +
>  void RateControl::updateVbvPlan(Encoder* enc)
>  {
>      bufferFill = bufferFillFinal;
> @@ -706,19 +738,25 @@
>  {
>      if (isAbr)
>      {
> -        if (rce->sliceType != B_SLICE)
> -            /* The factor 1.5 is to tune up the actual bits, otherwise
> the cplxrSum is scaled too low
> -             * to improve short term compensation for next frame. */
> -            cplxrSum += bits * qp2qScale(rce->qpaRc) / rce->qRceq;
> -        else
> +        if (!isVbv)
> +            checkAndResetABR(rce);
> +
> +        if(!isAbrReset)
>

ws


>          {
> -            /* Depends on the fact that B-frame's QP is an offset from
> the following P-frame's.
> -             * Not perfectly accurate with B-refs, but good enough. */
> -            cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->qRceq *
> fabs(cfg->param.rc.pbFactor));
> +            if (rce->sliceType != B_SLICE)
> +                /* The factor 1.5 is to tune up the actual bits,
> otherwise the cplxrSum is scaled too low
> +                 * to improve short term compensation for next frame. */
> +                cplxrSum += bits * qp2qScale(rce->qpaRc) / rce->qRceq;
> +            else
> +            {
> +                /* Depends on the fact that B-frame's QP is an offset
> from the following P-frame's.
> +                 * Not perfectly accurate with B-refs, but good enough. */
> +                cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->qRceq *
> fabs(cfg->param.rc.pbFactor));
> +            }
> +            wantedBitsWindow += frameDuration * bitrate;
> +            totalBits += bits;
>          }
> -        wantedBitsWindow += frameDuration * bitrate;
>      }
> -    totalBits += bits;
>
>      if (isVbv)
>      {
> @@ -732,8 +770,9 @@
>                  bframeBits = 0;
>              }
>          }
> +        updateVbv(bits, rce);
>      }
>
> -    updateVbv(bits, rce);
> +
>      return 0;
>  }
> diff -r bb33ab0f4ef9 -r bf00f495951e source/encoder/ratecontrol.h
> --- a/source/encoder/ratecontrol.h Sat Feb 01 16:39:12 2014 -0600
> +++ b/source/encoder/ratecontrol.h Sun Feb 02 17:54:55 2014 +0530
> @@ -60,6 +60,7 @@
>      double qRceq;
>      double frameSizePlanned;
>      double bufferRate;
> +    double movingAvgSum;
>  };
>
>  struct Predictor
> @@ -97,7 +98,7 @@
>      int bframes;
>      int bframeBits;
>      double leadingNoBSatd;
> -
> +    bool isAbrReset;
>      int64_t lastSatd;
>      int    qpConstant[3];
>      double cplxrSum;          /* sum of bits*qscale/rceq */
> @@ -136,6 +137,7 @@
>      double clipQscale(double q);
>      void updateVbvPlan(Encoder* enc);
>      double predictSize(Predictor *p, double q, double var);
> +    void checkAndResetABR( RateControlEntry* rce );
>

ws


>  };
>  }
>
>
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
>


-- 
Steve Borho
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20140202/bece86b0/attachment-0001.html>


More information about the x265-devel mailing list