[x265] [PATCH 2/3]SBRC :Relax strict buffer constraint put on SBRC
Kirithika Kalirathnam
kirithika at multicorewareinc.com
Tue Mar 3 06:12:59 UTC 2026
From e3fe449700643c23d7b16bd90644dc440bc28893 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Thu, 10 Jul 2025 22:46:28 +0530
Subject: [PATCH] SBRC :Relax strict buffer constraint put on SBRC
---
source/encoder/ratecontrol.cpp | 50 +++++++++++++++++++++++++++++-----
source/encoder/ratecontrol.h | 5 ++--
2 files changed, 46 insertions(+), 9 deletions(-)
diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
index 6207ef16f..3de97c278 100644
--- a/source/encoder/ratecontrol.cpp
+++ b/source/encoder/ratecontrol.cpp
@@ -263,6 +263,7 @@ RateControl::RateControl(x265_param& p, Encoder *top)
m_rateTolerance = 1.0;
m_encodedSegmentBits = 0;
m_segDur = 0;
+ m_totalframesInSegment = 0;
if (m_param->rc.vbvBufferSize)
{
@@ -321,6 +322,7 @@ RateControl::RateControl(x265_param& p, Encoder *top)
m_leadingNoBSatd = 0;
m_ipOffset = 6.0 * X265_LOG2(m_param->rc.ipFactor);
m_pbOffset = 6.0 * X265_LOG2(m_param->rc.pbFactor);
+ m_iBits = 0;
for (int i = 0; i < QP_MAX_MAX; i++)
m_qpToEncodedBits[i] = 0;
@@ -1372,6 +1374,9 @@ int RateControl::rateControlStart(Frame* curFrame, RateControlEntry* rce, Encode
//Reset SBRC buffer
m_encodedSegmentBits = 0;
m_segDur = 0;
+ m_iBits = 0;
+ m_totalframesInSegment = m_param->totalFrames - m_framesDone;
+
for (int i = 0; i < 3; i++)
{
m_frameCountSeg[i] = 0;
@@ -2033,7 +2038,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)
if (m_param->bEnableSBRC)
{
- qScale = tuneQscaleForSBRC(curFrame, qScale);
+ qScale = tuneQscaleForSBRC(curFrame, qScale, rce);
rce->qpNoVbv = x265_qScale2qp(qScale);
}
@@ -2359,7 +2364,7 @@ double RateControl::rateEstimateQscale(Frame* curFrame, RateControlEntry *rce)
m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale, m_lastQScaleFor[P_SLICE]);
}
if (m_param->bEnableSBRC)
- q = tuneQscaleForSBRC(curFrame, q);
+ q = tuneQscaleForSBRC(curFrame, q, rce);
rce->qpNoVbv = x265_qScale2qp(q);
if (m_sliceType == P_SLICE)
@@ -2541,7 +2546,7 @@ double RateControl::predictSize(Predictor *p, double q, double var)
return (p->coeff * var + p->offset) / (q * p->count);
}
-double RateControl::tuneQscaleForSBRC(Frame* curFrame, double q)
+double RateControl::tuneQscaleForSBRC(Frame* curFrame, double q, RateControlEntry* rce)
{
int depth = 0;
int framesDoneInSeg = m_framesDone % m_param->keyframeMax;
@@ -2553,6 +2558,8 @@ double RateControl::tuneQscaleForSBRC(Frame* curFrame, double q)
{
double totalDuration = m_segDur;
double frameBitsTotal = m_encodedSegmentBits + predictSize(&m_pred[m_predType], q, (double)m_currentSatd);
+ double lookaheadBits = 0;
+ double lookaheadDur = 0;
for (int i = 0; i < depth; i++)
{
int type = curFrame->m_lowres.plannedType[i];
@@ -2563,17 +2570,42 @@ double RateControl::tuneQscaleForSBRC(Frame* curFrame, double q)
int predType = getPredictorType(curFrame->m_lowres.plannedType[i], type);
double curBits = predictSize(&m_pred[predType], q, (double)satd);
frameBitsTotal += curBits;
+ lookaheadBits += curBits;
+ lookaheadDur += m_frameDuration;
totalDuration += m_frameDuration;
}
//Check for segment buffer overflow and adjust QP accordingly
double segDur = m_param->keyframeMax / m_fps;
double allowedSize = m_vbvMaxRate * segDur;
double remDur = segDur - totalDuration;
- double remainingBits = frameBitsTotal / totalDuration * remDur;
- if (frameBitsTotal + remainingBits > 0.9 * allowedSize)
- q = q * 1.01;
+ double remainingBits = frameBitsTotal;
+
+ int framesLeft = m_param->totalFrames - m_framesDone;
+ int isLastSegmentInaEncode = m_totalframesInSegment < m_param->keyframeMax;
+ remainingBits = lookaheadBits / lookaheadDur * remDur;
+
+ //Reduce over estimation due to I frame size
+ if (m_iBits == 0)
+ {
+ //Compute number of I frames
+ double estimatedIBits = predictSize(&m_pred[m_predType], q, (double)m_currentSatd) * remDur;
+ remainingBits -= estimatedIBits;
+ }
+
+ if (!isLastSegmentInaEncode && m_segDur < (0.2 * segDur))
+ {
+ if (frameBitsTotal + remainingBits > (allowedSize * 2))
+ q = q * 1.01;
+ else
+ break;
+ }
else
- break;
+ {
+ if (frameBitsTotal + remainingBits > (allowedSize))
+ q = q * 1.01;
+ else
+ break;
+ }
}
return q;
}
@@ -3249,6 +3281,10 @@ int RateControl::rateControlEnd(Frame* curFrame, int64_t bits, RateControlEntry*
rce->hrdTiming->dpbOutputTime = (double)rce->picTimingSEI->m_picDpbOutputDelay * time->numUnitsInTick / time->timeScale + rce->hrdTiming->cpbRemovalTime;
}
}
+ if (rce->sliceType == I_SLICE)
+ {
+ m_iBits = actualBits;
+ }
rce->isActive = false;
// Allow rateControlStart of next frame only when rateControlEnd of previous frame is over
m_startEndOrder.incr();
diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h
index 6ecf3d962..244511e45 100644
--- a/source/encoder/ratecontrol.h
+++ b/source/encoder/ratecontrol.h
@@ -178,7 +178,7 @@ public:
int m_qpConstant[3];
int m_lastNonBPictType;
int m_framesDone; /* # of frames passed through RateCotrol already */
-
+ int m_iBits;
double m_cplxrSum; /* sum of bits*qscale/rceq */
double m_wantedBitsWindow; /* target bitrate * window */
double m_accumPQp; /* for determining I-frame quant */
@@ -203,6 +203,7 @@ public:
int m_sliderPos;
int64_t m_lastRemovedSatdCost;
double m_movingAvgSum;
+ int m_totalframesInSegment;
/* To detect a pattern of low detailed static frames in single pass ABR using satdcosts */
int64_t m_lastBsliceSatdCost;
@@ -304,7 +305,7 @@ protected:
double rateEstimateQscale(Frame* pic, RateControlEntry *rce); // main logic for calculating QP based on ABR
double tuneAbrQScaleFromFeedback(double qScale);
double tuneQScaleForZone(RateControlEntry *rce, double qScale); // Tune qScale to adhere to zone budget
- double tuneQscaleForSBRC(Frame* curFrame, double q); // Tune qScale to adhere to segment budget
+ double tuneQscaleForSBRC(Frame* curFrame, double q, RateControlEntry *rce); // Tune qScale to adhere to segment budget
void accumPQpUpdate();
int getPredictorType(int lowresSliceType, int sliceType);
--
2.51.0.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20260303/986be392/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch2-sbrc-improved.diff
Type: application/octet-stream
Size: 7017 bytes
Desc: patch2-sbrc-improved.diff
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20260303/986be392/attachment-0001.obj>
More information about the x265-devel
mailing list