<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>