[x265] [PATCH RFC] 1. Bug fix - improved quality drop for low resolution videos in ABR by 5%

sumalatha at multicorewareinc.com sumalatha at multicorewareinc.com
Thu Sep 12 13:46:47 CEST 2013


# HG changeset patch
# User sumalatha polureddy
# Date 1378986299 -19800
# Node ID f8ac7c593a80639220d4c445167383fdaad48dc8
# Parent  8fdafe573ef7bc2f9ca3eab968f5a563aa06ac54
1. Bug fix - improved quality drop for low resolution videos in ABR by 5%
  - Clipped the qp for the 1st frame to improve quality.
2. Changed tuning factors in rateControlEnd from 1.1 to 1.5
 -  to tune up the actual bits else the cplxrSum is scaled too low to improve short term compensation.

diff -r 8fdafe573ef7 -r f8ac7c593a80 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Wed Sep 11 12:19:17 2013 -0500
+++ b/source/encoder/ratecontrol.cpp	Thu Sep 12 17:14:59 2013 +0530
@@ -72,13 +72,14 @@
     shortTermCplxCount = 0;
     if (rateControlMode == X265_RC_ABR)
     {
-        //TODO : confirm this value. obtained it from x264 when crf is disabled , abr enabled.
-        //h->param.rc.i_rc_method == X264_RC_CRF ? h->param.rc.f_rf_constant : 24  -- can be tweaked for x265.
-#define ABR_INIT_QP (24  + QP_BD_OFFSET)
+        
+        //introduced to margin QP for first frame to an optimum level in order to stabilize the quality.
+#define ABR_INIT_QP_MIN (24 + QP_BD_OFFSET)
+#define ABR_INIT_QP_MAX (38 + QP_BD_OFFSET)
         accumPNorm = .01;
-        accumPQp = (ABR_INIT_QP)*accumPNorm;
+        accumPQp = (ABR_INIT_QP_MIN)*accumPNorm;
         /* estimated ratio that produces a reasonable QP for the first I-frame  */
-        cplxrSum = .01 * pow(7.0e5, qCompress) * pow(2 *ncu, 0.5);
+        cplxrSum = .01 * pow(7.0e5, qCompress) * pow(2 * ncu, 0.5);
         wantedBitsWindow = bitrate * frameDuration;
         lastNonBPictType = I_SLICE;
     }
@@ -86,7 +87,7 @@
     pbOffset = 6.0 * (float)(X265_LOG2(param->rc.pbFactor));
     for (int i = 0; i < 3; i++)
     {
-        lastQScaleFor[i] = qp2qScale(ABR_INIT_QP);
+        lastQScaleFor[i] = qp2qScale(ABR_INIT_QP_MIN);
         lmin[i] = qp2qScale(MIN_QP);
         lmax[i] = qp2qScale(MAX_QP);  
     }
@@ -160,16 +161,19 @@
     {
         /* B-frames don't have independent rate control, but rather get the
          * average QP of the two adjacent P-frames + an offset */
+        TComSlice* prevRefSlice = curFrame->getRefPic(REF_PIC_LIST_0, 0)->getSlice();
+        TComSlice* nextRefSlice = curFrame->getRefPic(REF_PIC_LIST_1, 0)->getSlice();
+        bool i0 = prevRefSlice->getSliceType() == I_SLICE;
+        bool i1 = nextRefSlice->getSliceType() == I_SLICE;
+        int dt0 = abs(curFrame->getPOC() - prevRefSlice->getPOC());
+        int dt1 = abs(curFrame->getPOC() - nextRefSlice->getPOC());
+        double q0 = prevRefSlice->getSliceQp();
+        double q1 = nextRefSlice->getSliceQp();
 
-        int i0 = curFrame->getRefPic(REF_PIC_LIST_0, 0)->getSlice()->getSliceType() == I_SLICE;
-        int i1 = curFrame->getRefPic(REF_PIC_LIST_1, 0)->getSlice()->getSliceType() == I_SLICE;
-        int dt0 = abs(curFrame->getPOC() - curFrame->getRefPic(REF_PIC_LIST_0, 0)->getPOC());
-        int dt1 = abs(curFrame->getPOC() - curFrame->getRefPic(REF_PIC_LIST_1, 0)->getPOC());
-
-        //TODO:need to figure out this
-        double q0 = curFrame->getRefPic(REF_PIC_LIST_0, 0)->getSlice()->getSliceQp();
-        double q1 = curFrame->getRefPic(REF_PIC_LIST_1, 0)->getSlice()->getSliceQp();
-
+        if (prevRefSlice->getSliceType()  == B_SLICE && prevRefSlice->isReferenced())
+            q0 -= pbOffset / 2;
+        if (nextRefSlice->getSliceType()  == B_SLICE && nextRefSlice->isReferenced())
+            q1 -= pbOffset / 2;
         if (i0 && i1)
             q = (q0 + q1) / 2 + ipOffset;
         else if (i0)
@@ -183,12 +187,8 @@
             q += pbOffset / 2;
         else
             q += pbOffset;
-        
-        double qScale = qp2qScale(q);
 
-        lastQScaleFor[P_SLICE] = lastQScale = qScale/pbFactor;
-
-        return qScale;
+        return qp2qScale(q);
     }
     else
     {
@@ -242,21 +242,29 @@
             q = qp2qScale(accumPQp / accumPNorm);
             q /= fabs(ipFactor);
         }
-        else if (curFrame->getPOC() > 0)
+        if (rateControlMode != X265_RC_CRF)
         {
-            if (rateControlMode != X265_RC_CRF)
+            double lqmin = 0, lqmax = 0;
+
+            /* Clip the qp of 1st frame to ensure it doesnt detoriate the quality */
+            if (curFrame->getPOC() == 0)
             {
-                /* Asymmetric clipping, because symmetric would prevent
-                 * overflow control in areas of rapidly oscillating complexity */
-                double lqmin = lastQScaleFor[pictType] / lstep;
-                double lqmax = lastQScaleFor[pictType] * lstep;
-                if (overflow > 1.1 && curFrame->getPOC() > 3)
-                    lqmax *= lstep;
-                else if (overflow < 0.9)
-                    lqmin /= lstep;
+                lqmin = qp2qScale(ABR_INIT_QP_MIN) / lstep;
+                lqmax = qp2qScale(ABR_INIT_QP_MAX) * lstep;
+            }
+            /* Asymmetric clipping, because symmetric would prevent
+             * overflow control in areas of rapidly oscillating complexity */
+            else if (curFrame->getPOC() > 0)
+            {
+                lqmin = lastQScaleFor[pictType] / lstep;
+                lqmax = lastQScaleFor[pictType] * lstep;
+            }
+            if (overflow > 1.1 && curFrame->getPOC() > 3)
+                lqmax *= lstep;
+            else if (overflow < 0.9)
+                lqmin /= lstep;
 
-                q = Clip3(lqmin, lqmax, q);
-            }
+            q = Clip3(lqmin, lqmax, q);
         }
 
         //FIXME use get_diff_limited_q() ?
@@ -300,12 +308,14 @@
     if (rateControlMode == X265_RC_ABR)
     {
         if (frameType != B_SLICE)
-            cplxrSum +=  1.1 *bits * qp2qScale(rce->qpaRc) / rce->lastRceq;
+            /* 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 += 1.5 *bits * qp2qScale(rce->qpaRc) / rce->lastRceq;
         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->lastRceq * fabs(0.5 * pbFactor));
+            cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->lastRceq * fabs(pbFactor));
         }
         cplxrSum *= cbrDecay;
         wantedBitsWindow += frameDuration * bitrate;


More information about the x265-devel mailing list