<div dir="ltr">I would rename the "<span style="font-size:12.8px;text-decoration-style:initial;text-decoration-color:initial;float:none;display:inline">usersei-file" option into something like "nalu-file", as the input file format allows arbitrary NAL units rather than only SEIs (despite only prefix SEIs being implemented).</span><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Jun 20, 2018 at 4:43 AM,  <span dir="ltr"><<a href="mailto:indumathi@multicorewareinc.com" target="_blank">indumathi@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 <a href="mailto:indumathi@multicorewareinc.com">indumathi@multicorewareinc.com</a><br>
# Date 1528726491 -19800<br>
#      Mon Jun 11 19:44:51 2018 +0530<br>
# Node ID e1dd8424a3bd5f9f61f4a73aec6f2a<wbr>ee27591772<br>
# Parent  a8a5ccf5aaf7e04e439a216e5c3969<wbr>91c6b76999<br>
CEA 608/708 Support<br>
<br>
Parse the SEI messages from text file and insert it into the userSEI with cli option.<br>
<br>
diff -r a8a5ccf5aaf7 -r e1dd8424a3bd doc/reST/cli.rst<br>
--- a/doc/reST/cli.rst  Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/doc/reST/cli.rst  Mon Jun 11 19:44:51 2018 +0530<br>
@@ -2135,6 +2135,12 @@<br>
<br>
        Maximum luma value allowed for input pictures. Any values above max-luma<br>
        are clipped.  No default.<br>
+    <br>
+.. option:: --usersei-file <filename><br>
+<br>
+    Text file containing userSEI in POC order : <POC><space><PREFIX><space><<wbr>NAL UNIT TYPE>/<SEI TYPE><space><SEI Payload><br>
+    Parse the input file specified and inserts SEI messages into the bitstream. <br>
+    Currently, we support only PREFIX SEI messages. This is an "application-only" feature.<br>
<br>
 .. option:: --atc-sei <integer><br>
<br>
diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/CMakeLists.txt<br>
--- a/source/CMakeLists.txt     Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/source/CMakeLists.txt     Mon Jun 11 19:44:51 2018 +0530<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 161)<br>
+set(X265_BUILD 162)<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 -r a8a5ccf5aaf7 -r e1dd8424a3bd source/common/param.cpp<br>
--- a/source/common/param.cpp   Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/source/common/param.cpp   Mon Jun 11 19:44:51 2018 +0530<br>
@@ -302,6 +302,7 @@<br>
     param->bDisableLookahead = 0;<br>
     param->bCopyPicToFrame = 1;<br>
     param->maxAUSizeFactor = 1;<br>
+    param->userSeiFile = NULL;<br>
<br>
     /* DCT Approximations */<br>
     param->bLowPassDct = 0;<br>
@@ -1048,6 +1049,7 @@<br>
                OPT("pic-struct") p->pictureStructure = atoi(value);<br>
         OPT("chunk-start") p->chunkStart = atoi(value);<br>
         OPT("chunk-end") p->chunkEnd = atoi(value);<br>
+        OPT("usersei-file") p->userSeiFile = strdup(value);<br>
         else<br>
             return X265_PARAM_BAD_NAME;<br>
     }<br>
diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp        Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/source/encoder/encoder.cpp        Mon Jun 11 19:44:51 2018 +0530<br>
@@ -79,6 +79,7 @@<br>
     m_threadPool = NULL;<br>
     m_analysisFileIn = NULL;<br>
     m_analysisFileOut = NULL;<br>
+    m_seiFile = NULL;<br>
     m_offsetEmergency = NULL;<br>
     m_iFrameNum = 0;<br>
     m_iPPSQpMinus26 = 0;<br>
@@ -412,6 +413,20 @@<br>
<br>
     m_emitCLLSEI = p->maxCLL || p->maxFALL;<br>
<br>
+    if (m_param->userSeiFile)<br>
+    {<br>
+        m_seiFile = x265_fopen(m_param-><wbr>userSeiFile, "r");<br>
+        if (!m_seiFile)<br>
+        {<br>
+            x265_log_file(NULL, X265_LOG_ERROR, "%s file not found or Failed to open\n", m_param->userSeiFile);<br>
+            m_aborted = true;<br>
+        }<br>
+        else<br>
+             m_enableUserSei = 1;<br>
+    }<br>
+    else<br>
+         m_enableUserSei = 0;<br>
+<br>
 #if ENABLE_HDR10_PLUS<br>
     if (m_bToneMap)<br>
         m_numCimInfo = m_hdr10plus_api->hdr10plus_<wbr>json_to_movie_cim(m_param-><wbr>toneMapFile, m_cim);<br>
@@ -782,6 +797,8 @@<br>
         }<br>
         X265_FREE(temp);<br>
      }<br>
+    if (m_seiFile)<br>
+        fclose(m_seiFile);<br>
     if (m_param)<br>
     {<br>
         if (m_param->csvfpt)<br>
@@ -922,7 +939,14 @@<br>
             }<br>
         }<br>
 #endif<br>
-<br>
+/* seiMsg will contain SEI messages specified in a fixed file format in POC order.<br>
+* Format of the file : <POC><space><PREFIX><space><<wbr>NAL UNIT TYPE>/<SEI TYPE><space><SEI Payload> */<br>
+        x265_sei_payload seiMsg;<br>
+        seiMsg.payload = NULL;<br>
+        if (m_enableUserSei)<br>
+        {<br>
+            seiMsg = readUserSeiFile(m_pocLast);<br>
+        }<br>
         if (pic_in->bitDepth < 8 || pic_in->bitDepth > 16)<br>
         {<br>
             x265_log(m_param, X265_LOG_ERROR, "Input bit depth (%d) must be between 8 and 16\n",<br>
@@ -1008,6 +1032,8 @@<br>
         if (m_bToneMap && toneMap.payload)<br>
             toneMapEnable = 1;<br>
         int numPayloads = pic_in->userSEI.numPayloads + toneMapEnable;<br>
+        if (m_enableUserSei && seiMsg.payload)<br>
+            numPayloads += m_enableUserSei;<br>
         inFrame->m_userSEI.numPayloads = numPayloads;<br>
<br>
         if (inFrame->m_userSEI.<wbr>numPayloads)<br>
@@ -1023,6 +1049,8 @@<br>
                 x265_sei_payload input;<br>
                 if ((i == (numPayloads - 1)) && toneMapEnable)<br>
                     input = toneMap;<br>
+                else if (m_enableUserSei)<br>
+                    input = seiMsg;<br>
                 else<br>
                     input = pic_in->userSEI.payloads[i];<br>
                 int size = inFrame->m_userSEI.payloads[i]<wbr>.payloadSize = input.payloadSize;<br>
@@ -1033,6 +1061,8 @@<br>
             }<br>
             if (toneMap.payload)<br>
                 x265_free(toneMap.payload);<br>
+            if (seiMsg.payload)<br>
+                x265_free(seiMsg.payload);<br>
         }<br>
<br>
         if (pic_in->quantOffsets != NULL)<br>
@@ -4706,6 +4736,55 @@<br>
     TOOLCMP(oldParam->rc.<wbr>rfConstant, newParam->rc.rfConstant, "crf=%f to %f\n");<br>
 }<br>
<br>
+x265_sei_payload Encoder::readUserSeiFile(int curPoc)<br>
+{<br>
+    x265_sei_payload seiMsg;<br>
+    seiMsg.payload = NULL;<br>
+    char line[1024];<br>
+    while (!feof(m_seiFile))<br>
+    {<br>
+        fgets(line, sizeof(line), m_seiFile);<br>
+        int poc = atoi(strtok(line, " "));<br>
+        char *prefix = strtok(NULL, " ");<br>
+        int nalType = atoi(strtok(NULL, "/"));<br>
+        int payloadType = atoi(strtok(NULL, " "));<br>
+        char *base64Encode = strtok(NULL, "\n");<br>
+        int base64EncodeLength = (int)strlen(base64Encode);<br>
+        char *base64Decode = SEI::base64Decode(<wbr>base64Encode, base64EncodeLength);<br>
+        if (nalType == NAL_UNIT_PREFIX_SEI && (!strcmp(prefix, "PREFIX")))<br>
+        {<br>
+            int currentPOC = curPoc + 1;<br>
+            if (currentPOC == poc)<br>
+            {<br>
+                seiMsg.payloadSize = (base64EncodeLength / 4) * 3;<br>
+                seiMsg.payload = (uint8_t*)x265_malloc(sizeof(<wbr>uint8_t) * seiMsg.payloadSize);<br>
+                if (!seiMsg.payload)<br>
+                {<br>
+                    x265_log(m_param, X265_LOG_ERROR, "Unable to allocate memory for SEI payload\n");<br>
+                    break;<br>
+                }<br>
+                if (payloadType == 4)<br>
+                    seiMsg.payloadType = USER_DATA_REGISTERED_ITU_T_<wbr>T35;<br>
+                else if (payloadType == 5)<br>
+                    seiMsg.payloadType = USER_DATA_UNREGISTERED;<br>
+                else<br>
+                {<br>
+                    x265_log(m_param, X265_LOG_WARNING, "Unsupported SEI payload Type for frame %d\n", poc);<br>
+                    break;<br>
+                }<br>
+                memcpy(seiMsg.payload, base64Decode, seiMsg.payloadSize);<br>
+                return seiMsg;<br>
+            }<br>
+        }<br>
+        else<br>
+        {<br>
+            x265_log(m_param, X265_LOG_WARNING, "SEI message for frame %d is not inserted. Will support only PREFIX SEI messages.\n", poc);<br>
+            break;<br>
+        }<br>
+    }<br>
+    return seiMsg;<br>
+}<br>
+<br>
 bool Encoder::computeSPSRPSIndex()<br>
 {<br>
     RPS* rpsInSPS = m_sps.spsrps;<br>
diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/encoder/encoder.h<br>
--- a/source/encoder/encoder.h  Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/source/encoder/encoder.h  Mon Jun 11 19:44:51 2018 +0530<br>
@@ -169,6 +169,7 @@<br>
     Frame*             m_exportedPic;<br>
     FILE*              m_analysisFileIn;<br>
     FILE*              m_analysisFileOut;<br>
+    FILE*              m_seiFile;<br>
     x265_param*        m_param;<br>
     x265_param*        m_latestParam;     // Holds latest param during a reconfigure<br>
     RateControl*       m_rateControl;<br>
@@ -212,6 +213,7 @@<br>
     double                m_cR;<br>
<br>
     int                     m_bToneMap; // Enables tone-mapping<br>
+    int                     m_enableUserSei;<br>
<br>
 #ifdef ENABLE_HDR10_PLUS<br>
     const hdr10plus_api     *m_hdr10plus_api;<br>
@@ -299,6 +301,8 @@<br>
<br>
     int validateAnalysisData(x265_<wbr>analysis_data* analysis, int readWriteFlag);<br>
<br>
+    x265_sei_payload readUserSeiFile(int poc);<br>
+<br>
     void calcRefreshInterval(Frame* frameEnc);<br>
<br>
     void initRefIdx();<br>
diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/encoder/sei.cpp<br>
--- a/source/encoder/sei.cpp    Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/source/encoder/sei.cpp    Mon Jun 11 19:44:51 2018 +0530<br>
@@ -90,3 +90,63 @@<br>
 {<br>
     m_payloadSize = size;<br>
 }<br>
+<br>
+/* charSet = "<wbr>ABCDEFGHIJKLMNOPQRSTUVWXYZabcd<wbr>efghijklmnopqrstuvwxyz01234567<wbr>89+/" */<br>
+<br>
+char* SEI::base64Decode(char encodedString[], int base64EncodeLength)<br>
+{<br>
+    char* decodedString;<br>
+    decodedString = (char*)malloc(sizeof(char) * ((base64EncodeLength / 4) * 3));<br>
+    int i, j, k = 0;<br>
+    // stores the bitstream<br>
+    int bitstream = 0;<br>
+    // countBits stores current number of bits in bitstream<br>
+    int countBits = 0;<br>
+    // selects 4 characters from encodedString at a time. Find the position of each encoded character in charSet and stores in bitstream<br>
+    for (i = 0; i < base64EncodeLength; i += 4)<br>
+    {<br>
+        bitstream = 0, countBits = 0;<br>
+        for (j = 0; j < 4; j++)<br>
+        {<br>
+            // make space for 6 bits<br>
+            if (encodedString[i + j] != '=')<br>
+            {<br>
+                bitstream = bitstream << 6;<br>
+                countBits += 6;<br>
+            }<br>
+            // Finding the position of each encoded character in charSet and storing in bitstream, use OR '|' operator to store bits<br>
+<br>
+            if (encodedString[i + j] >= 'A' && encodedString[i + j] <= 'Z')<br>
+                bitstream = bitstream | (encodedString[i + j] - 'A');<br>
+<br>
+            else if (encodedString[i + j] >= 'a' && encodedString[i + j] <= 'z')<br>
+                bitstream = bitstream | (encodedString[i + j] - 'a' + 26);<br>
+            <br>
+            else if (encodedString[i + j] >= '0' && encodedString[i + j] <= '9')<br>
+                bitstream = bitstream | (encodedString[i + j] - '0' + 52);<br>
+            <br>
+            // '+' occurs in 62nd position in charSet<br>
+            else if (encodedString[i + j] == '+')<br>
+                bitstream = bitstream | 62;<br>
+            <br>
+            // '/' occurs in 63rd position in charSet<br>
+            else if (encodedString[i + j] == '/')<br>
+                bitstream = bitstream | 63;<br>
+            <br>
+            // to delete appended bits during encoding<br>
+            else<br>
+            {<br>
+                bitstream = bitstream >> 2;<br>
+                countBits -= 2;<br>
+            }<br>
+        }<br>
+    <br>
+        while (countBits != 0)<br>
+        {<br>
+            countBits -= 8;<br>
+            decodedString[k++] = (bitstream >> countBits) & 255;<br>
+        }<br>
+    }<br>
+    return decodedString;<br>
+}<br>
+<br>
diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/encoder/sei.h<br>
--- a/source/encoder/sei.h      Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/source/encoder/sei.h      Mon Jun 11 19:44:51 2018 +0530<br>
@@ -41,6 +41,7 @@<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>
+    static char* base64Decode(char encodedString[], int base64EncodeLength);<br>
     virtual ~SEI() {}<br>
 protected:<br>
     SEIPayloadType  m_payloadType;<br>
diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/x265.h<br>
--- a/source/x265.h     Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/source/x265.h     Mon Jun 11 19:44:51 2018 +0530<br>
@@ -1641,6 +1641,8 @@<br>
        * used in taking lookahead decisions, but, they will not be encoded.<br>
     * Default 0 (disabled). */<br>
     int       chunkEnd;<br>
+    /* File containing base64 encoded SEI messages in POC order */<br>
+    const char*    userSeiFile;<br>
<br>
 } x265_param;<br>
<br>
diff -r a8a5ccf5aaf7 -r e1dd8424a3bd source/x265cli.h<br>
--- a/source/x265cli.h  Wed Jun 13 09:54:27 2018 +0530<br>
+++ b/source/x265cli.h  Mon Jun 11 19:44:51 2018 +0530<br>
@@ -304,6 +304,7 @@<br>
     { "no-single-sei", no_argument, NULL, 0 },<br>
        { "atc-sei", required_argument, NULL, 0 },<br>
        { "pic-struct", required_argument, NULL, 0 },<br>
+    { "usersei-file", required_argument, NULL, 0 },<br>
     { 0, 0, 0, 0 },<br>
     { 0, 0, 0, 0 },<br>
     { 0, 0, 0, 0 },<br>
@@ -354,6 +355,7 @@<br>
     H0("   --dhdr10-info <filename>      JSON file containing the Creative Intent Metadata to be encoded as Dynamic Tone Mapping\n");<br>
     H0("   --[no-]dhdr10-opt             Insert tone mapping SEI only for IDR frames and when the tone mapping information changes. Default disabled\n");<br>
 #endif<br>
+    H0("   --usersei-file <filename>     Text file containing SEI messages in the following format : <POC><space><PREFIX><space><<wbr>NAL UNIT TYPE>/<SEI TYPE><space><SEI Payload>\n");<br>
     H0("-f/--frames <integer>            Maximum number of frames to encode. Default all\n");<br>
     H0("   --seek <integer>              First frame to encode\n");<br>
     H1("   --[no-]interlace <bff|tff>    Indicate input pictures are interlace fields in temporal order. Default progressive\n");<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>