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