[x265] [PATCH] Add: End Of Bitstream and End Of Sequence NAL units

Aruna Matheswaran aruna at multicorewareinc.com
Fri Mar 19 05:56:24 UTC 2021


On Thu, Mar 18, 2021 at 11:36 PM Niranjan Bala <
niranjan at multicorewareinc.com> wrote:

> From d8dfb330dfdf5704dbf761d43e7814a56927dac5 Mon Sep 17 00:00:00 2001
> From: Niranjan <niranjan at multicorewareinc.com>
> Date: Thu, 18 Mar 2021 16:57:24 +0530
> Subject: [PATCH] Add: End Of Bitstream and End Of Sequence NAL units
>
> ---
>  doc/reST/cli.rst                 |  9 +++++++++
>  source/CMakeLists.txt            |  2 +-
>  source/abrEncApp.cpp             | 12 ++++++++++++
>  source/common/param.cpp          |  8 ++++++++
>  source/encoder/api.cpp           | 11 +++++++++++
>  source/encoder/encoder.cpp       | 13 +++++++++++++
>  source/encoder/encoder.h         |  2 ++
>  source/encoder/frameencoder.cpp  |  6 ++++++
>  source/test/regression-tests.txt |  1 +
>  source/x265.h                    |  8 ++++++++
>  source/x265cli.cpp               |  2 ++
>  source/x265cli.h                 |  4 ++++
>  12 files changed, 77 insertions(+), 1 deletion(-)
>
> diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
> index c39fee8..f0f8d2a 100755
> --- a/doc/reST/cli.rst
> +++ b/doc/reST/cli.rst
> @@ -2529,6 +2529,15 @@ Bitstream options
>   the very first AUD will be skipped since it cannot be placed at the
>   start of the access unit, where it belongs. Default disabled
>
> +.. option:: --eob, --no-eob
> +
> + Emit an end of bitstream NAL unit at the end of the bitstream.
> +
> +.. option:: --eos, --no-eos
> +
> + Emit an end of sequence NAL unit at the end of every coded
> + video sequence.
> +
>
[AM] Please mention the default settings.
Also, API documentation for x265_encoder_end_nal_units() is missing.

>  .. option:: --hrd, --no-hrd
>
>   Enable the signaling of HRD parameters to the decoder. The HRD
> diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
> index a407271..b4e57b5 100755
> --- a/source/CMakeLists.txt
> +++ b/source/CMakeLists.txt
> @@ -29,7 +29,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 199)
> +set(X265_BUILD 200)
>  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/abrEncApp.cpp b/source/abrEncApp.cpp
> index cd85154..fcb1978 100644
> --- a/source/abrEncApp.cpp
> +++ b/source/abrEncApp.cpp
> @@ -797,6 +797,18 @@ ret:
>                      break;
>              }
>
> +            if ((m_param->bEnableEndOfBitstream ||
> m_param->bEnableEndOfSequence) && outFrameCount ==
> (uint32_t)m_param->totalFrames)
>
[AM] This may not work with live input streams. Please check.

> +            {
> +                if (api->encoder_end_nal_units(m_encoder, &p_nal, &nal) <
> 0)
> +                {
> +                    x265_log(NULL, X265_LOG_ERROR, "Failure generating
> end nal units\n");
> +                    m_ret = 3;
> +                    goto fail;
> +                }
> +                else
> +                    m_cliopt.totalbytes +=
> m_cliopt.output->writeHeaders(p_nal, nal);
>
[AM] Should we mark --eob as `CLI only` option? Given that EOB insertion is
handled completely in the application, I don't see the need for the APIs
specific to EOB. Please clarify.

> +            }
> +
>              if (bDolbyVisionRPU)
>              {
>                  if (fgetc(m_cliopt.dolbyVisionRpu) != EOF)
> diff --git a/source/common/param.cpp b/source/common/param.cpp
> index fb74d75..8a27aae 100755
> --- a/source/common/param.cpp
> +++ b/source/common/param.cpp
> @@ -145,6 +145,8 @@ void x265_param_default(x265_param* param)
>      param->bAnnexB = 1;
>      param->bRepeatHeaders = 0;
>      param->bEnableAccessUnitDelimiters = 0;
> +    param->bEnableEndOfBitstream = 0;
> +    param->bEnableEndOfSequence = 0;
>      param->bEmitHRDSEI = 0;
>      param->bEmitInfoSEI = 1;
>      param->bEmitHDRSEI = 0; /*Deprecated*/
> @@ -1448,6 +1450,8 @@ int x265_param_parse(x265_param* p, const char*
> name, const char* value)
>          OPT("min-vbv-fullness") p->minVbvFullness = atof(value);
>          OPT("max-vbv-fullness") p->maxVbvFullness = atof(value);
>          OPT("video-signal-type-preset") p->videoSignalTypePreset =
> strdup(value);
> +        OPT("eob") p->bEnableEndOfBitstream = atobool(value);
> +        OPT("eos") p->bEnableEndOfSequence = atobool(value);
>          else
>              return X265_PARAM_BAD_NAME;
>      }
> @@ -2130,6 +2134,8 @@ char *x265_param2string(x265_param* p, int padx, int
> pady)
>      BOOL(p->bRepeatHeaders, "repeat-headers");
>      BOOL(p->bAnnexB, "annexb");
>      BOOL(p->bEnableAccessUnitDelimiters, "aud");
> +    BOOL(p->bEnableEndOfBitstream, "eob");
> +    BOOL(p->bEnableEndOfSequence, "eos");
>      BOOL(p->bEmitHRDSEI, "hrd");
>      BOOL(p->bEmitInfoSEI, "info");
>      s += sprintf(s, " hash=%d", p->decodedPictureHashSEI);
> @@ -2444,6 +2450,8 @@ void x265_copy_params(x265_param* dst, x265_param*
> src)
>      dst->bRepeatHeaders = src->bRepeatHeaders;
>      dst->bAnnexB = src->bAnnexB;
>      dst->bEnableAccessUnitDelimiters = src->bEnableAccessUnitDelimiters;
> +    dst->bEnableEndOfBitstream = src->bEnableEndOfBitstream;
> +    dst->bEnableEndOfSequence = src->bEnableEndOfSequence;
>      dst->bEmitInfoSEI = src->bEmitInfoSEI;
>      dst->decodedPictureHashSEI = src->decodedPictureHashSEI;
>      dst->bEnableTemporalSubLayers = src->bEnableTemporalSubLayers;
> diff --git a/source/encoder/api.cpp b/source/encoder/api.cpp
> index a986355..e4eba71 100644
> --- a/source/encoder/api.cpp
> +++ b/source/encoder/api.cpp
> @@ -295,6 +295,16 @@ int x265_encoder_headers(x265_encoder *enc, x265_nal
> **pp_nal, uint32_t *pi_nal)
>      return -1;
>  }
>
> +int x265_encoder_end_nal_units(x265_encoder *enc, x265_nal **pp_nal,
> uint32_t *pi_nal)
> +{
> +    Encoder *encoder = static_cast<Encoder*>(enc);
> +    Bitstream bs;
> +    encoder->getEndNalUnits(encoder->m_nalList, bs);
> +    *pp_nal = &encoder->m_nalList.m_nal[0];
> +    if (pi_nal) *pi_nal = encoder->m_nalList.m_numNal;
> +    return encoder->m_nalList.m_occupancy;
> +}
> +
>  void x265_encoder_parameters(x265_encoder *enc, x265_param *out)
>  {
>      if (enc && out)
> @@ -1052,6 +1062,7 @@ static const x265_api libapi =
>      &x265_encoder_reconfig,
>      &x265_encoder_reconfig_zone,
>      &x265_encoder_headers,
> +    &x265_encoder_end_nal_units,
>      &x265_encoder_encode,
>      &x265_encoder_get_stats,
>      &x265_encoder_log,
> diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
> index 19d15fb..c1e1cb4 100644
> --- a/source/encoder/encoder.cpp
> +++ b/source/encoder/encoder.cpp
> @@ -3374,6 +3374,19 @@ void Encoder::getStreamHeaders(NALList& list,
> Entropy& sbacCoder, Bitstream& bs)
>      }
>  }
>
> +void Encoder::getEndNalUnits(NALList& list, Bitstream& bs)
> +{
> +    NALList nalList;
> +    bs.resetBits();
> +
> +    if (m_param->bEnableEndOfSequence)
> +        nalList.serialize(NAL_UNIT_EOS, bs);
> +    if (m_param->bEnableEndOfBitstream)
> +        nalList.serialize(NAL_UNIT_EOB, bs);
> +
> +    list.takeContents(nalList);
> +}
> +
>  void Encoder::initVPS(VPS *vps)
>  {
>      /* Note that much of the VPS is initialized by determineLevel() */
> diff --git a/source/encoder/encoder.h b/source/encoder/encoder.h
> index 22a886e..2ee5bda 100644
> --- a/source/encoder/encoder.h
> +++ b/source/encoder/encoder.h
> @@ -327,6 +327,8 @@ public:
>
>      void getStreamHeaders(NALList& list, Entropy& sbacCoder, Bitstream&
> bs);
>
> +    void getEndNalUnits(NALList& list, Bitstream& bs);
> +
>      void fetchStats(x265_stats* stats, size_t statsSizeBytes);
>
>      void printSummary();
> diff --git a/source/encoder/frameencoder.cpp
> b/source/encoder/frameencoder.cpp
> index efe8528..1b3875a 100644
> --- a/source/encoder/frameencoder.cpp
> +++ b/source/encoder/frameencoder.cpp
> @@ -467,6 +467,12 @@ void FrameEncoder::compressFrame()
>       * unit) */
>      Slice* slice = m_frame->m_encData->m_slice;
>
> +    if (m_param->bEnableEndOfSequence && m_frame->m_lowres.sliceType ==
> X265_TYPE_IDR && m_frame->m_poc)
> +    {
> +        m_bs.resetBits();
> +        m_nalList.serialize(NAL_UNIT_EOS, m_bs);
> +    }
> +
>      if (m_param->bEnableAccessUnitDelimiters && (m_frame->m_poc ||
> m_param->bRepeatHeaders))
>      {
>          m_bs.resetBits();
> diff --git a/source/test/regression-tests.txt
> b/source/test/regression-tests.txt
> index a4fcab8..971c854 100644
> --- a/source/test/regression-tests.txt
> +++ b/source/test/regression-tests.txt
> @@ -166,6 +166,7 @@ crowd_run_1920x1080_50.yuv, --preset fast --ctu 64
> --rskip 2 --rskip-edge-thresh
>  crowd_run_1920x1080_50.yuv, --preset slow --ctu 32 --rskip 2
> --rskip-edge-threshold 5 --hist-scenecut --hist-threshold 0.1
>  crowd_run_1920x1080_50.yuv, --preset slower --ctu 16 --rskip 2
> --rskip-edge-threshold 5 --hist-scenecut --hist-threshold 0.1 --aq-mode 4
>  crowd_run_1920x1080_50.yuv, --preset ultrafast --video-signal-type-preset
> BT2100_PQ_YCC:BT2100x108n0005
> +crowd_run_1920x1080_50.yuv, --preset ultrafast --eob --eos
>
>  # Main12 intraCost overflow bug test
>  720p50_parkrun_ter.y4m,--preset medium
> diff --git a/source/x265.h b/source/x265.h
> index 1c51e76..1d52ece 100644
> --- a/source/x265.h
> +++ b/source/x265.h
> @@ -1956,6 +1956,13 @@ typedef struct x265_param
>      * or color-volume, it will be discarded. */
>      const char* videoSignalTypePreset;
>
> +    /* Flag indicating whether the encoder should emit an End of Bitstream
> +     * NAL at the end of bitstream. Default false */
> +    int      bEnableEndOfBitstream;
> +
> +    /* Flag indicating whether the encoder should emit an End of Sequence
> +     * NAL at the end of every Coded Video Sequence. Default false */
> +    int      bEnableEndOfSequence;
>  } x265_param;
>
>  /* x265_param_alloc:
> @@ -2269,6 +2276,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*);
> +    int           (*encoder_end_nal_units)(x265_encoder*, x265_nal**,
> uint32_t*);
>      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**);
> diff --git a/source/x265cli.cpp b/source/x265cli.cpp
> index e9af67c..bfb6293 100755
> --- a/source/x265cli.cpp
> +++ b/source/x265cli.cpp
> @@ -351,6 +351,8 @@ namespace X265_NS {
>          H0("   --[no-]idr-recovery-sei      Emit recovery point infor SEI
> at each IDR frame \n");
>          H0("   --[no-]temporal-layers        Enable a temporal sublayer
> for unreferenced B frames. Default %s\n",
> OPT(param->bEnableTemporalSubLayers));
>          H0("   --[no-]aud                    Emit access unit delimiters
> at the start of each access unit. Default %s\n",
> OPT(param->bEnableAccessUnitDelimiters));
> +        H0("   --[no-]eob                    Emit end of bitstream nal
> unit at the end of the bitstream. Default %s\n",
> OPT(param->bEnableEndOfBitstream));
> +        H0("   --[no-]eos                    Emit end of sequence nal
> unit at the end of every coded video sequence. Default %s\n",
> OPT(param->bEnableEndOfSequence));
>          H1("   --hash <integer>              Decoded Picture Hash SEI 0:
> disabled, 1: MD5, 2: CRC, 3: Checksum. Default %d\n",
> param->decodedPictureHashSEI);
>          H0("   --atc-sei <integer>           Emit the alternative
> transfer characteristics SEI message where the integer is the preferred
> transfer characteristics. Default disabled\n");
>          H0("   --pic-struct <integer>        Set the picture structure
> and emits it in the picture timing SEI message. Values in the range 0..12.
> See D.3.3 of the HEVC spec. for a detailed explanation.\n");
> diff --git a/source/x265cli.h b/source/x265cli.h
> index 9eb571c..46a2b68 100644
> --- a/source/x265cli.h
> +++ b/source/x265cli.h
> @@ -264,6 +264,10 @@ static const struct option long_options[] =
>      { "repeat-headers",       no_argument, NULL, 0 },
>      { "aud",                  no_argument, NULL, 0 },
>      { "no-aud",               no_argument, NULL, 0 },
> +    { "eob",                  no_argument, NULL, 0 },
> +    { "no-eob",               no_argument, NULL, 0 },
> +    { "eos",                  no_argument, NULL, 0 },
> +    { "no-eos",               no_argument, NULL, 0 },
>      { "info",                 no_argument, NULL, 0 },
>      { "no-info",              no_argument, NULL, 0 },
>      { "zones",          required_argument, NULL, 0 },
> --
> 1.8.3.1
>
>
> --
>
> Thanks & Regards
> *Niranjan Kumar B*
> Video Codec Engineer
> Media & AI Analytics
> +91 958 511 1449
> <https://multicorewareinc.com/>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>


-- 
Regards,
*Aruna Matheswaran,*
Video Codec Engineer,
Media & AI analytics BU,
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20210319/6466cffe/attachment-0001.html>


More information about the x265-devel mailing list