[x265] [PATCH] API Support to enable VBV end feature
Yaswanth Sastry
yaswanth.sastry at multicorewareinc.com
Wed Sep 18 07:34:47 UTC 2024
Attaching the Patch for reference.
On Wed, Sep 18, 2024 at 1:03 PM Yaswanth Sastry <
yaswanth.sastry at multicorewareinc.com> wrote:
> 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/9f980308/attachment-0001.htm>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: Support_Vbv_End_With_FFmpeg_Through_API.diff
Type: application/octet-stream
Size: 9401 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240918/9f980308/attachment-0001.obj>
More information about the x265-devel
mailing list