[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