[x265] [PATCH] introduce new CLI single-sei to write all SEI messages in one single NAL
Ashok Kumar Mishra
ashok at multicorewareinc.com
Tue Apr 3 10:54:26 CEST 2018
On Mon, Apr 2, 2018 at 6:31 PM, <santhoshini at multicorewareinc.com> wrote:
> # 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 },
>
> _______________________________________________
> x265-devel mailing list
> x265-devel at videolan.org
> https://mailman.videolan.org/listinfo/x265-devel
>
>
Pushed.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20180403/1623a679/attachment-0001.html>
More information about the x265-devel
mailing list