[x265] [PATCH] rc: implement abr reset for single pass ABR + VBV

aarthi at multicorewareinc.com aarthi at multicorewareinc.com
Mon Feb 24 14:25:11 CET 2014


# HG changeset patch
# User Aarthi Thirumalai
# Date 1393248300 -19800
#      Mon Feb 24 18:55:00 2014 +0530
# Node ID da0cc611e8b8a0d1f7b71d08867e9947bb5e8b53
# Parent  3abef12d5b47106005c813bfd60ea49c31048f12
rc: implement abr reset for single pass ABR + VBV

diff -r 3abef12d5b47 -r da0cc611e8b8 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Mon Feb 24 17:53:07 2014 +0530
+++ b/source/encoder/ratecontrol.cpp	Mon Feb 24 18:55:00 2014 +0530
@@ -245,15 +245,12 @@
     }
 
     isAbr = cfg->param.rc.rateControlMode != X265_RC_CQP; // later add 2pass option
-
     bitrate = cfg->param.rc.bitrate * 1000;
     frameDuration = (double)cfg->param.fpsDenom / cfg->param.fpsNum;
     qp = cfg->param.rc.qp;
     lastRceq = 1; /* handles the cmplxrsum when the previous frame cost is zero */
-    totalBits = 0;
     shortTermCplxSum = 0;
     shortTermCplxCount = 0;
-    framesDone = 0;
     lastNonBPictType = I_SLICE;
     isAbrReset = false;
     lastAbrResetPoc = -1;
@@ -325,43 +322,20 @@
             && cfg->param.rc.vbvMaxBitrate <= cfg->param.rc.bitrate;
     }
 
-    for (int i = 0; i < 5; i++)
-    {
-        pred[i].coeff = 2.0;
-        pred[i].count = 1.0;
-        pred[i].decay = 0.5;
-        pred[i].offset = 0.0;
-    }
-
-    for (int i = 0; i < 4; i++)
-    {
-        rowPreds[i].coeff = 0.25;
-        rowPreds[i].count = 1.0;
-        rowPreds[i].decay = 0.5;
-        rowPreds[i].offset = 0.0;
-    }
-
-    predBfromP = pred[0];
     bframes = cfg->param.bframes;
     bframeBits = 0;
     leadingNoBSatd = 0;
-    accumPNorm = .01;
-    /* estimated ratio that produces a reasonable QP for the first I-frame */
-    cplxrSum = .01 * pow(7.0e5, qCompress) * pow(ncu, 0.5);
-    wantedBitsWindow = bitrate * frameDuration;
-
     if (cfg->param.rc.rateControlMode == X265_RC_ABR)
     {
         /* Adjust the first frame in order to stabilize the quality level compared to the rest */
 #define ABR_INIT_QP_MIN (24 + QP_BD_OFFSET)
 #define ABR_INIT_QP_MAX (34 + QP_BD_OFFSET)
-        accumPQp = (ABR_INIT_QP_MIN)*accumPNorm;
     }
     else if (cfg->param.rc.rateControlMode == X265_RC_CRF)
     {
 #define ABR_INIT_QP ((int)cfg->param.rc.rfConstant + QP_BD_OFFSET)
-        accumPQp = ABR_INIT_QP * accumPNorm;
     }
+    reInit();
 
     ipOffset = 6.0 * X265_LOG2(cfg->param.rc.ipFactor);
     pbOffset = 6.0 * X265_LOG2(cfg->param.rc.pbFactor);
@@ -383,6 +357,36 @@
     lstep = pow(2, cfg->param.rc.qpStep / 6.0);
 }
 
+void RateControl::reInit()
+{
+    totalBits = 0;
+    framesDone = 0;
+
+    /* estimated ratio that produces a reasonable QP for the first I-frame */
+    cplxrSum = .01 * pow(7.0e5, qCompress) * pow(ncu, 0.5);
+    wantedBitsWindow = bitrate * frameDuration;
+    accumPNorm = .01;
+    accumPQp = (cfg->param.rc.rateControlMode == X265_RC_CRF ? ABR_INIT_QP : ABR_INIT_QP_MIN) * accumPNorm;
+
+    /* Frame Predictors and Row predictors used in vbv */
+    for (int i = 0; i < 5; i++)
+    {
+        pred[i].coeff = 2.0;
+        pred[i].count = 1.0;
+        pred[i].decay = 0.5;
+        pred[i].offset = 0.0;
+    }
+    for (int i = 0; i < 4; i++)
+    {
+        rowPreds[i].coeff = 0.25;
+        rowPreds[i].count = 1.0;
+        rowPreds[i].decay = 0.5;
+        rowPreds[i].offset = 0.0;
+    }
+    predBfromP = pred[0];
+}
+
+
 void RateControl::rateControlStart(TComPic* pic, Lookahead *l, RateControlEntry* rce, Encoder* enc)
 {
     curSlice = pic->getSlice();
@@ -466,7 +470,7 @@
         int dt1 = abs(curSlice->getPOC() - nextRefSlice->getPOC());
 
         // Skip taking a reference frame before the Scenecut if ABR has been reset.
-        if (lastAbrResetPoc >= 0 && !isVbv)
+        if (lastAbrResetPoc >= 0)
         {
             if (prevRefSlice->getSliceType() == P_SLICE && prevRefSlice->getPOC() < lastAbrResetPoc)
             {
@@ -532,10 +536,8 @@
         }
         else
         {
-            if (!isVbv)
-            {
-                checkAndResetABR(pic, rce);
-            }
+
+            checkAndResetABR(rce, false);
             q = getQScale(rce, wantedBitsWindow / cplxrSum);
 
             /* ABR code can potentially be counterproductive in CBR, so just
@@ -571,7 +573,7 @@
                 lqmax = qp2qScale(ABR_INIT_QP_MAX) * lstep;
                 q = Clip3(lqmin, lqmax, q);
             }
-            else if (totalBits > 0 || (isVbv && rce->poc > 0))
+            else if (totalBits > 0 || (isVbv && framesDone > 0))
             {
                 lqmin = lastQScaleFor[sliceType] / lstep;
                 lqmax = lastQScaleFor[sliceType] * lstep;
@@ -605,7 +607,7 @@
     }
 }
 
-void RateControl::checkAndResetABR(TComPic* pic, RateControlEntry* rce)
+void RateControl::checkAndResetABR(RateControlEntry* rce, bool isFrameDone)
 {
     double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;
 
@@ -616,14 +618,9 @@
         {
             // 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 && pic->m_avgQpRc == 0)
+            if (underflow < 1 && !isFrameDone)
             {
-                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;
+                reInit();
                 shortTermCplxSum = rce->lastSatd / (CLIP_DURATION(frameDuration) / BASE_FRAME_DURATION);
                 shortTermCplxCount = 1;
                 isAbrReset = true;
@@ -1011,9 +1008,9 @@
 {
     if (isAbr)
     {
-        if (!isVbv && cfg->param.rc.rateControlMode == X265_RC_ABR)
+        if (cfg->param.rc.rateControlMode == X265_RC_ABR)
         {
-            checkAndResetABR(pic, rce);
+            checkAndResetABR(rce, true);
         }
         if (!isAbrReset)
         {
diff -r 3abef12d5b47 -r da0cc611e8b8 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h	Mon Feb 24 17:53:07 2014 +0530
+++ b/source/encoder/ratecontrol.h	Mon Feb 24 18:55:00 2014 +0530
@@ -134,6 +134,7 @@
 
 protected:
 
+    void reInit();
     double getQScale(RateControlEntry *rce, double rateFactor);
     double rateEstimateQscale(TComPic* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR
     void accumPQpUpdate();
@@ -144,7 +145,7 @@
     double clipQscale(TComPic* pic, double q);
     void updateVbvPlan(Encoder* enc);
     double predictSize(Predictor *p, double q, double var);
-    void checkAndResetABR(TComPic* pic, RateControlEntry* rce);
+    void checkAndResetABR(RateControlEntry* rce, bool isFrameDone);
     double predictRowsSizeSum(TComPic* pic, double qpm, int32_t& encodedBits);
 };
 }


More information about the x265-devel mailing list