[x265] [x265 PATCH] Fix quality drop with SBRC feature
Mahesh Pittala
mahesh at multicorewareinc.com
Wed Dec 13 05:28:12 UTC 2023
Both patches pushed to master branch,
On Wed, Nov 22, 2023 at 10:54 AM Kirithika Kalirathnam <
kirithika at multicorewareinc.com> wrote:
> From d409be0b90ce91f8ffda343864636debd62ffe37 Mon Sep 17 00:00:00 2001
> From: Kirithika <kirithika at multicorewareinc.com>
> Date: Thu, 5 Oct 2023 12:26:35 +0530
> Subject: [PATCH] Fix quality drop with SBRC feature
>
> ---
> source/encoder/encoder.cpp | 21 +++++++++++++++------
> source/encoder/ratecontrol.cpp | 31 +++++++++++++++++++------------
> source/x265.h | 2 ++
> 3 files changed, 36 insertions(+), 18 deletions(-)
>
> diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
> index 8ec01bebe..1280ccc66 100644
> --- a/source/encoder/encoder.cpp
> +++ b/source/encoder/encoder.cpp
> @@ -4402,16 +4402,25 @@ void Encoder::configure(x265_param *p)
> m_param->searchRange = m_param->hmeRange[2];
> }
>
> - if (p->bEnableSBRC && p->bOpenGOP)
> + if (p->bEnableSBRC && (p->rc.rateControlMode != X265_RC_CRF ||
> (p->rc.vbvBufferSize == 0 || p->rc.vbvMaxBitrate == 0)))
> {
> - x265_log(p, X265_LOG_WARNING, "Segment based RateControl requires
> closed gop structure. Enabling closed GOP.\n");
> - p->bOpenGOP = 0;
> + x265_log(p, X265_LOG_WARNING, "SBRC can be enabled only with
> CRF+VBV mode. Disabling SBRC\n");
> + p->bEnableSBRC = 0;
> }
>
> - if (p->bEnableSBRC && (p->keyframeMax != p->keyframeMin))
> + if (p->bEnableSBRC)
> {
> - x265_log(p, X265_LOG_WARNING, "Segment based RateControl requires
> fixed gop length. Force set min-keyint equal to keyint.\n");
> - p->keyframeMin = p->keyframeMax;
> + p->rc.ipFactor = p->rc.ipFactor * X265_IPRATIO_STRENGTH;
> + if (p->bOpenGOP)
> + {
> + x265_log(p, X265_LOG_WARNING, "Segment based RateControl
> requires closed gop structure. Enabling closed GOP.\n");
> + p->bOpenGOP = 0;
> + }
> + if (p->keyframeMax != p->keyframeMin)
> + {
> + x265_log(p, X265_LOG_WARNING, "Segment based RateControl
> requires fixed gop length. Force set min-keyint equal to keyint.\n");
> + p->keyframeMin = p->keyframeMax;
> + }
> }
> }
>
> diff --git a/source/encoder/ratecontrol.cpp
> b/source/encoder/ratecontrol.cpp
> index 80f4ac3e9..099a03f0a 100644
> --- a/source/encoder/ratecontrol.cpp
> +++ b/source/encoder/ratecontrol.cpp
> @@ -433,7 +433,7 @@ void RateControl::initVBV(const SPS& sps)
>
> bool RateControl::init(const SPS& sps)
> {
> - if (m_isVbv && (!m_initVbv || m_param->bEnableSBRC))
> + if (m_isVbv && !m_initVbv)
> initVBV(sps);
>
> if (!m_param->bResetZoneConfig && (m_relativeComplexity == NULL))
> @@ -480,7 +480,7 @@ bool RateControl::init(const SPS& sps)
>
> /* estimated ratio that produces a reasonable QP for the first
> I-frame */
> m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) *
> tuneCplxFactor;
> - m_wantedBitsWindow = (m_param->bEnableSBRC ? (m_bitrate * ( 1.0 /
> m_param->keyframeMax )) :m_bitrate * m_frameDuration);
> + m_wantedBitsWindow = m_bitrate * m_frameDuration;
> m_accumPNorm = .01;
> m_accumPQp = (m_param->rc.rateControlMode == X265_RC_CRF ?
> CRF_INIT_QP : ABR_INIT_QP_MIN) * m_accumPNorm;
>
> @@ -1823,8 +1823,7 @@ double RateControl::tuneAbrQScaleFromFeedback(double
> qScale)
> double abrBuffer = 2 * m_rateTolerance * m_bitrate;
> /* use framesDone instead of POC as poc count is not serial with
> bframes enabled */
> double overflow = 1.0;
> - double duration = m_param->bEnableSBRC ? (1.0 / m_param->keyframeMax)
> : m_frameDuration;
> - double timeDone = (double)(m_framesDone - m_param->frameNumThreads +
> 1) * duration;
> + double timeDone = (double)(m_framesDone - m_param->frameNumThreads +
> 1) * m_frameDuration;
> double wantedBits = timeDone * m_bitrate;
> int64_t encodedBits = m_totalBits;
> if (m_param->totalFrames && m_param->totalFrames <= 2 * m_fps)
> @@ -1834,7 +1833,7 @@ double RateControl::tuneAbrQScaleFromFeedback(double
> qScale)
> }
>
> if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames ||
> - m_param->rc.bStrictCbr || m_isGrainEnabled ||
> m_param->bEnableSBRC))
> + m_param->rc.bStrictCbr || m_isGrainEnabled))
> {
> abrBuffer *= X265_MAX(1, sqrt(timeDone));
> overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) /
> abrBuffer);
> @@ -1924,7 +1923,7 @@ double RateControl::rateEstimateQscale(Frame*
> curFrame, RateControlEntry *rce)
> m_sliderPos++;
> }
>
> - if (m_sliceType == B_SLICE)
> + if((!m_param->bEnableSBRC && m_sliceType == B_SLICE) ||
> (m_param->bEnableSBRC && !IS_REFERENCED(curFrame)))
> {
> /* B-frames don't have independent rate control, but rather get
> the
> * average QP of the two adjacent P-frames + an offset */
> @@ -2196,8 +2195,18 @@ double RateControl::rateEstimateQscale(Frame*
> curFrame, RateControlEntry *rce)
>
> if (m_param->rc.rateControlMode == X265_RC_CRF)
> {
> - if (!m_param->rc.bStatRead && m_param->bEnableSBRC)
> - checkAndResetCRF(rce);
> + if (m_param->bEnableSBRC)
> + {
> + double rfConstant = m_param->rc.rfConstant;
> + if (m_currentSatd < rce->movingAvgSum)
> + rfConstant += 2;
> + rfConstant = (rce->sliceType == I_SLICE ? rfConstant
> - m_ipOffset :
> + (rce->sliceType == B_SLICE ? rfConstant +
> m_pbOffset : rfConstant));
> + double mbtree_offset = m_param->rc.cuTree ? (1.0 -
> m_param->rc.qCompress) * 13.5 : 0;
> + double qComp = (m_param->rc.cuTree &&
> !m_param->rc.hevcAq) ? 0.99 : m_param->rc.qCompress;
> + m_rateFactorConstant = pow(m_currentSatd, 1.0 -
> qComp) /
> + x265_qp2qScale(rfConstant + mbtree_offset);
> + }
> q = getQScale(rce, m_rateFactorConstant);
> x265_zone* zone = getZone();
> if (zone)
> @@ -2223,7 +2232,7 @@ double RateControl::rateEstimateQscale(Frame*
> curFrame, RateControlEntry *rce)
> }
> double tunedQScale =
> tuneAbrQScaleFromFeedback(initialQScale);
> overflow = tunedQScale / initialQScale;
> - q = (!m_partialResidualFrames || m_param->bEnableSBRC)?
> tunedQScale : initialQScale;
> + q = !m_partialResidualFrames ? tunedQScale :
> initialQScale;
> bool isEncodeEnd = (m_param->totalFrames &&
> m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;
> bool isEncodeBeg = m_framesDone < (int)(m_fps + 0.5);
> @@ -2420,8 +2429,6 @@ void RateControl::checkAndResetABR(RateControlEntry*
> rce, bool isFrameDone)
> m_shortTermCplxCount = 1;
> m_isAbrReset = true;
> m_lastAbrResetPoc = rce->poc;
> - if(m_param->bEnableSBRC)
> - rce->blurredComplexity = m_shortTermCplxSum /
> m_shortTermCplxCount;
> }
> }
> else if (m_isAbrReset && isFrameDone)
> @@ -3062,7 +3069,7 @@ int RateControl::rateControlEnd(Frame* curFrame,
> int64_t bits, RateControlEntry*
> * Not perfectly accurate with B-refs, but good enough. */
> m_cplxrSum += (bits * x265_qp2qScale(rce->qpaRc) /
> (rce->qRceq * fabs(m_param->rc.pbFactor))) - (rce->rowCplxrSum);
> }
> - m_wantedBitsWindow += (m_param->bEnableSBRC ? (m_bitrate * (1.0 /
> m_param->keyframeMax)) : m_frameDuration * m_bitrate);
> + m_wantedBitsWindow += m_frameDuration * m_bitrate;
> m_totalBits += bits - rce->rowTotalBits;
> m_encodedBits += actualBits;
> int pos = m_sliderPos - m_param->frameNumThreads;
> diff --git a/source/x265.h b/source/x265.h
> index fb1a5dca7..d2bee6e37 100644
> --- a/source/x265.h
> +++ b/source/x265.h
> @@ -623,6 +623,8 @@ typedef enum
> #define X265_MAX_GOP_LENGTH 16
> #define MAX_T_LAYERS 7
>
> +#define X265_IPRATIO_STRENGTH 1.43
> +
> typedef struct x265_cli_csp
> {
> int planes;
> --
> 2.28.0.windows.1
>
> *Thanks,*
> *Kirithika*
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20231213/2e16cc7b/attachment.htm>
More information about the x265-devel
mailing list