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

Aarthi Priya Thirumalai aarthi at multicorewareinc.com
Sun Feb 2 13:37:32 CET 2014


# 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.

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 )
+{
+    double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;
+    // Check if current SLice is a scene cut that follow low
detailed/blank frames
+    if (rce->lastSatd > 4 * rce->movingAvgSum)
+    {
+        if (!isAbrReset && rce->movingAvgSum > 0 )
+        {
+            // 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)
+            {
+                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.
+       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)
         {
-            /* 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 );
 };
 }
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20140202/0cbce182/attachment.html>


More information about the x265-devel mailing list