[x265] [PATCH 4 of 6] vbv: fix bugs in vbv flow with single pass ABR

aarthi at multicorewareinc.com aarthi at multicorewareinc.com
Fri Feb 21 07:08:39 CET 2014


# HG changeset patch
# User Aarthi Thirumalai
# Date 1392899993 -19800
#      Thu Feb 20 18:09:53 2014 +0530
# Node ID d058d4dd84a547b9b72a043ed065a94220b2f32b
# Parent  9517ea331f3e87f41c687db11de02cb95ded8756
vbv: fix bugs in vbv flow with single pass ABR

diff -r 9517ea331f3e -r d058d4dd84a5 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp	Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/encoder.cpp	Thu Feb 20 18:09:53 2014 +0530
@@ -365,11 +365,8 @@
 
         // Allow this frame to be recycled if no frame encoders are using it for reference
         ATOMIC_DEC(&out->m_countRefEncoders);
-
-        m_rateControl->rateControlEnd(bits, &(curEncoder->m_rce));
-
+        m_rateControl->rateControlEnd(out, bits, &(curEncoder->m_rce));
         m_dpb->recycleUnreferenced(m_freeList);
-
         ret = 1;
     }
 
diff -r 9517ea331f3e -r d058d4dd84a5 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/ratecontrol.cpp	Thu Feb 20 18:09:53 2014 +0530
@@ -207,8 +207,9 @@
 RateControl::RateControl(TEncCfg * _cfg)
 {
     this->cfg = _cfg;
-    ncu = (int)((cfg->param.sourceHeight * cfg->param.sourceWidth) / pow((int)16, 2.0));
-
+    int lowresCuWidth = ((cfg->param.sourceWidth/2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
+    int lowresCuHeight = ((cfg->param.sourceHeight/2)  + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
+    ncu = lowresCuWidth * lowresCuHeight;
     if (cfg->param.rc.cuTree)
     {
         qCompress = 1;
@@ -441,13 +442,12 @@
          * average QP of the two adjacent P-frames + an offset */
         TComSlice* prevRefSlice = curSlice->getRefPic(REF_PIC_LIST_0, 0)->getSlice();
         TComSlice* nextRefSlice = curSlice->getRefPic(REF_PIC_LIST_1, 0)->getSlice();
+        double q0 = curSlice->getRefPic(REF_PIC_LIST_0, 0)->m_avgQpRc;
+        double q1 = curSlice->getRefPic(REF_PIC_LIST_1, 0)->m_avgQpRc;
         bool i0 = prevRefSlice->getSliceType() == I_SLICE;
         bool i1 = nextRefSlice->getSliceType() == I_SLICE;
         int dt0 = abs(curSlice->getPOC() - prevRefSlice->getPOC());
         int dt1 = abs(curSlice->getPOC() - nextRefSlice->getPOC());
-        double q0 = prevRefSlice->m_avgQpRc;
-        double q1 = nextRefSlice->m_avgQpRc;
-
         // Skip taking a reference frame before the Scenecut if ABR has been reset.
         if (lastAbrResetPoc >= 0 && !isVbv)
         {
@@ -517,10 +517,9 @@
         {
             if (!isVbv)
             {
-                checkAndResetABR(rce);
+                checkAndResetABR(pic, rce);
             }
             q = getQScale(rce, wantedBitsWindow / cplxrSum);
-
             /* ABR code can potentially be counterproductive in CBR, so just don't bother.
              * Don't run it if the frame complexity is zero either. */
             if (!vbvMinRate && currentSatd)
@@ -547,23 +546,22 @@
         if (cfg->param.rc.rateControlMode != X265_RC_CRF)
         {
             double lqmin = 0, lqmax = 0;
-            if (totalBits == 0)
+            if (totalBits == 0 && !isVbv)
             {
                 lqmin = qp2qScale(ABR_INIT_QP_MIN) / lstep;
                 lqmax = qp2qScale(ABR_INIT_QP_MAX) * lstep;
+                q = Clip3(lqmin, lqmax, q);
             }
-            else
+            else if(totalBits > 0 || (isVbv && rce->poc > 0 ))
             {
                 lqmin = lastQScaleFor[sliceType] / lstep;
                 lqmax = lastQScaleFor[sliceType] * lstep;
+                if (overflow > 1.1 && framesDone > 3)
+                    lqmax *= lstep;
+                else if (overflow < 0.9)
+                    lqmin /= lstep;
+                q = Clip3(lqmin, lqmax, q);
             }
-
-            if (overflow > 1.1 && framesDone > 3)
-                lqmax *= lstep;
-            else if (overflow < 0.9)
-                lqmin /= lstep;
-
-            q = Clip3(lqmin, lqmax, q);
         }
         else
         {
@@ -587,11 +585,9 @@
         return q;
     }
 }
-
-void RateControl::checkAndResetABR(RateControlEntry* rce)
+void RateControl::checkAndResetABR(TComPic* pic, RateControlEntry* rce)
 {
     double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;
-
     // Check if current Slice is a scene cut that follows low detailed/blank frames
     if (rce->lastSatd > 4 * rce->movingAvgSum)
     {
@@ -599,7 +595,7 @@
         {
             // 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)
+            if (underflow < 1 && pic->m_avgQpRc == 0)
             {
                 totalBits = 0;
                 framesDone = 0;
@@ -654,10 +650,9 @@
                 double bufferFillCur = bufferFill - curBits;
                 double targetFill;
                 double totalDuration = 0;
-                frameQ[0] = sliceType == I_SLICE ? q * cfg->param.rc.ipFactor : q;
-                frameQ[1] = frameQ[0] * cfg->param.rc.pbFactor;
-                frameQ[2] = frameQ[0] / cfg->param.rc.ipFactor;
-
+                frameQ[P_SLICE] = sliceType == I_SLICE ? q * cfg->param.rc.ipFactor : q;
+                frameQ[B_SLICE] = frameQ[P_SLICE] * cfg->param.rc.pbFactor;
+                frameQ[I_SLICE] = frameQ[P_SLICE] / cfg->param.rc.ipFactor;
                 /* Loop over the planned future frames. */
                 for (int j = 0; bufferFillCur >= 0 && bufferFillCur <= bufferSize; j++)
                 {
@@ -799,14 +794,10 @@
     p->coeff  += new_coeff;
     p->offset += new_offset;
 }
-
 void RateControl::updateVbv(int64_t bits, RateControlEntry* rce)
 {
-    int mbCount = (int)((cfg->param.sourceHeight * cfg->param.sourceWidth) / pow((int)16, 2.0));
-
-    if  (rce->lastSatd >= mbCount)
+    if (rce->lastSatd >= ncu)
         updatePredictor(&pred[rce->sliceType], qp2qScale(rce->qpaRc), (double)rce->lastSatd, (double)bits);
-
     if (!isVbv)
         return;
 
@@ -819,19 +810,27 @@
     bufferFillFinal += bufferRate;
     bufferFillFinal = X265_MIN(bufferFillFinal, bufferSize);
 }
-
 /* After encoding one frame, update rate control state */
-int RateControl::rateControlEnd(int64_t bits, RateControlEntry* rce)
+int RateControl::rateControlEnd(TComPic* pic, int64_t bits, RateControlEntry* rce)
 {
     if (isAbr)
     {
         if (!isVbv && cfg->param.rc.rateControlMode == X265_RC_ABR)
         {
-            checkAndResetABR(rce);
+            checkAndResetABR(pic, rce);
         }
-
         if (!isAbrReset)
         {
+            if (pic->m_qpaRc)
+            {
+                for (uint32_t i = 0; i < pic->getFrameHeightInCU(); i++)
+                {
+                    pic->m_avgQpRc += pic->m_qpaRc[i];
+                }
+                pic->m_avgQpRc /= (pic->getFrameHeightInCU() * pic->getFrameWidthInCU());
+                rce->qpaRc = pic->m_avgQpRc;
+            }
+
             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. */
diff -r 9517ea331f3e -r d058d4dd84a5 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h	Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/ratecontrol.h	Thu Feb 20 18:09:53 2014 +0530
@@ -126,10 +126,8 @@
     // to be called for each frame to process RateControl and set QP
     void rateControlStart(TComPic* pic, Lookahead *, RateControlEntry* rce, Encoder* enc);
     void calcAdaptiveQuantFrame(TComPic *pic);
-    int rateControlEnd(int64_t bits, RateControlEntry* rce);
-
+    int rateControlEnd(TComPic* pic, int64_t bits, RateControlEntry* rce);
 protected:
-
     double getQScale(RateControlEntry *rce, double rateFactor);
     double rateEstimateQscale(TComPic* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR
     void accumPQpUpdate();
@@ -140,7 +138,7 @@
     double clipQscale(TComPic* pic, double q);
     void updateVbvPlan(Encoder* enc);
     double predictSize(Predictor *p, double q, double var);
-    void checkAndResetABR(RateControlEntry* rce);
+    void checkAndResetABR(TComPic* pic, RateControlEntry* rce);
 };
 }
 


More information about the x265-devel mailing list