<div dir="ltr">ignore the previous patch - contains a build error. Sending the corrected version here:<div><br></div><div><div># HG changeset patch</div><div># User Aarthi Thirumalai</div><div># Date 1439287054 -19800</div><div>#      Tue Aug 11 15:27:34 2015 +0530</div><div># Node ID 4f5109967676d983d8ccc4f5f410f96f5f30a5cb</div><div># Parent  cea0ce5bf57d5decc14743aa69234a1dfe84996b</div><div>rc: adjust qp for scene transitions and fade ins to avoid quality loss with vbv</div><div><br></div><div>diff -r cea0ce5bf57d -r 4f5109967676 source/encoder/ratecontrol.cpp</div><div>--- a/source/encoder/ratecontrol.cpp<span class="Apple-tab-span" style="white-space:pre">    </span>Wed Jul 22 00:29:26 2015 +0530</div><div>+++ b/source/encoder/ratecontrol.cpp<span class="Apple-tab-span" style="white-space:pre">   </span>Tue Aug 11 15:27:34 2015 +0530</div><div>@@ -181,6 +181,7 @@</div><div>     m_bTerminated = false;</div><div>     m_finalFrameCount = 0;</div><div>     m_numEntries = 0;</div><div>+    m_isSceneTransition = 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>@@ -273,7 +274,6 @@</div><div>     if(m_param->rc.bStrictCbr)</div><div>         m_rateTolerance = 0.7;</div><div> </div><div>-    m_leadingBframes = m_param->bframes;</div><div>     m_bframeBits = 0;</div><div>     m_leadingNoBSatd = 0;</div><div>     m_ipOffset = 6.0 * X265_LOG2(m_param->rc.ipFactor);</div><div>@@ -282,6 +282,7 @@</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_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>         m_lastQScaleFor[i] = x265_qp2qScale(m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN);</div><div>@@ -960,10 +961,22 @@</div><div>         copyRceData(rce, &m_rce2Pass[rce->poc]);</div><div>     }</div><div>     rce->isActive = true;</div><div>-    if (m_sliceType == B_SLICE)</div><div>-        rce->bframes = m_leadingBframes;</div><div>-    else</div><div>-        m_leadingBframes = curFrame->m_lowres.leadingBframes;</div><div>+    bool isframeAfterKeyframe = m_sliceType != I_SLICE && m_curSlice->m_refFrameList[0][0]->m_encData->m_slice->m_sliceType == I_SLICE;</div><div>+    if (curFrame->m_lowres.bScenecut)</div><div>+    {</div><div>+        m_isSceneTransition = true;</div><div>+        /* Frame Predictors and Row predictors used in vbv */</div><div>+        for (int i = 0; i < 4; i++)</div><div>+        {</div><div>+            m_pred[i].coeff = 1.0;</div><div>+            m_pred[i].count = 1.0;</div><div>+            m_pred[i].decay = 0.5;</div><div>+            m_pred[i].offset = 0.0;</div><div>+        }</div><div>+        m_pred[0].coeff = m_pred[3].coeff = 0.75;</div><div>+    }</div><div>+    else if (m_sliceType != B_SLICE && !isframeAfterKeyframe)</div><div>+        m_isSceneTransition = false;</div><div> </div><div>     rce->bLastMiniGopBFrame = curFrame->m_lowres.bLastMiniGopBFrame;</div><div>     rce->bufferRate = m_bufferRate;</div><div>@@ -1040,6 +1053,10 @@</div><div>                 }</div><div>             }</div><div>         }</div><div>+        /* For a scenecut that occurs within the mini-gop, enable scene transition</div><div>+         * switch until the next mini-gop to ensure a min qp for all the frames within </div><div>+         * the scene-transition mini-gop */</div><div>+</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>@@ -1382,6 +1399,13 @@</div><div>         else</div><div>             q += m_pbOffset;</div><div> </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>+            double minScenecutQscale =x265_qp2qScale(ABR_SCENECUT_INIT_QP_MIN); </div><div>+            m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale, m_lastQScaleFor[P_SLICE]);</div><div>+        }</div><div>         double qScale = x265_qp2qScale(q);</div><div>         rce->qpNoVbv = q;</div><div>         double lmin = 0, lmax = 0;</div><div>@@ -1544,6 +1568,13 @@</div><div>                 q = X265_MIN(lqmax, q);</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>+            if (m_isSceneTransition)</div><div>+            {</div><div>+               double minScenecutQscale =x265_qp2qScale(ABR_SCENECUT_INIT_QP_MIN); </div><div>+               q = X265_MAX(minScenecutQscale, q);</div><div>+               m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale, m_lastQScaleFor[P_SLICE]);</div><div>+            }</div><div>             rce->qpNoVbv = x265_qScale2qp(q);</div><div>             q = clipQscale(curFrame, rce, q);</div><div>             /*  clip qp to permissible range after vbv-lookahead estimation to avoid possible</div><div>@@ -1750,7 +1781,7 @@</div><div>                 }</div><div>                 /* Try to get the buffer not more than 80% filled, but don't set an impossible goal. */</div><div>                 targetFill = x265_clip3(m_bufferSize * (1 - 0.2 * finalDur), m_bufferSize, m_bufferFill - totalDuration * m_vbvMaxRate * 0.5);</div><div>-                if (m_isCbr && bufferFillCur > targetFill)</div><div>+                if (m_isCbr && bufferFillCur > targetFill && !m_isSceneTransition)</div><div>                 {</div><div>                     q /= 1.01;</div><div>                     loopTerminate |= 2;</div><div>diff -r cea0ce5bf57d -r 4f5109967676 source/encoder/ratecontrol.h</div><div>--- a/source/encoder/ratecontrol.h<span class="Apple-tab-span" style="white-space:pre">     </span>Wed Jul 22 00:29:26 2015 +0530</div><div>+++ b/source/encoder/ratecontrol.h<span class="Apple-tab-span" style="white-space:pre">     </span>Tue Aug 11 15:27:34 2015 +0530</div><div>@@ -147,7 +147,6 @@</div><div>     double  m_pbOffset;</div><div>     int64_t m_bframeBits;</div><div>     int64_t m_currentSatd;</div><div>-    int     m_leadingBframes;</div><div>     int     m_qpConstant[3];</div><div>     int     m_lastNonBPictType;</div><div>     int     m_framesDone;        /* # of frames passed through RateCotrol already */</div><div>@@ -173,6 +172,7 @@</div><div>     int64_t m_lastBsliceSatdCost;</div><div>     int     m_numBframesInPattern;</div><div>     bool    m_isPatternPresent;</div><div>+    bool    m_isSceneTransition;</div><div> </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><br></div><div><br></div><div><br></div></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Aug 17, 2015 at 11:11 AM,  <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 1439287054 -19800<br>
#      Tue Aug 11 15:27:34 2015 +0530<br>
# Node ID 201a9d44179524d7ef498c9fe0e69ccb83f68bc7<br>
# Parent  51320561d41f32faa75dd3d04d88ea68500ce995<br>
rc: adjust qp for scene transitions and fade ins to avoid quality loss with vbv<br>
<br>
diff -r 51320561d41f -r 201a9d441795 source/encoder/ratecontrol.cpp<br>
--- a/source/encoder/ratecontrol.cpp    Wed Jul 22 00:29:26 2015 +0530<br>
+++ b/source/encoder/ratecontrol.cpp    Tue Aug 11 15:27:34 2015 +0530<br>
@@ -181,6 +181,7 @@<br>
     m_bTerminated = false;<br>
     m_finalFrameCount = 0;<br>
     m_numEntries = 0;<br>
+    m_isSceneTransition = false;<br>
     if (m_param->rc.rateControlMode == X265_RC_CRF)<br>
     {<br>
         m_param->rc.qp = (int)m_param->rc.rfConstant;<br>
@@ -273,7 +274,6 @@<br>
     if(m_param->rc.bStrictCbr)<br>
         m_rateTolerance = 0.7;<br>
<br>
-    m_leadingBframes = m_param->bframes;<br>
     m_bframeBits = 0;<br>
     m_leadingNoBSatd = 0;<br>
     m_ipOffset = 6.0 * X265_LOG2(m_param->rc.ipFactor);<br>
@@ -282,6 +282,7 @@<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>
+#define ABR_SCENECUT_INIT_QP_MIN (12)<br>
 #define CRF_INIT_QP (int)m_param->rc.rfConstant<br>
     for (int i = 0; i < 3; i++)<br>
         m_lastQScaleFor[i] = x265_qp2qScale(m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN);<br>
@@ -960,10 +961,22 @@<br>
         copyRceData(rce, &m_rce2Pass[rce->poc]);<br>
     }<br>
     rce->isActive = true;<br>
-    if (m_sliceType == B_SLICE)<br>
-        rce->bframes = m_leadingBframes;<br>
-    else<br>
-        m_leadingBframes = curFrame->m_lowres.leadingBframes;<br>
+    bool isframeAfterKeyframe = m_sliceType != I_SLICE && m_curSlice->m_refPicList[0][0]->m_encData->m_slice->m_sliceType == I_SLICE;<br>
+    if (curFrame->m_lowres.bScenecut)<br>
+    {<br>
+        m_isSceneTransition = true;<br>
+        /* Frame Predictors and Row predictors used in vbv */<br>
+        for (int i = 0; i < 4; i++)<br>
+        {<br>
+            m_pred[i].coeff = 1.0;<br>
+            m_pred[i].count = 1.0;<br>
+            m_pred[i].decay = 0.5;<br>
+            m_pred[i].offset = 0.0;<br>
+        }<br>
+        m_pred[0].coeff = m_pred[3].coeff = 0.75;<br>
+    }<br>
+    else if (m_sliceType != B_SLICE && !isframeAfterKeyframe)<br>
+        m_isSceneTransition = false;<br>
<br>
     rce->bLastMiniGopBFrame = curFrame->m_lowres.bLastMiniGopBFrame;<br>
     rce->bufferRate = m_bufferRate;<br>
@@ -1040,6 +1053,10 @@<br>
                 }<br>
             }<br>
         }<br>
+        /* For a scenecut that occurs within the mini-gop, enable scene transition<br>
+         * switch until the next mini-gop to ensure a min qp for all the frames within<br>
+         * the scene-transition mini-gop */<br>
+<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>
@@ -1382,6 +1399,13 @@<br>
         else<br>
             q += m_pbOffset;<br>
<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>
+            double minScenecutQscale =x265_qp2qScale(ABR_SCENECUT_INIT_QP_MIN);<br>
+            m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale, m_lastQScaleFor[P_SLICE]);<br>
+        }<br>
         double qScale = x265_qp2qScale(q);<br>
         rce->qpNoVbv = q;<br>
         double lmin = 0, lmax = 0;<br>
@@ -1544,6 +1568,13 @@<br>
                 q = X265_MIN(lqmax, q);<br>
             }<br>
             q = x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);<br>
+            /* Set a min qp at scenechanges and transitions */<br>
+            if (m_isSceneTransition)<br>
+            {<br>
+               double minScenecutQscale =x265_qp2qScale(ABR_SCENECUT_INIT_QP_MIN);<br>
+               q = X265_MAX(minScenecutQscale, q);<br>
+               m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale, m_lastQScaleFor[P_SLICE]);<br>
+            }<br>
             rce->qpNoVbv = x265_qScale2qp(q);<br>
             q = clipQscale(curFrame, rce, q);<br>
             /*  clip qp to permissible range after vbv-lookahead estimation to avoid possible<br>
@@ -1750,7 +1781,7 @@<br>
                 }<br>
                 /* Try to get the buffer not more than 80% filled, but don't set an impossible goal. */<br>
                 targetFill = x265_clip3(m_bufferSize * (1 - 0.2 * finalDur), m_bufferSize, m_bufferFill - totalDuration * m_vbvMaxRate * 0.5);<br>
-                if (m_isCbr && bufferFillCur > targetFill)<br>
+                if (m_isCbr && bufferFillCur > targetFill && !m_isSceneTransition)<br>
                 {<br>
                     q /= 1.01;<br>
                     loopTerminate |= 2;<br>
diff -r 51320561d41f -r 201a9d441795 source/encoder/ratecontrol.h<br>
--- a/source/encoder/ratecontrol.h      Wed Jul 22 00:29:26 2015 +0530<br>
+++ b/source/encoder/ratecontrol.h      Tue Aug 11 15:27:34 2015 +0530<br>
@@ -147,7 +147,6 @@<br>
     double  m_pbOffset;<br>
     int64_t m_bframeBits;<br>
     int64_t m_currentSatd;<br>
-    int     m_leadingBframes;<br>
     int     m_qpConstant[3];<br>
     int     m_lastNonBPictType;<br>
     int     m_framesDone;        /* # of frames passed through RateCotrol already */<br>
@@ -173,6 +172,7 @@<br>
     int64_t m_lastBsliceSatdCost;<br>
     int     m_numBframesInPattern;<br>
     bool    m_isPatternPresent;<br>
+    bool    m_isSceneTransition;<br>
<br>
     /* a common variable on which rateControlStart, rateControlEnd and rateControUpdateStats waits to<br>
      * sync the calls to these functions. For example<br>
</blockquote></div><br></div>