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

aarthi at multicorewareinc.com aarthi at multicorewareinc.com
Thu Feb 20 14:25:46 CET 2014


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

diff -r ebc23ec5ac1c -r c5c07a3ee7fc 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
@@ -367,7 +367,7 @@
         // 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);
 
diff -r ebc23ec5ac1c -r c5c07a3ee7fc 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,7 +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)
     {
@@ -445,12 +447,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)
@@ -522,7 +524,7 @@
         {
             if (!isVbv)
             {
-                checkAndResetABR(rce);
+                checkAndResetABR(pic, rce);
             }
             q = getQScale(rce, wantedBitsWindow / cplxrSum);
 
@@ -552,23 +554,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
         {
@@ -593,7 +594,7 @@
     }
 }
 
-void RateControl::checkAndResetABR(RateControlEntry* rce)
+void RateControl::checkAndResetABR(TComPic* pic, RateControlEntry* rce)
 {
     double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;
 
@@ -604,7 +605,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;
@@ -659,9 +660,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++)
@@ -807,9 +808,8 @@
 
 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)
@@ -826,17 +826,27 @@
 }
 
 /* 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 ebc23ec5ac1c -r c5c07a3ee7fc 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
@@ -128,7 +128,7 @@
     // 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:
 
@@ -142,7 +142,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