[x265] [PATCH 5 of 6] vbv: implement row wise vbvRateControl at each row diagonal
aarthi at multicorewareinc.com
aarthi at multicorewareinc.com
Thu Feb 20 14:25:47 CET 2014
# HG changeset patch
# User Aarthi Thirumalai
# Date 1392900828 -19800
# Thu Feb 20 18:23:48 2014 +0530
# Node ID 49b90667f050a7dd9c28b5017f389f5c29a1c191
# Parent c5c07a3ee7fcf0f331f06f83b7b3bc0b1bcc1668
vbv: implement row wise vbvRateControl at each row diagonal.
diff -r c5c07a3ee7fc -r 49b90667f050 source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Thu Feb 20 18:09:53 2014 +0530
+++ b/source/encoder/ratecontrol.cpp Thu Feb 20 18:23:48 2014 +0530
@@ -221,6 +221,10 @@
// validate for cfg->param.rc, maybe it is need to add a function like x265_parameters_valiate()
cfg->param.rc.rfConstant = Clip3((double)-QP_BD_OFFSET, (double)51, cfg->param.rc.rfConstant);
+ cfg->param.rc.rfConstantMax = Clip3((double)-QP_BD_OFFSET, (double)51, cfg->param.rc.rfConstantMax);
+ rateFactorMaxIncrement = 0;
+ vbvMinRate = 0;
+
if (cfg->param.rc.rateControlMode == X265_RC_CRF)
{
cfg->param.rc.qp = (int)cfg->param.rc.rfConstant + QP_BD_OFFSET;
@@ -230,6 +234,15 @@
double mbtree_offset = cfg->param.rc.cuTree ? (1.0 - cfg->param.rc.qCompress) * 13.5 : 0;
rateFactorConstant = pow(baseCplx, 1 - qCompress) /
qp2qScale(cfg->param.rc.rfConstant + mbtree_offset + QP_BD_OFFSET);
+ if (cfg->param.rc.rfConstantMax)
+ {
+ rateFactorMaxIncrement = cfg->param.rc.rfConstantMax - cfg->param.rc.rfConstant;
+ if (rateFactorMaxIncrement <= 0)
+ {
+ x265_log(&cfg->param, X265_LOG_WARNING, "CRF max must be greater than CRF\n");
+ rateFactorMaxIncrement = 0;
+ }
+ }
}
isAbr = cfg->param.rc.rateControlMode != X265_RC_CQP; // later add 2pass option
@@ -760,6 +773,181 @@
return Clip3(lmin1, lmax1, q);
}
+ double RateControl::predictRowsSizeSum(TComPic* pic, double qpVbv, int32_t & encodedBitsSoFar)
+{
+ uint32_t rowSatdCostSoFar = 0 ,totalSatdBits = 0;
+ encodedBitsSoFar = 0;
+ double qScale = qp2qScale(qpVbv);
+ int sliceType = pic->getSlice()->getSliceType();
+ TComPic* refPic = pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0);
+ int maxRows = pic->getPicSym()->getFrameHeightInCU();
+ for (int row = 0 ; row < maxRows; row++)
+ {
+ encodedBitsSoFar += pic->m_rowEncodedBits[row];
+ rowSatdCostSoFar = pic->m_rowDiagSatd[row];
+ uint32_t satdCostForPendingCus = pic->m_rowSatdForVbv[row] - rowSatdCostSoFar;
+ if (satdCostForPendingCus > 0)
+ {
+ double pred_s = predictSize(rowPred[0], qScale, satdCostForPendingCus);
+ uint32_t refRowSatdCost= 0 , refRowBits = 0;
+ double refQScale=0;
+
+ if (sliceType != I_SLICE)
+ {
+ for (uint32_t cuAddr = pic->m_numEncodedCusPerRow[row] + 1; cuAddr < pic->getPicSym()->getFrameWidthInCU() * (row + 1); cuAddr++)
+ {
+ refRowSatdCost += refPic->m_cuCostsForVbv[cuAddr];
+ refRowBits = refPic->getCU(cuAddr)->m_totalBits;
+ }
+ refQScale = row == maxRows - 1 ? refPic->m_rowDiagQScale[row] : refPic->m_rowDiagQScale[row + 1];
+ }
+
+ if (sliceType == I_SLICE || qScale >= refQScale)
+ {
+ if (sliceType == P_SLICE
+ && refPic->getSlice()->getSliceType() == sliceType
+ && refQScale > 0
+ && refRowSatdCost > 0)
+ {
+ if (abs(int32_t(refRowSatdCost - satdCostForPendingCus)) < (int32_t)satdCostForPendingCus / 2)
+ {
+ double pred_t = refRowBits * satdCostForPendingCus / refRowSatdCost
+ * refQScale / qScale;
+ totalSatdBits += int32_t((pred_s + pred_t) * 0.5);
+ }
+ }
+
+ else
+ totalSatdBits += int32_t(pred_s);
+ }
+ else
+ {
+ /* Our QP is lower than the reference! */
+ double pred_intra = predictSize(rowPred[1], qScale, refRowSatdCost);
+ /* Sum: better to overestimate than underestimate by using only one of the two predictors. */
+ totalSatdBits += int32_t(pred_intra + pred_s);
+ }
+ }
+ }
+ return totalSatdBits + encodedBitsSoFar;
+ }
+
+int RateControl::rowDiagonalVbvRateControl(TComPic* pic, uint32_t row, RateControlEntry* rce, double& qpVbv)
+{
+ fprintf(fp,"\n poc :%d , type : %d , slice Qp : %d , row : %d , startvbv : %f ", pic->getPOC(), rce->sliceType, pic->getSlice()->getSliceQp(), row, qpVbv);
+ if (rce->poc == 24)
+ {
+ int i=0; i++;
+ }
+ double qScaleVbv = qp2qScale(qpVbv);
+ pic->m_rowDiagQp[row] = qpVbv;
+ pic->m_rowDiagQScale[row] = qScaleVbv;
+ //TODO : check whther we gotto update prodictor using whole Row Satd or only satd of blocks upto the diagonal in row.
+ updatePredictor(rowPred[0], qScaleVbv, (double)pic->m_rowDiagSatd[row], (double)pic->m_rowEncodedBits[row]);
+ if (pic->getSlice()->getSliceType() == P_SLICE)
+ {
+ TComPic* refSlice = pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0);
+ if (qpVbv < refSlice->m_rowDiagQp[row])
+ {
+ updatePredictor(rowPred[1], qScaleVbv, refSlice->m_rowDiagSatd[row], refSlice->m_rowEncodedBits[row]);
+ }
+ }
+
+ int canReencodeRow = 1;
+ /* tweak quality based on difference from predicted size */
+ double prevRowQp = qpVbv;
+ double qpAbsoluteMax = MAX_MAX_QP;
+ if (rateFactorMaxIncrement)
+ qpAbsoluteMax = X265_MIN(qpAbsoluteMax, rce->qpNoVbv + rateFactorMaxIncrement);
+ double qpMax = X265_MIN(prevRowQp + cfg->param.rc.qpStep, qpAbsoluteMax );
+ double qpMin = X265_MAX(prevRowQp - cfg->param.rc.qpStep, MIN_QP );
+ double stepSize = 0.5;
+ double bufferLeftPlanned = bufferFill - rce->frameSizePlanned;
+ if (bufferLeftPlanned < 0 )
+ { int i=0; i ++;
+ }
+ double maxFrameError = X265_MAX(0.05, 1.0 / pic->getFrameHeightInCU());
+
+ if (row < pic->getPicSym()->getFrameHeightInCU() - 1)
+ {
+ /* B-frames shouldn't use lower QP than their reference frames. */
+ if (rce->sliceType == B_SLICE)
+ {
+ TComPic* refSlice1 = pic->getSlice()->getRefPic(REF_PIC_LIST_0, 0);
+ TComPic* refSlice2 = pic->getSlice()->getRefPic(REF_PIC_LIST_1, 0);
+ qpMin = X265_MAX(qpMin, X265_MAX(refSlice1->m_rowDiagQp[row], refSlice2->m_rowDiagQp[row]));
+ qpVbv = X265_MAX(qpVbv, qpMin);
+ }
+ /* More threads means we have to be more cautious in letting ratecontrol use up extra bits. */
+ double rcTol = bufferLeftPlanned / cfg->param.frameNumThreads * cfg->param.rc.rateTolerance;
+ int32_t encodedBitsSoFar = 0;
+ double b1 = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+
+ /* Don't increase the row QPs until a sufficent amount of the bits of the frame have been processed, in case a flat */
+ /* area at the top of the frame was measured inaccurately. */
+ if (encodedBitsSoFar < 0.05f * rce->frameSizePlanned)
+ qpMax = qpAbsoluteMax = prevRowQp;
+
+ if (rce->sliceType != I_SLICE)
+ rcTol *= 0.5;
+
+ if (!vbvMinRate)
+ qpMin = X265_MAX(qpMin, rce->qpNoVbv);
+
+ while (qpVbv < qpMax
+ && ((b1 > rce->frameSizePlanned + rcTol) ||
+ (bufferFill - b1 < bufferLeftPlanned * 0.5) ||
+ (b1 > rce->frameSizePlanned && qpVbv < rce->qpNoVbv)))
+ {
+ qpVbv += stepSize;
+ b1 = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+ }
+
+ while (qpVbv > qpMin
+ && (qpVbv > pic->m_rowDiagQp[0] || singleFrameVbv)
+ && ((b1 < rce->frameSizePlanned * 0.8f && qpVbv <= prevRowQp)
+ || b1 < (bufferFill - bufferSize + bufferRate) * 1.1))
+ {
+ qpVbv -= stepSize;
+ b1 = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+ }
+ /* avoid VBV underflow */
+ while ((qpVbv < qpAbsoluteMax)
+ && (bufferFill - b1 < bufferRate * maxFrameError))
+ {
+ qpVbv += stepSize;
+ b1 = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+ }
+ frameSizeEstimated = b1;
+
+ /* If the current row was large enough to cause a large QP jump, try re-encoding it. */
+ if (qpVbv > qpMax && prevRowQp < qpMax && canReencodeRow)
+ {
+ /* Bump QP to halfway in between... close enough. */
+ qpVbv = Clip3(prevRowQp + 1.0f, qpMax, (prevRowQp + qpVbv)*0.5);
+ fprintf(fp,", endvbv : %f ", qpVbv);
+ return -1;
+ }
+ }
+ else
+ {
+ int32_t encodedBitsSoFar = 0;
+ frameSizeEstimated = predictRowsSizeSum(pic, qpVbv, encodedBitsSoFar);
+ /* Last-ditch attempt: if the last row of the frame underflowed the VBV,
+ * try again. */
+ if((frameSizeEstimated > (bufferFill - bufferRate * maxFrameError) &&
+ qpVbv < qpMax && canReencodeRow))
+ {
+ qpVbv = qpMax;
+ fprintf(fp,", endvbv : %f ", qpVbv);
+ return -1;
+ }
+ }
+ fprintf(fp,", endvbv : %f ", qpVbv);
+ return 0;
+}
+
+
/* modify the bitrate curve from pass1 for one frame */
double RateControl::getQScale(RateControlEntry *rce, double rateFactor)
{
diff -r c5c07a3ee7fc -r 49b90667f050 source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Thu Feb 20 18:09:53 2014 +0530
+++ b/source/encoder/ratecontrol.h Thu Feb 20 18:23:48 2014 +0530
@@ -92,6 +92,7 @@
double vbvMaxRate; /* in kbps */
double vbvMinRate; /* in kbps */
bool singleFrameVbv;
+ double rateFactorMaxIncrement; /* Don't allow RF above (CRF + this value). */
bool isVbv;
Predictor pred[5];
Predictor predBfromP;
@@ -129,6 +130,7 @@
void rateControlStart(TComPic* pic, Lookahead *, RateControlEntry* rce, Encoder* enc);
void calcAdaptiveQuantFrame(TComPic *pic);
int rateControlEnd(TComPic* pic, int64_t bits, RateControlEntry* rce);
+ int rowDiagonalVbvRateControl(TComPic* pic, uint32_t row, RateControlEntry* rce, double& qpVbv);
protected:
@@ -143,6 +145,7 @@
void updateVbvPlan(Encoder* enc);
double predictSize(Predictor *p, double q, double var);
void checkAndResetABR(TComPic* pic, RateControlEntry* rce);
+ double predictRowsSizeSum(TComPic* pic, double qpm , int32_t& encodedBits);
};
}
More information about the x265-devel
mailing list