[x265] [PATCH] rc: add qpmin and qpmax options
Deepthi Nandakumar
deepthi at multicorewareinc.com
Tue Jul 19 07:24:23 CEST 2016
On Fri, Jul 15, 2016 at 7:03 PM, <gopi.satykrishna at multicorewareinc.com>
wrote:
> # 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);
>
I suggest you print this only if they are different from the defaults, to
avoid cluttering up the console output.
> 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)
>
This should be qpMax?
> {
> 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");
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
--
Deepthi Nandakumar
Engineering Manager, x265
Multicoreware, Inc
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20160719/8c8797b0/attachment-0001.html>
More information about the x265-devel
mailing list