[x265] [PATCH] rc: add qpmin and qpmax options
gopi.satykrishna at multicorewareinc.com
gopi.satykrishna at multicorewareinc.com
Fri Jul 15 15:33:19 CEST 2016
# HG changeset patch
# User Gopi Satykrishna Akisetty <gopi.satykrishna at multicorewareinc.com>
# Date 1468581281 -19800
# Fri Jul 15 16:44:41 2016 +0530
# Node ID 98a948623fdc745a37123f52a00fefeecaadaad7
# Parent 43ca544799c240f6eefb66424dc73ec65b7dcfea
rc: add qpmin and qpmax options
diff -r 43ca544799c2 -r 98a948623fdc doc/reST/cli.rst
--- a/doc/reST/cli.rst Fri Jul 15 12:43:23 2016 +0530
+++ b/doc/reST/cli.rst Fri Jul 15 16:44:41 2016 +0530
@@ -1434,6 +1434,14 @@
The maximum single adjustment in QP allowed to rate control. Default
4
+.. option:: --qpmin <integer>
+
+ sets a hard lower limit on QP allowed to ratecontrol. Default 0
+
+.. option:: --qpmax <integer>
+
+ sets a hard upper limit on QP allowed to ratecontrol. Default 69
+
.. option:: --rc-grain, --no-rc-grain
Enables a specialised ratecontrol algorithm for film grain content. This
diff -r 43ca544799c2 -r 98a948623fdc source/CMakeLists.txt
--- a/source/CMakeLists.txt Fri Jul 15 12:43:23 2016 +0530
+++ b/source/CMakeLists.txt Fri Jul 15 16:44:41 2016 +0530
@@ -30,7 +30,7 @@
mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
# X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 88)
+set(X265_BUILD 89)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff -r 43ca544799c2 -r 98a948623fdc source/common/param.cpp
--- a/source/common/param.cpp Fri Jul 15 12:43:23 2016 +0530
+++ b/source/common/param.cpp Fri Jul 15 16:44:41 2016 +0530
@@ -224,6 +224,8 @@
param->rc.bEnableSlowFirstPass = 1;
param->rc.bStrictCbr = 0;
param->rc.bEnableGrain = 0;
+ param->rc.qpMin = 0;
+ param->rc.qpMax = QP_MAX_MAX;
/* Video Usability Information (VUI) */
param->vui.aspectRatioIdc = 0;
@@ -509,6 +511,7 @@
bool bError = false;
bool bNameWasBool = false;
bool bValueWasNull = !value;
+ bool bExtraParams = false;
char nameBuf[64];
if (!name)
@@ -747,6 +750,7 @@
OPT("vbv-init") p->rc.vbvBufferInit = atof(value);
OPT("crf-max") p->rc.rfConstantMax = atof(value);
OPT("crf-min") p->rc.rfConstantMin = atof(value);
+ OPT("qpmax") p->rc.qpMax = atoi(value);
OPT("crf")
{
p->rc.rfConstant = atof(value);
@@ -885,7 +889,14 @@
OPT("max-luma") p->maxLuma = (uint16_t)atoi(value);
OPT("uhd-bd") p->uhdBluray = atobool(value);
else
- return X265_PARAM_BAD_NAME;
+ bExtraParams = true;
+ if (bExtraParams)
+ {
+ if (0) ;
+ OPT("qpmin") p->rc.qpMin = atoi(value);
+ else
+ return X265_PARAM_BAD_NAME;
+ }
#undef OPT
#undef atobool
#undef atoi
@@ -1208,6 +1219,10 @@
"Strict-cbr cannot be applied without specifying target bitrate or vbv bufsize");
CHECK(param->analysisMode && (param->analysisMode < X265_ANALYSIS_OFF || param->analysisMode > X265_ANALYSIS_LOAD),
"Invalid analysis mode. Analysis mode 0: OFF 1: SAVE : 2 LOAD");
+ CHECK(param->rc.qpMax < QP_MIN || param->rc.qpMax > QP_MAX_MAX,
+ "qpmax exceeds supported range (0 to 69)");
+ CHECK(param->rc.qpMin < QP_MIN || param->rc.qpMin > QP_MAX_MAX,
+ "qpmin exceeds supported range (0 to 69)");
return check_failed;
}
@@ -1463,7 +1478,7 @@
else
s += sprintf(s, " bitrate=%d", p->rc.bitrate);
s += sprintf(s, " qcomp=%.2f qpmin=%d qpmax=%d qpstep=%d",
- p->rc.qCompress, QP_MIN, QP_MAX_SPEC, p->rc.qpStep);
+ p->rc.qCompress, p->rc.qpMin, p->rc.qpMax, p->rc.qpStep);
if (p->rc.bStatRead)
s += sprintf( s, " cplxblur=%.1f qblur=%.1f",
p->rc.complexityBlur, p->rc.qblur);
diff -r 43ca544799c2 -r 98a948623fdc source/encoder/analysis.cpp
--- a/source/encoder/analysis.cpp Fri Jul 15 12:43:23 2016 +0530
+++ b/source/encoder/analysis.cpp Fri Jul 15 16:44:41 2016 +0530
@@ -255,7 +255,7 @@
cuPrevCost = origCUCost;
int modCUQP = qp + dir;
- while (modCUQP >= QP_MIN && modCUQP <= QP_MAX_SPEC)
+ while (modCUQP >= m_param->rc.qpMin && modCUQP <= QP_MAX_SPEC)
{
recodeCU(parentCTU, cuGeom, modCUQP, qp);
cuCost = md.bestMode->rdCost;
@@ -2667,5 +2667,5 @@
qp += qp_offset;
}
- return x265_clip3(QP_MIN, QP_MAX_MAX, (int)(qp + 0.5));
+ return x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, (int)(qp + 0.5));
}
diff -r 43ca544799c2 -r 98a948623fdc source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp Fri Jul 15 12:43:23 2016 +0530
+++ b/source/encoder/frameencoder.cpp Fri Jul 15 16:44:41 2016 +0530
@@ -1127,7 +1127,7 @@
{
double qpBase = curEncData.m_cuStat[cuAddr].baseQp;
int reEncode = m_top->m_rateControl->rowDiagonalVbvRateControl(m_frame, row, &m_rce, qpBase);
- qpBase = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, qpBase);
+ qpBase = x265_clip3((double)m_param->rc.qpMin, (double)m_param->rc.qpMax, qpBase);
curEncData.m_rowStat[row].diagQp = qpBase;
curEncData.m_rowStat[row].diagQpScale = x265_qp2qScale(qpBase);
diff -r 43ca544799c2 -r 98a948623fdc source/encoder/ratecontrol.cpp
--- a/source/encoder/ratecontrol.cpp Fri Jul 15 12:43:23 2016 +0530
+++ b/source/encoder/ratecontrol.cpp Fri Jul 15 16:44:41 2016 +0530
@@ -284,7 +284,11 @@
#define ABR_SCENECUT_INIT_QP_MIN (12)
#define CRF_INIT_QP (int)m_param->rc.rfConstant
for (int i = 0; i < 3; i++)
+ {
m_lastQScaleFor[i] = x265_qp2qScale(m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN);
+ m_lmin[i] = x265_qp2qScale(m_param->rc.qpMin);
+ m_lmax[i] = x265_qp2qScale(m_param->rc.qpMax);
+ }
if (m_param->rc.rateControlMode == X265_RC_CQP)
{
@@ -808,13 +812,19 @@
(double)m_param->rc.bitrate,
expectedBits * m_fps / (m_numEntries * 1000.),
avgq);
- if (expectedBits < allAvailableBits && avgq < QP_MIN + 2)
+ if (expectedBits < allAvailableBits && avgq < m_param->rc.qpMin + 2)
{
- x265_log(m_param, X265_LOG_WARNING, "try reducing target bitrate\n");
+ if (m_param->rc.qpMin > 0)
+ x265_log(m_param, X265_LOG_WARNING, "try reducing target bitrate or reducing qp_min (currently %d)\n", m_param->rc.qpMin);
+ else
+ x265_log(m_param, X265_LOG_WARNING, "try reducing target bitrate\n");
}
- else if (expectedBits > allAvailableBits && avgq > QP_MAX_SPEC - 2)
+ else if (expectedBits > allAvailableBits && avgq > m_param->rc.qpMax - 2)
{
- x265_log(m_param, X265_LOG_WARNING, "try increasing target bitrate\n");
+ if (m_param->rc.qpMax < QP_MAX_MAX)
+ x265_log(m_param, X265_LOG_WARNING, "try increasing target bitrate or increasing qp_max (currently %d)\n", m_param->rc.qpMax);
+ else
+ x265_log(m_param, X265_LOG_WARNING, "try increasing target bitrate\n");
}
else if (!(m_2pass && m_isVbv))
x265_log(m_param, X265_LOG_WARNING, "internal error\n");
@@ -966,6 +976,8 @@
double adjustment;
double prevBits = 0;
int t0, t1;
+ double qScaleMin = x265_qp2qScale(m_param->rc.qpMin);
+ double qScaleMax = x265_qp2qScale(m_param->rc.qpMax);
int iterations = 0 , adjMin, adjMax;
CHECKED_MALLOC(fills, double, m_numEntries + 1);
fills++;
@@ -985,7 +997,7 @@
adjMin = 1;
while (adjMin && findUnderflow(fills, &t0, &t1, 1, endPos))
{
- adjMin = fixUnderflow(t0, t1, adjustment, MIN_QPSCALE, MAX_MAX_QPSCALE);
+ adjMin = fixUnderflow(t0, t1, adjustment, qScaleMin, qScaleMax);
t0 = t1;
}
}
@@ -995,7 +1007,7 @@
/* fix underflows -- should be done after overflow, as we'd better undersize target than underflowing VBV */
adjMax = 1;
while (adjMax && findUnderflow(fills, &t0, &t1, 0, endPos))
- adjMax = fixUnderflow(t0, t1, 1.001, MIN_QPSCALE, MAX_MAX_QPSCALE );
+ adjMax = fixUnderflow(t0, t1, 1.001, qScaleMin, qScaleMax);
expectedBits = countExpectedBits(startPos, endPos);
}
while ((expectedBits < .995 * allAvailableBits) && ((int64_t)(expectedBits+.5) > (int64_t)(prevBits+.5)) && !(m_param->rc.rateControlMode == X265_RC_CRF));
@@ -1216,7 +1228,7 @@
* the scene-transition mini-gop */
double q = x265_qScale2qp(rateEstimateQscale(curFrame, rce));
- q = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, q);
+ q = x265_clip3((double)m_param->rc.qpMin, (double)m_param->rc.qpMax, q);
m_qp = int(q + 0.5);
q = m_isGrainEnabled ? m_qp : q;
rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = q;
@@ -1254,7 +1266,7 @@
if (curFrame->m_forceqp)
{
m_qp = (int32_t)(curFrame->m_forceqp + 0.5) - 1;
- m_qp = x265_clip3(QP_MIN, QP_MAX_MAX, m_qp);
+ m_qp = x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, m_qp);
rce->qpaRc = curEncData.m_avgQpRc = curEncData.m_avgQpAq = m_qp;
if (m_isAbr || m_2pass)
{
@@ -1647,6 +1659,8 @@
double abrBuffer = 2 * m_rateTolerance * m_bitrate;
if (m_2pass)
{
+ double lmin = m_lmin[m_sliceType];
+ double lmax = m_lmax[m_sliceType];
int64_t diff;
if (!m_isVbv)
{
@@ -1697,17 +1711,17 @@
double sizeConstraint = 1 + expectedFullness;
qmax = X265_MAX(qmax, rce->newQScale);
if (expectedFullness < .05)
- qmax = MAX_MAX_QPSCALE;
- qmax = X265_MIN(qmax, MAX_MAX_QPSCALE);
+ qmax = lmax;
+ qmax = X265_MIN(qmax, lmax);
while (((expectedVbv < rce->expectedVbv/sizeConstraint) && (q < qmax)) ||
- ((expectedVbv < 0) && (q < MAX_MAX_QPSCALE)))
+ ((expectedVbv < 0) && (q < lmax)))
{
q *= 1.05;
expectedSize = qScale2bits(rce, q);
expectedVbv = m_bufferFill + m_bufferRate - expectedSize;
}
}
- q = x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
+ q = x265_clip3(lmin, lmax, q);
}
else
{
@@ -1724,7 +1738,8 @@
* tolerances, the bit distribution approaches that of 2pass. */
double overflow = 1;
- double lqmin = MIN_QPSCALE, lqmax = MAX_MAX_QPSCALE;
+ double lqmin = m_lmin[m_sliceType];
+ double lqmax = m_lmax[m_sliceType];
m_shortTermCplxSum *= 0.5;
m_shortTermCplxCount *= 0.5;
m_shortTermCplxSum += m_currentSatd / (CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION);
@@ -1810,7 +1825,7 @@
x265_qp2qScale(ABR_INIT_QP_MAX);
q = X265_MIN(lqmax, q);
}
- q = x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
+ q = x265_clip3(lqmin, lqmax, q);
/* Set a min qp at scenechanges and transitions */
if (m_isSceneTransition)
{
@@ -1974,6 +1989,8 @@
{
// B-frames are not directly subject to VBV,
// since they are controlled by referenced P-frames' QPs.
+ double lmin = m_lmin[m_sliceType];
+ double lmax = m_lmax[m_sliceType];
double q0 = q;
if (m_isVbv && m_currentSatd > 0 && curFrame)
{
@@ -2087,20 +2104,20 @@
if (m_rateFactorMaxIncrement)
{
double qpNoVbv = x265_qScale2qp(q0);
- double qmax = X265_MIN(MAX_MAX_QPSCALE,x265_qp2qScale(qpNoVbv + m_rateFactorMaxIncrement));
- return x265_clip3(MIN_QPSCALE, qmax, q);
+ double qmax = X265_MIN(lmax,x265_qp2qScale(qpNoVbv + m_rateFactorMaxIncrement));
+ return x265_clip3(lmin, qmax, q);
}
}
if (m_2pass)
{
- double min = log(MIN_QPSCALE);
- double max = log(MAX_MAX_QPSCALE);
+ double min = log(lmin);
+ double max = log(lmax);
q = (log(q) - min) / (max - min) - 0.5;
q = 1.0 / (1.0 + exp(-4 * q));
q = q*(max - min) + min;
return exp(q);
}
- return x265_clip3(MIN_QPSCALE, MAX_MAX_QPSCALE, q);
+ return x265_clip3(lmin, lmax, q);
}
double RateControl::predictRowsSizeSum(Frame* curFrame, RateControlEntry* rce, double qpVbv, int32_t& encodedBitsSoFar)
@@ -2215,8 +2232,8 @@
int canReencodeRow = 1;
/* tweak quality based on difference from predicted size */
double prevRowQp = qpVbv;
- double qpAbsoluteMax = QP_MAX_MAX;
- double qpAbsoluteMin = QP_MIN;
+ double qpAbsoluteMax = m_param->rc.qpMax;
+ double qpAbsoluteMin = m_param->rc.qpMin;
if (m_rateFactorMaxIncrement)
qpAbsoluteMax = X265_MIN(qpAbsoluteMax, rce->qpNoVbv + m_rateFactorMaxIncrement);
@@ -2435,7 +2452,7 @@
avgQpRc += curEncData.m_rowStat[i].sumQpRc;
avgQpRc /= slice->m_sps->numCUsInFrame;
- curEncData.m_avgQpRc = x265_clip3((double)QP_MIN, (double)QP_MAX_MAX, avgQpRc);
+ curEncData.m_avgQpRc = x265_clip3((double)m_param->rc.qpMin, (double)m_param->rc.qpMax, avgQpRc);
rce->qpaRc = curEncData.m_avgQpRc;
}
diff -r 43ca544799c2 -r 98a948623fdc source/encoder/ratecontrol.h
--- a/source/encoder/ratecontrol.h Fri Jul 15 12:43:23 2016 +0530
+++ b/source/encoder/ratecontrol.h Fri Jul 15 16:44:41 2016 +0530
@@ -162,6 +162,8 @@
double m_accumPNorm;
double m_lastQScaleFor[3]; /* last qscale for a specific pict type, used for max_diff & ipb factor stuff */
double m_lstep;
+ double m_lmin[3];
+ double m_lmax[3];
double m_shortTermCplxSum;
double m_shortTermCplxCount;
double m_lastRceq;
diff -r 43ca544799c2 -r 98a948623fdc source/encoder/sao.cpp
--- a/source/encoder/sao.cpp Fri Jul 15 12:43:23 2016 +0530
+++ b/source/encoder/sao.cpp Fri Jul 15 16:44:41 2016 +0530
@@ -1197,7 +1197,7 @@
int qpCb = qp;
if (m_param->internalCsp == X265_CSP_I420)
- qpCb = x265_clip3(QP_MIN, QP_MAX_MAX, (int)g_chromaScale[qp + slice->m_pps->chromaQpOffset[0]]);
+ qpCb = x265_clip3(m_param->rc.qpMin, m_param->rc.qpMax, (int)g_chromaScale[qp + slice->m_pps->chromaQpOffset[0]]);
else
qpCb = X265_MIN(qp + slice->m_pps->chromaQpOffset[0], QP_MAX_SPEC);
diff -r 43ca544799c2 -r 98a948623fdc source/x265.h
--- a/source/x265.h Fri Jul 15 12:43:23 2016 +0530
+++ b/source/x265.h Fri Jul 15 16:44:41 2016 +0530
@@ -1161,6 +1161,12 @@
/* internally enable if tune grain is set */
int bEnableGrain;
+
+ /* sets a hard upper limit on QP */
+ int qpMax;
+
+ /* sets a hard lower limit on QP */
+ int qpMin;
} rc;
/*== Video Usability Information ==*/
diff -r 43ca544799c2 -r 98a948623fdc source/x265cli.h
--- a/source/x265cli.h Fri Jul 15 12:43:23 2016 +0530
+++ b/source/x265cli.h Fri Jul 15 16:44:41 2016 +0530
@@ -152,6 +152,8 @@
{ "pbratio", required_argument, NULL, 0 },
{ "qcomp", required_argument, NULL, 0 },
{ "qpstep", required_argument, NULL, 0 },
+ { "qpmin", required_argument, NULL, 0 },
+ { "qpmax", required_argument, NULL, 0 },
{ "ratetol", required_argument, NULL, 0 },
{ "cplxblur", required_argument, NULL, 0 },
{ "qblur", required_argument, NULL, 0 },
@@ -388,6 +390,8 @@
H1(" --pbratio <float> QP factor between P and B. Default %.2f\n", param->rc.pbFactor);
H1(" --qcomp <float> Weight given to predicted complexity. Default %.2f\n", param->rc.qCompress);
H1(" --qpstep <integer> The maximum single adjustment in QP allowed to rate control. Default %d\n", param->rc.qpStep);
+ H1(" --qpmin <integer> sets a hard lower limit on QP allowed to ratecontrol. Default %d\n", param->rc.qpMin);
+ H1(" --qpmax <integer> sets a hard upper limit on QP allowed to ratecontrol. Default %d\n", param->rc.qpMax);
H1(" --cbqpoffs <integer> Chroma Cb QP Offset [-12..12]. Default %d\n", param->cbQpOffset);
H1(" --crqpoffs <integer> Chroma Cr QP Offset [-12..12]. Default %d\n", param->crQpOffset);
H1(" --scaling-list <string> Specify a file containing HM style quant scaling lists or 'default' or 'off'. Default: off\n");
More information about the x265-devel
mailing list