[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