[x265] [PATCH] rc: change row diagonal vbv algorithm

Divya Manivannan divya at multicorewareinc.com
Thu May 19 14:04:03 CEST 2016


# HG changeset patch
# User Divya Manivannan <divya at multicorewareinc.com>
# Date 1462450702 -19800
#      Thu May 05 17:48:22 2016 +0530
# Node ID eadc0a1e233adb60326030825cab2ff71782ef9d
# Parent  7241944b3893cc7ee6df67ebceec06fa0916319a
rc: change row diagonal vbv algorithm

diff -r 7241944b3893 -r eadc0a1e233a source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Wed May 18 19:25:34 2016 +0000
+++ b/source/encoder/ratecontrol.cpp	Thu May 05 17:48:22 2016 +0530
@@ -2243,22 +2243,27 @@
     double qpMax = X265_MIN(prevRowQp + m_param->rc.qpStep, qpAbsoluteMax);
     double qpMin = X265_MAX(prevRowQp - m_param->rc.qpStep, qpAbsoluteMin);
     double stepSize = 0.5;
-    double bufferLeftPlanned = rce->bufferFill - rce->frameSizePlanned;
 
     const SPS& sps = *curEncData.m_slice->m_sps;
-    double maxFrameError = X265_MAX(0.05, 1.0 / sps.numCuInHeight);
+    double maxFrameError = x265_clip3(0.05, 0.25, 1.0 / sps.numCuInHeight);
+    double maxFrameSize = rce->frameSizeMaximum - rce->frameSizeMaximum * maxFrameError;
+    maxFrameSize = X265_MIN(maxFrameSize, rce->bufferFill - rce->bufferRate * maxFrameError);
 
     if (row < sps.numCuInHeight - 1)
     {
+        double bufferLeftPlanned = rce->bufferFill - rce->frameSizePlanned;
+        bufferLeftPlanned = X265_MAX(bufferLeftPlanned, 0.f);
+
         /* More threads means we have to be more cautious in letting ratecontrol use up extra bits. */
         double rcTol = bufferLeftPlanned / m_param->frameNumThreads * m_rateTolerance;
         int32_t encodedBitsSoFar = 0;
         double accFrameBits = predictRowsSizeSum(curFrame, rce, qpVbv, encodedBitsSoFar);
+        double trustCoeff = x265_clip3(0.0, 1.0, encodedBitsSoFar / rce->frameSizePlanned);
 
         /* * Don't increase the row QPs until a sufficent amount of the bits of
          * the frame have been processed, in case a flat area at the top of the
          * frame was measured inaccurately. */
-        if (encodedBitsSoFar < 0.05f * rce->frameSizePlanned)
+        if (trustCoeff < 0.05f)
             qpMax = qpAbsoluteMax = prevRowQp;
 
         if (rce->sliceType != I_SLICE || (m_param->rc.bStrictCbr && rce->poc > 0))
@@ -2274,7 +2279,7 @@
 
         while (qpVbv < qpMax
                && (((accFrameBits > rce->frameSizePlanned + rcTol) ||
-                   (rce->bufferFill - accFrameBits < bufferLeftPlanned * 0.5) ||
+                   (accFrameBits > rce->bufferFill - bufferLeftPlanned * 0.5) ||
                    (accFrameBits > rce->frameSizePlanned && qpVbv < rce->qpNoVbv))
                    && (!m_param->rc.bStrictCbr ? 1 : abrOvershoot > 0.1)))
         {
@@ -2283,16 +2288,22 @@
             abrOvershoot = (accFrameBits + m_totalBits - m_wantedBitsWindow) / totalBitsNeeded;
         }
 
-        while (qpVbv > qpMin
+        double accFrameBitsMax = accFrameBits + ((rce->bufferFill - m_bufferSize + m_bufferRate) * 0.90 - accFrameBits) * trustCoeff;
+        qpVbv -= stepSize;
+        double accFrameBitsTemp = predictRowsSizeSum(curFrame, rce, qpVbv, encodedBitsSoFar);
+        while (qpVbv > qpMin && qpVbv < prevRowQp
                && (qpVbv > curEncData.m_rowStat[0].diagQp || m_singleFrameVbv)
-               && (((accFrameBits < rce->frameSizePlanned * 0.8f && qpVbv <= prevRowQp)
-                   || accFrameBits < (rce->bufferFill - m_bufferSize + m_bufferRate) * 1.1)
+               && (accFrameBitsTemp < maxFrameSize)
+               && (((accFrameBitsTemp < rce->frameSizePlanned * 0.8f)
+                   || (accFrameBitsTemp < accFrameBitsMax))
                    && (!m_param->rc.bStrictCbr ? 1 : abrOvershoot < 0)))
         {
+            accFrameBits = accFrameBitsTemp;
             qpVbv -= stepSize;
-            accFrameBits = predictRowsSizeSum(curFrame, rce, qpVbv, encodedBitsSoFar);
+            accFrameBitsTemp = predictRowsSizeSum(curFrame, rce, qpVbv, encodedBitsSoFar);
             abrOvershoot = (accFrameBits + m_totalBits - m_wantedBitsWindow) / totalBitsNeeded;
         }
+        qpVbv += stepSize;
 
         if (m_param->rc.bStrictCbr && m_param->totalFrames)
         {
@@ -2313,9 +2324,7 @@
         }
 
         /* avoid VBV underflow or MinCr violation */
-        while ((qpVbv < qpAbsoluteMax)
-               && ((rce->bufferFill - accFrameBits < m_bufferRate * maxFrameError) ||
-                   (rce->frameSizeMaximum - accFrameBits < rce->frameSizeMaximum * maxFrameError)))
+        while (qpVbv < qpAbsoluteMax && (accFrameBits > maxFrameSize))
         {
             qpVbv += stepSize;
             accFrameBits = predictRowsSizeSum(curFrame, rce, qpVbv, encodedBitsSoFar);
@@ -2343,12 +2352,14 @@
     else
     {
         int32_t encodedBitsSoFar = 0;
-        rce->frameSizeEstimated = predictRowsSizeSum(curFrame, rce, qpVbv, encodedBitsSoFar);
+        for (uint32_t row = 0; row < sps.numCuInHeight; row++)
+            encodedBitsSoFar += curEncData.m_rowStat[row].encodedBits;
+
+        rce->frameSizeEstimated = encodedBitsSoFar;
 
         /* Last-ditch attempt: if the last row of the frame underflowed the VBV,
          * try again. */
-        if ((rce->frameSizeEstimated > (rce->bufferFill - m_bufferRate * maxFrameError) &&
-             qpVbv < qpMax && canReencodeRow))
+        if (qpVbv < qpMax && canReencodeRow && (rce->frameSizeEstimated > X265_MIN(rce->frameSizeMaximum, rce->bufferFill)))
         {
             qpVbv = qpMax;
             return -1;


More information about the x265-devel mailing list