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