[x265] [PATCH] introduce new CLI single-sei to write all SEI messages in one single NAL
santhoshini at multicorewareinc.com
santhoshini at multicorewareinc.com
Mon Apr 2 15:01:14 CEST 2018
# HG changeset patch
# User Santhoshini Sekar <santhoshini at multicorewareinc.com>
# Date 1522673234 -19800
# Mon Apr 02 18:17:14 2018 +0530
# Node ID 6337356c86a4f5a49f275eb466d6fae32e6eb145
# Parent 946f82dbf4e80cb272f43a32a78ba2b186469845
introduce new CLI single-sei to write all SEI messages in one single NAL
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst
--- a/doc/reST/cli.rst
+++ b/doc/reST/cli.rst
@@ -2221,6 +2221,10 @@
.. option:: --idr-recovery-sei, --no-idr-recoveery-sei
Emit RecoveryPoint info as sei in bitstream for each IDR frame. Default disabled.
+.. option:: --single-sei, --no-single-sei
+ Emit SEI messages in a single NAL unit instead of multiple NALs. Default disabled.
+ When HRD SEI is enabled the HM decoder will throw a warning.
+
DCT Approximations
=================
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt
--- a/source/CMakeLists.txt
+++ b/source/CMakeLists.txt
@@ -29,7 +29,7 @@
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 156)
+set(X265_BUILD 157)
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/param.cpp b/source/common/param.cpp
--- a/source/common/param.cpp
+++ b/source/common/param.cpp
@@ -301,6 +301,7 @@
/* DCT Approximations */
param->bLowPassDct = 0;
param->bMVType = 0;
+ param->bSingleSeiNal = 0;
}
int x265_param_default_preset(x265_param* param, const char* preset, const char* tune)
@@ -1017,6 +1018,7 @@
OPT("radl") p->radl = atoi(value);
OPT("max-ausize-factor") p->maxAUSizeFactor = atof(value);
OPT("dynamic-refine") p->bDynamicRefine = atobool(value);
+ OPT("single-sei") p->bSingleSeiNal = atobool(value);
else
return X265_PARAM_BAD_NAME;
}
@@ -1382,6 +1384,14 @@
if (param->masteringDisplayColorVolume || param->maxFALL || param->maxCLL)
param->bEmitHDRSEI = 1;
+ bool isSingleSEI = ((param->bEmitHRDSEI || param->bEmitInfoSEI || param->decodedPictureHashSEI ||
+ param->masteringDisplayColorVolume || param->maxCLL || param->maxFALL ||
+ param->bEmitHDRSEI || param->bEmitIDRRecoverySEI) && param->bSingleSeiNal);
+ if (!isSingleSEI)
+ {
+ param->bSingleSeiNal = 0;
+ x265_log(param, X265_LOG_WARNING, "None of the SEI messages are enabled. Diabling Single SEI NAL\n");
+ }
return check_failed;
}
@@ -1528,6 +1538,7 @@
TOOLOPT(!param->bSaoNonDeblocked && param->bEnableSAO, "sao");
TOOLOPT(param->rc.bStatWrite, "stats-write");
TOOLOPT(param->rc.bStatRead, "stats-read");
+ TOOLOPT(param->bSingleSeiNal, "single-sei");
#if ENABLE_HDR10_PLUS
TOOLOPT(param->toneMapFile != NULL, "dhdr10-info");
#endif
@@ -1751,6 +1762,7 @@
s += sprintf(s, " copy-pic=%d", p->bCopyPicToFrame);
s += sprintf(s, " max-ausize-factor=%.1f", p->maxAUSizeFactor);
BOOL(p->bDynamicRefine, "dynamic-refine");
+ BOOL(p->bSingleSeiNal, "single-sei");
#undef BOOL
return buf;
}
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp
--- a/source/encoder/encoder.cpp
+++ b/source/encoder/encoder.cpp
@@ -2289,26 +2289,26 @@
sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1), m_iPPSQpMinus26);
bs.writeByteAlignment();
list.serialize(NAL_UNIT_PPS, bs);
-
+ if (m_param->bSingleSeiNal)
+ bs.resetBits();
if (m_param->bEmitHDRSEI)
{
SEIContentLightLevel cllsei;
cllsei.max_content_light_level = m_param->maxCLL;
cllsei.max_pic_average_light_level = m_param->maxFALL;
- bs.resetBits();
+ if (!m_param->bSingleSeiNal)
+ bs.resetBits();
cllsei.write(bs, m_sps);
- bs.writeByteAlignment();
- list.serialize(NAL_UNIT_PREFIX_SEI, bs);
-
+ cllsei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);
if (m_param->masteringDisplayColorVolume)
{
SEIMasteringDisplayColorVolume mdsei;
if (mdsei.parse(m_param->masteringDisplayColorVolume))
{
- bs.resetBits();
+ if (!m_param->bSingleSeiNal)
+ bs.resetBits();
mdsei.write(bs, m_sps);
- bs.writeByteAlignment();
- list.serialize(NAL_UNIT_PREFIX_SEI, bs);
+ mdsei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);
}
else
x265_log(m_param, X265_LOG_WARNING, "unable to parse mastering display color volume info\n");
@@ -2328,15 +2328,13 @@
"Copyright 2013-2018 (c) Multicoreware, Inc - "
"http://x265.org - options: %s",
X265_BUILD, PFX(version_str), PFX(build_info_str), opts);
-
- bs.resetBits();
+ if (!m_param->bSingleSeiNal)
+ bs.resetBits();
SEIuserDataUnregistered idsei;
idsei.m_userData = (uint8_t*)buffer;
idsei.setSize((uint32_t)strlen(buffer));
idsei.write(bs, m_sps);
- bs.writeByteAlignment();
- list.serialize(NAL_UNIT_PREFIX_SEI, bs);
-
+ idsei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);
X265_FREE(buffer);
}
@@ -2350,12 +2348,12 @@
SEIActiveParameterSets sei;
sei.m_selfContainedCvsFlag = true;
sei.m_noParamSetUpdateFlag = true;
- bs.resetBits();
+ if (!m_param->bSingleSeiNal)
+ bs.resetBits();
int payloadSize = sei.countPayloadSize(m_sps);
sei.setSize(payloadSize);
sei.write(bs, m_sps);
- bs.writeByteAlignment();
- list.serialize(NAL_UNIT_PREFIX_SEI, bs);
+ sei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);
}
}
diff --git a/source/encoder/frameencoder.cpp b/source/encoder/frameencoder.cpp
--- a/source/encoder/frameencoder.cpp
+++ b/source/encoder/frameencoder.cpp
@@ -393,6 +393,7 @@
* not repeating headers (since AUD is supposed to be the first NAL in the access
* unit) */
Slice* slice = m_frame->m_encData->m_slice;
+
if (m_param->bEnableAccessUnitDelimiters && (m_frame->m_poc || m_param->bRepeatHeaders))
{
m_bs.resetBits();
@@ -400,6 +401,8 @@
m_entropyCoder.codeAUD(*slice);
m_bs.writeByteAlignment();
m_nalList.serialize(NAL_UNIT_ACCESS_UNIT_DELIMITER, m_bs);
+ if (m_param->bSingleSeiNal)
+ m_bs.resetBits();
}
if (m_frame->m_lowres.bKeyframe && m_param->bRepeatHeaders)
{
@@ -527,7 +530,7 @@
}
bool isIDR = m_frame->m_lowres.sliceType == X265_TYPE_IDR;
- writeSei = payloadChange || isIDR;
+ writeSei = (payloadChange || isIDR);
}
}
}
@@ -633,12 +636,12 @@
bpSei->m_dpbDelayOffset = 0;
// hrdFullness() calculates the initial CPB removal delay and offset
m_top->m_rateControl->hrdFullness(bpSei);
- m_bs.resetBits();
+ if (!m_param->bSingleSeiNal)
+ m_bs.resetBits();
int payloadSize = bpSei->countPayloadSize(*slice->m_sps);
bpSei->setSize(payloadSize);
bpSei->write(m_bs, *slice->m_sps);
- m_bs.writeByteAlignment();
- m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+ bpSei->alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);
m_top->m_lastBPSEI = m_rce.encodeOrder;
}
@@ -650,11 +653,11 @@
sei.m_recoveryPocCnt = 0;
sei.m_exactMatchingFlag = true;
sei.m_brokenLinkFlag = false;
- m_bs.resetBits();
+ if (!m_param->bSingleSeiNal)
+ m_bs.resetBits();
sei.setSize(sei.countPayloadSize(*slice->m_sps));
sei.write(m_bs, *slice->m_sps);
- m_bs.writeByteAlignment();
- m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+ sei.alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);
}
}
@@ -686,12 +689,12 @@
sei->m_auCpbRemovalDelay = X265_MIN(X265_MAX(1, m_rce.encodeOrder - prevBPSEI), (1 << hrd->cpbRemovalDelayLength));
sei->m_picDpbOutputDelay = slice->m_sps->numReorderPics + poc - m_rce.encodeOrder;
}
- m_bs.resetBits();
+ if (!m_param->bSingleSeiNal)
+ m_bs.resetBits();
int payloadSize = sei->countPayloadSize(*slice->m_sps);
sei->setSize(payloadSize);
sei->write(m_bs, *slice->m_sps);
- m_bs.writeByteAlignment();
- m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+ sei->alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);
}
/* Write user SEI */
@@ -702,11 +705,11 @@
{
SEIuserDataUnregistered sei;
sei.m_userData = payload->payload;
- m_bs.resetBits();
+ if (!m_param->bSingleSeiNal)
+ m_bs.resetBits();
sei.setSize(payload->payloadSize);
sei.write(m_bs, *slice->m_sps);
- m_bs.writeByteAlignment();
- m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+ sei.alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);
}
else if (payload->payloadType == USER_DATA_REGISTERED_ITU_T_T35)
{
@@ -717,13 +720,21 @@
m_bs.resetBits();
sei.setSize(payload->payloadSize);
sei.write(m_bs, *slice->m_sps);
- m_bs.writeByteAlignment();
- m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+ sei.alignAndSerialize(m_bs, true, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);
}
}
else
x265_log(m_param, X265_LOG_ERROR, "Unrecognized SEI type\n");
}
+ bool isSei = (m_frame->m_lowres.bKeyframe &&
+ (m_param->bRepeatHeaders || m_param->bEmitHRDSEI
+ || !!m_param->interlaceMode || m_param->bEmitIDRRecoverySEI));
+
+ if (isSei && m_param->bSingleSeiNal)
+ {
+ m_bs.writeByteAlignment();
+ m_nalList.serialize(NAL_UNIT_PREFIX_SEI, m_bs);
+ }
/* CQP and CRF (without capped VBV) doesn't use mid-frame statistics to
* tune RateControl parameters for other frames.
* Hence, for these modes, update m_startEndOrder and unlock RC for previous threads waiting in
@@ -1055,7 +1066,8 @@
m_nalList.serialize(slice->m_nalUnitType, m_bs);
}
-
+ if (isSei && m_param->bSingleSeiNal)
+ m_bs.resetBits();
if (m_param->decodedPictureHashSEI)
{
@@ -1085,8 +1097,7 @@
m_bs.resetBits();
m_seiReconPictureDigest.setSize(payloadSize);
m_seiReconPictureDigest.write(m_bs, *slice->m_sps);
- m_bs.writeByteAlignment();
- m_nalList.serialize(NAL_UNIT_SUFFIX_SEI, m_bs);
+ m_seiReconPictureDigest.alignAndSerialize(m_bs, true, m_param->bSingleSeiNal, NAL_UNIT_SUFFIX_SEI, m_nalList);
}
uint64_t bytes = 0;
diff --git a/source/encoder/sei.cpp b/source/encoder/sei.cpp
--- a/source/encoder/sei.cpp
+++ b/source/encoder/sei.cpp
@@ -44,6 +44,15 @@
return count;
}
+void SEI::alignAndSerialize(Bitstream& bs, int lastSei, int isSingleSei, NalUnitType nalUnitType, NALList& list)
+{
+ if (lastSei || !isSingleSei)
+ {
+ bs.writeByteAlignment();
+ list.serialize(nalUnitType, bs);
+ }
+}
+
/* marshal a single SEI message sei, storing the marshalled representation
* in bitstream bs */
void SEI::write(Bitstream& bs, const SPS& sps)
diff --git a/source/encoder/sei.h b/source/encoder/sei.h
--- a/source/encoder/sei.h
+++ b/source/encoder/sei.h
@@ -27,6 +27,7 @@
#include "common.h"
#include "bitstream.h"
#include "slice.h"
+#include "nal.h"
namespace X265_NS {
// private namespace
@@ -37,6 +38,7 @@
/* SEI users call write() to marshal an SEI to a bitstream.
* The write() method calls writeSEI() which encodes the header */
void write(Bitstream& bs, const SPS& sps);
+ void alignAndSerialize(Bitstream& bs, int lastSei, int isSingleSei, NalUnitType nalUnitType, NALList& list);
int countPayloadSize(const SPS& sps);
void setSize(uint32_t size);
virtual ~SEI() {}
diff --git a/source/x265.h b/source/x265.h
--- a/source/x265.h
+++ b/source/x265.h
@@ -1563,6 +1563,9 @@
/* Dynamically change refine-inter at block level*/
int bDynamicRefine;
+
+ /* Enable writing all SEI messgaes in one single NAL instead of mul*/
+ int bSingleSeiNal;
} x265_param;
/* x265_param_alloc:
diff --git a/source/x265cli.h b/source/x265cli.h
--- a/source/x265cli.h
+++ b/source/x265cli.h
@@ -298,6 +298,8 @@
{ "max-ausize-factor", required_argument, NULL, 0 },
{ "idr-recovery-sei", no_argument, NULL, 0 },
{ "no-idr-recovery-sei", no_argument, NULL, 0 },
+ { "single-sei", no_argument, NULL, 0 },
+ { "no-single-sei", no_argument, NULL, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265.patch
Type: text/x-patch
Size: 13647 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20180402/128ecbb1/attachment-0001.bin>
More information about the x265-devel
mailing list