<div dir="ltr">Please find the updated version<br><br>From 3f30f806b0e4235eb6ab805f23330a8311f086b6 Mon Sep 17 00:00:00 2001<br>From: Kirithika <<a href="mailto:kirithika@multicorewareinc.com">kirithika@multicorewareinc.com</a>><br>Date: Fri, 9 Dec 2022 12:31:27 +0530<br>Subject: [PATCH] Add support for Segment Based Rate Control<br><br>1.Configure segment length based on keyint<br>2.Changes frame duration settings with SBRC 3.Reset RateControl (CRF/ABR) at the segment beginning<br>---<br> doc/reST/cli.rst | 3 +-<br> source/common/common.h | 2 -<br> source/encoder/encoder.cpp | 12 ++++<br> source/encoder/ratecontrol.cpp | 108 +++++++++++++++++++--------------<br> source/encoder/ratecontrol.h | 3 +<br> 5 files changed, 80 insertions(+), 48 deletions(-)<br><br>diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst<br>index f40afc65c..f1d9fa36c 100755<br>--- a/doc/reST/cli.rst<br>+++ b/doc/reST/cli.rst<br>@@ -1761,7 +1761,8 @@ Quality, rate control and rate distortion options<br> <br> .. option:: --sbrc --no-sbrc<br> <br>- To enable and disable segment based rate control.<br>+ To enable and disable segment based rate control.Segment duration depends on the<br>+ keyframe interval specified.If unspecified,default keyframe interval will be used.<br> Default: disabled.<br> <br> .. option:: --hevc-aq<br>diff --git a/source/common/common.h b/source/common/common.h<br>index 3d7fc1ebf..37c19ae72 100644<br>--- a/source/common/common.h<br>+++ b/source/common/common.h<br>@@ -130,7 +130,6 @@ typedef uint64_t sum2_t;<br> typedef uint64_t pixel4;<br> typedef int64_t ssum2_t;<br> #define SHIFT_TO_BITPLANE 9<br>-#define HISTOGRAM_BINS 1024<br> #else<br> typedef uint8_t pixel;<br> typedef uint16_t sum_t;<br>@@ -138,7 +137,6 @@ typedef uint32_t sum2_t;<br> typedef uint32_t pixel4;<br> typedef int32_t ssum2_t; // Signed sum<br> #define SHIFT_TO_BITPLANE 7<br>-#define HISTOGRAM_BINS 256<br> #endif // if HIGH_BIT_DEPTH<br> <br> #if X265_DEPTH < 10<br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 64a4e231c..f20c9a266 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -4396,6 +4396,18 @@ void Encoder::configure(x265_param *p)<br> if (m_param->searchRange != m_param->hmeRange[2])<br> m_param->searchRange = m_param->hmeRange[2];<br> }<br>+<br>+ if (p->bEnableSBRC && p->bOpenGOP)<br>+ {<br>+ x265_log(p, X265_LOG_WARNING, "Segment based RateControl requires closed gop structure. Enabling closed GOP.\n");<br>+ p->bOpenGOP = 0;<br>+ }<br>+<br>+ if (p->bEnableSBRC && (p->keyframeMax != p->keyframeMin))<br>+ {<br>+ x265_log(p, X265_LOG_WARNING, "Segment based RateControl requires fixed gop length. Force set min-keyint equal to keyint.\n");<br>+ p->keyframeMin = p->keyframeMax;<br>+ }<br> }<br> <br> void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x265_picture* picIn, int paramBytes)<br>diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp<br>index 090d0a35f..162c9dd7b 100644<br>--- a/source/encoder/ratecontrol.cpp<br>+++ b/source/encoder/ratecontrol.cpp<br>@@ -392,46 +392,48 @@ bool RateControl::initCUTreeSharedMem()<br> return true;<br> }<br> <br>-bool RateControl::init(const SPS& sps)<br>+void RateControl::initVBV(const SPS& sps)<br> {<br>- if (m_isVbv && !m_initVbv)<br>+ /* We don't support changing the ABR bitrate right now,<br>+ * so if the stream starts as CBR, keep it CBR. */<br>+ if (m_param->rc.vbvBufferSize < (int)(m_param->rc.vbvMaxBitrate / m_fps))<br> {<br>- /* We don't support changing the ABR bitrate right now,<br>- * so if the stream starts as CBR, keep it CBR. */<br>- if (m_param->rc.vbvBufferSize < (int)(m_param->rc.vbvMaxBitrate / m_fps))<br>- {<br>- m_param->rc.vbvBufferSize = (int)(m_param->rc.vbvMaxBitrate / m_fps);<br>- x265_log(m_param, X265_LOG_WARNING, "VBV buffer size cannot be smaller than one frame, using %d kbit\n",<br>- m_param->rc.vbvBufferSize);<br>- }<br>- int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;<br>- int vbvMaxBitrate = m_param->rc.vbvMaxBitrate * 1000;<br>+ m_param->rc.vbvBufferSize = (int)(m_param->rc.vbvMaxBitrate / m_fps);<br>+ x265_log(m_param, X265_LOG_WARNING, "VBV buffer size cannot be smaller than one frame, using %d kbit\n",<br>+ m_param->rc.vbvBufferSize);<br>+ }<br>+ int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;<br>+ int vbvMaxBitrate = m_param->rc.vbvMaxBitrate * 1000;<br> <br>- if (m_param->bEmitHRDSEI && !m_param->decoderVbvMaxRate)<br>- {<br>- const HRDInfo* hrd = &sps.vuiParameters.hrdParameters;<br>- vbvBufferSize = hrd->cpbSizeValue << (hrd->cpbSizeScale + CPB_SHIFT);<br>- vbvMaxBitrate = hrd->bitRateValue << (hrd->bitRateScale + BR_SHIFT);<br>- }<br>- m_bufferRate = vbvMaxBitrate / m_fps;<br>- m_vbvMaxRate = vbvMaxBitrate;<br>- m_bufferSize = vbvBufferSize;<br>- m_singleFrameVbv = m_bufferRate * 1.1 > m_bufferSize;<br>+ if (m_param->bEmitHRDSEI && !m_param->decoderVbvMaxRate)<br>+ {<br>+ const HRDInfo* hrd = &sps.vuiParameters.hrdParameters;<br>+ vbvBufferSize = hrd->cpbSizeValue << (hrd->cpbSizeScale + CPB_SHIFT);<br>+ vbvMaxBitrate = hrd->bitRateValue << (hrd->bitRateScale + BR_SHIFT);<br>+ }<br>+ m_bufferRate = vbvMaxBitrate / m_fps;<br>+ m_vbvMaxRate = vbvMaxBitrate;<br>+ m_bufferSize = vbvBufferSize;<br>+ m_singleFrameVbv = m_bufferRate * 1.1 > m_bufferSize;<br>+<br>+ if (m_param->rc.vbvBufferInit > 1.)<br>+ m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);<br>+ if (m_param->vbvBufferEnd > 1.)<br>+ m_param->vbvBufferEnd = x265_clip3(0.0, 1.0, m_param->vbvBufferEnd / m_param->rc.vbvBufferSize);<br>+ if (m_param->vbvEndFrameAdjust > 1.)<br>+ m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0, m_param->vbvEndFrameAdjust);<br>+ m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, X265_MAX(m_param->rc.vbvBufferInit, m_bufferRate / m_bufferSize));<br>+ m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;<br>+ m_bufferFillActual = m_bufferFillFinal;<br>+ m_bufferExcess = 0;<br>+ m_minBufferFill = m_param->minVbvFullness / 100;<br>+ m_maxBufferFill = 1 - (m_param->maxVbvFullness / 100);<br>+}<br> <br>- if (m_param->rc.vbvBufferInit > 1.)<br>- m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);<br>- if (m_param->vbvBufferEnd > 1.)<br>- m_param->vbvBufferEnd = x265_clip3(0.0, 1.0, m_param->vbvBufferEnd / m_param->rc.vbvBufferSize);<br>- if (m_param->vbvEndFrameAdjust > 1.)<br>- m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0, m_param->vbvEndFrameAdjust);<br>- m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, X265_MAX(m_param->rc.vbvBufferInit, m_bufferRate / m_bufferSize));<br>- m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;<br>- m_bufferFillActual = m_bufferFillFinal;<br>- m_bufferExcess = 0;<br>- m_minBufferFill = m_param->minVbvFullness / 100;<br>- m_maxBufferFill = 1 - (m_param->maxVbvFullness / 100);<br>- m_initVbv = true;<br>- }<br>+bool RateControl::init(const SPS& sps)<br>+{<br>+ if (m_isVbv)<br>+ initVBV(sps);<br> <br> if (!m_param->bResetZoneConfig && (m_relativeComplexity == NULL))<br> {<br>@@ -477,7 +479,7 @@ bool RateControl::init(const SPS& sps)<br> <br> /* estimated ratio that produces a reasonable QP for the first I-frame */<br> m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) * tuneCplxFactor;<br>- m_wantedBitsWindow = m_bitrate * m_frameDuration;<br>+ m_wantedBitsWindow = (m_param->bEnableSBRC ? (m_bitrate * ( 1.0 / m_param->keyframeMax )) :m_bitrate * m_frameDuration);<br> m_accumPNorm = .01;<br> m_accumPQp = (m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN) * m_accumPNorm;<br> <br>@@ -1819,7 +1821,8 @@ double RateControl::tuneAbrQScaleFromFeedback(double qScale)<br> double abrBuffer = 2 * m_rateTolerance * m_bitrate;<br> /* use framesDone instead of POC as poc count is not serial with bframes enabled */<br> double overflow = 1.0;<br>- double timeDone = (double)(m_framesDone - m_param->frameNumThreads + 1) * m_frameDuration;<br>+ double duration = m_param->bEnableSBRC ? (1.0 / m_param->keyframeMax) : m_frameDuration;<br>+ double timeDone = (double)(m_framesDone - m_param->frameNumThreads + 1) * duration;<br> double wantedBits = timeDone * m_bitrate;<br> int64_t encodedBits = m_totalBits;<br> if (m_param->totalFrames && m_param->totalFrames <= 2 * m_fps)<br>@@ -1829,7 +1832,7 @@ double RateControl::tuneAbrQScaleFromFeedback(double qScale)<br> }<br> <br> if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames || <br>- m_param->rc.bStrictCbr || m_isGrainEnabled))<br>+ m_param->rc.bStrictCbr || m_isGrainEnabled || m_param->bEnableSBRC))<br> {<br> abrBuffer *= X265_MAX(1, sqrt(timeDone));<br> overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) / abrBuffer);<br>@@ -2191,6 +2194,8 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)<br> <br> if (m_param->rc.rateControlMode == X265_RC_CRF)<br> {<br>+ if (!m_param->rc.bStatRead && m_param->bEnableSBRC)<br>+ checkAndResetCRF(rce);<br> q = getQScale(rce, m_rateFactorConstant);<br> x265_zone* zone = getZone();<br> if (zone)<br>@@ -2216,7 +2221,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)<br> }<br> double tunedQScale = tuneAbrQScaleFromFeedback(initialQScale);<br> overflow = tunedQScale / initialQScale;<br>- q = !m_partialResidualFrames? tunedQScale : initialQScale;<br>+ q = (!m_partialResidualFrames || m_param->bEnableSBRC)? tunedQScale : initialQScale;<br> bool isEncodeEnd = (m_param->totalFrames && <br> m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;<br> bool isEncodeBeg = m_framesDone < (int)(m_fps + 0.5);<br>@@ -2385,15 +2390,27 @@ void RateControl::rateControlUpdateStats(RateControlEntry* rce)<br> }<br> }<br> <br>+<br>+void RateControl::checkAndResetCRF(RateControlEntry* rce)<br>+{<br>+ if(rce->poc % m_param->keyframeMax == 0)<br>+ {<br>+ init(*m_curSlice->m_sps);<br>+ m_shortTermCplxSum = rce->lastSatd / (CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION);<br>+ m_shortTermCplxCount = 1;<br>+ rce->blurredComplexity = m_shortTermCplxSum / m_shortTermCplxCount;<br>+ }<br>+}<br>+<br> void RateControl::checkAndResetABR(RateControlEntry* rce, bool isFrameDone)<br> {<br> double abrBuffer = 2 * m_rateTolerance * m_bitrate;<br> <br> // Check if current Slice is a scene cut that follows low detailed/blank frames<br>- if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut || rce->isFadeEnd)<br>+ if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut || rce->isFadeEnd || (m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0)))<br> {<br> if (!m_isAbrReset && rce->movingAvgSum > 0<br>- && (m_isPatternPresent || !m_param->bframes))<br>+ && (m_isPatternPresent || !m_param->bframes ||(m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0))))<br> {<br> int pos = X265_MAX(m_sliderPos - m_param->frameNumThreads, 0);<br> int64_t shrtTermWantedBits = (int64_t) (X265_MIN(pos, s_slidingWindowFrames) * m_bitrate * m_frameDuration);<br>@@ -2403,7 +2420,7 @@ void RateControl::checkAndResetABR(RateControlEntry* rce, bool isFrameDone)<br> shrtTermTotalBitsSum += m_encodedBitsWindow[i];<br> double underflow = (shrtTermTotalBitsSum - shrtTermWantedBits) / abrBuffer;<br> const double epsilon = 0.0001f;<br>- if ((underflow < epsilon || rce->isFadeEnd) && !isFrameDone)<br>+ if ((underflow < epsilon || rce->isFadeEnd || (m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0))) && !isFrameDone)<br> {<br> init(*m_curSlice->m_sps);<br> // Reduce tune complexity factor for scenes that follow blank frames<br>@@ -2413,6 +2430,7 @@ void RateControl::checkAndResetABR(RateControlEntry* rce, bool isFrameDone)<br> m_shortTermCplxCount = 1;<br> m_isAbrReset = true;<br> m_lastAbrResetPoc = rce->poc;<br>+ rce->blurredComplexity = m_shortTermCplxSum / m_shortTermCplxCount;<br> }<br> }<br> else if (m_isAbrReset && isFrameDone)<br>@@ -2487,7 +2505,7 @@ double RateControl::clipQscale(Frame* curFrame, RateControlEntry* rce, double q)<br> for (int j = 0; bufferFillCur >= 0 && iter ; j++)<br> {<br> int type = curFrame->m_lowres.plannedType[j];<br>- if (type == X265_TYPE_AUTO || totalDuration >= 1.0)<br>+ if (type == X265_TYPE_AUTO || totalDuration >= 1.0 || (m_param->bEnableSBRC && type == X265_TYPE_IDR))<br> break;<br> totalDuration += m_frameDuration;<br> double wantedFrameSize = m_vbvMaxRate * m_frameDuration;<br>@@ -3053,7 +3071,7 @@ int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry*<br> * Not perfectly accurate with B-refs, but good enough. */<br> m_cplxrSum += (bits * x265_qp2qScale(rce->qpaRc) / (rce->qRceq * fabs(m_param->rc.pbFactor))) - (rce->rowCplxrSum);<br> }<br>- m_wantedBitsWindow += m_frameDuration * m_bitrate;<br>+ m_wantedBitsWindow += (m_param->bEnableSBRC ? (m_bitrate * (1.0 / m_param->keyframeMax)) : m_frameDuration * m_bitrate);<br> m_totalBits += bits - rce->rowTotalBits;<br> m_encodedBits += actualBits;<br> int pos = m_sliderPos - m_param->frameNumThreads;<br>diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h<br>index e9fd0e182..9c2fe0ed6 100644<br>--- a/source/encoder/ratecontrol.h<br>+++ b/source/encoder/ratecontrol.h<br>@@ -150,6 +150,7 @@ public:<br> int m_lastScenecutAwareIFrame;<br> double m_rateTolerance;<br> double m_frameDuration; /* current frame duration in seconds */<br>+ double m_frameDurInGOP; /* current frame duration when considered as a segment */<br> double m_bitrate;<br> double m_rateFactorConstant;<br> double m_bufferSize;<br>@@ -255,6 +256,7 @@ public:<br> RateControl(x265_param& p, Encoder *enc);<br> bool init(const SPS& sps);<br> void initHRD(SPS& sps);<br>+ void initVBV(const SPS& sps);<br> void reconfigureRC();<br> <br> void setFinalFrameCount(int count);<br>@@ -315,6 +317,7 @@ protected:<br> double tuneQScaleForGrain(double rcOverflow);<br> void splitdeltaPOC(char deltapoc[], RateControlEntry *rce);<br> void splitbUsed(char deltapoc[], RateControlEntry *rce);<br>+ void checkAndResetCRF(RateControlEntry* rce);<br> };<br> }<br> #endif // ifndef X265_RATECONTROL_H<br>-- <br>2.28.0.windows.1<br><br><div><div dir="ltr" class="gmail_signature" data-smartmail="gmail_signature"><div dir="ltr"><i>Thanks,</i><div><i>Kirithika</i></div></div></div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Thu, Dec 29, 2022 at 9:59 PM Kirithika Kalirathnam <<a href="mailto:kirithika@multicorewareinc.com">kirithika@multicorewareinc.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">From 817342031263956fba544b1aac9f29e814bb1fdf Mon Sep 17 00:00:00 2001<br>From: Kirithika <<a href="mailto:kirithika@multicorewareinc.com" target="_blank">kirithika@multicorewareinc.com</a>><br>Date: Fri, 9 Dec 2022 12:31:27 +0530<br>Subject: [PATCH] Add support for Segment Based Rate Control<br><br>1.Configure keyframe interval to be 2 seconds<br><br>2.Changes frame duration settings with SBRC 3.Reset RateControl (CRF/ABR) at the GOP beginning<br>---<br> source/encoder/encoder.cpp | 10 +++<br> source/encoder/ratecontrol.cpp | 110 ++++++++++++++++++++-------------<br> source/encoder/ratecontrol.h | 3 +<br> 3 files changed, 79 insertions(+), 44 deletions(-)<br><br>diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>index 64a4e231c..ad15b984a 100644<br>--- a/source/encoder/encoder.cpp<br>+++ b/source/encoder/encoder.cpp<br>@@ -4396,6 +4396,16 @@ void Encoder::configure(x265_param *p)<br> if (m_param->searchRange != m_param->hmeRange[2])<br> m_param->searchRange = m_param->hmeRange[2];<br> }<br>+<br>+ if (m_param->bEnableSBRC && p->bOpenGOP)<br>+ {<br>+ x265_log(p, X265_LOG_WARNING, "Segment based RateControl requires closed gop structure. Enabling closed GOP.\n");<br>+ m_param->bOpenGOP = 0;<br>+<br>+ //Configure GOP to 2s duration<br>+ p->keyframeMax = 2 * (m_param->fpsNum / m_param->fpsDenom);<br>+ p->keyframeMin = 2 * (m_param->fpsNum / m_param->fpsDenom);<br>+ }<br> }<br> <br> void Encoder::readAnalysisFile(x265_analysis_data* analysis, int curPoc, const x265_picture* picIn, int paramBytes)<br>diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp<br>index 32399eda6..1c29e4a00 100644<br>--- a/source/encoder/ratecontrol.cpp<br>+++ b/source/encoder/ratecontrol.cpp<br>@@ -392,45 +392,49 @@ bool RateControl::initCUTreeSharedMem()<br> return true;<br> }<br> <br>-bool RateControl::init(const SPS& sps)<br>+void RateControl::initVBV(const SPS& sps)<br> {<br>- if (m_isVbv && !m_initVbv)<br>+ /* We don't support changing the ABR bitrate right now,<br>+ * so if the stream starts as CBR, keep it CBR. */<br>+ if (m_param->rc.vbvBufferSize < (int)(m_param->rc.vbvMaxBitrate / m_fps))<br> {<br>- /* We don't support changing the ABR bitrate right now,<br>- * so if the stream starts as CBR, keep it CBR. */<br>- if (m_param->rc.vbvBufferSize < (int)(m_param->rc.vbvMaxBitrate / m_fps))<br>- {<br>- m_param->rc.vbvBufferSize = (int)(m_param->rc.vbvMaxBitrate / m_fps);<br>- x265_log(m_param, X265_LOG_WARNING, "VBV buffer size cannot be smaller than one frame, using %d kbit\n",<br>- m_param->rc.vbvBufferSize);<br>- }<br>- int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;<br>- int vbvMaxBitrate = m_param->rc.vbvMaxBitrate * 1000;<br>+ m_param->rc.vbvBufferSize = (int)(m_param->rc.vbvMaxBitrate / m_fps);<br>+ x265_log(m_param, X265_LOG_WARNING, "VBV buffer size cannot be smaller than one frame, using %d kbit\n",<br>+ m_param->rc.vbvBufferSize);<br>+ }<br>+ int vbvBufferSize = m_param->rc.vbvBufferSize * 1000;<br>+ int vbvMaxBitrate = m_param->rc.vbvMaxBitrate * 1000;<br> <br>- if (m_param->bEmitHRDSEI && !m_param->decoderVbvMaxRate)<br>- {<br>- const HRDInfo* hrd = &sps.vuiParameters.hrdParameters;<br>- vbvBufferSize = hrd->cpbSizeValue << (hrd->cpbSizeScale + CPB_SHIFT);<br>- vbvMaxBitrate = hrd->bitRateValue << (hrd->bitRateScale + BR_SHIFT);<br>- }<br>- m_bufferRate = vbvMaxBitrate / m_fps;<br>- m_vbvMaxRate = vbvMaxBitrate;<br>- m_bufferSize = vbvBufferSize;<br>- m_singleFrameVbv = m_bufferRate * 1.1 > m_bufferSize;<br>+ if (m_param->bEmitHRDSEI && !m_param->decoderVbvMaxRate)<br>+ {<br>+ const HRDInfo* hrd = &sps.vuiParameters.hrdParameters;<br>+ vbvBufferSize = hrd->cpbSizeValue << (hrd->cpbSizeScale + CPB_SHIFT);<br>+ vbvMaxBitrate = hrd->bitRateValue << (hrd->bitRateScale + BR_SHIFT);<br>+ }<br>+ m_bufferRate = vbvMaxBitrate / m_fps;<br>+ m_vbvMaxRate = vbvMaxBitrate;<br>+ m_bufferSize = vbvBufferSize;<br>+ m_singleFrameVbv = m_bufferRate * 1.1 > m_bufferSize;<br>+<br>+ if (m_param->rc.vbvBufferInit > 1.)<br>+ m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);<br>+ if (m_param->vbvBufferEnd > 1.)<br>+ m_param->vbvBufferEnd = x265_clip3(0.0, 1.0, m_param->vbvBufferEnd / m_param->rc.vbvBufferSize);<br>+ if (m_param->vbvEndFrameAdjust > 1.)<br>+ m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0, m_param->vbvEndFrameAdjust);<br>+ m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, X265_MAX(m_param->rc.vbvBufferInit, m_bufferRate / m_bufferSize));<br>+ m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;<br>+ m_bufferFillActual = m_bufferFillFinal;<br>+ m_bufferExcess = 0;<br>+ m_minBufferFill = m_param->minVbvFullness / 100;<br>+ m_maxBufferFill = 1 - (m_param->maxVbvFullness / 100);<br>+}<br> <br>- if (m_param->rc.vbvBufferInit > 1.)<br>- m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, m_param->rc.vbvBufferInit / m_param->rc.vbvBufferSize);<br>- if (m_param->vbvBufferEnd > 1.)<br>- m_param->vbvBufferEnd = x265_clip3(0.0, 1.0, m_param->vbvBufferEnd / m_param->rc.vbvBufferSize);<br>- if (m_param->vbvEndFrameAdjust > 1.)<br>- m_param->vbvEndFrameAdjust = x265_clip3(0.0, 1.0, m_param->vbvEndFrameAdjust);<br>- m_param->rc.vbvBufferInit = x265_clip3(0.0, 1.0, X265_MAX(m_param->rc.vbvBufferInit, m_bufferRate / m_bufferSize));<br>- m_bufferFillFinal = m_bufferSize * m_param->rc.vbvBufferInit;<br>- m_bufferFillActual = m_bufferFillFinal;<br>- m_bufferExcess = 0;<br>- m_minBufferFill = m_param->minVbvFullness / 100;<br>- m_maxBufferFill = 1 - (m_param->maxVbvFullness / 100);<br>- m_initVbv = true;<br>+bool RateControl::init(const SPS& sps)<br>+{<br>+ if (m_isVbv)<br>+ {<br>+ initVBV(sps);<br> }<br> <br> if (!m_param->bResetZoneConfig && (m_relativeComplexity == NULL))<br>@@ -477,7 +481,7 @@ bool RateControl::init(const SPS& sps)<br> <br> /* estimated ratio that produces a reasonable QP for the first I-frame */<br> m_cplxrSum = .01 * pow(7.0e5, m_qCompress) * pow(m_ncu, 0.5) * tuneCplxFactor;<br>- m_wantedBitsWindow = m_bitrate * m_frameDuration;<br>+ m_wantedBitsWindow = (m_param->bEnableSBRC ? (m_bitrate * ( 1.0 / m_param->keyframeMax )) :m_bitrate * m_frameDuration);<br> m_accumPNorm = .01;<br> m_accumPQp = (m_param->rc.rateControlMode == X265_RC_CRF ? CRF_INIT_QP : ABR_INIT_QP_MIN) * m_accumPNorm;<br> <br>@@ -1819,7 +1823,8 @@ double RateControl::tuneAbrQScaleFromFeedback(double qScale)<br> double abrBuffer = 2 * m_rateTolerance * m_bitrate;<br> /* use framesDone instead of POC as poc count is not serial with bframes enabled */<br> double overflow = 1.0;<br>- double timeDone = (double)(m_framesDone - m_param->frameNumThreads + 1) * m_frameDuration;<br>+ double duration = m_param->bEnableSBRC ? (1.0 / m_param->keyframeMax) : m_frameDuration;<br>+ double timeDone = (double)(m_framesDone - m_param->frameNumThreads + 1) * duration;<br> double wantedBits = timeDone * m_bitrate;<br> int64_t encodedBits = m_totalBits;<br> if (m_param->totalFrames && m_param->totalFrames <= 2 * m_fps)<br>@@ -1829,7 +1834,7 @@ double RateControl::tuneAbrQScaleFromFeedback(double qScale)<br> }<br> <br> if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames || <br>- m_param->rc.bStrictCbr || m_isGrainEnabled))<br>+ m_param->rc.bStrictCbr || m_isGrainEnabled || m_param->bEnableSBRC))<br> {<br> abrBuffer *= X265_MAX(1, sqrt(timeDone));<br> overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) / abrBuffer);<br>@@ -2191,6 +2196,10 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)<br> <br> if (m_param->rc.rateControlMode == X265_RC_CRF)<br> {<br>+ if (!m_param->rc.bStatRead && m_param->bEnableSBRC)<br>+ {<br>+ checkAndResetCRF(rce);<br>+ }<br> q = getQScale(rce, m_rateFactorConstant);<br> x265_zone* zone = getZone();<br> if (zone)<br>@@ -2216,7 +2225,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)<br> }<br> double tunedQScale = tuneAbrQScaleFromFeedback(initialQScale);<br> overflow = tunedQScale / initialQScale;<br>- q = !m_partialResidualFrames? tunedQScale : initialQScale;<br>+ q = (!m_partialResidualFrames || m_param->bEnableSBRC)? tunedQScale : initialQScale;<br> bool isEncodeEnd = (m_param->totalFrames && <br> m_framesDone > 0.75 * m_param->totalFrames) ? 1 : 0;<br> bool isEncodeBeg = m_framesDone < (int)(m_fps + 0.5);<br>@@ -2385,15 +2394,27 @@ void RateControl::rateControlUpdateStats(RateControlEntry* rce)<br> }<br> }<br> <br>+<br>+void RateControl::checkAndResetCRF(RateControlEntry* rce)<br>+{<br>+ if(rce->poc % m_param->keyframeMax == 0)<br>+ {<br>+ init(*m_curSlice->m_sps);<br>+ m_shortTermCplxSum = rce->lastSatd / (CLIP_DURATION(m_frameDuration) / BASE_FRAME_DURATION);<br>+ m_shortTermCplxCount = 1;<br>+ rce->blurredComplexity = m_shortTermCplxSum / m_shortTermCplxCount;<br>+ }<br>+}<br>+<br> void RateControl::checkAndResetABR(RateControlEntry* rce, bool isFrameDone)<br> {<br> double abrBuffer = 2 * m_rateTolerance * m_bitrate;<br> <br> // Check if current Slice is a scene cut that follows low detailed/blank frames<br>- if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut || rce->isFadeEnd)<br>+ if (rce->lastSatd > 4 * rce->movingAvgSum || rce->scenecut || rce->isFadeEnd || (m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0)))<br> {<br> if (!m_isAbrReset && rce->movingAvgSum > 0<br>- && (m_isPatternPresent || !m_param->bframes))<br>+ && (m_isPatternPresent || !m_param->bframes ||(m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0))))<br> {<br> int pos = X265_MAX(m_sliderPos - m_param->frameNumThreads, 0);<br> int64_t shrtTermWantedBits = (int64_t) (X265_MIN(pos, s_slidingWindowFrames) * m_bitrate * m_frameDuration);<br>@@ -2403,7 +2424,7 @@ void RateControl::checkAndResetABR(RateControlEntry* rce, bool isFrameDone)<br> shrtTermTotalBitsSum += m_encodedBitsWindow[i];<br> double underflow = (shrtTermTotalBitsSum - shrtTermWantedBits) / abrBuffer;<br> const double epsilon = 0.0001f;<br>- if ((underflow < epsilon || rce->isFadeEnd) && !isFrameDone)<br>+ if ((underflow < epsilon || rce->isFadeEnd || (m_param->bEnableSBRC && (rce->poc % m_param->keyframeMax == 0))) && !isFrameDone)<br> {<br> init(*m_curSlice->m_sps);<br> // Reduce tune complexity factor for scenes that follow blank frames<br>@@ -2413,6 +2434,7 @@ void RateControl::checkAndResetABR(RateControlEntry* rce, bool isFrameDone)<br> m_shortTermCplxCount = 1;<br> m_isAbrReset = true;<br> m_lastAbrResetPoc = rce->poc;<br>+ rce->blurredComplexity = m_shortTermCplxSum / m_shortTermCplxCount;<br> }<br> }<br> else if (m_isAbrReset && isFrameDone)<br>@@ -2487,7 +2509,7 @@ double RateControl::clipQscale(Frame* curFrame, RateControlEntry* rce, double q)<br> for (int j = 0; bufferFillCur >= 0 && iter ; j++)<br> {<br> int type = curFrame->m_lowres.plannedType[j];<br>- if (type == X265_TYPE_AUTO || totalDuration >= 1.0)<br>+ if (type == X265_TYPE_AUTO || totalDuration >= 1.0 || (m_param->bEnableSBRC && type == X265_TYPE_IDR))<br> break;<br> totalDuration += m_frameDuration;<br> double wantedFrameSize = m_vbvMaxRate * m_frameDuration;<br>@@ -3053,7 +3075,7 @@ int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry*<br> * Not perfectly accurate with B-refs, but good enough. */<br> m_cplxrSum += (bits * x265_qp2qScale(rce->qpaRc) / (rce->qRceq * fabs(m_param->rc.pbFactor))) - (rce->rowCplxrSum);<br> }<br>- m_wantedBitsWindow += m_frameDuration * m_bitrate;<br>+ m_wantedBitsWindow += (m_param->bEnableSBRC ? (m_bitrate * (1.0 / m_param->keyframeMax)) : m_frameDuration * m_bitrate);<br> m_totalBits += bits - rce->rowTotalBits;<br> m_encodedBits += actualBits;<br> int pos = m_sliderPos - m_param->frameNumThreads;<br>diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h<br>index e9fd0e182..9c2fe0ed6 100644<br>--- a/source/encoder/ratecontrol.h<br>+++ b/source/encoder/ratecontrol.h<br>@@ -150,6 +150,7 @@ public:<br> int m_lastScenecutAwareIFrame;<br> double m_rateTolerance;<br> double m_frameDuration; /* current frame duration in seconds */<br>+ double m_frameDurInGOP; /* current frame duration when considered as a segment */<br> double m_bitrate;<br> double m_rateFactorConstant;<br> double m_bufferSize;<br>@@ -255,6 +256,7 @@ public:<br> RateControl(x265_param& p, Encoder *enc);<br> bool init(const SPS& sps);<br> void initHRD(SPS& sps);<br>+ void initVBV(const SPS& sps);<br> void reconfigureRC();<br> <br> void setFinalFrameCount(int count);<br>@@ -315,6 +317,7 @@ protected:<br> double tuneQScaleForGrain(double rcOverflow);<br> void splitdeltaPOC(char deltapoc[], RateControlEntry *rce);<br> void splitbUsed(char deltapoc[], RateControlEntry *rce);<br>+ void checkAndResetCRF(RateControlEntry* rce);<br> };<br> }<br> #endif // ifndef X265_RATECONTROL_H<br>-- <br>2.28.0.windows.1<br><br><div><div dir="ltr"><div dir="ltr"><i>Thanks,</i><div><i>Kirithika</i></div></div></div></div></div>
</blockquote></div>