[x265] [PATCH] Add support for Segment Based Rate Control
Mahesh Pittala
mahesh at multicorewareinc.com
Thu Jan 12 05:21:43 UTC 2023
pushed the patch to master branch
On Thu, Jan 5, 2023 at 9:42 AM Kirithika Kalirathnam <
kirithika at multicorewareinc.com> wrote:
> 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*
>>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20230112/f8a4226a/attachment-0001.htm>
More information about the x265-devel
mailing list