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

Niranjan Bala niranjan at multicorewareinc.com
Tue Mar 16 19:06:18 UTC 2021


>From 22a33a4d48d5f2134e21ac1cae4e97e282b18f5d Mon Sep 17 00:00:00 2001
From: Niranjan <niranjan at multicorewareinc.com>
Date: Tue, 16 Mar 2021 23:41:35 +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                    |  9 +++++++++
 source/x265cli.cpp               |  2 ++
 source/x265cli.h                 |  4 ++++
 12 files changed, 78 insertions(+), 1 deletion(-)

diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index 1bb90175b..fe5dd6a7b 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2488,6 +2488,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.
+
 .. 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 a407271b4..b4e57b592 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 fa62ebf63..b637908b9 100644
--- a/source/abrEncApp.cpp
+++ b/source/abrEncApp.cpp
@@ -795,6 +795,18 @@ ret:
                     break;
             }

+            if ((m_param->bEnableEndOfBitstream ||
m_param->bEnableEndOfSequence) && outFrameCount ==
(uint32_t)m_param->totalFrames)
+            {
+                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);
+            }
+
             if (bDolbyVisionRPU)
             {
                 if (fgetc(m_cliopt.dolbyVisionRpu) != EOF)
diff --git a/source/common/param.cpp b/source/common/param.cpp
index 90b80c8a4..11a3ddc96 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*/
@@ -1383,6 +1385,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;
     }
@@ -2056,6 +2060,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);
@@ -2370,6 +2376,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 a986355e0..e4eba7139 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 1dd247124..74f69d250 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 22a886ef4..2ee5bdaee 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 2086a15a5..1c0554c2d 100644
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -465,6 +465,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 a4fcab87f..971c854df 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 ad02072bf..796b134a9 100644
--- a/source/x265.h
+++ b/source/x265.h
@@ -1939,6 +1939,14 @@ typedef struct x265_param
      * together with this, which changes the values set corresponding to
the system-id
      * 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:
@@ -2252,6 +2260,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 f2b73f7db..334396e53 100755
--- a/source/x265cli.cpp
+++ b/source/x265cli.cpp
@@ -350,6 +350,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 3d2480374..2b0518d1f 100644
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -269,6 +269,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 },
-- 
2.18.0.windows.1


-- 

Thanks & Regards
*Niranjan Kumar B*
Video Codec Engineer
Media & AI Analytics
+91 958 511 1449
<https://multicorewareinc.com/>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20210317/abe8a9ec/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265.diff
Type: application/octet-stream
Size: 12065 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20210317/abe8a9ec/attachment-0001.obj>


More information about the x265-devel mailing list