[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