[x265] [PATCH] rc: fix Rate Control for grainy content

Aarthi Priya Thirumalai aarthi at multicorewareinc.com
Wed Jan 27 06:32:08 CET 2016


# HG changeset patch
# User Aarthi Thirumalai
# Date 1452501832 -19800
#      Mon Jan 11 14:13:52 2016 +0530
# Node ID cee55e38a09310c1c3384ee72e548bd72a00a4e7
# Parent  f548abe8eae8fb75513a85d1b09233e706c7b5ba
rc: fix Rate Control for grainy content

optimize params for tune grain, reduce frequent qp fluctions to prevent
grain loss

diff -r f548abe8eae8 -r cee55e38a093 source/common/param.cpp
--- a/source/common/param.cpp Wed Jan 20 18:27:42 2016 +0530
+++ b/source/common/param.cpp Mon Jan 11 14:13:52 2016 +0530
@@ -454,16 +454,11 @@
         }
         else if (!strcmp(tune, "grain"))
         {
-            param->deblockingFilterBetaOffset = -2;
-            param->deblockingFilterTCOffset = -2;
-            param->bIntraInBFrames = 0;
-            param->rdoqLevel = 2;
-            param->psyRdoq = 10.0;
-            param->psyRd = 0.5;
             param->rc.ipFactor = 1.1;
-            param->rc.pbFactor = 1.1;
-            param->rc.aqStrength = 0.3;
-            param->rc.qCompress = 0.8;
+            param->rc.pbFactor = 1.0;
+            param->rc.cuTree = 0;
+            param->rc.aqMode = 0;
+            param->rc.qpStep = 1.0;
         }
         else
             return -1;
diff -r f548abe8eae8 -r cee55e38a093 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Wed Jan 20 18:27:42 2016 +0530
+++ b/source/encoder/ratecontrol.cpp Mon Jan 11 14:13:52 2016 +0530
@@ -190,6 +190,8 @@
     m_numEntries = 0;
     m_isSceneTransition = false;
     m_lastPredictorReset = 0;
+    m_avgPFrameQp = 0;
+    m_isFirstMiniGop = false;
     if (m_param->rc.rateControlMode == X265_RC_CRF)
     {
         m_param->rc.qp = (int)m_param->rc.rfConstant;
@@ -288,9 +290,13 @@
     m_ipOffset = 6.0 * X265_LOG2(m_param->rc.ipFactor);
     m_pbOffset = 6.0 * X265_LOG2(m_param->rc.pbFactor);

+    for (int i = 0; i < QP_MAX_MAX; i++)
+        m_qpToEncodedBits[i] = 0;
+
     /* Adjust the first frame in order to stabilize the quality level
compared to the rest */
 #define ABR_INIT_QP_MIN (24)
 #define ABR_INIT_QP_MAX (40)
+#define ABR_INIT_QP_GRAIN_MAX (32)
 #define ABR_SCENECUT_INIT_QP_MIN (12)
 #define CRF_INIT_QP (int)m_param->rc.rfConstant
     for (int i = 0; i < 3; i++)
@@ -361,6 +367,7 @@
         m_amortizeFraction = 0.85;
         m_amortizeFrames = m_param->totalFrames / 2;
     }
+
     for (int i = 0; i < s_slidingWindowFrames; i++)
     {
         m_satdCostWindow[i] = 0;
@@ -370,15 +377,19 @@
     m_isPatternPresent = false;
     m_numBframesInPattern = 0;

+        m_isGrainEnabled = false;
+        if(m_param->rc.pbFactor <= 1.1 && !m_param->rc.cuTree) // tune for
grainy content OR equal p-b frame sizes
+        m_isGrainEnabled = true;
+
     /* 720p videos seem to be a good cutoff for cplxrSum */
-    double tuneCplxFactor = (m_param->rc.cuTree && m_ncu > 3600) ? 2.5 : 1;
-
+    double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree) ? 2.5 :
m_isGrainEnabled ? 1.9 : 1;
     /* estimated ratio that produces a reasonable QP for the first I-frame
*/
     m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) *
tuneCplxFactor;
     m_wantedBitsWindow = m_bitrate * m_frameDuration;
     m_accumPNorm = .01;
     m_accumPQp = (m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP
: ABR_INIT_QP_MIN) * m_accumPNorm;

+
     /* Frame Predictors used in vbv */
     initFramePredictors();
     if (!m_statFileOut && (m_param->rc.bStatWrite ||
m_param->rc.bStatRead))
@@ -1049,12 +1060,12 @@
     }
     m_pred[0].coeff = m_pred[3].coeff = 0.75;
     m_pred[0].coeffMin = m_pred[3].coeffMin = 0.75 / 4;
-    if (m_param->rc.qCompress >= 0.8) // when tuned for grain
+    if (m_isGrainEnabled) // when tuned for grain
     {
         m_pred[1].coeffMin = 0.75 / 4;
         m_pred[1].coeff = 0.75;
-        m_pred[0].coeff = m_pred[3].coeff = 0.5;
-        m_pred[0].coeffMin = m_pred[3].coeffMin = 0.5 / 4;
+        m_pred[0].coeff = m_pred[3].coeff = 0.75;
+        m_pred[0].coeffMin = m_pred[3].coeffMin = 0.75 / 4;
     }
 }

@@ -1089,10 +1100,12 @@
     }
     rce->isActive = true;
     bool isRefFrameScenecut = m_sliceType!= I_SLICE &&
m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut;
+    m_isFirstMiniGop = m_sliceType == I_SLICE ? true : m_isFirstMiniGop;
     if (curFrame->m_lowres.bScenecut)
     {
         m_isSceneTransition = true;
         m_lastPredictorReset = rce->encodeOrder;
+
         initFramePredictors();
     }
     else if (m_sliceType != B_SLICE && !isRefFrameScenecut)
@@ -1197,7 +1210,7 @@
         double q = x265_qScale2qp(rateEstimateQscale(curFrame, rce));
         q = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, q);
         m_qp = int(q + 0.5);
-        rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = q;
+        rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = int(q +
0.5);
         /* copy value of lastRceq into thread local rce struct *to be used
in RateControlEnd() */
         rce->qRceq = m_lastRceq;
         accumPQpUpdate();
@@ -1450,7 +1463,7 @@
         }

         if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames
||
-            m_param->rc.bStrictCbr))
+            m_param->rc.bStrictCbr || m_isGrainEnabled))
         {
             abrBuffer *= X265_MAX(1, sqrt(timeDone));
             overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits -
wantedBits) / abrBuffer);
@@ -1460,6 +1473,22 @@
     return qScale;
 }

+double RateControl::tuneQScaleForGrain(double rcOverflow)
+{
+    double qpstepBy1 = pow(2, 0.5 / 6.0);
+    double qScaleAvg = x265_qp2qScale(m_avgPFrameQp);
+    double  q = m_lastQScaleFor[P_SLICE];
+    int curQp = int (x265_qScale2qp(m_lastQScaleFor[P_SLICE]) + 0.5);
+    double curBitrate = m_qpToEncodedBits[curQp] * int(m_fps + 0.5);
+    int newQp = rcOverflow > 1 ? curQp + 1 : curQp - 1 ;
+    double projectedBitrate =  int(m_fps + 0.5) * m_qpToEncodedBits[newQp];
+    if (curBitrate > 0 && projectedBitrate > 0)
+        q =  abs(projectedBitrate - m_bitrate) < abs (curBitrate -
m_bitrate) ? x265_qp2qScale(newQp) : m_lastQScaleFor[P_SLICE];
+    else
+        q = rcOverflow > 1 ? qScaleAvg * qpstepBy1 : rcOverflow < 1 ?
 qScaleAvg / qpstepBy1 : m_lastQScaleFor[P_SLICE];
+    return q;
+}
+
 double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry
*rce)
 {
     double q;
@@ -1525,6 +1554,7 @@
                 q0 = q1;
             }
         }
+
         if (prevRefSlice->m_sliceType == B_SLICE &&
IS_REFERENCED(m_curSlice->m_refFrameList[0][0]))
             q0 -= m_pbOffset / 2;
         if (nextRefSlice->m_sliceType == B_SLICE &&
IS_REFERENCED(m_curSlice->m_refFrameList[1][0]))
@@ -1535,7 +1565,9 @@
             q = q1;
         else if (i1)
             q = q0;
-        else
+        else if(m_isGrainEnabled)
+                q = q1;
+            else
             q = (q0 * dt1 + q1 * dt0) / (dt0 + dt1);

         if (IS_REFERENCED(curFrame))
@@ -1543,7 +1575,7 @@
         else
             q += m_pbOffset;

-        /* Set a min qp at scenechanges and transitions */
+                /* Set a min qp at scenechanges and transitions */
         if (m_isSceneTransition)
         {
             q = X265_MAX(ABR_SCENECUT_INIT_QP_MIN, q);
@@ -1553,11 +1585,28 @@
         double qScale = x265_qp2qScale(q);
         rce->qpNoVbv = q;
         double lmin = 0, lmax = 0;
+        if (m_isGrainEnabled && m_isFirstMiniGop)
+        {
+            lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
+            lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
+            double tunedQscale = tuneAbrQScaleFromFeedback(qScale);
+            double overflow = tunedQscale / qScale;
+            if (!m_isAbrReset)
+                qScale = x265_clip3(lmin, lmax, qScale);
+            m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv :
m_avgPFrameQp;
+            if (overflow != 1)
+            {
+                qScale = tuneQScaleForGrain(overflow);
+                q = x265_qScale2qp(qScale);
+            }
+            rce->qpNoVbv = q;
+        }
         if (m_isVbv)
         {
             lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
             lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
-            if (m_isCbr)
+
+            if (m_isCbr && !m_isGrainEnabled)
             {
                 qScale = tuneAbrQScaleFromFeedback(qScale);
                 if (!m_isAbrReset)
@@ -1581,7 +1630,10 @@
             rce->frameSizePlanned = X265_MIN(rce->frameSizePlanned,
rce->frameSizeMaximum);
             rce->frameSizeEstimated = rce->frameSizePlanned;
         }
+
         rce->newQScale = qScale;
+        if(rce->bLastMiniGopBFrame)
+            m_isFirstMiniGop = false;
         return qScale;
     }
     else
@@ -1675,8 +1727,17 @@
                 if (!m_param->rc.bStatRead)
                     checkAndResetABR(rce, false);
                 double initialQScale = getQScale(rce, m_wantedBitsWindow /
m_cplxrSum);
-                q = tuneAbrQScaleFromFeedback(initialQScale);
-                overflow = q / initialQScale;
+                double tunedQScale =
tuneAbrQScaleFromFeedback(initialQScale);
+                overflow = tunedQScale / initialQScale;
+                q = !m_partialResidualFrames? tunedQScale : initialQScale;
+                bool isEncodeEnd = (m_param->totalFrames &&
+                    m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;
+                bool isEncodeBeg = m_framesDone < (int)(m_fps + 0.5);
+                if(m_isGrainEnabled && m_sliceType!= I_SLICE &&
!isEncodeEnd &&
+                    ((overflow < 1.05 && overflow > 0.95) || isEncodeBeg))
+                {
+                    q = tuneQScaleForGrain(overflow);
+                }
             }
             if (m_sliceType == I_SLICE && m_param->keyframeMax > 1
                 && m_lastNonBPictType != I_SLICE && !m_isAbrReset)
@@ -1684,6 +1745,7 @@
                 if (!m_param->rc.bStrictCbr)
                     q = x265_qp2qScale(m_accumPQp / m_accumPNorm);
                 q /= fabs(m_param->rc.ipFactor);
+                m_avgPFrameQp = 0;
             }
             else if (m_framesDone > 0)
             {
@@ -1708,8 +1770,18 @@
             else if (m_framesDone == 0 && !m_isVbv &&
m_param->rc.rateControlMode == X265_RC_ABR)
             {
                 /* for ABR alone, clip the first I frame qp */
-                lqmax = x265_qp2qScale(ABR_INIT_QP_MAX) * m_lstep;
-                q = X265_MIN(lqmax, q);
+                if (m_isGrainEnabled)
+                {
+                    /* to maintain grain uniformity, set I frame qp in a
fixed range */
+                    lqmax = x265_qp2qScale(ABR_INIT_QP_GRAIN_MAX) *
(m_lstep * m_lstep);
+                    lqmin = x265_qp2qScale(ABR_INIT_QP_GRAIN_MAX) /
(m_lstep * m_lstep);
+                    q = x265_clip3(lqmin, lqmax, q);
+                }
+                else
+                {
+                    lqmax = x265_qp2qScale(ABR_INIT_QP_MAX) * m_lstep;
+                    q = X265_MIN(lqmax, q);
+                }
             }
             q = x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
             /* Set a min qp at scenechanges and transitions */
@@ -1720,6 +1792,11 @@
                m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale,
m_lastQScaleFor[P_SLICE]);
             }
             rce->qpNoVbv = x265_qScale2qp(q);
+            if(m_sliceType == P_SLICE)
+            {
+                m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv :
m_avgPFrameQp;
+                m_avgPFrameQp = (m_avgPFrameQp + rce->qpNoVbv) / 2;
+            }
             q = clipQscale(curFrame, rce, q);
             /*  clip qp to permissible range after vbv-lookahead
estimation to avoid possible
              * mispredictions by initial frame size predictors, after each
scenecut */
@@ -2426,6 +2503,11 @@
         int pos = m_sliderPos - m_param->frameNumThreads;
         if (pos >= 0)
             m_encodedBitsWindow[pos % s_slidingWindowFrames] = actualBits;
+        if(rce->sliceType != I_SLICE)
+        {
+        int qp = int (rce->qpaRc + 0.5);
+        m_qpToEncodedBits[qp] =  m_qpToEncodedBits[qp] == 0 ? actualBits :
(m_qpToEncodedBits[qp] + actualBits) * 0.5;
+        }
     }

     if (m_2pass)
diff -r f548abe8eae8 -r cee55e38a093 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Wed Jan 20 18:27:42 2016 +0530
+++ b/source/encoder/ratecontrol.h Mon Jan 11 14:13:52 2016 +0530
@@ -126,7 +126,7 @@
     bool   m_isVbv;
     bool   m_isCbr;
     bool   m_singleFrameVbv;
-
+    bool   m_isGrainEnabled;
     bool   m_isAbrReset;
     int    m_lastAbrResetPoc;

@@ -141,7 +141,8 @@
     double m_vbvMaxRate;       /* in kbps */
     double m_rateFactorMaxIncrement; /* Don't allow RF above (CRF + this
value). */
     double m_rateFactorMaxDecrement; /* don't allow RF below (this value).
*/
-
+    double m_avgPFrameQp;
+    bool   m_isFirstMiniGop;
     Predictor m_pred[4];       /* Slice predictors to preidct bits for
each Slice type - I,P,Bref and B */
     int64_t m_leadingNoBSatd;
     int     m_predType;       /* Type of slice predictors to be used -
depends on the slice type */
@@ -178,7 +179,7 @@
     bool    m_isPatternPresent;
     bool    m_isSceneTransition;
     int     m_lastPredictorReset;
-
+    double m_qpToEncodedBits[QP_MAX_MAX];
     /* a common variable on which rateControlStart, rateControlEnd and
rateControUpdateStats waits to
      * sync the calls to these functions. For example
      * -F2:
@@ -269,6 +270,7 @@
     bool   vbv2Pass(uint64_t allAvailableBits, int frameCount, int
startPos);
     bool   findUnderflow(double *fills, int *t0, int *t1, int over, int
framesCount);
     bool   fixUnderflow(int t0, int t1, double adjustment, double
qscaleMin, double qscaleMax);
+    double tuneQScaleForGrain(double rcOverflow);
 };
 }
 #endif // ifndef X265_RATECONTROL_H


On Wed, Jan 20, 2016 at 2:33 PM, <aarthi at multicorewareinc.com> wrote:

> # HG changeset patch
> # User Aarthi Thirumalai
> # Date 1452501832 -19800
> #      Mon Jan 11 14:13:52 2016 +0530
> # Node ID 46e5a95c852732058200d9a7bb34261011341cff
> # Parent  808ece071d225f300feaf08709a9f5e0872edc89
> rc: fix Rate Control for grainy content
>
> optimize params for tune grain, reduce frequent qp fluctions to prevent
> grain loss
>
> diff -r 808ece071d22 -r 46e5a95c8527 source/common/param.cpp
> --- a/source/common/param.cpp   Mon Jan 18 21:21:25 2016 +0530
> +++ b/source/common/param.cpp   Mon Jan 11 14:13:52 2016 +0530
> @@ -454,16 +454,11 @@
>          }
>          else if (!strcmp(tune, "grain"))
>          {
> -            param->deblockingFilterBetaOffset = -2;
> -            param->deblockingFilterTCOffset = -2;
> -            param->bIntraInBFrames = 0;
> -            param->rdoqLevel = 2;
> -            param->psyRdoq = 10.0;
> -            param->psyRd = 0.5;
>              param->rc.ipFactor = 1.1;
> -            param->rc.pbFactor = 1.1;
> -            param->rc.aqStrength = 0.3;
> -            param->rc.qCompress = 0.8;
> +            param->rc.pbFactor = 1.0;
> +            param->rc.cuTree = 0;
> +            param->rc.aqMode = 0;
> +            param->rc.qpStep = 1.0;
>          }
>          else
>              return -1;
> diff -r 808ece071d22 -r 46e5a95c8527 source/encoder/ratecontrol.cpp
> --- a/source/encoder/ratecontrol.cpp    Mon Jan 18 21:21:25 2016 +0530
> +++ b/source/encoder/ratecontrol.cpp    Mon Jan 11 14:13:52 2016 +0530
> @@ -190,6 +190,8 @@
>      m_numEntries = 0;
>      m_isSceneTransition = false;
>      m_lastPredictorReset = 0;
> +    m_avgPFrameQp = 0;
> +    m_isFirstMiniGop = false;
>      if (m_param->rc.rateControlMode == X265_RC_CRF)
>      {
>          m_param->rc.qp = (int)m_param->rc.rfConstant;
> @@ -288,6 +290,9 @@
>      m_ipOffset = 6.0 * X265_LOG2(m_param->rc.ipFactor);
>      m_pbOffset = 6.0 * X265_LOG2(m_param->rc.pbFactor);
>
> +    for (int i = 0; i < QP_MAX_MAX; i++)
> +        m_qpToEncodedBits[i] = 0;
> +
>      /* Adjust the first frame in order to stabilize the quality level
> compared to the rest */
>  #define ABR_INIT_QP_MIN (24)
>  #define ABR_INIT_QP_MAX (40)
> @@ -361,6 +366,7 @@
>          m_amortizeFraction = 0.85;
>          m_amortizeFrames = m_param->totalFrames / 2;
>      }
> +
>      for (int i = 0; i < s_slidingWindowFrames; i++)
>      {
>          m_satdCostWindow[i] = 0;
> @@ -370,15 +376,19 @@
>      m_isPatternPresent = false;
>      m_numBframesInPattern = 0;
>
> +        m_isGrainEnabled = false;
> +        if(m_param->rc.pbFactor <= 1.1 && !m_param->rc.cuTree) // tune
> for grainy content OR equal p-b frame sizes
> +        m_isGrainEnabled = true;
> +
>      /* 720p videos seem to be a good cutoff for cplxrSum */
> -    double tuneCplxFactor = (m_param->rc.cuTree && m_ncu > 3600) ? 2.5 :
> 1;
> -
> +    double tuneCplxFactor = (m_ncu > 3600 && m_param->rc.cuTree) ? 2.5 :
> m_isGrainEnabled ? 2 : 1;
>      /* estimated ratio that produces a reasonable QP for the first
> I-frame */
>      m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) *
> tuneCplxFactor;
>      m_wantedBitsWindow = m_bitrate * m_frameDuration;
>      m_accumPNorm = .01;
>      m_accumPQp = (m_param->rc.rateControlMode == X265_RC_CRF ?
> CRF_INIT_QP : ABR_INIT_QP_MIN) * m_accumPNorm;
>
> +
>      /* Frame Predictors used in vbv */
>      initFramePredictors();
>      if (!m_statFileOut && (m_param->rc.bStatWrite ||
> m_param->rc.bStatRead))
> @@ -1049,7 +1059,7 @@
>      }
>      m_pred[0].coeff = m_pred[3].coeff = 0.75;
>      m_pred[0].coeffMin = m_pred[3].coeffMin = 0.75 / 4;
> -    if (m_param->rc.qCompress >= 0.8) // when tuned for grain
> +    if (m_isGrainEnabled) // when tuned for grain
>      {
>          m_pred[1].coeffMin = 0.75 / 4;
>          m_pred[1].coeff = 0.75;
> @@ -1089,10 +1099,12 @@
>      }
>      rce->isActive = true;
>      bool isRefFrameScenecut = m_sliceType!= I_SLICE &&
> m_curSlice->m_refFrameList[0][0]->m_lowres.bScenecut;
> +    m_isFirstMiniGop = m_sliceType == I_SLICE ? true : m_isFirstMiniGop;
>      if (curFrame->m_lowres.bScenecut)
>      {
>          m_isSceneTransition = true;
>          m_lastPredictorReset = rce->encodeOrder;
> +
>          initFramePredictors();
>      }
>      else if (m_sliceType != B_SLICE && !isRefFrameScenecut)
> @@ -1197,7 +1209,7 @@
>          double q = x265_qScale2qp(rateEstimateQscale(curFrame, rce));
>          q = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, q);
>          m_qp = int(q + 0.5);
> -        rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = q;
> +        rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = int(q
> + 0.5);
>          /* copy value of lastRceq into thread local rce struct *to be
> used in RateControlEnd() */
>          rce->qRceq = m_lastRceq;
>          accumPQpUpdate();
> @@ -1450,7 +1462,7 @@
>          }
>
>          if (wantedBits > 0 && encodedBits > 0 &&
> (!m_partialResidualFrames ||
> -            m_param->rc.bStrictCbr))
> +            m_param->rc.bStrictCbr || m_isGrainEnabled))
>          {
>              abrBuffer *= X265_MAX(1, sqrt(timeDone));
>              overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits -
> wantedBits) / abrBuffer);
> @@ -1460,6 +1472,22 @@
>      return qScale;
>  }
>
> +double RateControl::tuneQScaleForGrain(double rcOverflow)
> +{
> +    double qpstepBy1 = pow(2, 0.5 / 6.0);
> +    double qScaleAvg = x265_qp2qScale(m_avgPFrameQp);
> +    double  q = m_lastQScaleFor[P_SLICE];
> +    int curQp = int (x265_qScale2qp(m_lastQScaleFor[P_SLICE]) + 0.5);
> +    double curBitrate = m_qpToEncodedBits[curQp] * int(m_fps + 0.5);
> +    int newQp = rcOverflow > 1 ? curQp + 1 : curQp - 1 ;
> +    double projectedBitrate =  int(m_fps + 0.5) *
> m_qpToEncodedBits[newQp];
> +    if (curBitrate > 0 && projectedBitrate > 0)
> +        q =  abs(projectedBitrate - m_bitrate) < abs (curBitrate -
> m_bitrate) ? x265_qp2qScale(newQp) : m_lastQScaleFor[P_SLICE];
> +    else
> +        q = rcOverflow > 1 ? qScaleAvg * qpstepBy1 : rcOverflow < 1 ?
> qScaleAvg / qpstepBy1 : m_lastQScaleFor[P_SLICE];
> +    return q;
> +}
> +
>  double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry
> *rce)
>  {
>      double q;
> @@ -1525,6 +1553,7 @@
>                  q0 = q1;
>              }
>          }
> +
>          if (prevRefSlice->m_sliceType == B_SLICE &&
> IS_REFERENCED(m_curSlice->m_refFrameList[0][0]))
>              q0 -= m_pbOffset / 2;
>          if (nextRefSlice->m_sliceType == B_SLICE &&
> IS_REFERENCED(m_curSlice->m_refFrameList[1][0]))
> @@ -1535,7 +1564,9 @@
>              q = q1;
>          else if (i1)
>              q = q0;
> -        else
> +        else if(m_isGrainEnabled)
> +                q = q1;
> +            else
>              q = (q0 * dt1 + q1 * dt0) / (dt0 + dt1);
>
>          if (IS_REFERENCED(curFrame))
> @@ -1543,7 +1574,7 @@
>          else
>              q += m_pbOffset;
>
> -        /* Set a min qp at scenechanges and transitions */
> +                /* Set a min qp at scenechanges and transitions */
>          if (m_isSceneTransition)
>          {
>              q = X265_MAX(ABR_SCENECUT_INIT_QP_MIN, q);
> @@ -1553,11 +1584,28 @@
>          double qScale = x265_qp2qScale(q);
>          rce->qpNoVbv = q;
>          double lmin = 0, lmax = 0;
> +        if (m_isGrainEnabled && m_isFirstMiniGop)
> +        {
> +            lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
> +            lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
> +            double tunedQscale = tuneAbrQScaleFromFeedback(qScale);
> +            double overflow = tunedQscale / qScale;
> +            if (!m_isAbrReset)
> +                qScale = x265_clip3(lmin, lmax, qScale);
> +            m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv :
> m_avgPFrameQp;
> +            if (overflow != 1)
> +            {
> +                qScale = tuneQScaleForGrain(overflow);
> +                q = x265_qScale2qp(qScale);
> +            }
> +            rce->qpNoVbv = q;
> +        }
>          if (m_isVbv)
>          {
>              lmin = m_lastQScaleFor[P_SLICE] / m_lstep;
>              lmax = m_lastQScaleFor[P_SLICE] * m_lstep;
> -            if (m_isCbr)
> +
> +            if (m_isCbr && !m_isGrainEnabled)
>              {
>                  qScale = tuneAbrQScaleFromFeedback(qScale);
>                  if (!m_isAbrReset)
> @@ -1581,7 +1629,10 @@
>              rce->frameSizePlanned = X265_MIN(rce->frameSizePlanned,
> rce->frameSizeMaximum);
>              rce->frameSizeEstimated = rce->frameSizePlanned;
>          }
> +
>          rce->newQScale = qScale;
> +        if(rce->bLastMiniGopBFrame)
> +            m_isFirstMiniGop = false;
>          return qScale;
>      }
>      else
> @@ -1675,8 +1726,17 @@
>                  if (!m_param->rc.bStatRead)
>                      checkAndResetABR(rce, false);
>                  double initialQScale = getQScale(rce, m_wantedBitsWindow
> / m_cplxrSum);
> -                q = tuneAbrQScaleFromFeedback(initialQScale);
> -                overflow = q / initialQScale;
> +                double tunedQScale =
> tuneAbrQScaleFromFeedback(initialQScale);
> +                overflow = tunedQScale / initialQScale;
> +                q = !m_partialResidualFrames? tunedQScale : initialQScale;
> +                bool isEncodeEnd = (m_param->totalFrames &&
> +                    m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;
> +                bool isEncodeBeg = m_framesDone < (int)(m_fps + 0.5);
> +                if(m_isGrainEnabled && m_sliceType!= I_SLICE &&
> !isEncodeEnd &&
> +                    ((overflow < 1.05 && overflow > 0.95) || isEncodeBeg))
> +                {
> +                    q = tuneQScaleForGrain(overflow);
> +                }
>              }
>              if (m_sliceType == I_SLICE && m_param->keyframeMax > 1
>                  && m_lastNonBPictType != I_SLICE && !m_isAbrReset)
> @@ -1684,6 +1744,7 @@
>                  if (!m_param->rc.bStrictCbr)
>                      q = x265_qp2qScale(m_accumPQp / m_accumPNorm);
>                  q /= fabs(m_param->rc.ipFactor);
> +                m_avgPFrameQp = 0;
>              }
>              else if (m_framesDone > 0)
>              {
> @@ -1720,6 +1781,11 @@
>                 m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale,
> m_lastQScaleFor[P_SLICE]);
>              }
>              rce->qpNoVbv = x265_qScale2qp(q);
> +            if(m_sliceType == P_SLICE)
> +            {
> +                m_avgPFrameQp = m_avgPFrameQp == 0 ? rce->qpNoVbv :
> m_avgPFrameQp;
> +                m_avgPFrameQp = (m_avgPFrameQp + rce->qpNoVbv) / 2;
> +            }
>              q = clipQscale(curFrame, rce, q);
>              /*  clip qp to permissible range after vbv-lookahead
> estimation to avoid possible
>               * mispredictions by initial frame size predictors, after
> each scenecut */
> @@ -2426,6 +2492,11 @@
>          int pos = m_sliderPos - m_param->frameNumThreads;
>          if (pos >= 0)
>              m_encodedBitsWindow[pos % s_slidingWindowFrames] = actualBits;
> +        if(rce->sliceType != I_SLICE)
> +        {
> +        int qp = int (rce->qpaRc + 0.5);
> +        m_qpToEncodedBits[qp] =  m_qpToEncodedBits[qp] == 0 ? actualBits
> : (m_qpToEncodedBits[qp] + actualBits) * 0.5;
> +        }
>      }
>
>      if (m_2pass)
> diff -r 808ece071d22 -r 46e5a95c8527 source/encoder/ratecontrol.h
> --- a/source/encoder/ratecontrol.h      Mon Jan 18 21:21:25 2016 +0530
> +++ b/source/encoder/ratecontrol.h      Mon Jan 11 14:13:52 2016 +0530
> @@ -126,7 +126,7 @@
>      bool   m_isVbv;
>      bool   m_isCbr;
>      bool   m_singleFrameVbv;
> -
> +    bool   m_isGrainEnabled;
>      bool   m_isAbrReset;
>      int    m_lastAbrResetPoc;
>
> @@ -141,7 +141,8 @@
>      double m_vbvMaxRate;       /* in kbps */
>      double m_rateFactorMaxIncrement; /* Don't allow RF above (CRF + this
> value). */
>      double m_rateFactorMaxDecrement; /* don't allow RF below (this
> value). */
> -
> +    double m_avgPFrameQp;
> +    bool   m_isFirstMiniGop;
>      Predictor m_pred[4];       /* Slice predictors to preidct bits for
> each Slice type - I,P,Bref and B */
>      int64_t m_leadingNoBSatd;
>      int     m_predType;       /* Type of slice predictors to be used -
> depends on the slice type */
> @@ -178,7 +179,7 @@
>      bool    m_isPatternPresent;
>      bool    m_isSceneTransition;
>      int     m_lastPredictorReset;
> -
> +    double m_qpToEncodedBits[QP_MAX_MAX];
>      /* a common variable on which rateControlStart, rateControlEnd and
> rateControUpdateStats waits to
>       * sync the calls to these functions. For example
>       * -F2:
> @@ -269,6 +270,7 @@
>      bool   vbv2Pass(uint64_t allAvailableBits, int frameCount, int
> startPos);
>      bool   findUnderflow(double *fills, int *t0, int *t1, int over, int
> framesCount);
>      bool   fixUnderflow(int t0, int t1, double adjustment, double
> qscaleMin, double qscaleMax);
> +    double tuneQScaleForGrain(double rcOverflow);
>  };
>  }
>  #endif // ifndef X265_RATECONTROL_H
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20160127/4ce89453/attachment-0001.html>


More information about the x265-devel mailing list