[x265] [PATCH] rc: apply maxAU size restrictions while encoding each frame
aarthi at multicorewareinc.com
aarthi at multicorewareinc.com
Tue Sep 30 10:53:03 CEST 2014
# HG changeset patch
# User Aarthi Thirumalai
# Date 1411987402 -19800
# Mon Sep 29 16:13:22 2014 +0530
# Node ID e87b6941e7f44af27ae797fb68696bacb74b12ac
# Parent 5a6845566d1492d29af29ecc0cf75d644994735c
rc: apply maxAU size restrictions while encoding each frame
diff -r 5a6845566d14 -r e87b6941e7f4 source/common/slice.h
--- a/source/common/slice.h Mon Sep 29 17:37:47 2014 -0500
+++ b/source/common/slice.h Mon Sep 29 16:13:22 2014 +0530
@@ -102,6 +102,8 @@
bool interlacedSourceFlag;
bool nonPackedConstraintFlag;
bool frameOnlyConstraintFlag;
+ uint32_t minCrForLevel;
+ uint32_t maxLumaSrForLevel;
};
struct HRDInfo
diff -r 5a6845566d14 -r e87b6941e7f4 source/encoder/level.cpp
--- a/source/encoder/level.cpp Mon Sep 29 17:37:47 2014 -0500
+++ b/source/encoder/level.cpp Mon Sep 29 16:13:22 2014 +0530
@@ -156,6 +156,9 @@
}
vps.ptl.levelIdc = levels[i].levelEnum;
+ vps.ptl.minCrForLevel = levels[i].minCompressionRatio;
+ vps.ptl.maxLumaSrForLevel = levels[i].maxLumaSamplesPerSecond;
+
if (bitrate > levels[i].maxBitrateMain && bitrate <= levels[i].maxBitrateHigh &&
levels[i].maxBitrateHigh != MAX_UINT)
vps.ptl.tierFlag = Level::HIGH;
diff -r 5a6845566d14 -r e87b6941e7f4 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Mon Sep 29 17:37:47 2014 -0500
+++ b/source/encoder/ratecontrol.cpp Mon Sep 29 16:13:22 2014 +0530
@@ -887,7 +887,7 @@
for (int i = 0; i < m_numEntries; i++)
{
RateControlEntry *rce = &m_rce2Pass[i];
- rce->newQScale = clipQscale(NULL, blurredQscale[i]); // check if needed
+ rce->newQScale = clipQscale(NULL, rce, blurredQscale[i]); // check if needed
X265_CHECK(rce->newQScale >= 0, "new Qscale is negative\n");
expectedBits += qScale2bits(rce, rce->newQScale);
}
@@ -1093,6 +1093,27 @@
m_predictedBits = m_totalBits;
updateVbvPlan(enc);
rce->bufferFill = m_bufferFill;
+
+ int mincr = enc->m_vps.ptl.minCrForLevel;
+ /* Profiles above Main10 don't require maxAU size check, so just set the maximum to a large value. */
+ if (enc->m_vps.ptl.profileIdc > Profile::MAIN10 || enc->m_vps.ptl.levelIdc == Level::NONE)
+ rce->frameSizeMaximum = 1e9;
+ else
+ {
+ /* The spec has a special case for the first frame. */
+ if (rce->encodeOrder == 0)
+ {
+ /* 1.5 * (Max( PicSizeInSamplesY, fR * MaxLumaSr) + MaxLumaSr * (AuCpbRemovalTime[ 0 ] -AuNominalRemovalTime[ 0 ])) ÷ MinCr */
+ double fr = 1. / 300;
+ int picSizeInSamplesY = m_param->sourceWidth * m_param->sourceHeight;
+ rce->frameSizeMaximum = 8 * 1.5 * (X265_MAX(picSizeInSamplesY, fr * enc->m_vps.ptl.maxLumaSrForLevel) + enc->m_vps.ptl.maxLumaSrForLevel * m_frameDuration) / mincr;
+ }
+ else
+ {
+ /* 1.5 * MaxLumaSr * (AuCpbRemovalTime[ n ] - AyCpbRemovalTime[ n - 1 ]) ÷ MinCr */
+ rce->frameSizeMaximum = 8 * 1.5 * enc->m_vps.ptl.maxLumaSrForLevel * m_frameDuration / mincr;
+ }
+ }
}
if (m_isAbr || m_2pass) // ABR,CRF
{
@@ -1370,7 +1391,7 @@
{
if (m_leadingBframes > 5)
{
- qScale = clipQscale(pic, qScale);
+ qScale = clipQscale(pic, rce, qScale);
m_lastQScaleFor[m_sliceType] = qScale;
}
rce->frameSizePlanned = predictSize(&m_predBfromP, qScale, (double)m_leadingNoBSatd);
@@ -1379,6 +1400,9 @@
{
rce->frameSizePlanned = qScale2bits(rce, qScale);
}
+ /* Limit planned size by MinCR */
+ if (m_isVbv)
+ rce->frameSizePlanned = X265_MIN(rce->frameSizePlanned, rce->frameSizeMaximum);
rce->frameSizeEstimated = rce->frameSizePlanned;
rce->newQScale = qScale;
return qScale;
@@ -1527,7 +1551,7 @@
}
q = Clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
rce->qpNoVbv = x265_qScale2qp(q);
- q = clipQscale(pic, q);
+ q = clipQscale(pic, rce, q);
}
m_lastQScaleFor[m_sliceType] = q;
if ((m_curSlice->m_poc == 0 || m_lastQScaleFor[P_SLICE] < q) && !(m_2pass && !m_isVbv))
@@ -1537,11 +1561,14 @@
rce->frameSizePlanned = qScale2bits(rce, q);
else
rce->frameSizePlanned = predictSize(&m_pred[m_sliceType], q, (double)m_currentSatd);
- rce->frameSizeEstimated = rce->frameSizePlanned;
+
/* Always use up the whole VBV in this case. */
if (m_singleFrameVbv)
rce->frameSizePlanned = m_bufferRate;
-
+ /* Limit planned size by MinCR */
+ if (m_isVbv)
+ rce->frameSizePlanned = X265_MIN(rce->frameSizePlanned, rce->frameSizeMaximum);
+ rce->frameSizeEstimated = rce->frameSizePlanned;
rce->newQScale = q;
return q;
}
@@ -1642,12 +1669,12 @@
return (p->coeff * var + p->offset) / (q * p->count);
}
-double RateControl::clipQscale(Frame* pic, double q)
+double RateControl::clipQscale(Frame* pic, RateControlEntry* rce, double q)
{
// B-frames are not directly subject to VBV,
// since they are controlled by referenced P-frames' QPs.
double q0 = q;
- if (m_isVbv && m_currentSatd > 0)
+ if (m_isVbv && m_currentSatd > 0 && pic)
{
if (m_param->lookaheadDepth || m_param->rc.cuTree ||
m_param->scenecutThreshold ||
@@ -1738,6 +1765,12 @@
q = X265_MAX(q0, q);
}
+
+ /* Apply MinCR restrictions */
+ double bits = predictSize(&m_pred[m_sliceType], q, (double)m_currentSatd);
+ if (bits > rce->frameSizeMaximum)
+ q *= bits / rce->frameSizeMaximum;
+
// Check B-frame complexity, and use up any bits that would
// overflow before the next P-frame.
if (m_leadingBframes <= 5 && m_sliceType == P_SLICE && !m_singleFrameVbv)
@@ -1934,9 +1967,10 @@
accFrameBits = predictRowsSizeSum(pic, rce, qpVbv, encodedBitsSoFar);
}
- /* avoid VBV underflow */
+ /* avoid VBV underflow or MinCr violation */
while ((qpVbv < qpAbsoluteMax)
- && (rce->bufferFill - accFrameBits < m_bufferRate * maxFrameError))
+ && ((rce->bufferFill - accFrameBits < m_bufferRate * maxFrameError) ||
+ (rce->frameSizeMaximum - accFrameBits < rce->frameSizeMaximum * maxFrameError)))
{
qpVbv += stepSize;
accFrameBits = predictRowsSizeSum(pic, rce, qpVbv, encodedBitsSoFar);
diff -r 5a6845566d14 -r e87b6941e7f4 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Mon Sep 29 17:37:47 2014 -0500
+++ b/source/encoder/ratecontrol.h Mon Sep 29 16:13:22 2014 +0530
@@ -99,6 +99,7 @@
Predictor rowPreds[3][2];
Predictor* rowPred[2];
double frameSizeEstimated; /* hold frameSize, updated from cu level vbv rc */
+ double frameSizeMaximum; /* max frame Size according to minCR restrictions and level of the video */
bool isActive;
SEIPictureTiming *picTimingSEI;
HRDTiming *hrdTiming;
@@ -246,7 +247,7 @@
void updateVbv(int64_t bits, RateControlEntry* rce);
void updatePredictor(Predictor *p, double q, double var, double bits);
- double clipQscale(Frame* pic, double q);
+ double clipQscale(Frame* pic, RateControlEntry* rce, double q);
void updateVbvPlan(Encoder* enc);
double predictSize(Predictor *p, double q, double var);
void checkAndResetABR(RateControlEntry* rce, bool isFrameDone);
More information about the x265-devel
mailing list