[x265] [x265 PATCH] Fix quality drop with SBRC feature
Kirithika Kalirathnam
kirithika at multicorewareinc.com
Wed Nov 22 05:24:02 UTC 2023
>From d409be0b90ce91f8ffda343864636debd62ffe37 Mon Sep 17 00:00:00 2001
From: Kirithika <kirithika at multicorewareinc.com>
Date: Thu, 5 Oct 2023 12:26:35 +0530
Subject: [PATCH] Fix quality drop with SBRC feature
---
source/encoder/encoder.cpp | 21 +++++++++++++++------
source/encoder/ratecontrol.cpp | 31 +++++++++++++++++++------------
source/x265.h | 2 ++
3 files changed, 36 insertions(+), 18 deletions(-)
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 8ec01bebe..1280ccc66 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -4402,16 +4402,25 @@ void Encoder::configure(x265_param *p)
m_param->searchRange = m_param->hmeRange[2];
}
- if (p->bEnableSBRC && p->bOpenGOP)
+ if (p->bEnableSBRC && (p->rc.rateControlMode != X265_RC_CRF ||
(p->rc.vbvBufferSize == 0 || p->rc.vbvMaxBitrate == 0)))
{
- x265_log(p, X265_LOG_WARNING, "Segment based RateControl requires
closed gop structure. Enabling closed GOP.\n");
- p->bOpenGOP = 0;
+ x265_log(p, X265_LOG_WARNING, "SBRC can be enabled only with
CRF+VBV mode. Disabling SBRC\n");
+ p->bEnableSBRC = 0;
}
- if (p->bEnableSBRC && (p->keyframeMax != p->keyframeMin))
+ if (p->bEnableSBRC)
{
- 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;
+ p->rc.ipFactor = p->rc.ipFactor * X265_IPRATIO_STRENGTH;
+ if (p->bOpenGOP)
+ {
+ x265_log(p, X265_LOG_WARNING, "Segment based RateControl
requires closed gop structure. Enabling closed GOP.\n");
+ p->bOpenGOP = 0;
+ }
+ if (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;
+ }
}
}
diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
index 80f4ac3e9..099a03f0a 100644
--- a/source/encoder/ratecontrol.cpp
+++ b/source/encoder/ratecontrol.cpp
@@ -433,7 +433,7 @@ void RateControl::initVBV(const SPS& sps)
bool RateControl::init(const SPS& sps)
{
- if (m_isVbv && (!m_initVbv || m_param->bEnableSBRC))
+ if (m_isVbv && !m_initVbv)
initVBV(sps);
if (!m_param->bResetZoneConfig && (m_relativeComplexity == NULL))
@@ -480,7 +480,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_param->bEnableSBRC ? (m_bitrate * ( 1.0 /
m_param->keyframeMax )) :m_bitrate * m_frameDuration);
+ m_wantedBitsWindow = 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;
@@ -1823,8 +1823,7 @@ 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 duration = m_param->bEnableSBRC ? (1.0 / m_param->keyframeMax)
: m_frameDuration;
- double timeDone = (double)(m_framesDone - m_param->frameNumThreads +
1) * duration;
+ double timeDone = (double)(m_framesDone - m_param->frameNumThreads +
1) * m_frameDuration;
double wantedBits = timeDone * m_bitrate;
int64_t encodedBits = m_totalBits;
if (m_param->totalFrames && m_param->totalFrames <= 2 * m_fps)
@@ -1834,7 +1833,7 @@ double RateControl::tuneAbrQScaleFromFeedback(double
qScale)
}
if (wantedBits > 0 && encodedBits > 0 && (!m_partialResidualFrames ||
- m_param->rc.bStrictCbr || m_isGrainEnabled ||
m_param->bEnableSBRC))
+ m_param->rc.bStrictCbr || m_isGrainEnabled))
{
abrBuffer *= X265_MAX(1, sqrt(timeDone));
overflow = x265_clip3(.5, 2.0, 1.0 + (encodedBits - wantedBits) /
abrBuffer);
@@ -1924,7 +1923,7 @@ double RateControl::rateEstimateQscale(Frame*
curFrame, RateControlEntry *rce)
m_sliderPos++;
}
- if (m_sliceType == B_SLICE)
+ if((!m_param->bEnableSBRC && m_sliceType == B_SLICE) ||
(m_param->bEnableSBRC && !IS_REFERENCED(curFrame)))
{
/* B-frames don't have independent rate control, but rather get the
* average QP of the two adjacent P-frames + an offset */
@@ -2196,8 +2195,18 @@ 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);
+ if (m_param->bEnableSBRC)
+ {
+ double rfConstant = m_param->rc.rfConstant;
+ if (m_currentSatd < rce->movingAvgSum)
+ rfConstant += 2;
+ rfConstant = (rce->sliceType == I_SLICE ? rfConstant -
m_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;
+ m_rateFactorConstant = pow(m_currentSatd, 1.0 - qComp)
/
+ x265_qp2qScale(rfConstant + mbtree_offset);
+ }
q = getQScale(rce, m_rateFactorConstant);
x265_zone* zone = getZone();
if (zone)
@@ -2223,7 +2232,7 @@ double RateControl::rateEstimateQscale(Frame*
curFrame, RateControlEntry *rce)
}
double tunedQScale =
tuneAbrQScaleFromFeedback(initialQScale);
overflow = tunedQScale / initialQScale;
- q = (!m_partialResidualFrames || m_param->bEnableSBRC)?
tunedQScale : initialQScale;
+ q = !m_partialResidualFrames ? 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);
@@ -2420,8 +2429,6 @@ void RateControl::checkAndResetABR(RateControlEntry*
rce, bool isFrameDone)
m_shortTermCplxCount = 1;
m_isAbrReset = true;
m_lastAbrResetPoc = rce->poc;
- if(m_param->bEnableSBRC)
- rce->blurredComplexity = m_shortTermCplxSum /
m_shortTermCplxCount;
}
}
else if (m_isAbrReset && isFrameDone)
@@ -3062,7 +3069,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_param->bEnableSBRC ? (m_bitrate * (1.0 /
m_param->keyframeMax)) : m_frameDuration * m_bitrate);
+ m_wantedBitsWindow += m_frameDuration * m_bitrate;
m_totalBits += bits - rce->rowTotalBits;
m_encodedBits += actualBits;
int pos = m_sliderPos - m_param->frameNumThreads;
diff --git a/source/x265.h b/source/x265.h
index fb1a5dca7..d2bee6e37 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -623,6 +623,8 @@ typedef enum
#define X265_MAX_GOP_LENGTH 16
#define MAX_T_LAYERS 7
+#define X265_IPRATIO_STRENGTH 1.43
+
typedef struct x265_cli_csp
{
int planes;
--
2.28.0.windows.1
*Thanks,*
*Kirithika*
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20231122/1e2090fc/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: patch2-sbrc.diff
Type: application/octet-stream
Size: 7865 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20231122/1e2090fc/attachment-0001.obj>
More information about the x265-devel
mailing list