[x265] [PATCH] Add support for Segment Based Rate Control

Kirithika Kalirathnam kirithika at multicorewareinc.com
Thu Jan 5 04:12:12 UTC 2023


Please find the updated version

>From 3f30f806b0e4235eb6ab805f23330a8311f086b6 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Fri, 9 Dec 2022 12:31:27 +0530
Subject: [PATCH] Add support for Segment Based Rate Control

1.Configure segment length based on keyint
2.Changes frame duration settings with SBRC 3.Reset RateControl (CRF/ABR)
at the segment beginning
---
 doc/reST/cli.rst               |   3 +-
 source/common/common.h         |   2 -
 source/encoder/encoder.cpp     |  12 ++++
 source/encoder/ratecontrol.cpp | 108 +++++++++++++++++++--------------
 source/encoder/ratecontrol.h   |   3 +
 5 files changed, 80 insertions(+), 48 deletions(-)

diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index f40afc65c..f1d9fa36c 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -1761,7 +1761,8 @@ Quality, rate control and rate distortion options

 .. option:: --sbrc --no-sbrc

- To enable and disable segment based rate control.
+ To enable and disable segment based rate control.Segment duration depends
on the
+ keyframe interval specified.If unspecified,default keyframe interval will
be used.
  Default: disabled.

 .. option:: --hevc-aq
diff --git a/source/common/common.h b/source/common/common.h
index 3d7fc1ebf..37c19ae72 100644
--- a/source/common/common.h
+++ b/source/common/common.h
@@ -130,7 +130,6 @@ typedef uint64_t sum2_t;
 typedef uint64_t pixel4;
 typedef int64_t  ssum2_t;
 #define SHIFT_TO_BITPLANE 9
-#define HISTOGRAM_BINS 1024
 #else
 typedef uint8_t  pixel;
 typedef uint16_t sum_t;
@@ -138,7 +137,6 @@ typedef uint32_t sum2_t;
 typedef uint32_t pixel4;
 typedef int32_t  ssum2_t; // Signed sum
 #define SHIFT_TO_BITPLANE 7
-#define HISTOGRAM_BINS 256
 #endif // if HIGH_BIT_DEPTH

 #if X265_DEPTH < 10
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 64a4e231c..f20c9a266 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -4396,6 +4396,18 @@ void Encoder::configure(x265_param *p)
         if (m_param->searchRange != m_param->hmeRange[2])
             m_param->searchRange = m_param->hmeRange[2];
     }
+
+    if (p->bEnableSBRC && p->bOpenGOP)
+    {
+        x265_log(p, X265_LOG_WARNING, "Segment based RateControl requires
closed gop structure. Enabling closed GOP.\n");
+        p->bOpenGOP = 0;
+    }
+
+    if (p->bEnableSBRC && (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;
+    }
 }

 void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc,
const x265_picture* picIn, int paramBytes)
diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
index 090d0a35f..162c9dd7b 100644
--- a/source/encoder/ratecontrol.cpp
+++ b/source/encoder/ratecontrol.cpp
@@ -392,46 +392,48 @@ bool RateControl::initCUTreeSharedMem()
     return true;
 }

-bool RateControl::init(const SPS& sps)
+void RateControl::initVBV(const SPS& sps)
 {
-    if (m_isVbv && !m_initVbv)
+    /* We don't support changing the ABR bitrate right now,
+ * so if the stream starts as CBR, keep it CBR. */
+    if (m_param->rc.vbvBufferSize < (int)(m_param->rc.vbvMaxBitrate /
m_fps))
     {
-        /* We don't support changing the ABR bitrate right now,
-         * so if the stream starts as CBR, keep it CBR. */
-        if (m_param->rc.vbvBufferSize < (int)(m_param->rc.vbvMaxBitrate /
m_fps))
-        {
-            m_param->rc.vbvBufferSize = (int)(m_param->rc.vbvMaxBitrate /
m_fps);
-            x265_log(m_param, X265_LOG_WARNING, "VBV buffer size cannot be
smaller than one frame, using %d kbit\n",
-                     m_param->rc.vbvBufferSize);
-        }
-        int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;
-        int vbvMaxBitrate = m_param->rc.vbvMaxBitrate * 1000;
+        m_param->rc.vbvBufferSize = (int)(m_param->rc.vbvMaxBitrate /
m_fps);
+        x265_log(m_param, X265_LOG_WARNING, "VBV buffer size cannot be
smaller than one frame, using %d kbit\n",
+            m_param->rc.vbvBufferSize);
+    }
+    int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;
+    int vbvMaxBitrate = m_param->rc.vbvMaxBitrate * 1000;

-        if (m_param->bEmitHRDSEI && !m_param->decoderVbvMaxRate)
-        {
-            const HRDInfo* hrd = &sps.vuiParameters.hrdParameters;
-            vbvBufferSize = hrd->cpbSizeValue << (hrd->cpbSizeScale +
CPB_SHIFT);
-            vbvMaxBitrate = hrd->bitRateValue << (hrd->bitRateScale +
BR_SHIFT);
-        }
-        m_bufferRate = vbvMaxBitrate / m_fps;
-        m_vbvMaxRate = vbvMaxBitrate;
-        m_bufferSize = vbvBufferSize;
-        m_singleFrameVbv = m_bufferRate * 1.1 > m_bufferSize;
+    if (m_param->bEmitHRDSEI && !m_param->decoderVbvMaxRate)
+    {
+        const HRDInfo* hrd = &sps.vuiParameters.hrdParameters;
+        vbvBufferSize = hrd->cpbSizeValue << (hrd->cpbSizeScale +
CPB_SHIFT);
+        vbvMaxBitrate = hrd->bitRateValue << (hrd->bitRateScale +
BR_SHIFT);
+    }
+    m_bufferRate = vbvMaxBitrate / m_fps;
+    m_vbvMaxRate = vbvMaxBitrate;
+    m_bufferSize = vbvBufferSize;
+    m_singleFrameVbv = m_bufferRate * 1.1 > m_bufferSize;
+
+    if (m_param->rc.vbvBufferInit > 1.)
+        m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0,
m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);
+    if (m_param->vbvBufferEnd > 1.)
+        m_param->vbvBufferEnd = x265_clip3(0.0, 1.0, m_param->vbvBufferEnd
/ m_param->rc.vbvBufferSize);
+    if (m_param->vbvEndFrameAdjust > 1.)
+        m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0,
m_param->vbvEndFrameAdjust);
+    m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0,
X265_MAX(m_param->rc.vbvBufferInit, m_bufferRate / m_bufferSize));
+    m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;
+    m_bufferFillActual = m_bufferFillFinal;
+    m_bufferExcess = 0;
+    m_minBufferFill = m_param->minVbvFullness / 100;
+    m_maxBufferFill = 1 - (m_param->maxVbvFullness / 100);
+}

-        if (m_param->rc.vbvBufferInit > 1.)
-            m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0,
m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);
-        if (m_param->vbvBufferEnd > 1.)
-            m_param->vbvBufferEnd = x265_clip3(0.0, 1.0,
m_param->vbvBufferEnd / m_param->rc.vbvBufferSize);
-        if (m_param->vbvEndFrameAdjust > 1.)
-            m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0,
m_param->vbvEndFrameAdjust);
-        m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0,
X265_MAX(m_param->rc.vbvBufferInit, m_bufferRate / m_bufferSize));
-        m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;
-        m_bufferFillActual = m_bufferFillFinal;
-        m_bufferExcess = 0;
-        m_minBufferFill = m_param->minVbvFullness / 100;
-        m_maxBufferFill = 1 - (m_param->maxVbvFullness / 100);
-        m_initVbv = true;
-    }
+bool RateControl::init(const SPS& sps)
+{
+    if (m_isVbv)
+        initVBV(sps);

     if (!m_param->bResetZoneConfig && (m_relativeComplexity == NULL))
     {
@@ -477,7 +479,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_bitrate * m_frameDuration;
+    m_wantedBitsWindow = (m_param->bEnableSBRC ? (m_bitrate * ( 1.0 /
m_param->keyframeMax )) :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;

@@ -1819,7 +1821,8 @@ 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 timeDone = (double)(m_framesDone - m_param->frameNumThreads +
1) * m_frameDuration;
+    double duration = m_param->bEnableSBRC ? (1.0 / m_param->keyframeMax)
: m_frameDuration;
+    double timeDone = (double)(m_framesDone - m_param->frameNumThreads +
1) * duration;
     double wantedBits = timeDone * m_bitrate;
     int64_t encodedBits = m_totalBits;
     if (m_param->totalFrames && m_param->totalFrames <= 2 * m_fps)
@@ -1829,7 +1832,7 @@ double RateControl::tuneAbrQScaleFromFeedback(double
qScale)
     }

     if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames ||
-        m_param->rc.bStrictCbr || m_isGrainEnabled))
+        m_param->rc.bStrictCbr || m_isGrainEnabled ||
m_param->bEnableSBRC))
     {
         abrBuffer *= X265_MAX(1, sqrt(timeDone));
         overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) /
abrBuffer);
@@ -2191,6 +2194,8 @@ 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);
                 q = getQScale(rce, m_rateFactorConstant);
                 x265_zone* zone = getZone();
                 if (zone)
@@ -2216,7 +2221,7 @@ double RateControl::rateEstimateQscale(Frame*
curFrame, RateControlEntry *rce)
                 }
                 double tunedQScale =
tuneAbrQScaleFromFeedback(initialQScale);
                 overflow = tunedQScale / initialQScale;
-                q = !m_partialResidualFrames? tunedQScale : initialQScale;
+                q = (!m_partialResidualFrames || m_param->bEnableSBRC)?
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);
@@ -2385,15 +2390,27 @@ void
RateControl::rateControlUpdateStats(RateControlEntry* rce)
     }
 }

+
+void RateControl::checkAndResetCRF(RateControlEntry* rce)
+{
+    if(rce->poc % m_param->keyframeMax == 0)
+    {
+        init(*m_curSlice->m_sps);
+        m_shortTermCplxSum = rce->lastSatd /
(CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION);
+        m_shortTermCplxCount = 1;
+        rce->blurredComplexity = m_shortTermCplxSum / m_shortTermCplxCount;
+    }
+}
+
 void RateControl::checkAndResetABR(RateControlEntry* rce, bool isFrameDone)
 {
     double abrBuffer = 2 * m_rateTolerance * m_bitrate;

     // Check if current Slice is a scene cut that follows low
detailed/blank frames
-    if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut ||
rce->isFadeEnd)
+    if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut ||
rce->isFadeEnd || (m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax
== 0)))
     {
         if (!m_isAbrReset && rce->movingAvgSum > 0
-            && (m_isPatternPresent || !m_param->bframes))
+            && (m_isPatternPresent || !m_param->bframes
||(m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0))))
         {
             int pos = X265_MAX(m_sliderPos - m_param->frameNumThreads, 0);
             int64_t shrtTermWantedBits = (int64_t) (X265_MIN(pos,
s_slidingWindowFrames) * m_bitrate * m_frameDuration);
@@ -2403,7 +2420,7 @@ void RateControl::checkAndResetABR(RateControlEntry*
rce, bool isFrameDone)
                 shrtTermTotalBitsSum += m_encodedBitsWindow[i];
             double underflow = (shrtTermTotalBitsSum - shrtTermWantedBits)
/ abrBuffer;
             const double epsilon = 0.0001f;
-            if ((underflow < epsilon || rce->isFadeEnd) && !isFrameDone)
+            if ((underflow < epsilon || rce->isFadeEnd ||
(m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0))) &&
!isFrameDone)
             {
                 init(*m_curSlice->m_sps);
                 // Reduce tune complexity factor for scenes that follow
blank frames
@@ -2413,6 +2430,7 @@ void RateControl::checkAndResetABR(RateControlEntry*
rce, bool isFrameDone)
                 m_shortTermCplxCount = 1;
                 m_isAbrReset = true;
                 m_lastAbrResetPoc = rce->poc;
+                rce->blurredComplexity = m_shortTermCplxSum /
m_shortTermCplxCount;
             }
         }
         else if (m_isAbrReset && isFrameDone)
@@ -2487,7 +2505,7 @@ double RateControl::clipQscale(Frame* curFrame,
RateControlEntry* rce, double q)
                 for (int j = 0; bufferFillCur >= 0 && iter ; j++)
                 {
                     int type = curFrame->m_lowres.plannedType[j];
-                    if (type == X265_TYPE_AUTO || totalDuration >= 1.0)
+                    if (type == X265_TYPE_AUTO || totalDuration >= 1.0 ||
(m_param->bEnableSBRC && type == X265_TYPE_IDR))
                         break;
                     totalDuration += m_frameDuration;
                     double wantedFrameSize = m_vbvMaxRate *
m_frameDuration;
@@ -3053,7 +3071,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_frameDuration * m_bitrate;
+        m_wantedBitsWindow += (m_param->bEnableSBRC ? (m_bitrate * (1.0 /
m_param->keyframeMax)) : m_frameDuration * m_bitrate);
         m_totalBits += bits - rce->rowTotalBits;
         m_encodedBits += actualBits;
         int pos = m_sliderPos - m_param->frameNumThreads;
diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h
index e9fd0e182..9c2fe0ed6 100644
--- a/source/encoder/ratecontrol.h
+++ b/source/encoder/ratecontrol.h
@@ -150,6 +150,7 @@ public:
     int    m_lastScenecutAwareIFrame;
     double m_rateTolerance;
     double m_frameDuration;     /* current frame duration in seconds */
+    double m_frameDurInGOP;     /* current frame duration when considered
as a segment */
     double m_bitrate;
     double m_rateFactorConstant;
     double m_bufferSize;
@@ -255,6 +256,7 @@ public:
     RateControl(x265_param& p, Encoder *enc);
     bool init(const SPS& sps);
     void initHRD(SPS& sps);
+    void initVBV(const SPS& sps);
     void reconfigureRC();

     void setFinalFrameCount(int count);
@@ -315,6 +317,7 @@ protected:
     double tuneQScaleForGrain(double rcOverflow);
     void   splitdeltaPOC(char deltapoc[], RateControlEntry *rce);
     void   splitbUsed(char deltapoc[], RateControlEntry *rce);
+    void   checkAndResetCRF(RateControlEntry* rce);
 };
 }
 #endif // ifndef X265_RATECONTROL_H
-- 
2.28.0.windows.1

*Thanks,*
*Kirithika*


On Thu, Dec 29, 2022 at 9:59 PM Kirithika Kalirathnam <
kirithika at multicorewareinc.com> wrote:

> From 817342031263956fba544b1aac9f29e814bb1fdf Mon Sep 17 00:00:00 2001
> From: Kirithika <kirithika at multicorewareinc.com>
> Date: Fri, 9 Dec 2022 12:31:27 +0530
> Subject: [PATCH] Add support for Segment Based Rate Control
>
> 1.Configure keyframe interval to be 2 seconds
>
> 2.Changes frame duration settings with SBRC 3.Reset RateControl (CRF/ABR)
> at the GOP beginning
> ---
>  source/encoder/encoder.cpp     |  10 +++
>  source/encoder/ratecontrol.cpp | 110 ++++++++++++++++++++-------------
>  source/encoder/ratecontrol.h   |   3 +
>  3 files changed, 79 insertions(+), 44 deletions(-)
>
> diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
> index 64a4e231c..ad15b984a 100644
> --- a/source/encoder/encoder.cpp
> +++ b/source/encoder/encoder.cpp
> @@ -4396,6 +4396,16 @@ void Encoder::configure(x265_param *p)
>          if (m_param->searchRange != m_param->hmeRange[2])
>              m_param->searchRange = m_param->hmeRange[2];
>      }
> +
> +    if (m_param->bEnableSBRC && p->bOpenGOP)
> +    {
> +        x265_log(p, X265_LOG_WARNING, "Segment based RateControl requires
> closed gop structure. Enabling closed GOP.\n");
> +        m_param->bOpenGOP = 0;
> +
> +        //Configure GOP to 2s duration
> +        p->keyframeMax = 2 * (m_param->fpsNum / m_param->fpsDenom);
> +        p->keyframeMin = 2 * (m_param->fpsNum / m_param->fpsDenom);
> +    }
>  }
>
>  void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc,
> const x265_picture* picIn, int paramBytes)
> diff --git a/source/encoder/ratecontrol.cpp
> b/source/encoder/ratecontrol.cpp
> index 32399eda6..1c29e4a00 100644
> --- a/source/encoder/ratecontrol.cpp
> +++ b/source/encoder/ratecontrol.cpp
> @@ -392,45 +392,49 @@ bool RateControl::initCUTreeSharedMem()
>      return true;
>  }
>
> -bool RateControl::init(const SPS& sps)
> +void RateControl::initVBV(const SPS& sps)
>  {
> -    if (m_isVbv && !m_initVbv)
> +    /* We don't support changing the ABR bitrate right now,
> + * so if the stream starts as CBR, keep it CBR. */
> +    if (m_param->rc.vbvBufferSize < (int)(m_param->rc.vbvMaxBitrate /
> m_fps))
>      {
> -        /* We don't support changing the ABR bitrate right now,
> -         * so if the stream starts as CBR, keep it CBR. */
> -        if (m_param->rc.vbvBufferSize < (int)(m_param->rc.vbvMaxBitrate /
> m_fps))
> -        {
> -            m_param->rc.vbvBufferSize = (int)(m_param->rc.vbvMaxBitrate /
> m_fps);
> -            x265_log(m_param, X265_LOG_WARNING, "VBV buffer size cannot
> be smaller than one frame, using %d kbit\n",
> -                     m_param->rc.vbvBufferSize);
> -        }
> -        int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;
> -        int vbvMaxBitrate = m_param->rc.vbvMaxBitrate * 1000;
> +        m_param->rc.vbvBufferSize = (int)(m_param->rc.vbvMaxBitrate /
> m_fps);
> +        x265_log(m_param, X265_LOG_WARNING, "VBV buffer size cannot be
> smaller than one frame, using %d kbit\n",
> +            m_param->rc.vbvBufferSize);
> +    }
> +    int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;
> +    int vbvMaxBitrate = m_param->rc.vbvMaxBitrate * 1000;
>
> -        if (m_param->bEmitHRDSEI && !m_param->decoderVbvMaxRate)
> -        {
> -            const HRDInfo* hrd = &sps.vuiParameters.hrdParameters;
> -            vbvBufferSize = hrd->cpbSizeValue << (hrd->cpbSizeScale +
> CPB_SHIFT);
> -            vbvMaxBitrate = hrd->bitRateValue << (hrd->bitRateScale +
> BR_SHIFT);
> -        }
> -        m_bufferRate = vbvMaxBitrate / m_fps;
> -        m_vbvMaxRate = vbvMaxBitrate;
> -        m_bufferSize = vbvBufferSize;
> -        m_singleFrameVbv = m_bufferRate * 1.1 > m_bufferSize;
> +    if (m_param->bEmitHRDSEI && !m_param->decoderVbvMaxRate)
> +    {
> +        const HRDInfo* hrd = &sps.vuiParameters.hrdParameters;
> +        vbvBufferSize = hrd->cpbSizeValue << (hrd->cpbSizeScale +
> CPB_SHIFT);
> +        vbvMaxBitrate = hrd->bitRateValue << (hrd->bitRateScale +
> BR_SHIFT);
> +    }
> +    m_bufferRate = vbvMaxBitrate / m_fps;
> +    m_vbvMaxRate = vbvMaxBitrate;
> +    m_bufferSize = vbvBufferSize;
> +    m_singleFrameVbv = m_bufferRate * 1.1 > m_bufferSize;
> +
> +    if (m_param->rc.vbvBufferInit > 1.)
> +        m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0,
> m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);
> +    if (m_param->vbvBufferEnd > 1.)
> +        m_param->vbvBufferEnd = x265_clip3(0.0, 1.0,
> m_param->vbvBufferEnd / m_param->rc.vbvBufferSize);
> +    if (m_param->vbvEndFrameAdjust > 1.)
> +        m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0,
> m_param->vbvEndFrameAdjust);
> +    m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0,
> X265_MAX(m_param->rc.vbvBufferInit, m_bufferRate / m_bufferSize));
> +    m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;
> +    m_bufferFillActual = m_bufferFillFinal;
> +    m_bufferExcess = 0;
> +    m_minBufferFill = m_param->minVbvFullness / 100;
> +    m_maxBufferFill = 1 - (m_param->maxVbvFullness / 100);
> +}
>
> -        if (m_param->rc.vbvBufferInit > 1.)
> -            m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0,
> m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);
> -        if (m_param->vbvBufferEnd > 1.)
> -            m_param->vbvBufferEnd = x265_clip3(0.0, 1.0,
> m_param->vbvBufferEnd / m_param->rc.vbvBufferSize);
> -        if (m_param->vbvEndFrameAdjust > 1.)
> -            m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0,
> m_param->vbvEndFrameAdjust);
> -        m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0,
> X265_MAX(m_param->rc.vbvBufferInit, m_bufferRate / m_bufferSize));
> -        m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;
> -        m_bufferFillActual = m_bufferFillFinal;
> -        m_bufferExcess = 0;
> -        m_minBufferFill = m_param->minVbvFullness / 100;
> -        m_maxBufferFill = 1 - (m_param->maxVbvFullness / 100);
> -        m_initVbv = true;
> +bool RateControl::init(const SPS& sps)
> +{
> +    if (m_isVbv)
> +    {
> +        initVBV(sps);
>      }
>
>      if (!m_param->bResetZoneConfig && (m_relativeComplexity == NULL))
> @@ -477,7 +481,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_bitrate * m_frameDuration;
> +    m_wantedBitsWindow = (m_param->bEnableSBRC ? (m_bitrate * ( 1.0 /
> m_param->keyframeMax )) :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;
>
> @@ -1819,7 +1823,8 @@ 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 timeDone = (double)(m_framesDone - m_param->frameNumThreads +
> 1) * m_frameDuration;
> +    double duration = m_param->bEnableSBRC ? (1.0 / m_param->keyframeMax)
> : m_frameDuration;
> +    double timeDone = (double)(m_framesDone - m_param->frameNumThreads +
> 1) * duration;
>      double wantedBits = timeDone * m_bitrate;
>      int64_t encodedBits = m_totalBits;
>      if (m_param->totalFrames && m_param->totalFrames <= 2 * m_fps)
> @@ -1829,7 +1834,7 @@ double RateControl::tuneAbrQScaleFromFeedback(double
> qScale)
>      }
>
>      if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames ||
> -        m_param->rc.bStrictCbr || m_isGrainEnabled))
> +        m_param->rc.bStrictCbr || m_isGrainEnabled ||
> m_param->bEnableSBRC))
>      {
>          abrBuffer *= X265_MAX(1, sqrt(timeDone));
>          overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) /
> abrBuffer);
> @@ -2191,6 +2196,10 @@ 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);
> +                }
>                  q = getQScale(rce, m_rateFactorConstant);
>                  x265_zone* zone = getZone();
>                  if (zone)
> @@ -2216,7 +2225,7 @@ double RateControl::rateEstimateQscale(Frame*
> curFrame, RateControlEntry *rce)
>                  }
>                  double tunedQScale =
> tuneAbrQScaleFromFeedback(initialQScale);
>                  overflow = tunedQScale / initialQScale;
> -                q = !m_partialResidualFrames? tunedQScale : initialQScale;
> +                q = (!m_partialResidualFrames || m_param->bEnableSBRC)?
> 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);
> @@ -2385,15 +2394,27 @@ void
> RateControl::rateControlUpdateStats(RateControlEntry* rce)
>      }
>  }
>
> +
> +void RateControl::checkAndResetCRF(RateControlEntry* rce)
> +{
> +    if(rce->poc % m_param->keyframeMax == 0)
> +    {
> +        init(*m_curSlice->m_sps);
> +        m_shortTermCplxSum = rce->lastSatd /
> (CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION);
> +        m_shortTermCplxCount = 1;
> +        rce->blurredComplexity = m_shortTermCplxSum /
> m_shortTermCplxCount;
> +    }
> +}
> +
>  void RateControl::checkAndResetABR(RateControlEntry* rce, bool
> isFrameDone)
>  {
>      double abrBuffer = 2 * m_rateTolerance * m_bitrate;
>
>      // Check if current Slice is a scene cut that follows low
> detailed/blank frames
> -    if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut ||
> rce->isFadeEnd)
> +    if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut ||
> rce->isFadeEnd || (m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax
> == 0)))
>      {
>          if (!m_isAbrReset && rce->movingAvgSum > 0
> -            && (m_isPatternPresent || !m_param->bframes))
> +            && (m_isPatternPresent || !m_param->bframes
> ||(m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0))))
>          {
>              int pos = X265_MAX(m_sliderPos - m_param->frameNumThreads, 0);
>              int64_t shrtTermWantedBits = (int64_t) (X265_MIN(pos,
> s_slidingWindowFrames) * m_bitrate * m_frameDuration);
> @@ -2403,7 +2424,7 @@ void RateControl::checkAndResetABR(RateControlEntry*
> rce, bool isFrameDone)
>                  shrtTermTotalBitsSum += m_encodedBitsWindow[i];
>              double underflow = (shrtTermTotalBitsSum -
> shrtTermWantedBits) / abrBuffer;
>              const double epsilon = 0.0001f;
> -            if ((underflow < epsilon || rce->isFadeEnd) && !isFrameDone)
> +            if ((underflow < epsilon || rce->isFadeEnd ||
> (m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0))) &&
> !isFrameDone)
>              {
>                  init(*m_curSlice->m_sps);
>                  // Reduce tune complexity factor for scenes that follow
> blank frames
> @@ -2413,6 +2434,7 @@ void RateControl::checkAndResetABR(RateControlEntry*
> rce, bool isFrameDone)
>                  m_shortTermCplxCount = 1;
>                  m_isAbrReset = true;
>                  m_lastAbrResetPoc = rce->poc;
> +                rce->blurredComplexity = m_shortTermCplxSum /
> m_shortTermCplxCount;
>              }
>          }
>          else if (m_isAbrReset && isFrameDone)
> @@ -2487,7 +2509,7 @@ double RateControl::clipQscale(Frame* curFrame,
> RateControlEntry* rce, double q)
>                  for (int j = 0; bufferFillCur >= 0 && iter ; j++)
>                  {
>                      int type = curFrame->m_lowres.plannedType[j];
> -                    if (type == X265_TYPE_AUTO || totalDuration >= 1.0)
> +                    if (type == X265_TYPE_AUTO || totalDuration >= 1.0 ||
> (m_param->bEnableSBRC && type == X265_TYPE_IDR))
>                          break;
>                      totalDuration += m_frameDuration;
>                      double wantedFrameSize = m_vbvMaxRate *
> m_frameDuration;
> @@ -3053,7 +3075,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_frameDuration * m_bitrate;
> +        m_wantedBitsWindow += (m_param->bEnableSBRC ? (m_bitrate * (1.0 /
> m_param->keyframeMax)) : m_frameDuration * m_bitrate);
>          m_totalBits += bits - rce->rowTotalBits;
>          m_encodedBits += actualBits;
>          int pos = m_sliderPos - m_param->frameNumThreads;
> diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h
> index e9fd0e182..9c2fe0ed6 100644
> --- a/source/encoder/ratecontrol.h
> +++ b/source/encoder/ratecontrol.h
> @@ -150,6 +150,7 @@ public:
>      int    m_lastScenecutAwareIFrame;
>      double m_rateTolerance;
>      double m_frameDuration;     /* current frame duration in seconds */
> +    double m_frameDurInGOP;     /* current frame duration when considered
> as a segment */
>      double m_bitrate;
>      double m_rateFactorConstant;
>      double m_bufferSize;
> @@ -255,6 +256,7 @@ public:
>      RateControl(x265_param& p, Encoder *enc);
>      bool init(const SPS& sps);
>      void initHRD(SPS& sps);
> +    void initVBV(const SPS& sps);
>      void reconfigureRC();
>
>      void setFinalFrameCount(int count);
> @@ -315,6 +317,7 @@ protected:
>      double tuneQScaleForGrain(double rcOverflow);
>      void   splitdeltaPOC(char deltapoc[], RateControlEntry *rce);
>      void   splitbUsed(char deltapoc[], RateControlEntry *rce);
> +    void   checkAndResetCRF(RateControlEntry* rce);
>  };
>  }
>  #endif // ifndef X265_RATECONTROL_H
> --
> 2.28.0.windows.1
>
> *Thanks,*
> *Kirithika*
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20230105/b2b0317c/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-sbrc-2.diff
Type: application/octet-stream
Size: 14607 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20230105/b2b0317c/attachment-0001.obj>


More information about the x265-devel mailing list