<div dir="ltr">Attaching the Patch for reference.<br> </div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Sep 18, 2024 at 1:03 PM Yaswanth Sastry <<a href="mailto:yaswanth.sastry@multicorewareinc.com">yaswanth.sastry@multicorewareinc.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><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" target="_blank">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><div><div><div></div></div></div></div><div><div><div><div dir="auto"><div><div><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" target="_blank">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" target="_blank">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>
</blockquote></div>