[x265] [PATCH] API Support to enable VBV end feature
Karam Singh
karam.singh at multicorewareinc.com
Thu Sep 26 07:52:19 UTC 2024
This patch has been pushed to the master branch.
*__________________________*
*Karam Singh*
*Ph.D. IIT Guwahati*
Senior Software (Video Coding) Engineer
Mobile: +91 8011279030
Block 9A, 6th floor, DLF Cyber City
Manapakkam, Chennai 600 089
On Wed, Sep 18, 2024 at 1:05 PM Yaswanth Sastry <
yaswanth.sastry at multicorewareinc.com> wrote:
> 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
>>
>> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20240926/d78fd199/attachment-0001.htm>
More information about the x265-devel
mailing list