[x265] [PATCH] SBRC:Tune Qp based on segment size constraints
Kirithika Kalirathnam
kirithika at multicorewareinc.com
Thu Mar 28 06:14:35 UTC 2024
>From 17f2420bbd07db40b618e96a36586da909a26efb Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Sat, 3 Feb 2024 08:28:18 +0530
Subject: [PATCH] SBRC:Tune Qp based on segment size constraints
This Commit adds support to tune QP for frames based on the segment
size constraints
---
source/encoder/ratecontrol.cpp | 67 +++++++++++++++++++++++++++++++++-
source/encoder/ratecontrol.h | 3 ++
2 files changed, 69 insertions(+), 1 deletion(-)
diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
index 099a03f0a..5c447d8ad 100644
--- a/source/encoder/ratecontrol.cpp
+++ b/source/encoder/ratecontrol.cpp
@@ -260,6 +260,8 @@ RateControl::RateControl(x265_param& p, Encoder *top)
m_initVbv = false;
m_singleFrameVbv = 0;
m_rateTolerance = 1.0;
+ m_encodedSegmentBits = 0;
+ m_segDur = 0;
if (m_param->rc.vbvBufferSize)
{
@@ -448,7 +450,9 @@ bool RateControl::init(const SPS& sps)
m_totalBits = 0;
m_encodedBits = 0;
+ m_encodedSegmentBits = 0;
m_framesDone = 0;
+ m_segDur = 0;
m_residualCost = 0;
m_partialResidualCost = 0;
m_amortizeFraction = 0.85;
@@ -1351,6 +1355,16 @@ int RateControl::rateControlStart(Frame* curFrame,
RateControlEntry* rce, Encode
m_predType = getPredictorType(curFrame->m_lowres.sliceType,
m_sliceType);
rce->poc = m_curSlice->m_poc;
+ if (m_param->bEnableSBRC)
+ {
+ if (rce->poc == 0 || (m_framesDone % m_param->keyframeMax == 0))
+ {
+ //Reset SBRC buffer
+ m_encodedSegmentBits = 0;
+ m_segDur = 0;
+ }
+ }
+
if (!m_param->bResetZoneConfig && (rce->encodeOrder %
m_param->reconfigWindowSize == 0))
{
int index = m_zoneBufferIdx % m_param->rc.zonefileCount;
@@ -1974,8 +1988,16 @@ double RateControl::rateEstimateQscale(Frame*
curFrame, RateControlEntry *rce)
double minScenecutQscale
=x265_qp2qScale(ABR_SCENECUT_INIT_QP_MIN);
m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale,
m_lastQScaleFor[P_SLICE]);
}
+
double qScale = x265_qp2qScale(q);
rce->qpNoVbv = q;
+
+ if (m_param->bEnableSBRC)
+ {
+ qScale = tuneQscaleForSBRC(curFrame, qScale);
+ rce->qpNoVbv = x265_qScale2qp(qScale);
+ }
+
double lmin = 0, lmax = 0;
if (m_isGrainEnabled && m_isFirstMiniGop)
{
@@ -2200,7 +2222,8 @@ double RateControl::rateEstimateQscale(Frame*
curFrame, RateControlEntry *rce)
double rfConstant = m_param->rc.rfConstant;
if (m_currentSatd < rce->movingAvgSum)
rfConstant += 2;
- rfConstant = (rce->sliceType == I_SLICE ? rfConstant -
m_ipOffset :
+ double ipOffset = (curFrame->m_lowres.bScenecut ?
m_ipOffset : m_ipOffset / 2.0);
+ rfConstant = (rce->sliceType == I_SLICE ? rfConstant -
ipOffset :
(rce->sliceType == B_SLICE ? rfConstant +
m_pbOffset : rfConstant));
double mbtree_offset = m_param->rc.cuTree ? (1.0 -
m_param->rc.qCompress) * 13.5 : 0;
double qComp = (m_param->rc.cuTree &&
!m_param->rc.hevcAq) ? 0.99 : m_param->rc.qCompress;
@@ -2288,6 +2311,9 @@ double RateControl::rateEstimateQscale(Frame*
curFrame, RateControlEntry *rce)
q = X265_MAX(minScenecutQscale, q);
m_lastQScaleFor[P_SLICE] = X265_MAX(minScenecutQscale,
m_lastQScaleFor[P_SLICE]);
}
+ if (m_param->bEnableSBRC)
+ q = tuneQscaleForSBRC(curFrame, q);
+
rce->qpNoVbv = x265_qScale2qp(q);
if (m_sliceType == P_SLICE)
{
@@ -2469,6 +2495,43 @@ 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)
+{
+ int depth = 0;
+ int framesDoneInSeg = m_framesDone % m_param->keyframeMax;
+ if (framesDoneInSeg + m_param->lookaheadDepth <= m_param->keyframeMax)
+ depth = m_param->lookaheadDepth;
+ else
+ depth = m_param->keyframeMax - framesDoneInSeg;
+ for (int iterations = 0; iterations < 1000; iterations++)
+ {
+ double totalDuration = m_segDur;
+ double frameBitsTotal = m_encodedSegmentBits +
predictSize(&m_pred[m_predType], q, (double)m_currentSatd);
+ for (int i = 0; i < depth; i++)
+ {
+ int type = curFrame->m_lowres.plannedType[i];
+ if (type == X265_TYPE_AUTO)
+ break;
+ int64_t satd = curFrame->m_lowres.plannedSatd[i] >>
(X265_DEPTH - 8);
+ type = IS_X265_TYPE_I(curFrame->m_lowres.plannedType[i]) ?
I_SLICE : IS_X265_TYPE_B(curFrame->m_lowres.plannedType[i]) ? B_SLICE :
P_SLICE;
+ int predType =
getPredictorType(curFrame->m_lowres.plannedType[i], type);
+ double curBits = predictSize(&m_pred[predType], q,
(double)satd);
+ frameBitsTotal += curBits;
+ 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;
+ else
+ break;
+ }
+ return q;
+}
+
double RateControl::clipQscale(Frame* curFrame, RateControlEntry* rce,
double q)
{
// B-frames are not directly subject to VBV,
@@ -3072,6 +3135,8 @@ int RateControl::rateControlEnd(Frame* curFrame,
int64_t bits, RateControlEntry*
m_wantedBitsWindow += m_frameDuration * m_bitrate;
m_totalBits += bits - rce->rowTotalBits;
m_encodedBits += actualBits;
+ m_encodedSegmentBits += actualBits;
+ m_segDur += m_frameDuration;
int pos = m_sliderPos - m_param->frameNumThreads;
if (pos >= 0)
m_encodedBitsWindow[pos % s_slidingWindowFrames] = actualBits;
diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h
index 7c3f60cc7..c3dc0406f 100644
--- a/source/encoder/ratecontrol.h
+++ b/source/encoder/ratecontrol.h
@@ -191,6 +191,8 @@ public:
double m_qCompress;
int64_t m_totalBits; /* total bits used for already encoded
frames (after ammortization) */
int64_t m_encodedBits; /* bits used for encoded frames (without
ammortization) */
+ int64_t m_encodedSegmentBits; /* bits used for encoded frames in
a segment*/
+ double m_segDur;
double m_fps;
int64_t m_satdCostWindow[50];
int64_t m_encodedBitsWindow[50];
@@ -296,6 +298,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
void accumPQpUpdate();
int getPredictorType(int lowresSliceType, int sliceType);
--
2.28.0.windows.1
*Thanks,*
*Kirithika*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240328/3cf0adc3/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch-SBRC-latest.diff
Type: application/octet-stream
Size: 7399 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240328/3cf0adc3/attachment-0001.obj>
More information about the x265-devel
mailing list