[x265] [PATCH 1 of 3] ratecontrol: avoid clipping QP multiple times when VBV is not enabled

deepthi at multicorewareinc.com deepthi at multicorewareinc.com
Tue May 6 12:18:08 CEST 2014


# HG changeset patch
# User Deepthi Nandakumar <deepthi at multicorewareinc.com>
# Date 1399370478 -19800
# Node ID 33772b1766588c9088dbf7c3c7f6f6e92b92d27d
# Parent  075705aa41a9144bb1a4d7f12d837169767630e1
ratecontrol: avoid clipping QP multiple times when VBV is not enabled.

diff -r 075705aa41a9 -r 33772b176658 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Mon May 05 23:26:59 2014 -0500
+++ b/source/encoder/ratecontrol.cpp	Tue May 06 15:31:18 2014 +0530
@@ -588,7 +588,8 @@
         q = Clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
         qpNoVbv = x265_qScale2qp(q);
 
-        q = clipQscale(pic, q);
+        if(isVbv && currentSatd > 0)
+            q = clipQscale(pic, q);
 
         lastQScaleFor[sliceType] = q;
 
@@ -642,117 +643,112 @@
 
 double RateControl::clipQscale(TComPic* pic, double q)
 {
-    double q0 = q;
-
     // B-frames are not directly subject to VBV,
     // since they are controlled by the P-frames' QPs.
-    if (isVbv && currentSatd > 0)
+    double q0 = q;
+    if (param->lookaheadDepth)
     {
-        if (param->lookaheadDepth)
+        int terminate = 0;
+
+        /* Avoid an infinite loop. */
+        for (int iterations = 0; iterations < 1000 && terminate != 3; iterations++)
         {
-            int terminate = 0;
-
-            /* Avoid an infinite loop. */
-            for (int iterations = 0; iterations < 1000 && terminate != 3; iterations++)
+            double frameQ[3];
+            double curBits = predictSize(&pred[sliceType], q, (double)currentSatd);
+            double bufferFillCur = bufferFill - curBits;
+            double targetFill;
+            double totalDuration = 0;
+            frameQ[P_SLICE] = sliceType == I_SLICE ? q * param->rc.ipFactor : q;
+            frameQ[B_SLICE] = frameQ[P_SLICE] * param->rc.pbFactor;
+            frameQ[I_SLICE] = frameQ[P_SLICE] / param->rc.ipFactor;
+            /* Loop over the planned future frames. */
+            for (int j = 0; bufferFillCur >= 0 && bufferFillCur <= bufferSize; j++)
             {
-                double frameQ[3];
-                double curBits = predictSize(&pred[sliceType], q, (double)currentSatd);
-                double bufferFillCur = bufferFill - curBits;
-                double targetFill;
-                double totalDuration = 0;
-                frameQ[P_SLICE] = sliceType == I_SLICE ? q * param->rc.ipFactor : q;
-                frameQ[B_SLICE] = frameQ[P_SLICE] * param->rc.pbFactor;
-                frameQ[I_SLICE] = frameQ[P_SLICE] / param->rc.ipFactor;
-                /* Loop over the planned future frames. */
-                for (int j = 0; bufferFillCur >= 0 && bufferFillCur <= bufferSize; j++)
-                {
-                    totalDuration += frameDuration;
-                    bufferFillCur += vbvMaxRate * frameDuration;
-                    int type = pic->m_lowres.plannedType[j];
-                    int64_t satd = pic->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
-                    if (type == X265_TYPE_AUTO)
-                        break;
-                    type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;
-                    curBits = predictSize(&pred[type], frameQ[type], (double)satd);
-                    bufferFillCur -= curBits;
-                }
-
-                /* Try to get the buffer at least 50% filled, but don't set an impossible goal. */
-                targetFill = X265_MIN(bufferFill + totalDuration * vbvMaxRate * 0.5, bufferSize * 0.5);
-                if (bufferFillCur < targetFill)
-                {
-                    q *= 1.01;
-                    terminate |= 1;
-                    continue;
-                }
-                /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */
-                targetFill = Clip3(bufferSize * 0.8, bufferSize, bufferFill - totalDuration * vbvMaxRate * 0.5);
-                if (vbvMinRate && bufferFillCur > targetFill)
-                {
-                    q /= 1.01;
-                    terminate |= 2;
-                    continue;
-                }
-                break;
-            }
-        }
-        else
-        {
-            if ((sliceType == P_SLICE ||
-                 (sliceType == I_SLICE && lastNonBPictType == I_SLICE)) &&
-                bufferFill / bufferSize < 0.5)
-            {
-                q /= Clip3(0.5, 1.0, 2.0 * bufferFill / bufferSize);
+                totalDuration += frameDuration;
+                bufferFillCur += vbvMaxRate * frameDuration;
+                int type = pic->m_lowres.plannedType[j];
+                int64_t satd = pic->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
+                if (type == X265_TYPE_AUTO)
+                    break;
+                type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;
+                curBits = predictSize(&pred[type], frameQ[type], (double)satd);
+                bufferFillCur -= curBits;
             }
 
-            // Now a hard threshold to make sure the frame fits in VBV.
-            // This one is mostly for I-frames.
-            double bits = predictSize(&pred[sliceType], q, (double)currentSatd);
-
-            // For small VBVs, allow the frame to use up the entire VBV.
-            double maxFillFactor;
-            maxFillFactor = bufferSize >= 5 * bufferRate ? 2 : 1;
-            // For single-frame VBVs, request that the frame use up the entire VBV.
-            double minFillFactor = singleFrameVbv ? 1 : 2;
-
-            for (int iterations = 0; iterations < 10; iterations++)
+            /* Try to get the buffer at least 50% filled, but don't set an impossible goal. */
+            targetFill = X265_MIN(bufferFill + totalDuration * vbvMaxRate * 0.5, bufferSize * 0.5);
+            if (bufferFillCur < targetFill)
             {
-                double qf = 1.0;
-                if (bits > bufferFill / maxFillFactor)
-                    qf = Clip3(0.2, 1.0, bufferFill / (maxFillFactor * bits));
-                q /= qf;
-                bits *= qf;
-                if (bits < bufferRate / minFillFactor)
-                    q *= bits * minFillFactor / bufferRate;
-                bits = predictSize(&pred[sliceType], q, (double)currentSatd);
+                q *= 1.01;
+                terminate |= 1;
+                continue;
             }
-
-            q = X265_MAX(q0, q);
+            /* Try to get the buffer no more than 80% filled, but don't set an impossible goal. */
+            targetFill = Clip3(bufferSize * 0.8, bufferSize, bufferFill - totalDuration * vbvMaxRate * 0.5);
+            if (vbvMinRate && bufferFillCur > targetFill)
+            {
+                q /= 1.01;
+                terminate |= 2;
+                continue;
+            }
+            break;
+        }
+    }
+    else
+    {
+        if ((sliceType == P_SLICE ||
+                (sliceType == I_SLICE && lastNonBPictType == I_SLICE)) &&
+            bufferFill / bufferSize < 0.5)
+        {
+            q /= Clip3(0.5, 1.0, 2.0 * bufferFill / bufferSize);
         }
 
-        // Check B-frame complexity, and use up any bits that would
-        // overflow before the next P-frame.
-        if (sliceType == P_SLICE)
+        // Now a hard threshold to make sure the frame fits in VBV.
+        // This one is mostly for I-frames.
+        double bits = predictSize(&pred[sliceType], q, (double)currentSatd);
+
+        // For small VBVs, allow the frame to use up the entire VBV.
+        double maxFillFactor;
+        maxFillFactor = bufferSize >= 5 * bufferRate ? 2 : 1;
+        // For single-frame VBVs, request that the frame use up the entire VBV.
+        double minFillFactor = singleFrameVbv ? 1 : 2;
+
+        for (int iterations = 0; iterations < 10; iterations++)
         {
-            int nb = bframes;
-            double bits = predictSize(&pred[sliceType], q, (double)currentSatd);
-            double bbits = predictSize(&predBfromP, q * param->rc.pbFactor, (double)currentSatd);
-            double space;
-            if (bbits > bufferRate)
-                nb = 0;
-            double pbbits = nb * bbits;
+            double qf = 1.0;
+            if (bits > bufferFill / maxFillFactor)
+                qf = Clip3(0.2, 1.0, bufferFill / (maxFillFactor * bits));
+            q /= qf;
+            bits *= qf;
+            if (bits < bufferRate / minFillFactor)
+                q *= bits * minFillFactor / bufferRate;
+            bits = predictSize(&pred[sliceType], q, (double)currentSatd);
+        }
 
-            space = bufferFill + (1 + nb) * bufferRate - bufferSize;
-            if (pbbits < space)
-            {
-                q *= X265_MAX(pbbits / space, bits / (0.5 * bufferSize));
-            }
-            q = X265_MAX(q0 / 2, q);
-        }
-        if (!vbvMinRate)
-            q = X265_MAX(q0, q);
+        q = X265_MAX(q0, q);
     }
 
+    // Check B-frame complexity, and use up any bits that would
+    // overflow before the next P-frame.
+    if (sliceType == P_SLICE)
+    {
+        int nb = bframes;
+        double bits = predictSize(&pred[sliceType], q, (double)currentSatd);
+        double bbits = predictSize(&predBfromP, q * param->rc.pbFactor, (double)currentSatd);
+        double space;
+        if (bbits > bufferRate)
+            nb = 0;
+        double pbbits = nb * bbits;
+
+        space = bufferFill + (1 + nb) * bufferRate - bufferSize;
+        if (pbbits < space)
+        {
+            q *= X265_MAX(pbbits / space, bits / (0.5 * bufferSize));
+        }
+        q = X265_MAX(q0 / 2, q);
+    }
+    if (!vbvMinRate)
+        q = X265_MAX(q0, q);
     return Clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
 }
 


More information about the x265-devel mailing list