<div dir="ltr"><br><div class="gmail_extra"><br><br><div class="gmail_quote">On Sun, Feb 2, 2014 at 6:37 AM, Aarthi Priya Thirumalai <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"><div dir="ltr"><div># HG changeset patch</div><div># User Aarthi Thirumalai</div><div># Date 1391343895 -19800</div><div>
# Sun Feb 02 17:54:55 2014 +0530</div><div># Node ID bf00f495951eb882e34225740c43540311bf51cb</div>
<div># Parent bb33ab0f4ef933315cedf388d70443bc97fefeea</div><div>abr: reset ABR to prevent high bitrate peaks in single pass ABR .</div><div><br></div><div>Long series of blank frames in video followed by detailed content causes heavy ABR underflow and overall bitrates surges high for a long while.</div>
<div>patch detects this condition in Single pass ABR mode and resets ABR - to not consider history from blank frames and continue from following scene-cut.</div></div></blockquote><div><br></div><div>The patch behavior seems reasonable, given what was documented in another email, however lots of coding style nits.</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><br></div><div>diff -r bb33ab0f4ef9 -r bf00f495951e source/encoder/ratecontrol.cpp</div>
<div>--- a/source/encoder/ratecontrol.cpp<span style="white-space:pre-wrap"> </span>Sat Feb 01 16:39:12 2014 -0600</div><div>+++ b/source/encoder/ratecontrol.cpp<span style="white-space:pre-wrap"> </span>Sun Feb 02 17:54:55 2014 +0530</div>
<div>@@ -240,7 +240,7 @@</div><div> shortTermCplxCount = 0;</div><div> framesDone = 0;</div><div> lastNonBPictType = I_SLICE;</div><div>-</div><div>+ isAbrReset = false;</div><div> // vbv initialization</div>
<div> cfg->param.rc.vbvBufferSize = Clip3(0, 2000000, cfg->param.rc.vbvBufferSize);</div><div> cfg->param.rc.vbvMaxBitrate = Clip3(0, 2000000, cfg->param.rc.vbvMaxBitrate);</div><div>@@ -375,12 +375,12 @@</div>
<div> if (isAbr) //ABR,CRF</div><div> {</div><div> lastSatd = l->getEstimatedPictureCost(pic);</div><div>+ rce->lastSatd = lastSatd;</div><div> double q = qScale2qp(rateEstimateQscale(rce));</div>
<div> qp = Clip3(MIN_QP, MAX_MAX_QP, (int)(q + 0.5));</div><div> rce->qpaRc = q;</div><div> /* copy value of lastRceq into thread local rce struct *to be used in RateControlEnd() */</div><div> rce->qRceq = lastRceq;</div>
<div>- rce->lastSatd = lastSatd;</div><div> accumPQpUpdate();</div><div> }</div><div> else //CQP</div><div>@@ -464,6 +464,7 @@</div><div> * tolerances, the bit distribution approaches that of 2pass. */</div>
<div> </div><div> double wantedBits, overflow = 1;</div><div>+ rce->movingAvgSum = shortTermCplxSum;</div><div> shortTermCplxSum *= 0.5;</div><div> shortTermCplxCount *= 0.5;</div><div> shortTermCplxSum += lastSatd / (CLIP_DURATION(frameDuration) / BASE_FRAME_DURATION);</div>
<div>@@ -479,6 +480,8 @@</div><div> }</div><div> else</div><div> {</div><div>+ if (!isVbv)</div><div>+ checkAndResetABR(rce);</div><div> q = getQScale(rce, wantedBitsWindow / cplxrSum);</div>
<div> </div><div> /* ABR code can potentially be counterproductive in CBR, so just don't bother.</div><div>@@ -498,7 +501,7 @@</div><div> }</div><div> </div><div> if (sliceType == I_SLICE && cfg->param.keyframeMax > 1</div>
<div>- && lastNonBPictType != I_SLICE)</div><div>+ && lastNonBPictType != I_SLICE && !isAbrReset) </div><div> {</div><div> q = qp2qScale(accumPQp / accumPNorm);</div>
<div> q /= fabs(cfg->param.rc.ipFactor);</div><div>@@ -539,7 +542,7 @@</div><div> </div><div> lastQScaleFor[sliceType] = q;</div><div> </div><div>- if (curSlice->getPOC() == 0)</div><div>
+ if (curSlice->getPOC() == 0 || (isAbrReset && sliceType == I_SLICE))</div>
<div> lastQScaleFor[P_SLICE] = q * fabs(cfg->param.rc.ipFactor);</div><div> </div><div> rce->frameSizePlanned = predictSize(&pred[sliceType], q, (double)lastSatd);</div><div>@@ -548,6 +551,35 @@</div>
<div> }</div><div> }</div><div> </div><div>+void RateControl::checkAndResetABR( RateControlEntry* rce )</div></div></blockquote><div><br></div><div>white-space</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div>+{</div><div>+ double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;</div><div>+ // Check if current SLice is a scene cut that follow low detailed/blank frames</div></div></blockquote>
<div><br></div><div>'slice' can be all lower case, `follow` should be follows</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">
<div>+ if (rce->lastSatd > 4 * rce->movingAvgSum)</div><div>+ {</div><div>+ if (!isAbrReset && rce->movingAvgSum > 0 )</div></div></blockquote><div><br></div><div>ws</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div>+ {</div><div>+ // Reset ABR if prev frames are blank to prevent further sudden overflows/ high bit rate spikes.</div>
<div>+ double underflow = 1.0 + (totalBits - wantedBitsWindow) / abrBuffer;</div><div>+ if (underflow < 1 && curSlice->m_avgQpRc==0)</div></div></blockquote><div><br></div><div>ws</div>
<div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div>+ {</div><div>+ totalBits = 0;</div>
<div>+ framesDone = 0; </div><div>+ cplxrSum = .01 * pow(7.0e5, qCompress) * pow(ncu, 0.5);</div><div>+ wantedBitsWindow = bitrate * frameDuration;</div><div>+ accumPNorm = .01;</div>
<div>+ accumPQp = (ABR_INIT_QP_MIN)*accumPNorm;</div><div>+ isAbrReset = true;</div><div>+ }</div><div>+ }</div><div>+ // Clear flag to reset ABR and continue as usual.</div>
</div></blockquote><div><br></div><div>we generally place else comments within the else braces</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">
<div>+ else</div><div>+ {</div><div>+ isAbrReset = false;</div><div>+ }</div><div>+ }</div><div>+}</div><div>+</div><div> void RateControl::updateVbvPlan(Encoder* enc)</div><div> {</div><div>
bufferFill = bufferFillFinal;</div><div>@@ -706,19 +738,25 @@</div><div> {</div><div> if (isAbr)</div><div> {</div><div>- if (rce->sliceType != B_SLICE)</div><div>- /* The factor 1.5 is to tune up the actual bits, otherwise the cplxrSum is scaled too low</div>
<div>- * to improve short term compensation for next frame. */</div><div>- cplxrSum += bits * qp2qScale(rce->qpaRc) / rce->qRceq;</div><div>- else</div><div>+ if (!isVbv)</div><div>
+ checkAndResetABR(rce);</div><div>+</div><div>+ if(!isAbrReset)</div></div></blockquote><div><br></div><div>ws</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<div dir="ltr"><div> {</div><div>- /* Depends on the fact that B-frame's QP is an offset from the following P-frame's.</div>
<div>- * Not perfectly accurate with B-refs, but good enough. */</div><div>- cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->qRceq * fabs(cfg->param.rc.pbFactor));</div><div>+ if (rce->sliceType != B_SLICE)</div>
<div>+ /* The factor 1.5 is to tune up the actual bits, otherwise the cplxrSum is scaled too low</div><div>+ * to improve short term compensation for next frame. */</div><div>+ cplxrSum += bits * qp2qScale(rce->qpaRc) / rce->qRceq;</div>
<div>+ else</div><div>+ {</div><div>+ /* Depends on the fact that B-frame's QP is an offset from the following P-frame's.</div><div>+ * Not perfectly accurate with B-refs, but good enough. */</div>
<div>+ cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->qRceq * fabs(cfg->param.rc.pbFactor));</div><div>+ }</div><div>+ wantedBitsWindow += frameDuration * bitrate;</div><div>
+ totalBits += bits;</div><div> }</div><div>- wantedBitsWindow += frameDuration * bitrate;</div><div> }</div><div>- totalBits += bits;</div><div> </div><div> if (isVbv)</div><div> {</div>
<div>@@ -732,8 +770,9 @@</div><div> bframeBits = 0;</div><div> }</div><div> }</div><div>+ updateVbv(bits, rce);</div><div> }</div><div> </div><div>- updateVbv(bits, rce);</div>
<div>+</div><div> return 0;</div><div> }</div><div>diff -r bb33ab0f4ef9 -r bf00f495951e source/encoder/ratecontrol.h</div><div>--- a/source/encoder/ratecontrol.h<span style="white-space:pre-wrap"> </span>Sat Feb 01 16:39:12 2014 -0600</div>
<div>+++ b/source/encoder/ratecontrol.h<span style="white-space:pre-wrap"> </span>Sun Feb 02 17:54:55 2014 +0530</div><div>@@ -60,6 +60,7 @@</div><div> double qRceq;</div><div> double frameSizePlanned;</div><div>
double bufferRate;</div><div>+ double movingAvgSum;</div><div> };</div><div> </div><div> struct Predictor</div><div>@@ -97,7 +98,7 @@</div><div> int bframes;</div><div> int bframeBits;</div><div> double leadingNoBSatd;</div>
<div>-</div><div>+ bool isAbrReset;</div><div> int64_t lastSatd;</div><div> int qpConstant[3];</div><div> double cplxrSum; /* sum of bits*qscale/rceq */</div><div>@@ -136,6 +137,7 @@</div><div>
double clipQscale(double q);</div>
<div> void updateVbvPlan(Encoder* enc);</div><div> double predictSize(Predictor *p, double q, double var);</div><div>+ void checkAndResetABR( RateControlEntry* rce );</div></div></blockquote><div><br></div><div>
ws</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div> };</div><div> }</div><div> </div>
<div><br></div></div>
<br>_______________________________________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" target="_blank">https://mailman.videolan.org/listinfo/x265-devel</a><br>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br>Steve Borho
</div></div>