[x265] [PATCH 4 of 6] vbv: fix bugs in vbv flow with single pass ABR
aarthi at multicorewareinc.com
aarthi at multicorewareinc.com
Fri Feb 21 07:08:39 CET 2014
# HG changeset patch
# User Aarthi Thirumalai
# Date 1392899993 -19800
# Thu Feb 20 18:09:53 2014 +0530
# Node ID d058d4dd84a547b9b72a043ed065a94220b2f32b
# Parent 9517ea331f3e87f41c687db11de02cb95ded8756
vbv: fix bugs in vbv flow with single pass ABR
diff -r 9517ea331f3e -r d058d4dd84a5 source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/encoder.cpp Thu Feb 20 18:09:53 2014 +0530
@@ -365,11 +365,8 @@
// Allow this frame to be recycled if no frame encoders are using it for reference
ATOMIC_DEC(&out->m_countRefEncoders);
-
- m_rateControl->rateControlEnd(bits, &(curEncoder->m_rce));
-
+ m_rateControl->rateControlEnd(out, bits, &(curEncoder->m_rce));
m_dpb->recycleUnreferenced(m_freeList);
-
ret = 1;
}
diff -r 9517ea331f3e -r d058d4dd84a5 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/ratecontrol.cpp Thu Feb 20 18:09:53 2014 +0530
@@ -207,8 +207,9 @@
RateControl::RateControl(TEncCfg * _cfg)
{
this->cfg = _cfg;
- ncu = (int)((cfg->param.sourceHeight * cfg->param.sourceWidth) / pow((int)16, 2.0));
-
+ int lowresCuWidth = ((cfg->param.sourceWidth/2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
+ int lowresCuHeight = ((cfg->param.sourceHeight/2) + X265_LOWRES_CU_SIZE - 1) >> X265_LOWRES_CU_BITS;
+ ncu = lowresCuWidth * lowresCuHeight;
if (cfg->param.rc.cuTree)
{
qCompress = 1;
@@ -441,13 +442,12 @@
* average QP of the two adjacent P-frames + an offset */
TComSlice* prevRefSlice = curSlice->getRefPic(REF_PIC_LIST_0, 0)->getSlice();
TComSlice* nextRefSlice = curSlice->getRefPic(REF_PIC_LIST_1, 0)->getSlice();
+ double q0 = curSlice->getRefPic(REF_PIC_LIST_0, 0)->m_avgQpRc;
+ double q1 = curSlice->getRefPic(REF_PIC_LIST_1, 0)->m_avgQpRc;
bool i0 = prevRefSlice->getSliceType() == I_SLICE;
bool i1 = nextRefSlice->getSliceType() == I_SLICE;
int dt0 = abs(curSlice->getPOC() - prevRefSlice->getPOC());
int dt1 = abs(curSlice->getPOC() - nextRefSlice->getPOC());
- double q0 = prevRefSlice->m_avgQpRc;
- double q1 = nextRefSlice->m_avgQpRc;
-
// Skip taking a reference frame before the Scenecut if ABR has been reset.
if (lastAbrResetPoc >= 0 && !isVbv)
{
@@ -517,10 +517,9 @@
{
if (!isVbv)
{
- checkAndResetABR(rce);
+ checkAndResetABR(pic, rce);
}
q = getQScale(rce, wantedBitsWindow / cplxrSum);
-
/* ABR code can potentially be counterproductive in CBR, so just don't bother.
* Don't run it if the frame complexity is zero either. */
if (!vbvMinRate && currentSatd)
@@ -547,23 +546,22 @@
if (cfg->param.rc.rateControlMode != X265_RC_CRF)
{
double lqmin = 0, lqmax = 0;
- if (totalBits == 0)
+ if (totalBits == 0 && !isVbv)
{
lqmin = qp2qScale(ABR_INIT_QP_MIN) / lstep;
lqmax = qp2qScale(ABR_INIT_QP_MAX) * lstep;
+ q = Clip3(lqmin, lqmax, q);
}
- else
+ else if(totalBits > 0 || (isVbv && rce->poc > 0 ))
{
lqmin = lastQScaleFor[sliceType] / lstep;
lqmax = lastQScaleFor[sliceType] * lstep;
+ if (overflow > 1.1 && framesDone > 3)
+ lqmax *= lstep;
+ else if (overflow < 0.9)
+ lqmin /= lstep;
+ q = Clip3(lqmin, lqmax, q);
}
-
- if (overflow > 1.1 && framesDone > 3)
- lqmax *= lstep;
- else if (overflow < 0.9)
- lqmin /= lstep;
-
- q = Clip3(lqmin, lqmax, q);
}
else
{
@@ -587,11 +585,9 @@
return q;
}
}
-
-void RateControl::checkAndResetABR(RateControlEntry* rce)
+void RateControl::checkAndResetABR(TComPic* pic, RateControlEntry* rce)
{
double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;
-
// Check if current Slice is a scene cut that follows low detailed/blank frames
if (rce->lastSatd > 4 * rce->movingAvgSum)
{
@@ -599,7 +595,7 @@
{
// 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)
+ if (underflow < 1 && pic->m_avgQpRc == 0)
{
totalBits = 0;
framesDone = 0;
@@ -654,10 +650,9 @@
double bufferFillCur = bufferFill - curBits;
double targetFill;
double totalDuration = 0;
- frameQ[0] = sliceType == I_SLICE ? q * cfg->param.rc.ipFactor : q;
- frameQ[1] = frameQ[0] * cfg->param.rc.pbFactor;
- frameQ[2] = frameQ[0] / cfg->param.rc.ipFactor;
-
+ frameQ[P_SLICE] = sliceType == I_SLICE ? q * cfg->param.rc.ipFactor : q;
+ frameQ[B_SLICE] = frameQ[P_SLICE] * cfg->param.rc.pbFactor;
+ frameQ[I_SLICE] = frameQ[P_SLICE] / cfg->param.rc.ipFactor;
/* Loop over the planned future frames. */
for (int j = 0; bufferFillCur >= 0 && bufferFillCur <= bufferSize; j++)
{
@@ -799,14 +794,10 @@
p->coeff += new_coeff;
p->offset += new_offset;
}
-
void RateControl::updateVbv(int64_t bits, RateControlEntry* rce)
{
- int mbCount = (int)((cfg->param.sourceHeight * cfg->param.sourceWidth) / pow((int)16, 2.0));
-
- if (rce->lastSatd >= mbCount)
+ if (rce->lastSatd >= ncu)
updatePredictor(&pred[rce->sliceType], qp2qScale(rce->qpaRc), (double)rce->lastSatd, (double)bits);
-
if (!isVbv)
return;
@@ -819,19 +810,27 @@
bufferFillFinal += bufferRate;
bufferFillFinal = X265_MIN(bufferFillFinal, bufferSize);
}
-
/* After encoding one frame, update rate control state */
-int RateControl::rateControlEnd(int64_t bits, RateControlEntry* rce)
+int RateControl::rateControlEnd(TComPic* pic, int64_t bits, RateControlEntry* rce)
{
if (isAbr)
{
if (!isVbv && cfg->param.rc.rateControlMode == X265_RC_ABR)
{
- checkAndResetABR(rce);
+ checkAndResetABR(pic, rce);
}
-
if (!isAbrReset)
{
+ if (pic->m_qpaRc)
+ {
+ for (uint32_t i = 0; i < pic->getFrameHeightInCU(); i++)
+ {
+ pic->m_avgQpRc += pic->m_qpaRc[i];
+ }
+ pic->m_avgQpRc /= (pic->getFrameHeightInCU() * pic->getFrameWidthInCU());
+ rce->qpaRc = pic->m_avgQpRc;
+ }
+
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. */
diff -r 9517ea331f3e -r d058d4dd84a5 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Thu Feb 20 17:47:53 2014 +0530
+++ b/source/encoder/ratecontrol.h Thu Feb 20 18:09:53 2014 +0530
@@ -126,10 +126,8 @@
// to be called for each frame to process RateControl and set QP
void rateControlStart(TComPic* pic, Lookahead *, RateControlEntry* rce, Encoder* enc);
void calcAdaptiveQuantFrame(TComPic *pic);
- int rateControlEnd(int64_t bits, RateControlEntry* rce);
-
+ int rateControlEnd(TComPic* pic, int64_t bits, RateControlEntry* rce);
protected:
-
double getQScale(RateControlEntry *rce, double rateFactor);
double rateEstimateQscale(TComPic* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR
void accumPQpUpdate();
@@ -140,7 +138,7 @@
double clipQscale(TComPic* pic, double q);
void updateVbvPlan(Encoder* enc);
double predictSize(Predictor *p, double q, double var);
- void checkAndResetABR(RateControlEntry* rce);
+ void checkAndResetABR(TComPic* pic, RateControlEntry* rce);
};
}
More information about the x265-devel
mailing list