[x265] [x265 PATCH] Fix quality drop with SBRC feature

Kirithika Kalirathnam kirithika at multicorewareinc.com
Wed Nov 22 05:24:02 UTC 2023


>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*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20231122/1e2090fc/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch2-sbrc.diff
Type: application/octet-stream
Size: 7865 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20231122/1e2090fc/attachment-0001.obj>


More information about the x265-devel mailing list