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