[x265] vbv rate control
Aarthi Priya Thirumalai
aarthi at multicorewareinc.com
Thu Feb 20 14:04:10 CET 2014
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 0 of 6 ] introduce cu level vbv ratecontrol
Message-Id: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:20 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 1 of 6] vbv: Introduce states to hold row data for row level
VBV ratecontrol
X-Mercurial-Node: 39efc006d3efa89df765b3d62e810854b41fe401
Message-Id: <39efc006d3efa89df765.1392901341 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:21 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org
# HG changeset patch
# User Aarthi Thirumalai
# Date 1392895417 -19800
# Thu Feb 20 16:53:37 2014 +0530
# Node ID 39efc006d3efa89df765b3d62e810854b41fe401
# Parent fec3cab870437c101b409425b6c2d6c403bd0efa
vbv: Introduce states to hold row data for row level VBV ratecontrol.
diff -r fec3cab87043 -r 39efc006d3ef source/Lib/TLibCommon/TComDataCU.cpp
--- a/source/Lib/TLibCommon/TComDataCU.cpp Thu Feb 20 15:54:52 2014 +0530
+++ b/source/Lib/TLibCommon/TComDataCU.cpp Thu Feb 20 16:53:37 2014 +0530
@@ -99,6 +99,7 @@
m_mvpIdx[0] = NULL;
m_mvpIdx[1] = NULL;
m_chromaFormat = 0;
+ m_baseQp = 0;
}
TComDataCU::~TComDataCU()
@@ -235,6 +236,7 @@
m_totalBits = 0;
m_numPartitions = pic->getNumPartInCU();
int qp = pic->m_lowres.invQscaleFactor ?
pic->getCU(getAddr())->getQP(0) : m_slice->getSliceQp();
+ m_baseQp = pic->getCU(getAddr())->m_baseQp;
for (int i = 0; i < 4; i++)
{
m_avgCost[i] = 0;
diff -r fec3cab87043 -r 39efc006d3ef source/Lib/TLibCommon/TComDataCU.h
--- a/source/Lib/TLibCommon/TComDataCU.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/Lib/TLibCommon/TComDataCU.h Thu Feb 20 16:53:37 2014 +0530
@@ -179,6 +179,7 @@
uint64_t m_avgCost[4]; // stores the avg cost of CU's in
frame for each depth
uint32_t m_count[4];
uint64_t m_sa8dCost;
+ double m_baseQp; //Qp of Cu set from RateControl/Vbv.
//
-------------------------------------------------------------------------------------------------------------------
// create / destroy / initialize / copy
diff -r fec3cab87043 -r 39efc006d3ef source/Lib/TLibCommon/TComPic.cpp
--- a/source/Lib/TLibCommon/TComPic.cpp Thu Feb 20 15:54:52 2014 +0530
+++ b/source/Lib/TLibCommon/TComPic.cpp Thu Feb 20 16:53:37 2014 +0530
@@ -56,6 +56,13 @@
, m_bUsedByCurr(false)
, m_bIsLongTerm(false)
, m_bCheckLTMSB(false)
+ , m_rowDiagQp(NULL)
+ , m_rowDiagQScale(NULL)
+ , m_rowDiagSatd(NULL)
+ , m_rowSatdForVbv(NULL)
+ , m_cuCostsForVbv(NULL)
+ , m_rowEncodedBits(NULL)
+ , m_numEncodedCusPerRow(NULL)
{
m_reconRowCount = 0;
m_countRefEncoders = 0;
@@ -69,6 +76,9 @@
m_ssimCnt = 0;
m_frameTime = 0.0;
m_elapsedCompressTime = 0.0;
+ m_qpaAq = 0;
+ m_qpaRc = 0;
+ m_avgQpRc = 0;
m_bChromaPlanesExtended = false;
}
@@ -94,7 +104,46 @@
ok &= m_origPicYuv->create(cfg->param.sourceWidth,
cfg->param.sourceHeight, cfg->param.internalCsp, g_maxCUWidth,
g_maxCUHeight, g_maxCUDepth);
ok &= m_reconPicYuv->create(cfg->param.sourceWidth,
cfg->param.sourceHeight, cfg->param.internalCsp, g_maxCUWidth,
g_maxCUHeight, g_maxCUDepth);
ok &= m_lowres.create(m_origPicYuv, cfg->param.bframes,
&cfg->param.rc.aqMode);
+
+ if (ok && cfg->param.rc.vbvBufferSize > 0 &&
cfg->param.rc.vbvMaxBitrate > 0)
+ {
+ int numRows = m_picSym->getFrameHeightInCU();
+ int numCols = m_picSym->getFrameWidthInCU();
+ CHECKED_MALLOC(m_rowDiagQp, double, numRows);
+ CHECKED_MALLOC(m_rowDiagQScale, double, numRows);
+ CHECKED_MALLOC(m_rowDiagSatd, uint32_t, numRows);
+ CHECKED_MALLOC(m_rowEncodedBits, uint32_t, numRows);
+ CHECKED_MALLOC(m_numEncodedCusPerRow, uint32_t, numRows);
+ CHECKED_MALLOC(m_rowSatdForVbv, uint32_t, numRows);
+ CHECKED_MALLOC(m_cuCostsForVbv, uint32_t, numRows * numCols);
+ CHECKED_MALLOC(m_qpaRc, double, numRows);
+ CHECKED_MALLOC(m_qpaAq, int, numRows);
+ reInit(cfg);
+ }
+
return ok;
+
+fail :
+ ok = false;
+ return ok;
+}
+
+void TComPic::reInit(TEncCfg* cfg)
+{
+ if (cfg->param.rc.vbvBufferSize > 0 && cfg->param.rc.vbvMaxBitrate > 0)
+ {
+ int numRows = m_picSym->getFrameHeightInCU();
+ int numCols = m_picSym->getFrameWidthInCU();
+ memset(m_rowDiagQp, 0, numRows * sizeof(double));
+ memset(m_rowDiagQScale, 0, numRows * sizeof(double));
+ memset(m_rowDiagSatd, 0, numRows * sizeof(uint32_t));
+ memset(m_rowEncodedBits, 0, numRows * sizeof(uint32_t));
+ memset(m_numEncodedCusPerRow, 0, numRows * sizeof(uint32_t));
+ memset(m_rowSatdForVbv, 0, numRows * sizeof(uint32_t));
+ memset(m_cuCostsForVbv, 0, numRows * numCols * sizeof(uint32_t));
+ memset(m_qpaRc, 0, numRows * sizeof(double));
+ memset(m_qpaAq, 0, numRows * sizeof(uint32_t));
+ }
}
void TComPic::destroy(int bframes)
@@ -121,6 +170,16 @@
}
m_lowres.destroy(bframes);
+
+ X265_FREE(m_rowDiagQp);
+ X265_FREE(m_rowDiagQScale);
+ X265_FREE(m_rowDiagSatd);
+ X265_FREE(m_rowEncodedBits);
+ X265_FREE(m_numEncodedCusPerRow);
+ X265_FREE(m_rowSatdForVbv);
+ X265_FREE(m_cuCostsForVbv);
+ X265_FREE(m_qpaAq);
+ X265_FREE(m_qpaRc);
}
//! \}
diff -r fec3cab87043 -r 39efc006d3ef source/Lib/TLibCommon/TComPic.h
--- a/source/Lib/TLibCommon/TComPic.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/Lib/TLibCommon/TComPic.h Thu Feb 20 16:53:37 2014 +0530
@@ -104,6 +104,16 @@
uint32_t m_checksum[3];
bool m_bChromaPlanesExtended; // orig chroma planes
motion extended for weightp analysis
+ double* m_rowDiagQp;
+ double* m_rowDiagQScale;
+ uint32_t* m_rowDiagSatd;
+ uint32_t* m_rowEncodedBits;
+ uint32_t* m_numEncodedCusPerRow;
+ uint32_t* m_rowSatdForVbv;
+ uint32_t* m_cuCostsForVbv;
+ int* m_qpaAq;
+ double* m_qpaRc;
+ double m_avgQpRc;
TComPic();
virtual ~TComPic();
@@ -112,6 +122,8 @@
virtual void destroy(int bframes);
+ void reInit(TEncCfg* cfg);
+
bool getUsedByCurr() { return m_bUsedByCurr; }
void setUsedByCurr(bool bUsed) { m_bUsedByCurr = bUsed; }
diff -r fec3cab87043 -r 39efc006d3ef source/common/lowres.h
--- a/source/common/lowres.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/common/lowres.h Thu Feb 20 16:53:37 2014 +0530
@@ -117,6 +117,7 @@
int intraMbs[X265_BFRAME_MAX + 2];
int32_t* intraCost;
int64_t satdCost;
+ uint16_t* lowresCostForRc;
uint16_t(*lowresCosts[X265_BFRAME_MAX + 2][X265_BFRAME_MAX + 2]);
int32_t* lowresMvCosts[2][X265_BFRAME_MAX + 1];
MV* lowresMvs[2][X265_BFRAME_MAX + 1];
diff -r fec3cab87043 -r 39efc006d3ef source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Thu Feb 20 15:54:52 2014 +0530
+++ b/source/encoder/encoder.cpp Thu Feb 20 16:53:37 2014 +0530
@@ -280,6 +280,7 @@
/* Copy input picture into a TComPic, send to lookahead */
pic->getSlice()->setPOC(++m_pocLast);
+ pic->reInit(this);
pic->getPicYuvOrg()->copyFromPicture(*pic_in, m_pad);
pic->m_userData = pic_in->userData;
pic->m_pts = pic_in->pts;
diff -r fec3cab87043 -r 39efc006d3ef source/encoder/encoder.h
--- a/source/encoder/encoder.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/encoder/encoder.h Thu Feb 20 16:53:37 2014 +0530
@@ -84,7 +84,6 @@
Lookahead* m_lookahead;
FrameEncoder* m_frameEncoder;
DPB* m_dpb;
- RateControl* m_rateControl;
/* frame parallelism */
int m_curEncoder;
@@ -145,6 +144,8 @@
void signalReconRowCompleted(int poc);
+ RateControl* m_rateControl;
+
protected:
// Returns total number of bits for encoded pic
diff -r fec3cab87043 -r 39efc006d3ef source/x265.h
--- a/source/x265.h Thu Feb 20 15:54:52 2014 +0530
+++ b/source/x265.h Thu Feb 20 16:53:37 2014 +0530
@@ -801,6 +801,8 @@
* across frames and assigns more bits to these CUs. Improves
encode efficiency.
* Default: OFF (0) */
int cuTree;
+ /* In CRF mode, maximum CRF as caused by VBV */
+ double rfConstantMax;
} rc;
} x265_param;
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 2 of 6] vbv: enable vbvLookahead for Keyframes;
accumulate frame rowSatds from lowres rowSatds
X-Mercurial-Node: 1c037c64274dce2f39db348967259d7d623c1b18
Message-Id: <1c037c64274dce2f39db.1392901342 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:22 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org
# HG changeset patch
# User Aarthi Thirumalai
# Date 1392896018 -19800
# Thu Feb 20 17:03:38 2014 +0530
# Node ID 1c037c64274dce2f39db348967259d7d623c1b18
# Parent 39efc006d3efa89df765b3d62e810854b41fe401
vbv: enable vbvLookahead for Keyframes; accumulate frame rowSatds from
lowres rowSatds.
diff -r 39efc006d3ef -r 1c037c64274d source/encoder/slicetype.cpp
--- a/source/encoder/slicetype.cpp Thu Feb 20 16:53:37 2014 +0530
+++ b/source/encoder/slicetype.cpp Thu Feb 20 17:03:38 2014 +0530
@@ -173,11 +173,39 @@
}
if (cfg->param.rc.cuTree)
+ {
pic->m_lowres.satdCost = frameCostRecalculate(frames, p0, p1, b);
+ if (b && cfg->param.rc.vbvBufferSize)
+ frameCostRecalculate(frames,b, b, b);
+ }
+
else if (cfg->param.rc.aqMode)
pic->m_lowres.satdCost = pic->m_lowres.costEstAq[b - p0][p1 - b];
else
pic->m_lowres.satdCost = pic->m_lowres.costEst[b - p0][p1 - b];
+
+ if (cfg->param.rc.vbvBufferSize > 0 && cfg->param.rc.vbvMaxBitrate > 0)
+ {
+ pic->m_lowres.lowresCostForRc = pic->m_lowres.lowresCosts[b -
p0][p1 - b];
+ uint32_t lowresRow = 0 , lowresCol = 0, lowresCuIdx = 0, sum = 0;
+ uint32_t scale = cfg->param.maxCUSize / (2 * X265_LOWRES_CU_SIZE);
+ uint32_t widthInLowresCu = (uint32_t)widthInCU, heightInLowresCu =
(uint32_t)heightInCU;
+
+ for (uint32_t row = 0; row < pic->getFrameHeightInCU(); row++)
+ {
+ lowresRow = row * scale;
+ for (uint32_t cnt = 0 ; cnt < scale && lowresRow <
heightInLowresCu; lowresRow++, cnt++)
+ {
+ sum = 0;
+ lowresCuIdx = lowresRow * widthInLowresCu ;
+ for (lowresCol = 0; lowresCol < widthInLowresCu;
lowresCol++, lowresCuIdx++)
+ {
+ sum += pic->m_lowres.lowresCostForRc[lowresCuIdx];
+ }
+ pic->m_rowSatdForVbv[row] += sum;
+ }
+ }
+ }
return pic->m_lowres.satdCost;
}
@@ -186,6 +214,7 @@
Lowres *frames[X265_LOOKAHEAD_MAX];
TComPic *list[X265_LOOKAHEAD_MAX];
TComPic *ipic = inputQueue.first();
+ bool isKeyFrameAnalyse = (cfg->param.rc.cuTree ||
(cfg->param.rc.vbvBufferSize && cfg->param.lookaheadDepth));
if (!est.rows && ipic)
est.init(cfg, ipic);
@@ -371,6 +400,10 @@
outputQueue.pushBack(*list[i]);
}
}
+ if (isKeyFrameAnalyse && IS_X265_TYPE_I(lastNonB->sliceType))
+ {
+ slicetypeAnalyse(frames,true);
+ }
}
void Lookahead::vbvLookahead(Lowres **frames, int numFrames, int keyframe)
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 3 of 6] vbv: Add row predictors, rc states for vbv
X-Mercurial-Node: ebc23ec5ac1c5f8e2abe0d0b88414fabd2fdf1bb
Message-Id: <ebc23ec5ac1c5f8e2abe.1392901343 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:23 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org
# HG changeset patch
# User Aarthi Thirumalai
# Date 1392898673 -19800
# Thu Feb 20 17:47:53 2014 +0530
# Node ID ebc23ec5ac1c5f8e2abe0d0b88414fabd2fdf1bb
# Parent 1c037c64274dce2f39db348967259d7d623c1b18
vbv: Add row predictors, rc states for vbv.
diff -r 1c037c64274d -r ebc23ec5ac1c source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp Thu Feb 20 17:03:38 2014 +0530
+++ b/source/encoder/encoder.cpp Thu Feb 20 17:47:53 2014 +0530
@@ -218,6 +218,7 @@
FrameEncoder *encoder = &m_frameEncoder[encIdx];
double bits;
bits = encoder->m_rce.frameSizePlanned;
+ bits = X265_MAX(bits, m_rateControl->frameSizeEstimated);
rc->bufferFill -= bits;
rc->bufferFill = X265_MAX(rc->bufferFill, 0);
rc->bufferFill += encoder->m_rce.bufferRate;
diff -r 1c037c64274d -r ebc23ec5ac1c source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Thu Feb 20 17:03:38 2014 +0530
+++ b/source/encoder/ratecontrol.cpp Thu Feb 20 17:47:53 2014 +0530
@@ -243,11 +243,12 @@
lastNonBPictType = I_SLICE;
isAbrReset = false;
lastAbrResetPoc = -1;
+ frameSizeEstimated = 0;
// vbv initialization
cfg->param.rc.vbvBufferSize = Clip3(0, 2000000,
cfg->param.rc.vbvBufferSize);
cfg->param.rc.vbvMaxBitrate = Clip3(0, 2000000,
cfg->param.rc.vbvMaxBitrate);
cfg->param.rc.vbvBufferInit = Clip3(0.0, 2000000.0,
cfg->param.rc.vbvBufferInit);
-
+ vbvMinRate = 0;
if (cfg->param.rc.vbvBufferSize)
{
if (cfg->param.rc.rateControlMode == X265_RC_CQP)
@@ -318,6 +319,14 @@
pred[i].offset = 0.0;
}
+ for (int i = 0; i < 4; i++)
+ {
+ rowPreds[i].coeff = 0.25;
+ rowPreds[i].count = 1.0;
+ rowPreds[i].decay = 0.5;
+ rowPreds[i].offset = 0.0;
+ }
+
predBfromP = pred[0];
bframes = cfg->param.bframes;
bframeBits = 0;
@@ -376,7 +385,11 @@
rce->poc = curSlice->getPOC();
if (isVbv)
+ {
+ rowPred[0] = &rowPreds[sliceType];
+ rowPred[1] = &rowPreds[3];
updateVbvPlan(enc);
+ }
if (isAbr) //ABR,CRF
{
@@ -385,9 +398,10 @@
rce->lastSatd = currentSatd;
double q = qScale2qp(rateEstimateQscale(pic, rce));
qp = Clip3(MIN_QP, MAX_MAX_QP, (int)(q + 0.5));
- rce->qpaRc = q;
+ rce->qpaRc = pic->m_avgQpRc = q;
/* copy value of lastRceq into thread local rce struct *to be used
in RateControlEnd() */
rce->qRceq = lastRceq;
+ rce->qpNoVbv = qpNoVbv;
accumPQpUpdate();
}
else //CQP
@@ -399,7 +413,11 @@
}
if (sliceType != B_SLICE)
+ {
lastNonBPictType = sliceType;
+ leadingNoBSatd = currentSatd;
+ }
+ rce->leadingNoBSatd = leadingNoBSatd;
framesDone++;
/* set the final QP to slice structure */
curSlice->setSliceQp(qp);
@@ -462,9 +480,11 @@
else
q += pbOffset;
- rce->frameSizePlanned = predictSize(&predBfromP, qp2qScale(q),
leadingNoBSatd);
-
- return qp2qScale(q);
+ qpNoVbv = q;
+ double qScale = qp2qScale(qpNoVbv);
+ rce->frameSizePlanned = predictSize(&predBfromP, qScale,
(double)leadingNoBSatd);
+ frameSizeEstimated = rce->frameSizePlanned;
+ return qScale;
}
else
{
@@ -555,7 +575,7 @@
if (qCompress != 1 && framesDone == 0)
q = qp2qScale(ABR_INIT_QP) / fabs(cfg->param.rc.ipFactor);
}
-
+ qpNoVbv = qScale2qp(q);
double lmin1 = lmin[sliceType];
double lmax1 = lmax[sliceType];
q = Clip3(lmin1, lmax1, q);
@@ -840,7 +860,7 @@
if (rce->bLastMiniGopBFrame)
{
if (rce->bframes != 0)
- updatePredictor(&predBfromP, qp2qScale(rce->qpaRc),
(double)rce->lastSatd, (double)bframeBits / rce->bframes);
+ updatePredictor(&predBfromP, qp2qScale(rce->qpaRc),
(double)rce->leadingNoBSatd, (double)bframeBits / rce->bframes);
bframeBits = 0;
}
}
diff -r 1c037c64274d -r ebc23ec5ac1c source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Thu Feb 20 17:03:38 2014 +0530
+++ b/source/encoder/ratecontrol.h Thu Feb 20 17:47:53 2014 +0530
@@ -53,7 +53,7 @@
int mvBits;
int bframes;
int poc;
-
+ int64_t leadingNoBSatd;
bool bLastMiniGopBFrame;
double blurredComplexity;
double qpaRc;
@@ -61,6 +61,7 @@
double frameSizePlanned;
double bufferRate;
double movingAvgSum;
+ double qpNoVbv;
};
struct Predictor
@@ -94,9 +95,10 @@
bool isVbv;
Predictor pred[5];
Predictor predBfromP;
+ Predictor rowPreds[4];
+ Predictor *rowPred[2];
int bframes;
int bframeBits;
- double leadingNoBSatd;
bool isAbrReset;
int lastAbrResetPoc;
int64_t currentSatd;
@@ -106,6 +108,7 @@
double ipOffset;
double pbOffset;
int lastNonBPictType;
+ int64_t leadingNoBSatd;
double accumPQp; /* for determining I-frame quant */
double accumPNorm;
double lastQScaleFor[3]; /* last qscale for a specific pict type,
used for max_diff & ipb factor stuff */
@@ -118,6 +121,8 @@
double lastRceq;
int framesDone; /* framesDone keeps track of # of frames
passed through RateCotrol already */
double qCompress;
+ double qpNoVbv; /* QP for the current frame if 1-pass VBV
was disabled. */
+ double frameSizeEstimated; /* hold synched frameSize, updated from cu
level vbv rc */
RateControl(TEncCfg * _cfg);
// to be called for each frame to process RateControl and set QP
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 4 of 6] vbv: fix bugs in vbv flow with single pass ABR
X-Mercurial-Node: c5c07a3ee7fcf0f331f06f83b7b3bc0b1bcc1668
Message-Id: <c5c07a3ee7fcf0f331f0.1392901344 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:24 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org
# HG changeset patch
# User Aarthi Thirumalai
# Date 1392899993 -19800
# Thu Feb 20 18:09:53 2014 +0530
# Node ID c5c07a3ee7fcf0f331f06f83b7b3bc0b1bcc1668
# Parent ebc23ec5ac1c5f8e2abe0d0b88414fabd2fdf1bb
vbv: fix bugs in vbv flow with single pass ABR
diff -r ebc23ec5ac1c -r c5c07a3ee7fc 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
@@ -367,7 +367,7 @@
// 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);
diff -r ebc23ec5ac1c -r c5c07a3ee7fc 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,7 +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)
{
@@ -445,12 +447,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)
@@ -522,7 +524,7 @@
{
if (!isVbv)
{
- checkAndResetABR(rce);
+ checkAndResetABR(pic, rce);
}
q = getQScale(rce, wantedBitsWindow / cplxrSum);
@@ -552,23 +554,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
{
@@ -593,7 +594,7 @@
}
}
-void RateControl::checkAndResetABR(RateControlEntry* rce)
+void RateControl::checkAndResetABR(TComPic* pic, RateControlEntry* rce)
{
double abrBuffer = 2 * cfg->param.rc.rateTolerance * bitrate;
@@ -604,7 +605,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;
@@ -659,9 +660,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++)
@@ -807,9 +808,8 @@
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)
@@ -826,17 +826,27 @@
}
/* 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 ebc23ec5ac1c -r c5c07a3ee7fc 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
@@ -128,7 +128,7 @@
// 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:
@@ -142,7 +142,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);
};
}
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 5 of 6] vbv: implement row wise vbvRateControl at each row
diagonal
X-Mercurial-Node: 49b90667f050a7dd9c28b5017f389f5c29a1c191
Message-Id: <49b90667f050a7dd9c28.1392901345 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:25 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org
# 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);
};
}
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Subject: [PATCH 6 of 6] vbv: integrate row level vbv ratecontrol at each
major
row diagonal
X-Mercurial-Node: 650d5f835e417f45bd8a9f86465ca1909eaa9526
Message-Id: <650d5f835e417f45bd8a.1392901346 at Aarthi-PC.router186658.com>
In-Reply-To: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
References: <patchbomb.1392901340 at Aarthi-PC.router186658.com>
User-Agent: Mercurial-patchbomb/2.7.1
Date: Thu, 20 Feb 2014 18:32:26 +0530
From: aarthi at multicorewareinc.com
To: x265-devel at videolan.org
# HG changeset patch
# User Aarthi Thirumalai
# Date 1392901254 -19800
# Thu Feb 20 18:30:54 2014 +0530
# Node ID 650d5f835e417f45bd8a9f86465ca1909eaa9526
# Parent 49b90667f050a7dd9c28b5017f389f5c29a1c191
vbv: integrate row level vbv ratecontrol at each major row diagonal.
diff -r 49b90667f050 -r 650d5f835e41 source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp Thu Feb 20 18:23:48 2014 +0530
+++ b/source/encoder/frameencoder.cpp Thu Feb 20 18:30:54 2014 +0530
@@ -1057,6 +1057,7 @@
CTURow& codeRow = m_rows[m_cfg->param.bEnableWavefront ? row : 0];
const uint32_t numCols = m_pic->getPicSym()->getFrameWidthInCU();
const uint32_t lineStartCUAddr = row * numCols;
+ double qpBase = m_pic->m_avgQpRc;
for (uint32_t col = curRow.m_completed; col < numCols; col++)
{
const uint32_t cuAddr = lineStartCUAddr + col;
@@ -1067,24 +1068,42 @@
codeRow.m_entropyCoder.resetEntropy();
TEncSbac *bufSbac = (m_cfg->param.bEnableWavefront && col == 0 &&
row > 0) ? &m_rows[row - 1].m_bufferSbacCoder : NULL;
- if (m_cfg->param.rc.aqMode)
+
+ if ((uint32_t)row >= col && (row !=0))
+ qpBase = m_pic->getCU(cuAddr - numCols + 1)->m_baseQp;
+
+ if (m_cfg->param.rc.aqMode || (m_cfg->param.rc.vbvBufferSize >0 &&
m_cfg->param.rc.vbvMaxBitrate >0))
{
- int qp = calcQpForCu(m_pic, cuAddr);
+ int qp = calcQpForCu(m_pic, cuAddr , qpBase);
setLambda(qp, row);
- if (qp > MAX_QP)
- qp = MAX_QP;
- cu->setQP(0, (char)qp);
+ qp = X265_MIN(qp, MAX_QP);
+ cu->setQP(0,char(qp));
+ cu->m_baseQp = qpBase;
}
codeRow.processCU(cu, m_pic->getSlice(), bufSbac,
m_cfg->param.bEnableWavefront && col == 1);
- // TODO: Keep atomic running totals for rate control?
- // cu->m_totalBits;
- // cu->m_totalCost;
- // cu->m_totalDistortion;
+ if (m_cfg->param.rc.vbvBufferSize && m_cfg->param.rc.vbvMaxBitrate)
+ {
+ // Update encoded bits, satdCost, baseQP for each CU
+ m_pic->m_rowDiagSatd[row] += m_pic->m_cuCostsForVbv[cuAddr];
+ m_pic->m_rowEncodedBits[row] += cu->m_totalBits;
+ m_pic->m_numEncodedCusPerRow[row] = cuAddr;
+ m_pic->m_qpaAq[row] += cu->getQP(0);
+ m_pic->m_qpaRc[row] += cu->m_baseQp;
+
+ if ((uint32_t)row == col)
+ m_pic->m_rowDiagQp[row] = qpBase;
+
+ // If current block is at row diagonal checkpoint, call vbv
ratecontrol.
+ if ((uint32_t)row == col && row != 0 )
+ {
+ m_top->m_rateControl->rowDiagonalVbvRateControl(m_pic,
row, &m_rce, qpBase);
+ qpBase = Clip3((double)MIN_QP, (double)MAX_MAX_QP,
qpBase);
+ }
+ }
// Completed CU processing
m_rows[row].m_completed++;
-
if (m_rows[row].m_completed >= 2 && row < m_numRows - 1)
{
ScopedLock below(m_rows[row + 1].m_lock);
@@ -1128,34 +1147,43 @@
curRow.m_busy = false;
}
-int FrameEncoder::calcQpForCu(TComPic *pic, uint32_t cuAddr)
+int FrameEncoder::calcQpForCu(TComPic *pic, uint32_t cuAddr, double baseQp)
{
x265_emms();
- double qp = pic->getSlice()->m_avgQpRc;
- if (m_cfg->param.rc.aqMode)
+ double qp = baseQp;
+
+ /* Derive qpOffet for each CU by averaging offsets for all 16x16
blocks in the cu. */
+ double qp_offset = 0;
+ int maxBlockCols = (pic->getPicYuvOrg()->getWidth() + (16 - 1)) / 16;
+ int maxBlockRows = (pic->getPicYuvOrg()->getHeight() + (16 - 1)) / 16;
+ int noOfBlocks = g_maxCUWidth / 16;
+ int block_y = (cuAddr / pic->getPicSym()->getFrameWidthInCU()) *
noOfBlocks;
+ int block_x = (cuAddr * noOfBlocks) - block_y *
pic->getPicSym()->getFrameWidthInCU();
+
+ double *qpoffs = (pic->getSlice()->isReferenced() &&
m_cfg->param.rc.cuTree) ? pic->m_lowres.qpOffset : pic->m_lowres.qpAqOffset;
+ int cnt = 0, idx =0;
+ for (int h = 0; h < noOfBlocks && block_y < maxBlockRows; h++,
block_y++)
{
- /* Derive qpOffet for each CU by averaging offsets for all 16x16
blocks in the cu. */
- double qp_offset = 0;
- int maxBlockCols = (pic->getPicYuvOrg()->getWidth() + (16 - 1)) /
16;
- int maxBlockRows = (pic->getPicYuvOrg()->getHeight() + (16 - 1)) /
16;
- int noOfBlocks = g_maxCUWidth / 16;
- int block_y = (cuAddr / pic->getPicSym()->getFrameWidthInCU()) *
noOfBlocks;
- int block_x = (cuAddr * noOfBlocks) - block_y *
pic->getPicSym()->getFrameWidthInCU();
+ for (int w = 0; w < noOfBlocks && (block_x + w) < maxBlockCols;
w++)
+ {
+ idx = block_x + w + (block_y * maxBlockCols);
+ if (m_cfg->param.rc.aqMode)
+ qp_offset += qpoffs[idx];
- double *qpoffs = (pic->getSlice()->isReferenced() &&
m_cfg->param.rc.cuTree) ? pic->m_lowres.qpOffset : pic->m_lowres.qpAqOffset;
- int cnt = 0;
- for (int h = 0; h < noOfBlocks && block_y < maxBlockRows; h++,
block_y++)
- {
- for (int w = 0; w < noOfBlocks && (block_x + w) <
maxBlockCols; w++)
+ if (m_cfg->param.rc.vbvBufferSize > 0 &&
m_cfg->param.rc.vbvMaxBitrate > 0)
{
- qp_offset += qpoffs[block_x + w + (block_y *
maxBlockCols)];
- cnt++;
+ m_pic->m_cuCostsForVbv[cuAddr] +=
m_pic->m_lowres.lowresCostForRc[idx];
+ if (!m_cfg->param.rc.cuTree)
+ m_pic->m_cuCostsForVbv[cuAddr] +=
m_pic->m_lowres.intraCost[idx];
}
+ cnt++;
}
+ }
- qp_offset /= cnt;
- qp += qp_offset;
- }
+ qp_offset /= cnt;
+ qp += qp_offset;
+
+
return Clip3(MIN_QP, MAX_MAX_QP, (int)(qp + 0.5));
}
diff -r 49b90667f050 -r 650d5f835e41 source/encoder/frameencoder.h
--- a/source/encoder/frameencoder.h Thu Feb 20 18:23:48 2014 +0530
+++ b/source/encoder/frameencoder.h Thu Feb 20 18:30:54 2014 +0530
@@ -173,7 +173,7 @@
protected:
void determineSliceBounds();
- int calcQpForCu(TComPic *pic, uint32_t cuAddr);
+ int calcQpForCu (TComPic *pic, uint32_t cuAddr, double baseQp);
Encoder* m_top;
TEncCfg* m_cfg;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20140220/4e443202/attachment-0001.html>
More information about the x265-devel
mailing list