[x265] [PATCH] abr: reset ABR to prevent high bitrate peaks in single pass ABR
Aarthi Priya Thirumalai
aarthi at multicorewareinc.com
Sun Feb 2 13:37:32 CET 2014
# HG changeset patch
# User Aarthi Thirumalai
# Date 1391343895 -19800
# Sun Feb 02 17:54:55 2014 +0530
# Node ID bf00f495951eb882e34225740c43540311bf51cb
# Parent bb33ab0f4ef933315cedf388d70443bc97fefeea
abr: reset ABR to prevent high bitrate peaks in single pass ABR .
Long series of blank frames in video followed by detailed content causes
heavy ABR underflow and overall bitrates surges high for a long while.
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.
diff -r bb33ab0f4ef9 -r bf00f495951e source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Sat Feb 01 16:39:12 2014 -0600
+++ b/source/encoder/ratecontrol.cpp Sun Feb 02 17:54:55 2014 +0530
@@ -240,7 +240,7 @@
shortTermCplxCount = 0;
framesDone = 0;
lastNonBPictType = I_SLICE;
-
+ isAbrReset = false;
// vbv initialization
cfg->param.rc.vbvBufferSize = Clip3(0, 2000000,
cfg->param.rc.vbvBufferSize);
cfg->param.rc.vbvMaxBitrate = Clip3(0, 2000000,
cfg->param.rc.vbvMaxBitrate);
@@ -375,12 +375,12 @@
if (isAbr) //ABR,CRF
{
lastSatd = l->getEstimatedPictureCost(pic);
+ rce->lastSatd = lastSatd;
double q = qScale2qp(rateEstimateQscale(rce));
qp = Clip3(MIN_QP, MAX_MAX_QP, (int)(q + 0.5));
rce->qpaRc = q;
/* copy value of lastRceq into thread local rce struct *to be used
in RateControlEnd() */
rce->qRceq = lastRceq;
- rce->lastSatd = lastSatd;
accumPQpUpdate();
}
else //CQP
@@ -464,6 +464,7 @@
* tolerances, the bit distribution approaches that of 2pass. */
double wantedBits, overflow = 1;
+ rce->movingAvgSum = shortTermCplxSum;
shortTermCplxSum *= 0.5;
shortTermCplxCount *= 0.5;
shortTermCplxSum += lastSatd / (CLIP_DURATION(frameDuration) /
BASE_FRAME_DURATION);
@@ -479,6 +480,8 @@
}
else
{
+ if (!isVbv)
+ checkAndResetABR(rce);
q = getQScale(rce, wantedBitsWindow / cplxrSum);
/* ABR code can potentially be counterproductive in CBR, so
just don't bother.
@@ -498,7 +501,7 @@
}
if (sliceType == I_SLICE && cfg->param.keyframeMax > 1
- && lastNonBPictType != I_SLICE)
+ && lastNonBPictType != I_SLICE && !isAbrReset)
{
q = qp2qScale(accumPQp / accumPNorm);
q /= fabs(cfg->param.rc.ipFactor);
@@ -539,7 +542,7 @@
lastQScaleFor[sliceType] = q;
- if (curSlice->getPOC() == 0)
+ if (curSlice->getPOC() == 0 || (isAbrReset && sliceType ==
I_SLICE))
lastQScaleFor[P_SLICE] = q * fabs(cfg->param.rc.ipFactor);
rce->frameSizePlanned = predictSize(&pred[sliceType], q,
(double)lastSatd);
@@ -548,6 +551,35 @@
}
}
+void RateControl::checkAndResetABR( RateControlEntry* rce )
+{
+ double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;
+ // Check if current SLice is a scene cut that follow low
detailed/blank frames
+ if (rce->lastSatd > 4 * rce->movingAvgSum)
+ {
+ if (!isAbrReset && rce->movingAvgSum > 0 )
+ {
+ // Reset ABR if prev frames are blank to prevent further
sudden overflows/ high bit rate spikes.
+ double underflow = 1.0 + (totalBits - wantedBitsWindow) /
abrBuffer;
+ if (underflow < 1 && curSlice->m_avgQpRc==0)
+ {
+ totalBits = 0;
+ framesDone = 0;
+ cplxrSum = .01 * pow(7.0e5, qCompress) * pow(ncu, 0.5);
+ wantedBitsWindow = bitrate * frameDuration;
+ accumPNorm = .01;
+ accumPQp = (ABR_INIT_QP_MIN)*accumPNorm;
+ isAbrReset = true;
+ }
+ }
+ // Clear flag to reset ABR and continue as usual.
+ else
+ {
+ isAbrReset = false;
+ }
+ }
+}
+
void RateControl::updateVbvPlan(Encoder* enc)
{
bufferFill = bufferFillFinal;
@@ -706,19 +738,25 @@
{
if (isAbr)
{
- if (rce->sliceType != B_SLICE)
- /* The factor 1.5 is to tune up the actual bits, otherwise the
cplxrSum is scaled too low
- * to improve short term compensation for next frame. */
- cplxrSum += bits * qp2qScale(rce->qpaRc) / rce->qRceq;
- else
+ if (!isVbv)
+ checkAndResetABR(rce);
+
+ if(!isAbrReset)
{
- /* Depends on the fact that B-frame's QP is an offset from the
following P-frame's.
- * Not perfectly accurate with B-refs, but good enough. */
- cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->qRceq *
fabs(cfg->param.rc.pbFactor));
+ if (rce->sliceType != B_SLICE)
+ /* The factor 1.5 is to tune up the actual bits, otherwise
the cplxrSum is scaled too low
+ * to improve short term compensation for next frame. */
+ cplxrSum += bits * qp2qScale(rce->qpaRc) / rce->qRceq;
+ else
+ {
+ /* Depends on the fact that B-frame's QP is an offset from
the following P-frame's.
+ * Not perfectly accurate with B-refs, but good enough. */
+ cplxrSum += bits * qp2qScale(rce->qpaRc) / (rce->qRceq *
fabs(cfg->param.rc.pbFactor));
+ }
+ wantedBitsWindow += frameDuration * bitrate;
+ totalBits += bits;
}
- wantedBitsWindow += frameDuration * bitrate;
}
- totalBits += bits;
if (isVbv)
{
@@ -732,8 +770,9 @@
bframeBits = 0;
}
}
+ updateVbv(bits, rce);
}
- updateVbv(bits, rce);
+
return 0;
}
diff -r bb33ab0f4ef9 -r bf00f495951e source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Sat Feb 01 16:39:12 2014 -0600
+++ b/source/encoder/ratecontrol.h Sun Feb 02 17:54:55 2014 +0530
@@ -60,6 +60,7 @@
double qRceq;
double frameSizePlanned;
double bufferRate;
+ double movingAvgSum;
};
struct Predictor
@@ -97,7 +98,7 @@
int bframes;
int bframeBits;
double leadingNoBSatd;
-
+ bool isAbrReset;
int64_t lastSatd;
int qpConstant[3];
double cplxrSum; /* sum of bits*qscale/rceq */
@@ -136,6 +137,7 @@
double clipQscale(double q);
void updateVbvPlan(Encoder* enc);
double predictSize(Predictor *p, double q, double var);
+ void checkAndResetABR( RateControlEntry* rce );
};
}
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20140202/0cbce182/attachment.html>
More information about the x265-devel
mailing list