[x265] [PATCH] API Support to enable VBV end feature
Yaswanth Sastry
yaswanth.sastry at multicorewareinc.com
Wed Sep 18 07:33:04 UTC 2024
>From b9de94104762177e25ad233ea6f6c89854621cef Mon Sep 17 00:00:00 2001
From: yaswanthsastry <yaswanth.sastry at multicorewareinc.com>
Date: Mon, 9 Sep 2024 14:57:14 +0530
Subject: [PATCH] API Support to enable VBV end feature
Added support for enabling the VBV-end feature in x265 when the total frame
count is unknown, using the x265_configure_vbv_end API.
---
source/CMakeLists.txt | 2 +-
source/common/frame.h | 2 ++
source/common/param.cpp | 2 --
source/encoder/api.cpp | 11 ++++++++++-
source/encoder/encoder.cpp | 1 +
source/encoder/ratecontrol.cpp | 22 +++++++++++++++-------
source/encoder/ratecontrol.h | 2 ++
source/x265.h | 9 +++++++++
8 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
index 1f5b9ca3c..f9a7f69ff 100755
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -31,7 +31,7 @@ option(NATIVE_BUILD "Target the build CPU" OFF)
option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)
mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)
# X265_BUILD must be incremented each time the public API is changed
-set(X265_BUILD 212)
+set(X265_BUILD 213)
configure_file("${PROJECT_SOURCE_DIR}/x265.def.in"
"${PROJECT_BINARY_DIR}/x265.def")
configure_file("${PROJECT_SOURCE_DIR}/x265_config.h.in"
diff --git a/source/common/frame.h b/source/common/frame.h
index 4fa90ef54..1f0a892b5 100644
--- a/source/common/frame.h
+++ b/source/common/frame.h
@@ -148,6 +148,8 @@ public:
Frame* m_prevMCSTF;
int* m_isSubSampled;
+ /*Vbv-End-Flag*/
+ int vbvEndFlag;
/* aq-mode 4 : Gaussian, edge and theta frames for edge information */
pixel* m_edgePic;
pixel* m_gaussianPic;
diff --git a/source/common/param.cpp b/source/common/param.cpp
index aad31b515..7700e94cf 100755
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -1819,8 +1819,6 @@ int x265_check_params(x265_param* param)
"Valid final VBV buffer emptiness must be a fraction 0 - 1, or
size in kbits");
CHECK(param->vbvEndFrameAdjust < 0,
"Valid vbv-end-fr-adj must be a fraction 0 - 1");
- CHECK(!param->totalFrames && param->vbvEndFrameAdjust,
- "vbv-end-fr-adj cannot be enabled when total number of frames is
unknown");
CHECK(param->minVbvFullness < 0 && param->minVbvFullness > 100,
"min-vbv-fullness must be a fraction 0 - 100");
CHECK(param->maxVbvFullness < 0 && param->maxVbvFullness > 100,
diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
index 96baf56c9..35c5a9be3 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -405,7 +405,14 @@ int x265_encoder_reconfig_zone(x265_encoder* enc,
x265_zone* zone_in)
return 0;
}
-
+void x265_configure_vbv_end(x265_encoder* enc, x265_picture* picture,
double totalstreamduration)
+{
+ Encoder* encoder = static_cast<Encoder*>(enc);
+ if ((totalstreamduration > 0) && (picture->poc) >
((encoder->m_param->vbvEndFrameAdjust)*(totalstreamduration)*((double)(encoder->m_param->fpsNum
/ encoder->m_param->fpsDenom))))
+ {
+ picture->vbvEndFlag = 1;
+ }
+}
int x265_encoder_encode(x265_encoder *enc, x265_nal **pp_nal, uint32_t
*pi_nal, x265_picture *pic_in, x265_picture **pic_out)
{
if (!enc)
@@ -1000,6 +1007,7 @@ void x265_picture_init(x265_param *param,
x265_picture *pic)
pic->rpu.payloadSize = 0;
pic->rpu.payload = NULL;
pic->picStruct = 0;
+ pic->vbvEndFlag = 0;
if ((param->analysisSave || param->analysisLoad) ||
(param->bAnalysisType == AVC_INFO))
{
@@ -1066,6 +1074,7 @@ static const x265_api libapi =
&x265_encoder_reconfig,
&x265_encoder_reconfig_zone,
&x265_encoder_headers,
+ &x265_configure_vbv_end,
&x265_encoder_encode,
&x265_encoder_get_stats,
&x265_encoder_log,
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
index 1a16f039d..76b3d3872 100644
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -1713,6 +1713,7 @@ int Encoder::encode(const x265_picture* pic_in,
x265_picture** pic_out)
inFrame[layer]->m_poc = (!layer) ? (++m_pocLast) : m_pocLast;
inFrame[layer]->m_userData = inputPic[0]->userData;
inFrame[layer]->m_pts = inputPic[0]->pts;
+ inFrame[layer]->vbvEndFlag = inputPic[layer]->vbvEndFlag;
if ((m_param->bEnableSceneCutAwareQp & BACKWARD) &&
m_param->rc.bStatRead)
{
diff --git a/source/encoder/ratecontrol.cpp b/source/encoder/ratecontrol.cpp
index 25cb7318e..e023db12d 100644
--- a/source/encoder/ratecontrol.cpp
+++ b/source/encoder/ratecontrol.cpp
@@ -210,6 +210,7 @@ RateControl::RateControl(x265_param& p, Encoder *top)
m_isFirstMiniGop = false;
m_lastScenecut = -1;
m_lastScenecutAwareIFrame = -1;
+ m_totalFrames = -1;
if (m_param->rc.rateControlMode == X265_RC_CRF)
{
m_param->rc.qp = (int)m_param->rc.rfConstant;
@@ -1458,11 +1459,14 @@ int RateControl::rateControlStart(Frame* curFrame,
RateControlEntry* rce, Encode
updateVbvPlan(enc);
rce->bufferFill = m_bufferFill;
rce->vbvEndAdj = false;
- if (m_param->vbvBufferEnd && rce->encodeOrder >=
m_param->vbvEndFrameAdjust * m_param->totalFrames)
- {
- rce->vbvEndAdj = true;
- rce->targetFill = 0;
- }
+ if (m_param->vbvBufferEnd && ((curFrame->vbvEndFlag) ||
((m_param->totalFrames) && (rce->encodeOrder >= (m_param->vbvEndFrameAdjust
* m_param->totalFrames)))))
+ {
+ if (m_totalFrames == -1)
+ m_totalFrames = curFrame->vbvEndFlag ? (1 /
m_param->vbvEndFrameAdjust) * rce->encodeOrder : m_param->totalFrames;
+ rce->remainingVbvEndFrames = ((m_totalFrames) -
(rce->encodeOrder));
+ rce->vbvEndAdj = true;
+ rce->targetFill = 0;
+ }
int mincr = enc->m_vps.ptl.minCrForLevel;
/* Profiles above Main10 don't require maxAU size check, so just
set the maximum to a large value. */
@@ -2584,8 +2588,12 @@ double RateControl::clipQscale(Frame* curFrame,
RateControlEntry* rce, double q)
{
bool loopBreak = false;
double bufferDiff = m_param->vbvBufferEnd -
(m_bufferFill / m_bufferSize);
- rce->targetFill = m_bufferFill + m_bufferSize *
(bufferDiff / (m_param->totalFrames - rce->encodeOrder));
- if (bufferFillCur < rce->targetFill)
+ if (rce->remainingVbvEndFrames > 0) {
+ rce->targetFill = m_bufferFill + m_bufferSize
* (bufferDiff / (double)(rce->remainingVbvEndFrames));
+ }
+ else
+ rce->targetFill = m_bufferFill + m_bufferSize
* bufferDiff;
+ if (bufferFillCur < rce->targetFill)
{
q *= 1.01;
loopTerminate |= 1;
diff --git a/source/encoder/ratecontrol.h b/source/encoder/ratecontrol.h
index c3dc0406f..7e138c43a 100644
--- a/source/encoder/ratecontrol.h
+++ b/source/encoder/ratecontrol.h
@@ -100,6 +100,7 @@ struct RateControlEntry
bool isActive;
double amortizeFrames;
double amortizeFraction;
+ int remainingVbvEndFrames;
/* Required in 2-pass rate control */
uint64_t expectedBits; /* total expected bits up to the current frame
(current one excluded) */
double iCuCount;
@@ -136,6 +137,7 @@ public:
double* m_relativeComplexity;
int m_zoneBufferIdx;
+ int m_totalFrames;
bool m_isAbr;
bool m_isVbv;
bool m_isCbr;
diff --git a/source/x265.h b/source/x265.h
index 80d1358cd..d0a80bf0c 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -408,6 +408,8 @@ typedef struct x265_picture
* on output */
int64_t dts;
+ int vbvEndFlag; // New flag for VBV end feature
+
/* force quantizer for != X265_QP_AUTO */
/* The value provided on input is returned with the same picture (POC)
on
* output */
@@ -2495,6 +2497,12 @@ int x265_encoder_headers(x265_encoder *, x265_nal
**pp_nal, uint32_t *pi_nal);
* Once flushing has begun, all subsequent calls must pass pic_in as
NULL. */
int x265_encoder_encode(x265_encoder *encoder, x265_nal **pp_nal, uint32_t
*pi_nal, x265_picture *pic_in, x265_picture **pic_out);
+/*
+x265_configure_vbv_end:
+* Set the Vbvend flag based on the totalstreamduration.
+*/
+void x265_configure_vbv_end(x265_encoder* enc, x265_picture* picture,
double totalstreamduration);
+
/* x265_encoder_reconfig:
* various parameters from x265_param are copied.
* this takes effect immediately, on whichever frame is encoded next;
@@ -2647,6 +2655,7 @@ typedef struct x265_api
int (*encoder_reconfig)(x265_encoder*, x265_param*);
int (*encoder_reconfig_zone)(x265_encoder*, x265_zone*);
int (*encoder_headers)(x265_encoder*, x265_nal**, uint32_t*);
+ void (*configure_vbv_end)(x265_encoder*, x265_picture*,
double );
int (*encoder_encode)(x265_encoder*, x265_nal**, uint32_t*,
x265_picture*, x265_picture**);
void (*encoder_get_stats)(x265_encoder*, x265_stats*,
uint32_t);
void (*encoder_log)(x265_encoder*, int, char**);
--
2.37.3.windows.1
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240918/601dadf0/attachment-0001.htm>
More information about the x265-devel
mailing list