[x265] [PATCH] Add: End Of Bitstream and End Of Sequence NAL units
Niranjan Bala
niranjan at multicorewareinc.com
Wed Mar 24 12:50:12 UTC 2021
>From 40a0343cb8c0b75c564fce8f0fd2f5df0d8d45ec Mon Sep 17 00:00:00 2001
From: Niranjan <niranjan at multicorewareinc.com>
Date: Thu, 18 Mar 2021 09:41:49 +0530
Subject: [PATCH] Add: End Of Bitstream and End Of Sequence NAL units
---
doc/reST/api.rst | 11 +++++++++++
doc/reST/cli.rst | 10 ++++++++++
source/CMakeLists.txt | 2 +-
source/abrEncApp.cpp | 13 +++++++++++++
source/common/param.cpp | 8 ++++++++
source/encoder/api.cpp | 21 +++++++++++++++++++++
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 ++++
13 files changed, 100 insertions(+), 1 deletion(-)
diff --git a/doc/reST/api.rst b/doc/reST/api.rst
index 7444f35af..3ea11859e 100644
--- a/doc/reST/api.rst
+++ b/doc/reST/api.rst
@@ -381,6 +381,17 @@ When the last of the raw input pictures has been sent
to the encoder,
returns a value less than or equal to 0 (indicating the output bitstream
is complete).
+HEVC streams have EOS and EOB NAL units which specify the end of coded
video
+sequence and end of bitstream respectively. You must explicitly query those
+NAL units at the end using::
+
+ /* x265_encoder_end_nal_units:
+ * return the EOS and EOB NAL units.
+ * *pi_nal is the number of NAL units outputted in pp_nal.
+ * returns negative on error, total byte size of payload data on
success
+ * the payloads of all output NALs are guaranteed to be sequential in
memory. */
+ int x265_encoder_end_nal_units(x265_encoder *enc, x265_nal **pp_nal,
uint32_t *pi_nal);
+
At any time during this process, the application may query running
statistics from the encoder::
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
index c39fee83f..2f556326b 100755
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2529,6 +2529,16 @@ 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.
+ Default disabled
+
+.. option:: --eos, --no-eos
+
+ Emit an end of sequence NAL unit at the end of every coded
+ video sequence. Default disabled
+
.. 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 cd85154f1..1492b6a3c 100644
--- a/source/abrEncApp.cpp
+++ b/source/abrEncApp.cpp
@@ -794,7 +794,20 @@ ret:
m_cliopt.printStatus(outFrameCount);
if (!numEncoded)
+ {
+ if (m_param->bEnableEndOfBitstream ||
m_param->bEnableEndOfSequence)
+ {
+ 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);
+ }
break;
+ }
}
if (bDolbyVisionRPU)
diff --git a/source/common/param.cpp b/source/common/param.cpp
index fb74d759b..8a27aaef3 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 a986355e0..72e508f2f 100644
--- a/source/encoder/api.cpp
+++ b/source/encoder/api.cpp
@@ -295,6 +295,26 @@ 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)
+{
+ if (pp_nal && enc)
+ {
+ 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;
+ }
+
+ if (enc)
+ {
+ Encoder *encoder = static_cast<Encoder*>(enc);
+ encoder->m_aborted = true;
+ }
+ return -1;
+}
+
void x265_encoder_parameters(x265_encoder *enc, x265_param *out)
{
if (enc && out)
@@ -1052,6 +1072,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 19d15fb0d..c1e1cb46d 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 efe85282f..1b3875a25 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 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 1c51e769d..1d52ece51 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 e9af67c09..bfb6293f3 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 9eb571cfb..46a2b68ae 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 },
--
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/20210324/f2008167/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265.diff
Type: application/octet-stream
Size: 13363 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20210324/f2008167/attachment-0001.obj>
More information about the x265-devel
mailing list