[x265] [PATCH 3 of 4 x265] Add real-time VBV fullness based QP tuning in VBV 2 pass
kirithika at multicorewareinc.com
kirithika at multicorewareinc.com
Wed Apr 22 09:14:16 CEST 2020
# HG changeset patch
# User Kirithika <kirithika at multicorewareinc.com>
# Date 1587532632 -19800
# Wed Apr 22 10:47:12 2020 +0530
# Node ID 94b6aa5db332550f7222bbc753b7c7ffdf78c67f
# Parent 0fa2ec307c561a07ba6e1679a1814f2fb37eb4e1
Add real-time VBV fullness based QP tuning in VBV 2 pass
This commit enables real-time VBV fullness based 2nd pass QP tuning.
The existing prediction based QP tuning is removed
diff -r 0fa2ec307c56 -r 94b6aa5db332 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Mon Jan 06 12:06:48 2020 +0530
+++ b/source/encoder/ratecontrol.cpp Wed Apr 22 10:47:12 2020 +0530
@@ -131,6 +131,7 @@
rce->qpNoVbv = rce2Pass->qpNoVbv;
rce->newQp = rce2Pass->newQp;
rce->qRceq = rce2Pass->qRceq;
+ rce->misPredCheck = rce2Pass->misPredCheck;
}
} // end anonymous namespace
@@ -599,9 +600,9 @@
m_encOrder[frameNumber] = encodeOrder;
if (!m_param->bMultiPassOptRPS)
{
- e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d icu:%lf pcu:%lf scu:%lf",
+ e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d misPredCheck:%d icu:%lf pcu:%lf scu:%lf",
&picType, &qpRc, &qpAq, &qNoVbv, &qRceq, &rce->coeffBits,
- &rce->mvBits, &rce->miscBits, &rce->iCuCount, &rce->pCuCount,
+ &rce->mvBits, &rce->miscBits, &rce->misPredCheck, &rce->iCuCount, &rce->pCuCount,
&rce->skipCuCount);
}
else
@@ -610,9 +611,9 @@
char bUsed[40];
memset(deltaPOC, 0, sizeof(deltaPOC));
memset(bUsed, 0, sizeof(bUsed));
- e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d icu:%lf pcu:%lf scu:%lf nump:%d numnegp:%d numposp:%d deltapoc:%s bused:%s",
+ e += sscanf(p, " in:%*d out:%*d type:%c q:%lf q-aq:%lf q-noVbv:%lf q-Rceq:%lf tex:%d mv:%d misc:%d misPredCheck:%d icu:%lf pcu:%lf scu:%lf nump:%d numnegp:%d numposp:%d deltapoc:%s bused:%s",
&picType, &qpRc, &qpAq, &qNoVbv, &qRceq, &rce->coeffBits,
- &rce->mvBits, &rce->miscBits, &rce->iCuCount, &rce->pCuCount,
+ &rce->mvBits, &rce->miscBits, &rce->misPredCheck, &rce->iCuCount, &rce->pCuCount,
&rce->skipCuCount, &rce->rpsData.numberOfPictures, &rce->rpsData.numberOfNegativePictures, &rce->rpsData.numberOfPositivePictures, deltaPOC, bUsed);
splitdeltaPOC(deltaPOC, rce);
splitbUsed(bUsed, rce);
@@ -1880,13 +1881,11 @@
qScale = tuneQScaleForZone(rce, qScale);
qScale = x265_clip3(lqmin, lqmax, qScale);
}
-
+ /* clip qp to permissible range after vbv-lookahead estimation to avoid possible
+ * mispredictions by initial frame size predictors */
+ qScale = clipQscale(curFrame, rce, qScale);
if (!m_2pass)
{
- /* clip qp to permissible range after vbv-lookahead estimation to avoid possible
- * mispredictions by initial frame size predictors */
- qScale = clipQscale(curFrame, rce, qScale);
-
if (m_pred[m_predType].count == 1)
qScale = x265_clip3(lmin, lmax, qScale);
m_lastQScaleFor[m_sliceType] = qScale;
@@ -1949,7 +1948,9 @@
else
q /= zone->bitrateFactor;
}
- q /= x265_clip3(0.5, 2.0, (double)(abrBuffer - diff) / abrBuffer);
+ /*Existing ABR conformance check may not be valid with real time VBV*/
+ if(!m_isVbv)
+ q /= x265_clip3(0.5, 2.0, (double)(abrBuffer - diff) / abrBuffer);
if (m_expectedBitsSum > 0)
{
/* Adjust quant based on the difference between
@@ -1972,23 +1973,9 @@
if (m_isVbv)
{
- /* Do not overflow vbv */
- double expectedSize = qScale2bits(rce, q);
- double expectedVbv = m_bufferFill + m_bufferRate - expectedSize;
- double expectedFullness = rce->expectedVbv / m_bufferSize;
- double qmax = q * (2 - expectedFullness);
- double sizeConstraint = 1 + expectedFullness;
- qmax = X265_MAX(qmax, rce->newQScale);
- if (expectedFullness < .05)
- qmax = lmax;
- qmax = X265_MIN(qmax, lmax);
- while (((expectedVbv < rce->expectedVbv/sizeConstraint) && (q < qmax)) ||
- ((expectedVbv < 0) && (q < lmax)))
- {
- q *= 1.05;
- expectedSize = qScale2bits(rce, q);
- expectedVbv = m_bufferFill + m_bufferRate - expectedSize;
- }
+ /* clip qp to permissible range after vbv-lookahead estimation to avoid possible
+ * mispredictions by Rate Control pass 1 statistics analysis */
+ q = clipQscale(curFrame, rce, q);
}
q = x265_clip3(lmin, lmax, q);
}
@@ -2286,11 +2273,11 @@
double lmin = m_lmin[rce->sliceType];
double lmax = m_lmax[rce->sliceType];
double q0 = q;
- if (m_isVbv && m_currentSatd > 0 && curFrame)
+ if (m_isVbv && curFrame && (m_currentSatd > 0 || m_2pass))
{
if (m_param->lookaheadDepth || m_param->rc.cuTree ||
(m_param->scenecutThreshold || m_param->bHistBasedSceneCut) ||
- (m_param->bFrameAdaptive && m_param->bframes))
+ (m_param->bFrameAdaptive && m_param->bframes) || m_2pass)
{
/* Lookahead VBV: If lookahead is done, raise the quantizer as necessary
* such that no frames in the lookahead overflow and such that the buffer
@@ -2301,7 +2288,7 @@
{
double frameQ[3];
double curBits;
- curBits = predictSize(&m_pred[m_predType], q, (double)m_currentSatd);
+ curBits = !m_2pass ? predictSize(&m_pred[m_predType], q, (double)m_currentSatd) : qScale2bits(rce, q);
double bufferFillCur = m_bufferFill - curBits;
double targetFill;
double totalDuration = m_frameDuration;
@@ -2310,19 +2297,27 @@
frameQ[I_SLICE] = frameQ[P_SLICE] / m_param->rc.ipFactor;
/* Loop over the planned future frames. */
bool iter = true;
- for (int j = 0; bufferFillCur >= 0 && iter ; j++)
+ int startLookahead = !m_2pass ? 0 : rce->encodeOrder + 1;
+ for (int j = startLookahead; bufferFillCur >= 0 && iter; j++)
{
- int type = curFrame->m_lowres.plannedType[j];
- if (type == X265_TYPE_AUTO || totalDuration >= 1.0)
+ int type;
+ if (!m_2pass)
+ type = curFrame->m_lowres.plannedType[j];
+ if ((!m_2pass && type == X265_TYPE_AUTO) || (m_2pass && j >= m_param->totalFrames) || totalDuration >= 1.0)
break;
totalDuration += m_frameDuration;
double wantedFrameSize = m_vbvMaxRate * m_frameDuration;
if (bufferFillCur + wantedFrameSize <= m_bufferSize)
bufferFillCur += wantedFrameSize;
- int64_t satd = curFrame->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
- type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;
- int predType = getPredictorType(curFrame->m_lowres.plannedType[j], type);
- curBits = predictSize(&m_pred[predType], frameQ[type], (double)satd);
+ if (!m_2pass)
+ {
+ int64_t satd = curFrame->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
+ type = IS_X265_TYPE_I(type) ? I_SLICE : IS_X265_TYPE_B(type) ? B_SLICE : P_SLICE;
+ int predType = getPredictorType(curFrame->m_lowres.plannedType[j], type);
+ curBits = predictSize(&m_pred[predType], frameQ[type], (double)satd);
+ }
+ else
+ curBits = qScale2bits(&m_rce2Pass[j], q);
bufferFillCur -= curBits;
if (!m_param->bResetZoneConfig && ((uint64_t)j == (m_param->reconfigWindowSize - 1)))
iter = false;
@@ -2410,14 +2405,16 @@
}
/* Apply MinCR restrictions */
- double pbits = predictSize(&m_pred[m_predType], q, (double)m_currentSatd);
+ double pbits = !m_2pass ? predictSize(&m_pred[m_predType], q, (double)m_currentSatd) : qScale2bits(rce, q);
if (pbits > rce->frameSizeMaximum)
q *= pbits / rce->frameSizeMaximum;
/* To detect frames that are more complex in SATD costs compared to prev window, yet
* lookahead vbv reduces its qscale by half its value. Be on safer side and avoid drastic
* qscale reductions for frames high in complexity */
- bool mispredCheck = rce->movingAvgSum && m_currentSatd >= rce->movingAvgSum && q <= q0 / 2;
- if (!m_isCbr || (m_isAbr && mispredCheck))
+ if (!m_2pass)
+ rce->misPredCheck = rce->movingAvgSum && m_currentSatd >= rce->movingAvgSum;
+ bool mispredCheck = rce->misPredCheck && q <= q0 / 2;
+ if (!m_isCbr || ((m_isAbr || m_2pass) && mispredCheck))
q = X265_MAX(q0, q);
if (m_rateFactorMaxIncrement)
@@ -2427,7 +2424,7 @@
return x265_clip3(lmin, qmax, q);
}
}
- if (m_2pass)
+ if (!curFrame && m_2pass)
{
double min = log(lmin);
double max = log(lmax);
@@ -2963,13 +2960,14 @@
if (!curEncData.m_param->bMultiPassOptRPS)
{
if (fprintf(m_statFileOut,
- "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d icu:%.2f pcu:%.2f scu:%.2f ;\n",
+ "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d misPredCheck:%d icu:%.2f pcu:%.2f scu:%.2f ;\n",
rce->poc, rce->encodeOrder,
cType, curEncData.m_avgQpRc, curEncData.m_avgQpAq,
rce->qpNoVbv, rce->qRceq,
curFrame->m_encData->m_frameStats.coeffBits,
curFrame->m_encData->m_frameStats.mvBits,
curFrame->m_encData->m_frameStats.miscBits,
+ rce->misPredCheck,
curFrame->m_encData->m_frameStats.percent8x8Intra * m_ncu,
curFrame->m_encData->m_frameStats.percent8x8Inter * m_ncu,
curFrame->m_encData->m_frameStats.percent8x8Skip * m_ncu) < 0)
@@ -2993,13 +2991,14 @@
}
if (fprintf(m_statFileOut,
- "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d icu:%.2f pcu:%.2f scu:%.2f nump:%d numnegp:%d numposp:%d %s %s ;\n",
+ "in:%d out:%d type:%c q:%.2f q-aq:%.2f q-noVbv:%.2f q-Rceq:%.2f tex:%d mv:%d misc:%d misPredCheck:%d icu:%.2f pcu:%.2f scu:%.2f nump:%d numnegp:%d numposp:%d %s %s ;\n",
rce->poc, rce->encodeOrder,
cType, curEncData.m_avgQpRc, curEncData.m_avgQpAq,
rce->qpNoVbv, rce->qRceq,
curFrame->m_encData->m_frameStats.coeffBits,
curFrame->m_encData->m_frameStats.mvBits,
curFrame->m_encData->m_frameStats.miscBits,
+ rce->misPredCheck,
curFrame->m_encData->m_frameStats.percent8x8Intra * m_ncu,
curFrame->m_encData->m_frameStats.percent8x8Inter * m_ncu,
curFrame->m_encData->m_frameStats.percent8x8Skip * m_ncu,
diff -r 0fa2ec307c56 -r 94b6aa5db332 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Mon Jan 06 12:06:48 2020 +0530
+++ b/source/encoder/ratecontrol.h Wed Apr 22 10:47:12 2020 +0530
@@ -123,6 +123,7 @@
int rpsIdx;
RPS rpsData;
bool isFadeEnd;
+ int misPredCheck;
};
class RateControl
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265-3.patch
Type: text/x-patch
Size: 12429 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20200422/1c771f10/attachment-0001.bin>
More information about the x265-devel
mailing list