[x265] [PATCH] Relax frame level bitrate constraints with frame-rc feature

Kirithika Kalirathnam kirithika at multicorewareinc.com
Thu Mar 6 09:23:02 UTC 2025


>From bd0a7bb60ede41680f6217bf32f05805db779b2f Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 29 Nov 2024 14:07:31 +0530
Subject: [PATCH] Relax frame level bitrate constraints with frame-rc feature

This patch relaxes the frame level bitrate constraints when frame-rc is enabled in bitrate mode
to improve quality
---
 source/encoder/ratecontrol.cpp | 65 +++-------------------------------
 source/encoder/ratecontrol.h   |  1 -
 2 files changed, 4 insertions(+), 62 deletions(-)

diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
index b2db871ac..6749503b1 100644
--- a/source/encoder/ratecontrol.cpp
+++ b/source/encoder/ratecontrol.cpp
@@ -1863,14 +1863,10 @@ double RateControl::tuneAbrQScaleFromFeedback(double qScale)
     }

     if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames ||
-        m_param->rc.bStrictCbr || m_isGrainEnabled || (m_bRcReConfig && m_param->rc.rateControlMode == X265_RC_ABR)))
+        m_param->rc.bStrictCbr || m_isGrainEnabled))
     {
         abrBuffer *= X265_MAX(1, sqrt(timeDone));
         overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) / abrBuffer);
-        if (m_bRcReConfig && overflow > 1.05)
-            qScale *= m_lstep;
-        if (m_bRcReConfig && overflow < 0.95)
-            qScale /= m_lstep;
         qScale *= overflow;
     }
     return qScale;
@@ -1920,7 +1916,6 @@ double RateControl::tuneQScaleForGrain(double rcOverflow)
 double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)
 {
     double q;
-
     if (m_2pass)
     {
         if (m_sliceType != rce->sliceType)
@@ -2097,13 +2092,6 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)
                     qScale = x265_clip3(lmin, lmax, qScale);
                 m_lastQScaleFor[m_sliceType] = qScale;
             }
-
-            if (m_bRcReConfig && m_param->rc.rateControlMode == X265_RC_ABR)
-            {
-                qScale = tuneQscaleToUpdatedBitrate(curFrame, qScale);
-                rce->qpNoVbv = x265_qScale2qp(qScale);
-                m_lastQScaleFor[m_sliceType] = qScale;
-            }
         }

         if (m_2pass)
@@ -2299,7 +2287,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)
                 }
                 double tunedQScale = tuneAbrQScaleFromFeedback(initialQScale);
                 overflow = tunedQScale / initialQScale;
-                q = (!m_partialResidualFrames || m_bRcReConfig) ? 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);
@@ -2326,7 +2314,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)
                 {
                     lqmin = m_lastQScaleFor[m_sliceType] / m_lstep;
                     lqmax = m_lastQScaleFor[m_sliceType] * m_lstep;
-                    if (!m_partialResidualFrames || m_isGrainEnabled || m_bRcReConfig)
+                    if (!m_partialResidualFrames || m_isGrainEnabled)
                     {
                         if (overflow > 1.1 && m_framesDone > 3)
                             lqmax *= m_lstep;
@@ -2385,13 +2373,6 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)
                 rce->qpNoVbv = x265_qScale2qp(q);
             }
             q = clipQscale(curFrame, rce, q);
-
-            if (m_bRcReConfig && m_param->rc.rateControlMode == X265_RC_ABR)
-            {
-                q = tuneQscaleToUpdatedBitrate(curFrame, q);
-                rce->qpNoVbv = x265_qScale2qp(q);
-            }
-
             if (m_2pass)
                 rce->frameSizePlanned = qScale2bits(rce, q);
             else
@@ -2582,43 +2563,6 @@ double RateControl::tuneQscaleForSBRC(Frame* curFrame, double q)
     return q;
 }

-double RateControl::tuneQscaleToUpdatedBitrate(Frame* curFrame, double q)
-{
-    int depth = 18;
-    if (m_isVbv && m_currentSatd > 0 && curFrame)
-    {
-        for (int iterations = 0; iterations < 100; iterations++)
-        {
-            int i;
-            double frameBitsTotal = m_fps * predictSize(&m_pred[m_predType], q, (double)m_currentSatd);
-            for (i = 0; i < depth; i++)
-            {
-                int type = curFrame->m_lowres.plannedType[i];
-                if (type == X265_TYPE_AUTO)
-                    break;
-                int64_t satd = curFrame->m_lowres.plannedSatd[i] >> (X265_DEPTH - 8);
-                type = IS_X265_TYPE_I(curFrame->m_lowres.plannedType[i]) ? I_SLICE : IS_X265_TYPE_B(curFrame->m_lowres.plannedType[i]) ? B_SLICE : P_SLICE;
-                int predType = getPredictorType(curFrame->m_lowres.plannedType[i], type);
-                double curBits = m_fps * predictSize(&m_pred[predType], q, (double)satd);
-                frameBitsTotal += curBits;
-            }
-            frameBitsTotal /= i;
-            double allowedSize = (double)(curFrame->m_targetBitrate * 1000);
-            if (frameBitsTotal >= 1.1 * allowedSize)
-                q = q * 1.1;
-            else if (frameBitsTotal >= 1.05 * allowedSize)
-                q = q * 1.05;
-            else if (frameBitsTotal <= 0.9 * allowedSize)
-                q = q / 1.1;
-            else if (frameBitsTotal <= 0.95 * allowedSize)
-                q = q / 1.05;
-            else
-                break;
-        }
-    }
-    return q;
-}
-
 double RateControl::clipQscale(Frame* curFrame, RateControlEntry* rce, double q)
 {
     // B-frames are not directly subject to VBV,
@@ -2656,8 +2600,7 @@ double RateControl::clipQscale(Frame* curFrame, RateControlEntry* rce, double q)
                     if (type == X265_TYPE_AUTO || totalDuration >= 1.0)
                         break;
                     totalDuration += m_frameDuration;
-                    double wantedFrameSize = ((m_bRcReConfig && m_param->rc.rateControlMode == X265_RC_ABR) ?
-                        curFrame->m_targetBitrate * 1000 : m_vbvMaxRate) * m_frameDuration;
+                    double wantedFrameSize = m_vbvMaxRate * m_frameDuration;
                     if (bufferFillCur + wantedFrameSize <= m_bufferSize)
                         bufferFillCur += wantedFrameSize;
                     int64_t satd = curFrame->m_lowres.plannedSatd[j] >> (X265_DEPTH - 8);
diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h
index 9a6b889b8..40e568d53 100644
--- a/source/encoder/ratecontrol.h
+++ b/source/encoder/ratecontrol.h
@@ -303,7 +303,6 @@ protected:
     double tuneAbrQScaleFromFeedback(double qScale);
     double tuneQScaleForZone(RateControlEntry *rce, double qScale); // Tune qScale to adhere to zone budget
     double tuneQscaleForSBRC(Frame* curFrame, double q); // Tune qScale to adhere to segment budget
-    double tuneQscaleToUpdatedBitrate(Frame* curFrame, double q); // Tune qScale according to updated bitrate
     void   accumPQpUpdate();

     int    getPredictorType(int lowresSliceType, int sliceType);
--
2.28.0.windows.1



-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20250306/d5a5003f/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-frame-rc.diff
Type: application/octet-stream
Size: 7252 bytes
Desc: patch-frame-rc.diff
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20250306/d5a5003f/attachment-0001.obj>


More information about the x265-devel mailing list