[x265] [PATCH 3 of 4 x265] Add real-time VBV fullness based QP tuning in VBV 2 pass

kirithika at multicorewareinc.com kirithika at multicorewareinc.com
Wed Apr 22 09:14:16 CEST 2020


# HG changeset patch
# User Kirithika <kirithika at multicorewareinc.com>
# Date 1587532632 -19800
#      Wed Apr 22 10:47:12 2020 +0530
# Node ID 94b6aa5db332550f7222bbc753b7c7ffdf78c67f
# Parent  0fa2ec307c561a07ba6e1679a1814f2fb37eb4e1
Add real-time VBV fullness based QP tuning in VBV 2 pass

This commit enables real-time VBV fullness based 2nd pass QP  tuning.
The existing prediction based QP tuning is removed

diff -r 0fa2ec307c56 -r 94b6aa5db332 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp	Mon Jan 06 12:06:48 2020 +0530
+++ b/source/encoder/ratecontrol.cpp	Wed Apr 22 10:47:12 2020 +0530
@@ -131,6 +131,7 @@
     rce->qpNoVbv = rce2Pass->qpNoVbv;
     rce->newQp = rce2Pass->newQp;
     rce->qRceq = rce2Pass->qRceq;
+    rce->misPredCheck = rce2Pass->misPredCheck;
 }
 
 }  // end anonymous namespace
@@ -599,9 +600,9 @@
                 m_encOrder[frameNumber] = encodeOrder;
                 if (!m_param->bMultiPassOptRPS)
                 {
-                    e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d icu:%lf pcu:%lf scu:%lf",
+                    e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d misPredCheck:%d icu:%lf pcu:%lf scu:%lf",
                         &picType, &qpRc, &qpAq, &qNoVbv, &qRceq, &rce->coeffBits,
-                        &rce->mvBits, &rce->miscBits, &rce->iCuCount, &rce->pCuCount,
+                        &rce->mvBits, &rce->miscBits, &rce->misPredCheck, &rce->iCuCount, &rce->pCuCount,
                         &rce->skipCuCount);
                 }
                 else
@@ -610,9 +611,9 @@
                     char bUsed[40];
                     memset(deltaPOC, 0, sizeof(deltaPOC));
                     memset(bUsed, 0, sizeof(bUsed));
-                    e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d icu:%lf pcu:%lf scu:%lf nump:%d numnegp:%d numposp:%d deltapoc:%s bused:%s",
+                    e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d misPredCheck:%d icu:%lf pcu:%lf scu:%lf nump:%d numnegp:%d numposp:%d deltapoc:%s bused:%s",
                         &picType, &qpRc, &qpAq, &qNoVbv, &qRceq, &rce->coeffBits,
-                        &rce->mvBits, &rce->miscBits, &rce->iCuCount, &rce->pCuCount,
+                        &rce->mvBits, &rce->miscBits, &rce->misPredCheck, &rce->iCuCount, &rce->pCuCount,
                         &rce->skipCuCount, &rce->rpsData.numberOfPictures, &rce->rpsData.numberOfNegativePictures, &rce->rpsData.numberOfPositivePictures, deltaPOC, bUsed);
                     splitdeltaPOC(deltaPOC, rce);
                     splitbUsed(bUsed, rce);
@@ -1880,13 +1881,11 @@
                 qScale = tuneQScaleForZone(rce, qScale);
                 qScale = x265_clip3(lqmin, lqmax, qScale);
             }
-
+            /* clip qp to permissible range after vbv-lookahead estimation to avoid possible
+             * mispredictions by initial frame size predictors */
+            qScale = clipQscale(curFrame, rce, qScale);
             if (!m_2pass)
             {
-                /* clip qp to permissible range after vbv-lookahead estimation to avoid possible 
-                 * mispredictions by initial frame size predictors */
-                qScale = clipQscale(curFrame, rce, qScale);
-
                 if (m_pred[m_predType].count == 1)
                     qScale = x265_clip3(lmin, lmax, qScale);
                 m_lastQScaleFor[m_sliceType] = qScale;
@@ -1949,7 +1948,9 @@
                 else
                     q /= zone->bitrateFactor;
             }
-            q /= x265_clip3(0.5, 2.0, (double)(abrBuffer - diff) / abrBuffer);
+            /*Existing ABR conformance check may not be valid with real time VBV*/
+            if(!m_isVbv)
+                q /= x265_clip3(0.5, 2.0, (double)(abrBuffer - diff) / abrBuffer);
             if (m_expectedBitsSum > 0)
             {
                 /* Adjust quant based on the difference between
@@ -1972,23 +1973,9 @@
 
             if (m_isVbv)
             {
-                /* Do not overflow vbv */
-                double expectedSize = qScale2bits(rce, q);
-                double expectedVbv = m_bufferFill + m_bufferRate - expectedSize;
-                double expectedFullness = rce->expectedVbv / m_bufferSize;
-                double qmax = q * (2 - expectedFullness);
-                double sizeConstraint = 1 + expectedFullness;
-                qmax = X265_MAX(qmax, rce->newQScale);
-                if (expectedFullness < .05)
-                    qmax = lmax;
-                qmax = X265_MIN(qmax, lmax);
-                while (((expectedVbv < rce->expectedVbv/sizeConstraint) && (q < qmax)) ||
-                        ((expectedVbv < 0) && (q < lmax)))
-                {
-                    q *= 1.05;
-                    expectedSize = qScale2bits(rce, q);
-                    expectedVbv = m_bufferFill + m_bufferRate - expectedSize;
-                }
+                /*  clip qp to permissible range after vbv-lookahead estimation to avoid possible
+                 * mispredictions by Rate Control pass 1 statistics analysis */
+                q = clipQscale(curFrame, rce, q);
             }
             q = x265_clip3(lmin, lmax, q);
         }
@@ -2286,11 +2273,11 @@
     double lmin = m_lmin[rce->sliceType];
     double lmax = m_lmax[rce->sliceType];
     double q0 = q;
-    if (m_isVbv && m_currentSatd > 0 && curFrame)
+    if (m_isVbv && curFrame && (m_currentSatd > 0 || m_2pass))
     {
         if (m_param->lookaheadDepth || m_param->rc.cuTree ||
             (m_param->scenecutThreshold || m_param->bHistBasedSceneCut) ||
-            (m_param->bFrameAdaptive && m_param->bframes))
+            (m_param->bFrameAdaptive && m_param->bframes) || m_2pass)
         {
            /* Lookahead VBV: If lookahead is done, raise the quantizer as necessary
             * such that no frames in the lookahead overflow and such that the buffer
@@ -2301,7 +2288,7 @@
             {
                 double frameQ[3];
                 double curBits;
-                curBits = predictSize(&m_pred[m_predType], q, (double)m_currentSatd);
+                curBits = !m_2pass ? predictSize(&m_pred[m_predType], q, (double)m_currentSatd) : qScale2bits(rce, q);
                 double bufferFillCur = m_bufferFill - curBits;
                 double targetFill;
                 double totalDuration = m_frameDuration;
@@ -2310,19 +2297,27 @@
                 frameQ[I_SLICE] = frameQ[P_SLICE] / m_param->rc.ipFactor;
                 /* Loop over the planned future frames. */
                 bool iter = true;
-                for (int j = 0; bufferFillCur >= 0 && iter ; j++)
+                int startLookahead = !m_2pass ? 0 : rce->encodeOrder + 1;
+                for (int j = startLookahead; bufferFillCur >= 0 && iter; j++)
                 {
-                    int type = curFrame->m_lowres.plannedType[j];
-                    if (type == X265_TYPE_AUTO || totalDuration >= 1.0)
+                    int type;
+                    if (!m_2pass)
+                        type = curFrame->m_lowres.plannedType[j];
+                    if ((!m_2pass && type == X265_TYPE_AUTO) || (m_2pass && j >= m_param->totalFrames) || totalDuration >= 1.0)
                         break;
                     totalDuration += m_frameDuration;
                     double wantedFrameSize = m_vbvMaxRate * m_frameDuration;
                     if (bufferFillCur + wantedFrameSize <= m_bufferSize)
                         bufferFillCur += wantedFrameSize;
-                    int64_t satd = curFrame->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
-                    type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;
-                    int predType = getPredictorType(curFrame->m_lowres.plannedType[j], type);
-                    curBits = predictSize(&m_pred[predType], frameQ[type], (double)satd);
+                    if (!m_2pass)
+                    {
+                        int64_t satd = curFrame->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
+                        type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;
+                        int predType = getPredictorType(curFrame->m_lowres.plannedType[j], type);
+                        curBits = predictSize(&m_pred[predType], frameQ[type], (double)satd);
+                    }
+                    else
+                        curBits = qScale2bits(&m_rce2Pass[j], q);
                     bufferFillCur -= curBits;
                     if (!m_param->bResetZoneConfig && ((uint64_t)j == (m_param->reconfigWindowSize - 1)))
                         iter = false;
@@ -2410,14 +2405,16 @@
         }
 
         /* Apply MinCR restrictions */
-        double pbits = predictSize(&m_pred[m_predType], q, (double)m_currentSatd);
+        double pbits = !m_2pass ? predictSize(&m_pred[m_predType], q, (double)m_currentSatd) : qScale2bits(rce, q);
         if (pbits > rce->frameSizeMaximum)
             q *= pbits / rce->frameSizeMaximum;
         /* To detect frames that are more complex in SATD costs compared to prev window, yet 
          * lookahead vbv reduces its qscale by half its value. Be on safer side and avoid drastic 
          * qscale reductions for frames high in complexity */
-        bool mispredCheck = rce->movingAvgSum && m_currentSatd >= rce->movingAvgSum && q <= q0 / 2;
-        if (!m_isCbr || (m_isAbr && mispredCheck))
+        if (!m_2pass)
+            rce->misPredCheck = rce->movingAvgSum && m_currentSatd >= rce->movingAvgSum;
+        bool mispredCheck = rce->misPredCheck && q <= q0 / 2;
+        if (!m_isCbr || ((m_isAbr || m_2pass) && mispredCheck))
             q = X265_MAX(q0, q);
 
         if (m_rateFactorMaxIncrement)
@@ -2427,7 +2424,7 @@
             return x265_clip3(lmin, qmax, q);
         }
     }
-    if (m_2pass)
+    if (!curFrame && m_2pass)
     {
         double min = log(lmin);
         double max = log(lmax);
@@ -2963,13 +2960,14 @@
     if (!curEncData.m_param->bMultiPassOptRPS)
     {
         if (fprintf(m_statFileOut,
-            "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d icu:%.2f pcu:%.2f scu:%.2f ;\n",
+            "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d misPredCheck:%d icu:%.2f pcu:%.2f scu:%.2f ;\n",
             rce->poc, rce->encodeOrder,
             cType, curEncData.m_avgQpRc, curEncData.m_avgQpAq,
             rce->qpNoVbv, rce->qRceq,
             curFrame->m_encData->m_frameStats.coeffBits,
             curFrame->m_encData->m_frameStats.mvBits,
             curFrame->m_encData->m_frameStats.miscBits,
+            rce->misPredCheck,
             curFrame->m_encData->m_frameStats.percent8x8Intra * m_ncu,
             curFrame->m_encData->m_frameStats.percent8x8Inter * m_ncu,
             curFrame->m_encData->m_frameStats.percent8x8Skip  * m_ncu) < 0)
@@ -2993,13 +2991,14 @@
         }
 
         if (fprintf(m_statFileOut,
-            "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d icu:%.2f pcu:%.2f scu:%.2f nump:%d numnegp:%d numposp:%d %s %s ;\n",
+            "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d misPredCheck:%d icu:%.2f pcu:%.2f scu:%.2f nump:%d numnegp:%d numposp:%d %s %s ;\n",
             rce->poc, rce->encodeOrder,
             cType, curEncData.m_avgQpRc, curEncData.m_avgQpAq,
             rce->qpNoVbv, rce->qRceq,
             curFrame->m_encData->m_frameStats.coeffBits,
             curFrame->m_encData->m_frameStats.mvBits,
             curFrame->m_encData->m_frameStats.miscBits,
+            rce->misPredCheck,
             curFrame->m_encData->m_frameStats.percent8x8Intra * m_ncu,
             curFrame->m_encData->m_frameStats.percent8x8Inter * m_ncu,
             curFrame->m_encData->m_frameStats.percent8x8Skip  * m_ncu,
diff -r 0fa2ec307c56 -r 94b6aa5db332 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h	Mon Jan 06 12:06:48 2020 +0530
+++ b/source/encoder/ratecontrol.h	Wed Apr 22 10:47:12 2020 +0530
@@ -123,6 +123,7 @@
     int      rpsIdx;
     RPS      rpsData;
     bool     isFadeEnd;
+    int      misPredCheck;
 };
 
 class RateControl
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265-3.patch
Type: text/x-patch
Size: 12429 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20200422/1c771f10/attachment-0001.bin>


More information about the x265-devel mailing list