<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Apr 2, 2018 at 6:31 PM,  <span dir="ltr"><<a href="mailto:santhoshini@multicorewareinc.com" target="_blank">santhoshini@multicorewareinc.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"># HG changeset patch<br>
# User Santhoshini Sekar <<a href="mailto:santhoshini@multicorewareinc.com">santhoshini@multicorewareinc.<wbr>com</a>><br>
# Date 1522673234 -19800<br>
#      Mon Apr 02 18:17:14 2018 +0530<br>
# Node ID 6337356c86a4f5a49f275eb466d6fa<wbr>e32e6eb145<br>
# Parent  946f82dbf4e80cb272f43a32a78ba2<wbr>b186469845<br>
introduce new CLI single-sei to write all SEI messages in one single NAL<br>
<br>
diff --git a/doc/reST/cli.rst b/doc/reST/cli.rst<br>
--- a/doc/reST/cli.rst<br>
+++ b/doc/reST/cli.rst<br>
@@ -2221,6 +2221,10 @@<br>
 .. option:: --idr-recovery-sei, --no-idr-recoveery-sei<br>
     Emit RecoveryPoint info as sei in bitstream for each IDR frame. Default disabled.<br>
<br>
+.. option:: --single-sei, --no-single-sei<br>
+    Emit SEI messages in a single NAL unit instead of multiple NALs. Default disabled.<br>
+    When HRD SEI is enabled the HM decoder will throw a warning.<br>
+<br>
 DCT Approximations<br>
 =================<br>
<br>
diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt<br>
+++ b/source/CMakeLists.txt<br>
@@ -29,7 +29,7 @@<br>
 option(STATIC_LINK_CRT "Statically link C runtime for release builds" OFF)<br>
 mark_as_advanced(FPROFILE_USE FPROFILE_GENERATE NATIVE_BUILD)<br>
 # X265_BUILD must be incremented each time the public API is changed<br>
-set(X265_BUILD 156)<br>
+set(X265_BUILD 157)<br>
 configure_file("${PROJECT_<wbr>SOURCE_DIR}/<a href="http://x265.def.in" rel="noreferrer" target="_blank">x265.def.in</a>"<br>
                "${PROJECT_BINARY_DIR}/x265.<wbr>def")<br>
 configure_file("${PROJECT_<wbr>SOURCE_DIR}/<a href="http://x265_config.h.in" rel="noreferrer" target="_blank">x265_config.h.in</a>"<br>
diff --git a/source/common/param.cpp b/source/common/param.cpp<br>
--- a/source/common/param.cpp<br>
+++ b/source/common/param.cpp<br>
@@ -301,6 +301,7 @@<br>
     /* DCT Approximations */<br>
     param->bLowPassDct = 0;<br>
     param->bMVType = 0;<br>
+    param->bSingleSeiNal = 0;<br>
 }<br>
<br>
 int x265_param_default_preset(<wbr>x265_param* param, const char* preset, const char* tune)<br>
@@ -1017,6 +1018,7 @@<br>
         OPT("radl") p->radl = atoi(value);<br>
         OPT("max-ausize-factor") p->maxAUSizeFactor = atof(value);<br>
         OPT("dynamic-refine") p->bDynamicRefine = atobool(value);<br>
+        OPT("single-sei") p->bSingleSeiNal = atobool(value);<br>
         else<br>
             return X265_PARAM_BAD_NAME;<br>
     }<br>
@@ -1382,6 +1384,14 @@<br>
     if (param-><wbr>masteringDisplayColorVolume || param->maxFALL || param->maxCLL)<br>
         param->bEmitHDRSEI = 1;<br>
<br>
+    bool isSingleSEI = ((param->bEmitHRDSEI || param->bEmitInfoSEI || param->decodedPictureHashSEI ||<br>
+                         param-><wbr>masteringDisplayColorVolume || param->maxCLL || param->maxFALL ||<br>
+                         param->bEmitHDRSEI || param->bEmitIDRRecoverySEI) && param->bSingleSeiNal);<br>
+    if (!isSingleSEI)<br>
+    {<br>
+        param->bSingleSeiNal = 0;<br>
+        x265_log(param, X265_LOG_WARNING, "None of the SEI messages are enabled. Diabling Single SEI NAL\n");<br>
+    }<br>
     return check_failed;<br>
 }<br>
<br>
@@ -1528,6 +1538,7 @@<br>
     TOOLOPT(!param-><wbr>bSaoNonDeblocked && param->bEnableSAO, "sao");<br>
     TOOLOPT(param->rc.bStatWrite, "stats-write");<br>
     TOOLOPT(param->rc.bStatRead,  "stats-read");<br>
+    TOOLOPT(param->bSingleSeiNal, "single-sei");<br>
 #if ENABLE_HDR10_PLUS<br>
     TOOLOPT(param->toneMapFile != NULL, "dhdr10-info");<br>
 #endif<br>
@@ -1751,6 +1762,7 @@<br>
     s += sprintf(s, " copy-pic=%d", p->bCopyPicToFrame);<br>
     s += sprintf(s, " max-ausize-factor=%.1f", p->maxAUSizeFactor);<br>
     BOOL(p->bDynamicRefine, "dynamic-refine");<br>
+    BOOL(p->bSingleSeiNal, "single-sei");<br>
 #undef BOOL<br>
     return buf;<br>
 }<br>
diff --git a/source/encoder/encoder.cpp b/source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp<br>
+++ b/source/encoder/encoder.cpp<br>
@@ -2289,26 +2289,26 @@<br>
     sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1), m_iPPSQpMinus26);<br>
     bs.writeByteAlignment();<br>
     list.serialize(NAL_UNIT_PPS, bs);<br>
-<br>
+    if (m_param->bSingleSeiNal)<br>
+        bs.resetBits();<br>
     if (m_param->bEmitHDRSEI)<br>
     {<br>
         SEIContentLightLevel cllsei;<br>
         cllsei.max_content_light_level = m_param->maxCLL;<br>
         cllsei.max_pic_average_light_<wbr>level = m_param->maxFALL;<br>
-        bs.resetBits();<br>
+        if (!m_param->bSingleSeiNal)<br>
+            bs.resetBits();<br>
         cllsei.write(bs, m_sps);<br>
-        bs.writeByteAlignment();<br>
-        list.serialize(NAL_UNIT_<wbr>PREFIX_SEI, bs);<br>
-<br>
+        cllsei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);<br>
         if (m_param-><wbr>masteringDisplayColorVolume)<br>
         {<br>
             SEIMasteringDisplayColorVolume mdsei;<br>
             if (mdsei.parse(m_param-><wbr>masteringDisplayColorVolume))<br>
             {<br>
-                bs.resetBits();<br>
+                if (!m_param->bSingleSeiNal)<br>
+                    bs.resetBits();<br>
                 mdsei.write(bs, m_sps);<br>
-                bs.writeByteAlignment();<br>
-                list.serialize(NAL_UNIT_<wbr>PREFIX_SEI, bs);<br>
+                mdsei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);<br>
             }<br>
             else<br>
                 x265_log(m_param, X265_LOG_WARNING, "unable to parse mastering display color volume info\n");<br>
@@ -2328,15 +2328,13 @@<br>
                     "Copyright 2013-2018 (c) Multicoreware, Inc - "<br>
                     "<a href="http://x265.org" rel="noreferrer" target="_blank">http://x265.org</a> - options: %s",<br>
                     X265_BUILD, PFX(version_str), PFX(build_info_str), opts);<br>
-<br>
-                bs.resetBits();<br>
+                if (!m_param->bSingleSeiNal)<br>
+                    bs.resetBits();<br>
                 SEIuserDataUnregistered idsei;<br>
                 idsei.m_userData = (uint8_t*)buffer;<br>
                 idsei.setSize((uint32_t)<wbr>strlen(buffer));<br>
                 idsei.write(bs, m_sps);<br>
-                bs.writeByteAlignment();<br>
-                list.serialize(NAL_UNIT_<wbr>PREFIX_SEI, bs);<br>
-<br>
+                idsei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);<br>
                 X265_FREE(buffer);<br>
             }<br>
<br>
@@ -2350,12 +2348,12 @@<br>
         SEIActiveParameterSets sei;<br>
         sei.m_selfContainedCvsFlag = true;<br>
         sei.m_noParamSetUpdateFlag = true;<br>
-        bs.resetBits();<br>
+        if (!m_param->bSingleSeiNal)<br>
+            bs.resetBits();<br>
         int payloadSize = sei.countPayloadSize(m_sps);<br>
         sei.setSize(payloadSize);<br>
         sei.write(bs, m_sps);<br>
-        bs.writeByteAlignment();<br>
-        list.serialize(NAL_UNIT_<wbr>PREFIX_SEI, bs);<br>
+        sei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);<br>
     }<br>
 }<br>
<br>
diff --git a/source/encoder/frameencoder.<wbr>cpp b/source/encoder/frameencoder.<wbr>cpp<br>
--- a/source/encoder/frameencoder.<wbr>cpp<br>
+++ b/source/encoder/frameencoder.<wbr>cpp<br>
@@ -393,6 +393,7 @@<br>
      * not repeating headers (since AUD is supposed to be the first NAL in the access<br>
      * unit) */<br>
     Slice* slice = m_frame->m_encData->m_slice;<br>
+<br>
     if (m_param-><wbr>bEnableAccessUnitDelimiters && (m_frame->m_poc || m_param->bRepeatHeaders))<br>
     {<br>
         m_bs.resetBits();<br>
@@ -400,6 +401,8 @@<br>
         m_entropyCoder.codeAUD(*slice)<wbr>;<br>
         m_bs.writeByteAlignment();<br>
         m_nalList.serialize(NAL_UNIT_<wbr>ACCESS_UNIT_DELIMITER, m_bs);<br>
+        if (m_param->bSingleSeiNal)<br>
+            m_bs.resetBits();<br>
     }<br>
     if (m_frame->m_lowres.bKeyframe && m_param->bRepeatHeaders)<br>
     {<br>
@@ -527,7 +530,7 @@<br>
                 }<br>
<br>
                 bool isIDR = m_frame->m_lowres.sliceType == X265_TYPE_IDR;<br>
-                writeSei = payloadChange || isIDR;<br>
+                writeSei = (payloadChange || isIDR);<br>
             }<br>
         }<br>
     }<br>
@@ -633,12 +636,12 @@<br>
             bpSei->m_dpbDelayOffset = 0;<br>
             // hrdFullness() calculates the initial CPB removal delay and offset<br>
             m_top->m_rateControl-><wbr>hrdFullness(bpSei);<br>
-            m_bs.resetBits();<br>
+            if (!m_param->bSingleSeiNal)<br>
+                m_bs.resetBits();<br>
             int payloadSize = bpSei->countPayloadSize(*<wbr>slice->m_sps);<br>
             bpSei->setSize(payloadSize);<br>
             bpSei->write(m_bs, *slice->m_sps);<br>
-            m_bs.writeByteAlignment();<br>
-            m_nalList.serialize(NAL_UNIT_<wbr>PREFIX_SEI, m_bs);<br>
+            bpSei->alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
<br>
             m_top->m_lastBPSEI = m_rce.encodeOrder;<br>
         }<br>
@@ -650,11 +653,11 @@<br>
             sei.m_recoveryPocCnt = 0;<br>
             sei.m_exactMatchingFlag = true;<br>
             sei.m_brokenLinkFlag = false;<br>
-            m_bs.resetBits();<br>
+            if (!m_param->bSingleSeiNal)<br>
+                m_bs.resetBits();<br>
             sei.setSize(sei.<wbr>countPayloadSize(*slice->m_<wbr>sps));<br>
             sei.write(m_bs, *slice->m_sps);<br>
-            m_bs.writeByteAlignment();<br>
-            m_nalList.serialize(NAL_UNIT_<wbr>PREFIX_SEI, m_bs);<br>
+            sei.alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
         }<br>
     }<br>
<br>
@@ -686,12 +689,12 @@<br>
             sei->m_auCpbRemovalDelay = X265_MIN(X265_MAX(1, m_rce.encodeOrder - prevBPSEI), (1 << hrd->cpbRemovalDelayLength));<br>
             sei->m_picDpbOutputDelay = slice->m_sps->numReorderPics + poc - m_rce.encodeOrder;<br>
         }<br>
-        m_bs.resetBits();<br>
+        if (!m_param->bSingleSeiNal)<br>
+            m_bs.resetBits();<br>
         int payloadSize = sei->countPayloadSize(*slice-><wbr>m_sps);<br>
         sei->setSize(payloadSize);<br>
         sei->write(m_bs, *slice->m_sps);<br>
-        m_bs.writeByteAlignment();<br>
-        m_nalList.serialize(NAL_UNIT_<wbr>PREFIX_SEI, m_bs);<br>
+        sei->alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
     }<br>
<br>
     /* Write user SEI */<br>
@@ -702,11 +705,11 @@<br>
         {<br>
             SEIuserDataUnregistered sei;<br>
             sei.m_userData = payload->payload;<br>
-            m_bs.resetBits();<br>
+            if (!m_param->bSingleSeiNal)<br>
+                m_bs.resetBits();<br>
             sei.setSize(payload-><wbr>payloadSize);<br>
             sei.write(m_bs, *slice->m_sps);<br>
-            m_bs.writeByteAlignment();<br>
-            m_nalList.serialize(NAL_UNIT_<wbr>PREFIX_SEI, m_bs);<br>
+            sei.alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
         }<br>
         else if (payload->payloadType == USER_DATA_REGISTERED_ITU_T_<wbr>T35)<br>
         {<br>
@@ -717,13 +720,21 @@<br>
                 m_bs.resetBits();<br>
                 sei.setSize(payload-><wbr>payloadSize);<br>
                 sei.write(m_bs, *slice->m_sps);<br>
-                m_bs.writeByteAlignment();<br>
-                m_nalList.serialize(NAL_UNIT_<wbr>PREFIX_SEI, m_bs);<br>
+                sei.alignAndSerialize(m_bs, true, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
             }<br>
         }<br>
         else<br>
             x265_log(m_param, X265_LOG_ERROR, "Unrecognized SEI type\n");<br>
     }<br>
+    bool isSei = (m_frame->m_lowres.bKeyframe &&<br>
+            (m_param->bRepeatHeaders || m_param->bEmitHRDSEI<br>
+            || !!m_param->interlaceMode || m_param->bEmitIDRRecoverySEI))<wbr>;<br>
+<br>
+    if (isSei && m_param->bSingleSeiNal)<br>
+    {<br>
+        m_bs.writeByteAlignment();<br>
+        m_nalList.serialize(NAL_UNIT_<wbr>PREFIX_SEI, m_bs);<br>
+    }<br>
     /* CQP and CRF (without capped VBV) doesn't use mid-frame statistics to<br>
      * tune RateControl parameters for other frames.<br>
      * Hence, for these modes, update m_startEndOrder and unlock RC for previous threads waiting in<br>
@@ -1055,7 +1066,8 @@<br>
<br>
         m_nalList.serialize(slice->m_<wbr>nalUnitType, m_bs);<br>
     }<br>
-<br>
+    if (isSei && m_param->bSingleSeiNal)<br>
+        m_bs.resetBits();<br>
<br>
     if (m_param-><wbr>decodedPictureHashSEI)<br>
     {<br>
@@ -1085,8 +1097,7 @@<br>
         m_bs.resetBits();<br>
         m_seiReconPictureDigest.<wbr>setSize(payloadSize);<br>
         m_seiReconPictureDigest.write(<wbr>m_bs, *slice->m_sps);<br>
-        m_bs.writeByteAlignment();<br>
-        m_nalList.serialize(NAL_UNIT_<wbr>SUFFIX_SEI, m_bs);<br>
+        m_seiReconPictureDigest.<wbr>alignAndSerialize(m_bs, true, m_param->bSingleSeiNal, NAL_UNIT_SUFFIX_SEI, m_nalList);<br>
     }<br>
<br>
     uint64_t bytes = 0;<br>
diff --git a/source/encoder/sei.cpp b/source/encoder/sei.cpp<br>
--- a/source/encoder/sei.cpp<br>
+++ b/source/encoder/sei.cpp<br>
@@ -44,6 +44,15 @@<br>
     return count;<br>
 }<br>
<br>
+void SEI::alignAndSerialize(<wbr>Bitstream& bs, int lastSei, int isSingleSei, NalUnitType nalUnitType, NALList& list)<br>
+{<br>
+    if (lastSei || !isSingleSei)<br>
+    {<br>
+        bs.writeByteAlignment();<br>
+        list.serialize(nalUnitType, bs);<br>
+    }<br>
+}<br>
+<br>
 /* marshal a single SEI message sei, storing the marshalled representation<br>
  * in bitstream bs */<br>
 void SEI::write(Bitstream& bs, const SPS& sps)<br>
diff --git a/source/encoder/sei.h b/source/encoder/sei.h<br>
--- a/source/encoder/sei.h<br>
+++ b/source/encoder/sei.h<br>
@@ -27,6 +27,7 @@<br>
 #include "common.h"<br>
 #include "bitstream.h"<br>
 #include "slice.h"<br>
+#include "nal.h"<br>
<br>
 namespace X265_NS {<br>
 // private namespace<br>
@@ -37,6 +38,7 @@<br>
     /* SEI users call write() to marshal an SEI to a bitstream.<br>
      * The write() method calls writeSEI() which encodes the header */<br>
     void write(Bitstream& bs, const SPS& sps);<br>
+    void alignAndSerialize(Bitstream& bs, int lastSei, int isSingleSei, NalUnitType nalUnitType, NALList& list);<br>
     int countPayloadSize(const SPS& sps);<br>
     void setSize(uint32_t size);<br>
     virtual ~SEI() {}<br>
diff --git a/source/x265.h b/source/x265.h<br>
--- a/source/x265.h<br>
+++ b/source/x265.h<br>
@@ -1563,6 +1563,9 @@<br>
<br>
     /* Dynamically change refine-inter at block level*/<br>
     int       bDynamicRefine;<br>
+<br>
+    /* Enable writing all SEI messgaes in one single NAL instead of mul*/<br>
+    int       bSingleSeiNal;<br>
 } x265_param;<br>
<br>
 /* x265_param_alloc:<br>
diff --git a/source/x265cli.h b/source/x265cli.h<br>
--- a/source/x265cli.h<br>
+++ b/source/x265cli.h<br>
@@ -298,6 +298,8 @@<br>
     { "max-ausize-factor", required_argument, NULL, 0 },<br>
     { "idr-recovery-sei",     no_argument, NULL, 0 },<br>
     { "no-idr-recovery-sei",  no_argument, NULL, 0 },<br>
+    { "single-sei", no_argument, NULL, 0 },<br>
+    { "no-single-sei", no_argument, NULL, 0 },<br>
     { 0, 0, 0, 0 },<br>
     { 0, 0, 0, 0 },<br>
     { 0, 0, 0, 0 },<br>
<br>______________________________<wbr>_________________<br>
x265-devel mailing list<br>
<a href="mailto:x265-devel@videolan.org">x265-devel@videolan.org</a><br>
<a href="https://mailman.videolan.org/listinfo/x265-devel" rel="noreferrer" target="_blank">https://mailman.videolan.org/<wbr>listinfo/x265-devel</a><br>
<br></blockquote></div><br></div><div class="gmail_extra">Pushed.</div></div>