<div dir="ltr">Kindly ignore this patch. Resending the patch after removing whitespaces.<br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Jul 23, 2018 at 6:47 PM,  <span dir="ltr"><<a href="mailto:ashok@multicorewareinc.com" target="_blank">ashok@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 Ashok Kumar Mishra <<a href="mailto:ashok@multicorewareinc.com">ashok@multicorewareinc.com</a>><br>
# Date 1532100263 -19800<br>
#      Fri Jul 20 20:54:23 2018 +0530<br>
# Node ID 44f14617642334bca3ee83036cb5d4<wbr>c6ed96abd5<br>
# Parent  c258d214c978a5c64ec8dd3986a3b3<wbr>cc3d2381ac<br>
Refactor SEI code to handle more user SEI types<br>
<br>
diff -r c258d214c978 -r 44f146176423 source/common/param.cpp<br>
--- a/source/common/param.cpp   Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/common/param.cpp   Fri Jul 20 20:54:23 2018 +0530<br>
@@ -1415,9 +1415,16 @@<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));<br>
+       bool isSingleSEI = ( param->bRepeatHeaders <br>
+                             || param->bEmitHRDSEI<br>
+                                         || param->bEmitInfoSEI                                                                                                          <br>
+                                         || param->bEmitHDRSEI<br>
+                                         || param->bEmitIDRRecoverySEI<br>
+                                         || !!param->interlaceMode                                      <br>
+                                         || param-><wbr>preferredTransferCharacteristi<wbr>cs > 1<br>
+                                         || param->toneMapFile<br>
+                                         || param->naluFile);<br>
+<br>
     if (!isSingleSEI && param->bSingleSeiNal)<br>
     {<br>
         param->bSingleSeiNal = 0;<br>
diff -r c258d214c978 -r 44f146176423 source/encoder/encoder.cpp<br>
--- a/source/encoder/encoder.cpp        Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/encoder/encoder.cpp        Fri Jul 20 20:54:23 2018 +0530<br>
@@ -442,6 +442,8 @@<br>
     fail:<br>
         m_aborted = true;<br>
     }<br>
+<br>
+       m_seiEncoder.init(p);<br>
 }<br>
<br>
 void Encoder::stopJobs()<br>
@@ -875,6 +877,77 @@<br>
     }<br>
 }<br>
<br>
+void Encoder::copyUserSEIMessages(<wbr>Frame *frame, const x265_picture* pic_in)<br>
+{<br>
+       x265_sei_payload toneMap;<br>
+       toneMap.payload = NULL;<br>
+       int toneMapPayload = 0;<br>
+<br>
+#if ENABLE_HDR10_PLUS<br>
+       if (m_bToneMap)<br>
+       {<br>
+               int currentPOC = m_pocLast;<br>
+               if (currentPOC < m_numCimInfo)<br>
+               {<br>
+                       int32_t i = 0;<br>
+                       toneMap.payloadSize = 0;<br>
+                       while (m_cim[currentPOC][i] == 0xFF)<br>
+                               toneMap.payloadSize += m_cim[currentPOC][i++];<br>
+                       toneMap.payloadSize += m_cim[currentPOC][i];<br>
+<br>
+                       toneMap.payload = (uint8_t*)x265_malloc(sizeof(<wbr>uint8_t) * toneMap.payloadSize);<br>
+                       toneMap.payloadType = USER_DATA_REGISTERED_ITU_T_<wbr>T35;<br>
+                       memcpy(toneMap.payload, &m_cim[currentPOC][i + 1], toneMap.payloadSize);<br>
+                       toneMapPayload = 1;<br>
+               }<br>
+       }<br>
+#endif<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>
+       int userPayload = 0;<br>
+       if (m_enableNal)<br>
+       {<br>
+               readUserSeiFile(seiMsg, m_pocLast);<br>
+               if (seiMsg.payload)<br>
+                       userPayload = 1;;<br>
+       }<br>
+<br>
+       int numPayloads = pic_in->userSEI.numPayloads + toneMapPayload + userPayload;<br>
+       frame->m_userSEI.numPayloads = numPayloads;<br>
+<br>
+       if (frame->m_userSEI.numPayloads)<br>
+       {<br>
+               if (!frame->m_userSEI.payloads)<br>
+               {<br>
+                       frame->m_userSEI.payloads = new x265_sei_payload[numPayloads];<br>
+                       for (int i = 0; i < numPayloads; i++)<br>
+                               frame->m_userSEI.payloads[i].<wbr>payload = NULL;<br>
+               }<br>
+               for (int i = 0; i < numPayloads; i++)<br>
+               {<br>
+                       x265_sei_payload input;<br>
+                       if ((i == (numPayloads - 1)) && toneMapPayload)<br>
+                               input = toneMap;<br>
+                       else if (m_enableNal)<br>
+                               input = seiMsg;<br>
+                       else<br>
+                               input = pic_in->userSEI.payloads[i];<br>
+<br>
+                       if (!frame->m_userSEI.payloads[i]<wbr>.payload)<br>
+                               frame->m_userSEI.payloads[i].<wbr>payload = new uint8_t[input.payloadSize];<br>
+                       memcpy(frame->m_userSEI.<wbr>payloads[i].payload, input.payload, input.payloadSize);<br>
+                       frame->m_userSEI.payloads[i].<wbr>payloadSize = input.payloadSize;<br>
+                       frame->m_userSEI.payloads[i].<wbr>payloadType = input.payloadType;<br>
+               }<br>
+               if (toneMap.payload)<br>
+                       x265_free(toneMap.payload);<br>
+               if (seiMsg.payload)<br>
+                       x265_free(seiMsg.payload);<br>
+       }<br>
+}<br>
+<br>
 /**<br>
  * Feed one new input frame into the encoder, get one frame out. If pic_in is<br>
  * NULL, a flush condition is implied and pic_in must be NULL for all subsequent<br>
@@ -919,32 +992,6 @@<br>
             m_latestParam->forceFlush = 0;<br>
         }<br>
<br>
-        x265_sei_payload toneMap;<br>
-        toneMap.payload = NULL;<br>
-#if ENABLE_HDR10_PLUS<br>
-        if (m_bToneMap)<br>
-        {<br>
-            int currentPOC = m_pocLast + 1;<br>
-            if (currentPOC < m_numCimInfo)<br>
-            {<br>
-                int32_t i = 0;<br>
-                toneMap.payloadSize = 0;<br>
-                while (m_cim[currentPOC][i] == 0xFF)<br>
-                    toneMap.payloadSize += m_cim[currentPOC][i++];<br>
-                toneMap.payloadSize += m_cim[currentPOC][i];<br>
-<br>
-                toneMap.payload = (uint8_t*)x265_malloc(sizeof(<wbr>uint8_t) * toneMap.payloadSize);<br>
-                toneMap.payloadType = USER_DATA_REGISTERED_ITU_T_<wbr>T35;<br>
-                memcpy(toneMap.payload, &m_cim[currentPOC][i+1], toneMap.payloadSize);<br>
-            }<br>
-        }<br>
-#endif<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_enableNal)<br>
-            readUserSeiFile(seiMsg, m_pocLast);<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>
@@ -1026,42 +1073,7 @@<br>
         inFrame->m_forceqp   = pic_in->forceqp;<br>
         inFrame->m_param     = (m_reconfigure || m_reconfigureRc) ? m_latestParam : m_param;<br>
<br>
-        int toneMapEnable = 0;<br>
-        if (m_bToneMap && toneMap.payload)<br>
-            toneMapEnable = 1;<br>
-        int numPayloads = pic_in->userSEI.numPayloads + toneMapEnable;<br>
-        if (m_enableNal && seiMsg.payload)<br>
-            numPayloads += m_enableNal;<br>
-        inFrame->m_userSEI.numPayloads = numPayloads;<br>
-<br>
-        if (inFrame->m_userSEI.<wbr>numPayloads)<br>
-        {<br>
-            if (!inFrame->m_userSEI.payloads)<br>
-            {<br>
-                inFrame->m_userSEI.payloads = new x265_sei_payload[numPayloads];<br>
-                for (int i = 0; i < numPayloads; i++)<br>
-                    inFrame->m_userSEI.payloads[i]<wbr>.payload = NULL;<br>
-            }<br>
-            for (int i = 0; i < numPayloads; i++)<br>
-            {<br>
-                x265_sei_payload input;<br>
-                if ((i == (numPayloads - 1)) && toneMapEnable)<br>
-                    input = toneMap;<br>
-                else if (m_enableNal)<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>
-                inFrame->m_userSEI.payloads[i]<wbr>.payloadType = input.payloadType;<br>
-                if (!inFrame->m_userSEI.payloads[<wbr>i].payload)<br>
-                    inFrame->m_userSEI.payloads[i]<wbr>.payload = new uint8_t[size];<br>
-                memcpy(inFrame->m_userSEI.<wbr>payloads[i].payload, input.payload, size);<br>
-            }<br>
-            if (toneMap.payload)<br>
-                x265_free(toneMap.payload);<br>
-            if (seiMsg.payload)<br>
-                x265_free(seiMsg.payload);<br>
-        }<br>
+               copyUserSEIMessages(inFrame, pic_in);<br>
<br>
         if (pic_in->quantOffsets != NULL)<br>
         {<br>
@@ -2364,29 +2376,21 @@<br>
     sbacCoder.codePPS(m_pps, (m_param->maxSlices <= 1), m_iPPSQpMinus26);<br>
     bs.writeByteAlignment();<br>
     list.serialize(NAL_UNIT_PPS, bs);<br>
-    if (m_param->bSingleSeiNal)<br>
+<br>
+       if (m_seiEncoder.isNestedSEI)<br>
         bs.resetBits();<br>
+<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>
-        if (!m_param->bSingleSeiNal)<br>
-            bs.resetBits();<br>
-        cllsei.write(bs, m_sps);<br>
-        cllsei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);<br>
+               SEIContentLightLevel cllsei;<br>
+               cllsei.max_content_light_level = m_param->maxCLL;<br>
+               cllsei.max_pic_average_light_<wbr>level = m_param->maxFALL;<br>
+               m_seiEncoder.<wbr>encodeSEIContentLightLevel(<wbr>cllsei, bs, m_sps, NAL_UNIT_PREFIX_SEI, list);<br>
+<br>
         if (m_param-><wbr>masteringDisplayColorVolume)<br>
         {<br>
-            SEIMasteringDisplayColorVolume mdsei;<br>
-            if (mdsei.parse(m_param-><wbr>masteringDisplayColorVolume))<br>
-            {<br>
-                if (!m_param->bSingleSeiNal)<br>
-                    bs.resetBits();<br>
-                mdsei.write(bs, m_sps);<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>
+                       SEIMasteringDisplayColorVolume mdsei;                   <br>
+                       m_seiEncoder.<wbr>encodeSEIMasteringDisplayColor<wbr>Volume(mdsei, bs, m_sps, NAL_UNIT_PREFIX_SEI, list);<br>
         }<br>
     }<br>
<br>
@@ -2403,13 +2407,12 @@<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>
-                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>
-                idsei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);<br>
+<br>
+                               SEIuserDataUnregistered idsei;<br>
+                               idsei.m_userData = (uint8_t*)buffer;<br>
+                               idsei.setSize((uint32_t)<wbr>strlen(buffer));<br>
+                               m_seiEncoder.<wbr>encodeSEIuserDataUnregistered(<wbr>idsei, bs, m_sps, NAL_UNIT_PREFIX_SEI, list);<br>
+<br>
                 X265_FREE(buffer);<br>
             }<br>
<br>
@@ -2420,15 +2423,8 @@<br>
     if ((m_param->bEmitHRDSEI || !!m_param->interlaceMode))<br>
     {<br>
         /* Picture Timing and Buffering Period SEI require the SPS to be "activated" */<br>
-        SEIActiveParameterSets sei;<br>
-        sei.m_selfContainedCvsFlag = true;<br>
-        sei.m_noParamSetUpdateFlag = true;<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>
-        sei.alignAndSerialize(bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, list);<br>
+               SEIActiveParameterSets sei;<br>
+               m_seiEncoder.<wbr>encodeSEIActiveParameterSets(<wbr>sei, bs, m_sps, NAL_UNIT_PREFIX_SEI, list);<br>
     }<br>
 }<br>
<br>
@@ -4530,7 +4526,7 @@<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>
+            int currentPOC = curPoc;<br>
             if (currentPOC == poc)<br>
             {<br>
                 seiMsg.payloadSize = (base64EncodeLength / 4) * 3;<br>
diff -r c258d214c978 -r 44f146176423 source/encoder/encoder.h<br>
--- a/source/encoder/encoder.h  Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/encoder/encoder.h  Fri Jul 20 20:54:23 2018 +0530<br>
@@ -31,6 +31,7 @@<br>
 #include "x265.h"<br>
 #include "nal.h"<br>
 #include "framedata.h"<br>
+#include "sei.h"<br>
 #ifdef ENABLE_HDR10_PLUS<br>
     #include "dynamicHDR10/hdr10plus.h"<br>
 #endif<br>
@@ -209,16 +210,17 @@<br>
     Lock               m_rpsInSpsLock;<br>
     int                m_rpsInSpsCount;<br>
     /* For HDR*/<br>
-    double                m_cB;<br>
-    double                m_cR;<br>
+    double             m_cB;<br>
+    double             m_cR;<br>
<br>
-    int                     m_bToneMap; // Enables tone-mapping<br>
-    int                     m_enableNal;<br>
+    int                m_bToneMap; // Enables tone-mapping<br>
+    int                m_enableNal;<br>
+       SEIEncoder         m_seiEncoder;<br>
<br>
 #ifdef ENABLE_HDR10_PLUS<br>
     const hdr10plus_api     *m_hdr10plus_api;<br>
-    uint8_t                 **m_cim;<br>
-    int                     m_numCimInfo;<br>
+    uint8_t                **m_cim;<br>
+    int                      m_numCimInfo;<br>
 #endif<br>
<br>
     x265_sei_payload        m_prevTonemapPayload;<br>
@@ -230,7 +232,7 @@<br>
     int32_t                 m_startPoint;<br>
     Lock                    m_dynamicRefineLock;<br>
<br>
-    bool                    m_saveCTUSize;<br>
+    bool                    m_saveCTUSize;     <br>
<br>
     Encoder();<br>
     ~Encoder()<br>
@@ -301,6 +303,8 @@<br>
     void analyseRefIdx(int *numRefIdx);<br>
     void updateRefIdx();<br>
     bool computeSPSRPSIndex();<br>
+       <br>
+       void copyUserSEIMessages(Frame *frame, const x265_picture* pic_in);<br>
<br>
 protected:<br>
<br>
diff -r c258d214c978 -r 44f146176423 source/encoder/frameencoder.<wbr>cpp<br>
--- a/source/encoder/frameencoder.<wbr>cpp   Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/encoder/frameencoder.<wbr>cpp   Fri Jul 20 20:54:23 2018 +0530<br>
@@ -365,6 +365,155 @@<br>
     return length;<br>
 }<br>
<br>
+bool FrameEncoder::<wbr>writeToneMapInfo(x265_sei_<wbr>payload *payload)<br>
+{<br>
+       bool payloadChange = false;<br>
+       if (m_top->m_prevTonemapPayload.<wbr>payload != NULL && payload->payloadSize == m_top->m_prevTonemapPayload.<wbr>payloadSize)<br>
+       {<br>
+               if (memcmp(m_top->m_<wbr>prevTonemapPayload.payload, payload->payload, payload->payloadSize) != 0)<br>
+                       payloadChange = true;<br>
+       }<br>
+       else<br>
+       {<br>
+               payloadChange = true;<br>
+               if (m_top->m_prevTonemapPayload.<wbr>payload != NULL)<br>
+                       x265_free(m_top->m_<wbr>prevTonemapPayload.payload);<br>
+               m_top->m_prevTonemapPayload.<wbr>payload = (uint8_t*)x265_malloc(sizeof(<wbr>uint8_t) * payload->payloadSize);<br>
+       }<br>
+<br>
+       if (payloadChange)<br>
+       {<br>
+               m_top->m_prevTonemapPayload.<wbr>payloadType = payload->payloadType;<br>
+               m_top->m_prevTonemapPayload.<wbr>payloadSize = payload->payloadSize;<br>
+               memcpy(m_top->m_<wbr>prevTonemapPayload.payload, payload->payload, payload->payloadSize);<br>
+       }<br>
+<br>
+       bool isIDR = m_frame->m_lowres.sliceType == X265_TYPE_IDR;<br>
+       return (payloadChange || isIDR);<br>
+}<br>
+<br>
+void FrameEncoder::<wbr>writeTrailingSEIMessages()<br>
+{<br>
+       Slice* slice = m_frame->m_encData->m_slice;<br>
+       int planes = (m_param->internalCsp != X265_CSP_I400) ? 3 : 1;<br>
+       int32_t payloadSize = 0;<br>
+<br>
+       if (m_param-><wbr>decodedPictureHashSEI == 1)<br>
+       {<br>
+               m_seiReconPictureDigest.m_<wbr>method = SEIDecodedPictureHash::MD5;<br>
+               for (int i = 0; i < planes; i++)<br>
+                       MD5Final(&m_<wbr>seiReconPictureDigest.m_state[<wbr>i], m_seiReconPictureDigest.m_<wbr>digest[i]);<br>
+               payloadSize = 1 + 16 * planes;<br>
+       }<br>
+       else if (m_param-><wbr>decodedPictureHashSEI == 2)<br>
+       {<br>
+               m_seiReconPictureDigest.m_<wbr>method = SEIDecodedPictureHash::CRC;<br>
+               for (int i = 0; i < planes; i++)<br>
+                       crcFinish(m_<wbr>seiReconPictureDigest.m_crc[i]<wbr>, m_seiReconPictureDigest.m_<wbr>digest[i]);<br>
+               payloadSize = 1 + 2 * planes;<br>
+       }<br>
+       else if (m_param-><wbr>decodedPictureHashSEI == 3)<br>
+       {<br>
+               m_seiReconPictureDigest.m_<wbr>method = SEIDecodedPictureHash::<wbr>CHECKSUM;<br>
+               for (int i = 0; i < planes; i++)<br>
+                       checksumFinish(m_<wbr>seiReconPictureDigest.m_<wbr>checksum[i], m_seiReconPictureDigest.m_<wbr>digest[i]);<br>
+               payloadSize = 1 + 4 * planes;<br>
+       }<br>
+<br>
+       m_seiReconPictureDigest.<wbr>setSize(payloadSize);<br>
+       m_top->m_seiEncoder.<wbr>encodeSEIDecodedPictureHash(m_<wbr>seiReconPictureDigest, m_bs, slice, NAL_UNIT_SUFFIX_SEI, m_nalList);<br>
+}<br>
+<br>
+void FrameEncoder::<wbr>writeLeadingSEIMessages()<br>
+{<br>
+       Slice* slice = m_frame->m_encData->m_slice;<br>
+       int prevBPSEI = m_rce.encodeOrder ? m_top->m_lastBPSEI : 0;<br>
+<br>
+       if (m_frame->m_lowres.bKeyframe)<br>
+       {<br>
+               if (m_param->bEmitHRDSEI)<br>
+               {<br>
+                       SEIBufferingPeriod* bpSei = &m_top->m_rateControl->m_<wbr>bufPeriodSEI;<br>
+                       // hrdFullness() calculates the initial CPB removal delay and offset<br>
+                       m_top->m_rateControl-><wbr>hrdFullness(bpSei);<br>
+                       m_top->m_seiEncoder.<wbr>encodeSEIBufferingPeriod(<wbr>bpSei, m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
+<br>
+                       m_top->m_lastBPSEI = m_rce.encodeOrder;<br>
+               }<br>
+<br>
+               if (m_frame->m_lowres.sliceType == X265_TYPE_IDR && m_param->bEmitIDRRecoverySEI)<br>
+               {<br>
+                       /* Recovery Point SEI require the SPS to be "activated" */<br>
+                       SEIRecoveryPoint rpSei;<br>
+                       m_top->m_seiEncoder.<wbr>encodeSEIRecoveryPoint(rpSei, m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
+               }<br>
+       }<br>
+<br>
+       if ((m_param->bEmitHRDSEI || !!m_param->interlaceMode))<br>
+       {<br>
+               SEIPictureTiming *ptSei = m_rce.picTimingSEI;<br>
+               const VUI *vui = &slice->m_sps->vuiParameters;<br>
+               const HRDInfo *hrd = &vui->hrdParameters;<br>
+               int poc = slice->m_poc;<br>
+<br>
+               if (vui-><wbr>hrdParametersPresentFlag)<br>
+               {<br>
+                       // The m_aucpbremoval delay specifies how many clock ticks the<br>
+                       // access unit associated with the picture timing SEI message has to<br>
+                       // wait after removal of the access unit with the most recent<br>
+                       // buffering period SEI message<br>
+                       ptSei->m_auCpbRemovalDelay = X265_MIN(X265_MAX(1, m_rce.encodeOrder - prevBPSEI), (1 << hrd->cpbRemovalDelayLength));<br>
+                       ptSei->m_picDpbOutputDelay = slice->m_sps->numReorderPics + poc - m_rce.encodeOrder;<br>
+               }<br>
+<br>
+               m_top->m_seiEncoder.<wbr>encodeSEIPictureTiming(ptSei, m_bs, slice, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
+       }<br>
+<br>
+       if (m_param-><wbr>preferredTransferCharacteristi<wbr>cs > -1 && slice->isIRAP())<br>
+       {<br>
+               SEIAlternativeTC seiAlternativeTC;<br>
+               seiAlternativeTC.m_<wbr>preferredTransferCharacteristi<wbr>cs = m_param-><wbr>preferredTransferCharacteristi<wbr>cs;<br>
+               m_top->m_seiEncoder.<wbr>encodeSEIAlternativeTransferCh<wbr>aracteristics(<wbr>seiAlternativeTC, m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
+       }<br>
+<br>
+       /* Write user SEI */<br>
+       for (int i = 0; i < m_frame->m_userSEI.<wbr>numPayloads; i++)<br>
+       {<br>
+               x265_sei_payload *payload = &m_frame->m_userSEI.payloads[<wbr>i];<br>
+               if (payload->payloadType == USER_DATA_UNREGISTERED)<br>
+               {<br>
+                       SEIuserDataUnregistered sei;<br>
+                       sei.m_userData = payload->payload;<br>
+                       sei.setSize(payload-><wbr>payloadSize);<br>
+                       m_top->m_seiEncoder.<wbr>encodeSEIuserDataUnregistered(<wbr>sei, m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
+               }<br>
+               else if (payload->payloadType == USER_DATA_REGISTERED_ITU_T_<wbr>T35)<br>
+               {<br>
+                       bool writeSei = m_param->bDhdr10opt ? writeToneMapInfo(payload) : true;<br>
+                       if (writeSei)<br>
+                       {<br>
+                               SEIuserDataRegistered sei;<br>
+                               sei.m_userData = payload->payload;<br>
+                               sei.setSize(payload-><wbr>payloadSize);<br>
+                               m_top->m_seiEncoder.<wbr>encodeSEIuserDataRegistered(<wbr>sei, m_bs, *slice->m_sps, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
+                       }<br>
+               }<br>
+               else<br>
+                       x265_log(m_param, X265_LOG_ERROR, "Unrecognized SEI type\n");<br>
+       }<br>
+<br>
+       bool isSei = (m_frame->m_lowres.bKeyframe && (m_param->bRepeatHeaders || (m_frame->m_lowres.sliceType == X265_TYPE_IDR && m_param->bEmitIDRRecoverySEI))<wbr>) ||<br>
+                        (m_param-><wbr>preferredTransferCharacteristi<wbr>cs > -1 && slice->isIRAP()) ||<br>
+                        (m_param->bEmitHRDSEI || !!m_param->interlaceMode) ||<br>
+                         m_frame->m_userSEI.<wbr>numPayloads;<br>
+<br>
+       if (isSei && m_top->m_seiEncoder.<wbr>isNestedSEI)<br>
+       {<br>
+               m_bs.writeByteAlignment();<br>
+               m_nalList.serialize(NAL_UNIT_<wbr>PREFIX_SEI, m_bs);<br>
+       }<br>
+}<br>
+<br>
 void FrameEncoder::compressFrame()<br>
 {<br>
     ProfileScopeEvent(frameThread)<wbr>;<br>
@@ -401,7 +550,7 @@<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>
+               if (m_top->m_seiEncoder.<wbr>isNestedSEI)<br>
             m_bs.resetBits();<br>
     }<br>
     if (m_frame->m_lowres.bKeyframe && m_param->bRepeatHeaders)<br>
@@ -462,9 +611,7 @@<br>
                 wa.waitForExit();<br>
             else<br>
                 weightAnalyse(*slice, *m_frame, *m_param);<br>
-<br>
         }<br>
-<br>
     }<br>
     else<br>
         slice->disableWeights();<br>
@@ -499,41 +646,6 @@<br>
<br>
     /* Get the QP for this frame from rate control. This call may block until<br>
      * frames ahead of it in encode order have called rateControlEnd() */<br>
-    m_rce.encodeOrder = m_frame->m_encodeOrder;<br>
-    bool payloadChange = false;<br>
-    bool writeSei = true;<br>
-    if (m_param->bDhdr10opt)<br>
-    {<br>
-        for (int i = 0; i < m_frame->m_userSEI.<wbr>numPayloads; i++)<br>
-        {<br>
-            x265_sei_payload *payload = &m_frame->m_userSEI.payloads[<wbr>i];<br>
-            if(payload->payloadType == USER_DATA_REGISTERED_ITU_T_<wbr>T35)<br>
-            {<br>
-                if (m_top->m_prevTonemapPayload.<wbr>payload != NULL && payload->payloadSize == m_top->m_prevTonemapPayload.<wbr>payloadSize)<br>
-                {<br>
-                    if (memcmp(m_top->m_<wbr>prevTonemapPayload.payload, payload->payload, payload->payloadSize) != 0)<br>
-                        payloadChange = true;<br>
-                }<br>
-                else<br>
-                {<br>
-                    payloadChange = true;<br>
-                    if (m_top->m_prevTonemapPayload.<wbr>payload != NULL)<br>
-                        x265_free(m_top->m_<wbr>prevTonemapPayload.payload);<br>
-                    m_top->m_prevTonemapPayload.<wbr>payload = (uint8_t*)x265_malloc(sizeof(<wbr>uint8_t) * payload->payloadSize);<br>
-                }<br>
-<br>
-                if (payloadChange)<br>
-                {<br>
-                    m_top->m_prevTonemapPayload.<wbr>payloadType = payload->payloadType;<br>
-                    m_top->m_prevTonemapPayload.<wbr>payloadSize = payload->payloadSize;<br>
-                    memcpy(m_top->m_<wbr>prevTonemapPayload.payload, payload->payload, payload->payloadSize);<br>
-                }<br>
-<br>
-                bool isIDR = m_frame->m_lowres.sliceType == X265_TYPE_IDR;<br>
-                writeSei = (payloadChange || isIDR);<br>
-            }<br>
-        }<br>
-    }<br>
     int qp = m_top->m_rateControl-><wbr>rateControlStart(m_frame, &m_rce, m_top);<br>
     m_rce.newQp = qp;<br>
<br>
@@ -622,139 +734,10 @@<br>
             m_outStreams[i].resetBits();<br>
     }<br>
<br>
-    int prevBPSEI = m_rce.encodeOrder ? m_top->m_lastBPSEI : 0;<br>
-<br>
-    if (m_frame->m_lowres.bKeyframe)<br>
-    {<br>
-        if (m_param->bEmitHRDSEI)<br>
-        {<br>
-            SEIBufferingPeriod* bpSei = &m_top->m_rateControl->m_<wbr>bufPeriodSEI;<br>
-<br>
-            // since the temporal layer HRD is not ready, we assumed it is fixed<br>
-            bpSei->m_<wbr>auCpbRemovalDelayDelta = 1;<br>
-            bpSei->m_cpbDelayOffset = 0;<br>
-            bpSei->m_dpbDelayOffset = 0;<br>
-            // hrdFullness() calculates the initial CPB removal delay and offset<br>
-            m_top->m_rateControl-><wbr>hrdFullness(bpSei);<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>
-            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>
-<br>
-        if (m_frame->m_lowres.sliceType == X265_TYPE_IDR && m_param->bEmitIDRRecoverySEI)<br>
-        {<br>
-            /* Recovery Point SEI require the SPS to be "activated" */<br>
-            SEIRecoveryPoint sei;<br>
-            sei.m_recoveryPocCnt = 0;<br>
-            sei.m_exactMatchingFlag = true;<br>
-            sei.m_brokenLinkFlag = false;<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>
-            sei.alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
-        }<br>
-    }<br>
-<br>
-    if ((m_param->bEmitHRDSEI || !!m_param->interlaceMode))<br>
-    {<br>
-        SEIPictureTiming *sei = m_rce.picTimingSEI;<br>
-        const VUI *vui = &slice->m_sps->vuiParameters;<br>
-        const HRDInfo *hrd = &vui->hrdParameters;<br>
-        int poc = slice->m_poc;<br>
-<br>
-        if (vui-><wbr>frameFieldInfoPresentFlag)<br>
-        {<br>
-            if (m_param->interlaceMode == 2)<br>
-                sei->m_picStruct = (poc & 1) ? 1 /* top */ : 2 /* bottom */;<br>
-            else if (m_param->interlaceMode == 1)<br>
-                sei->m_picStruct = (poc & 1) ? 2 /* bottom */ : 1 /* top */;<br>
-                       else<br>
-                               sei->m_picStruct = m_param->pictureStructure;<br>
-                       <br>
-                   if (m_param->interlaceMode)<br>
-                                sei->m_sourceScanType = 0;<br>
-                       else<br>
-                                sei->m_sourceScanType = 1;<br>
-                       <br>
-            sei->m_duplicateFlag = false;<br>
-        }<br>
+       m_rce.encodeOrder = m_frame->m_encodeOrder;<br>
+       <br>
+       writeLeadingSEIMessages();<br>
<br>
-        if (vui-><wbr>hrdParametersPresentFlag)<br>
-        {<br>
-            // The m_aucpbremoval delay specifies how many clock ticks the<br>
-            // access unit associated with the picture timing SEI message has to<br>
-            // wait after removal of the access unit with the most recent<br>
-            // buffering period SEI message<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>
-        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>
-        sei->alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
-    }<br>
-<br>
-       if (m_param-><wbr>preferredTransferCharacteristi<wbr>cs > -1 && slice->isIRAP())<br>
-       {<br>
-           SEIAlternativeTC m_seiAlternativeTC;<br>
-               m_seiAlternativeTC.m_<wbr>preferredTransferCharacteristi<wbr>cs = m_param-><wbr>preferredTransferCharacteristi<wbr>cs;<br>
-               m_bs.resetBits();<br>
-               int payloadSize = m_seiAlternativeTC.<wbr>countPayloadSize(*slice->m_<wbr>sps);<br>
-               m_seiAlternativeTC.setSize(<wbr>payloadSize);<br>
-               m_seiAlternativeTC.write(m_bs, *slice->m_sps);<br>
-               m_seiAlternativeTC.<wbr>alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
-       }<br>
-       <br>
-    bool isSei = false;<br>
-    /* Write user SEI */<br>
-    for (int i = 0; i < m_frame->m_userSEI.<wbr>numPayloads; i++)<br>
-    {<br>
-        x265_sei_payload *payload = &m_frame->m_userSEI.payloads[<wbr>i];<br>
-        if (payload->payloadType == USER_DATA_UNREGISTERED)<br>
-        {<br>
-            SEIuserDataUnregistered sei;<br>
-            sei.m_userData = payload->payload;<br>
-            if (!m_param->bSingleSeiNal)<br>
-                m_bs.resetBits();<br>
-            sei.setSize(payload-><wbr>payloadSize);<br>
-            sei.write(m_bs, *slice->m_sps);<br>
-            sei.alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
-            isSei = true;<br>
-        }<br>
-        else if (payload->payloadType == USER_DATA_REGISTERED_ITU_T_<wbr>T35)<br>
-        {<br>
-            if (writeSei)<br>
-            {<br>
-                SEICreativeIntentMeta sei;<br>
-                sei.m_payload = payload->payload;<br>
-                if (!m_param->bSingleSeiNal)<br>
-                    m_bs.resetBits();<br>
-                sei.setSize(payload-><wbr>payloadSize);<br>
-                sei.write(m_bs, *slice->m_sps);<br>
-                sei.alignAndSerialize(m_bs, false, m_param->bSingleSeiNal, NAL_UNIT_PREFIX_SEI, m_nalList);<br>
-                isSei = true;<br>
-            }<br>
-        }<br>
-        else<br>
-            x265_log(m_param, X265_LOG_ERROR, "Unrecognized SEI type\n");<br>
-    }<br>
-<br>
-    isSei |= ((m_frame->m_lowres.bKeyframe && m_param->bRepeatHeaders) || m_param->bEmitHRDSEI ||<br>
-             !!m_param->interlaceMode || (m_frame->m_lowres.sliceType == X265_TYPE_IDR && 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>
@@ -888,73 +871,10 @@<br>
<br>
     if (m_param->maxSlices > 1)<br>
     {<br>
-        PicYuv *reconPic = m_frame->m_reconPic;<br>
-        uint32_t height = reconPic->m_picHeight;<br>
-        uint32_t width = reconPic->m_picWidth;<br>
-        intptr_t stride = reconPic->m_stride;<br>
-        const uint32_t hChromaShift = CHROMA_H_SHIFT(m_param-><wbr>internalCsp);<br>
-        const uint32_t vChromaShift = CHROMA_V_SHIFT(m_param-><wbr>internalCsp);<br>
-<br>
-        if (m_param-><wbr>decodedPictureHashSEI == 1)<br>
-        {<br>
-<br>
-            MD5Init(&m_state[0]);<br>
-<br>
-            updateMD5Plane(m_state[0], reconPic->m_picOrg[0], width, height, stride);<br>
-<br>
-            if (m_param->internalCsp != X265_CSP_I400)<br>
-            {<br>
-                MD5Init(&m_state[1]);<br>
-                MD5Init(&m_state[2]);<br>
-<br>
-                width >>= hChromaShift;<br>
-                height >>= vChromaShift;<br>
-                stride = reconPic->m_strideC;<br>
-<br>
-                updateMD5Plane(m_state[1], reconPic->m_picOrg[1], width, height, stride);<br>
-                updateMD5Plane(m_state[2], reconPic->m_picOrg[2], width, height, stride);<br>
-            }<br>
-        }<br>
-        // TODO: NOT verify code in below mode<br>
-        else if (m_param-><wbr>decodedPictureHashSEI == 2)<br>
-        {<br>
-            m_crc[0] = 0xffff;<br>
-<br>
-            updateCRC(reconPic->m_picOrg[<wbr>0], m_crc[0], height, width, stride);<br>
-<br>
-            if (m_param->internalCsp != X265_CSP_I400)<br>
-            {<br>
-                width >>= hChromaShift;<br>
-                height >>= vChromaShift;<br>
-                stride = reconPic->m_strideC;<br>
-                m_crc[1] = m_crc[2] = 0xffff;<br>
-<br>
-                updateCRC(reconPic->m_picOrg[<wbr>1], m_crc[1], height, width, stride);<br>
-                updateCRC(reconPic->m_picOrg[<wbr>2], m_crc[2], height, width, stride);<br>
-            }<br>
-        }<br>
-        else if (m_param-><wbr>decodedPictureHashSEI == 3)<br>
-        {<br>
-            uint32_t cuHeight = m_param->maxCUSize;<br>
-<br>
-            m_checksum[0] = 0;<br>
-<br>
-            updateChecksum(reconPic->m_<wbr>picOrg[0], m_checksum[0], height, width, stride, 0, cuHeight);<br>
-<br>
-            if (m_param->internalCsp != X265_CSP_I400)<br>
-            {<br>
-                width >>= hChromaShift;<br>
-                height >>= vChromaShift;<br>
-                stride = reconPic->m_strideC;<br>
-                cuHeight >>= vChromaShift;<br>
-<br>
-                m_checksum[1] = m_checksum[2] = 0;<br>
-<br>
-                updateChecksum(reconPic->m_<wbr>picOrg[1], m_checksum[1], height, width, stride, 0, cuHeight);<br>
-                updateChecksum(reconPic->m_<wbr>picOrg[2], m_checksum[2], height, width, stride, 0, cuHeight);<br>
-            }<br>
-        }  <br>
-    } // end of (m_param->maxSlices > 1)<br>
+               PicYuv *reconPic = m_frame->m_reconPic;<br>
+               uint32_t height = reconPic->m_picHeight;<br>
+               initDecodedPictureHashSEI(0, 0, height);<br>
+    } <br>
<br>
     if (m_param->bDynamicRefine && m_top->m_startPoint <= m_frame->m_encodeOrder) //Avoid collecting data that will not be used by future frames.<br>
         collectDynDataFrame();<br>
@@ -1045,8 +965,6 @@<br>
             m_bs.resetBits();<br>
<br>
             const uint32_t sliceAddr = nextSliceRow * m_numCols;<br>
-            //CUData* ctu = m_frame->m_encData->getPicCTU(<wbr>sliceAddr);<br>
-            //const int sliceQp = ctu->m_qp[0];<br>
             if (m_param-><wbr>bOptRefListLengthPPS)<br>
             {<br>
                 ScopedLock refIdxLock(m_top->m_<wbr>sliceRefIdxLock);<br>
@@ -1068,7 +986,6 @@<br>
                 m_entropyCoder.<wbr>codeSliceHeaderWPPEntryPoints(<wbr>&m_substreamSizes[<wbr>prevSliceRow], (nextSliceRow - prevSliceRow - 1), maxStreamSize);<br>
<br>
             m_bs.writeByteAlignment();<br>
-<br>
             m_nalList.serialize(slice->m_<wbr>nalUnitType, m_bs);<br>
         }<br>
     }<br>
@@ -1088,43 +1005,13 @@<br>
         m_entropyCoder.setBitstream(&<wbr>m_bs);<br>
         if (slice->m_pps-><wbr>bEntropyCodingSyncEnabled)<br>
             m_entropyCoder.<wbr>codeSliceHeaderWPPEntryPoints(<wbr>m_substreamSizes, (slice->m_sps->numCuInHeight - 1), maxStreamSize);<br>
+<br>
         m_bs.writeByteAlignment();<br>
-<br>
         m_nalList.serialize(slice->m_<wbr>nalUnitType, m_bs);<br>
     }<br>
-    if (isSei && m_param->bSingleSeiNal)<br>
-        m_bs.resetBits();<br>
<br>
-    if (m_param-><wbr>decodedPictureHashSEI)<br>
-    {<br>
-        int planes = (m_frame->m_param->internalCsp != X265_CSP_I400) ? 3 : 1;<br>
-        int32_t payloadSize = 0;<br>
-        if (m_param-><wbr>decodedPictureHashSEI == 1)<br>
-        {<br>
-            m_seiReconPictureDigest.m_<wbr>method = SEIDecodedPictureHash::MD5;<br>
-            for (int i = 0; i < planes; i++)<br>
-                MD5Final(&m_state[i], m_seiReconPictureDigest.m_<wbr>digest[i]);<br>
-            payloadSize = 1 + 16 * planes;<br>
-        }<br>
-        else if (m_param-><wbr>decodedPictureHashSEI == 2)<br>
-        {<br>
-            m_seiReconPictureDigest.m_<wbr>method = SEIDecodedPictureHash::CRC;<br>
-            for (int i = 0; i < planes; i++)<br>
-                crcFinish(m_crc[i], m_seiReconPictureDigest.m_<wbr>digest[i]);<br>
-            payloadSize = 1 + 2 * planes;<br>
-        }<br>
-        else if (m_param-><wbr>decodedPictureHashSEI == 3)<br>
-        {<br>
-            m_seiReconPictureDigest.m_<wbr>method = SEIDecodedPictureHash::<wbr>CHECKSUM;<br>
-            for (int i = 0; i < planes; i++)<br>
-                checksumFinish(m_checksum[i], m_seiReconPictureDigest.m_<wbr>digest[i]);<br>
-            payloadSize = 1 + 4 * planes;<br>
-        }<br>
-        m_bs.resetBits();<br>
-        m_seiReconPictureDigest.<wbr>setSize(payloadSize);<br>
-        m_seiReconPictureDigest.write(<wbr>m_bs, *slice->m_sps);<br>
-        m_seiReconPictureDigest.<wbr>alignAndSerialize(m_bs, true, m_param->bSingleSeiNal, NAL_UNIT_SUFFIX_SEI, m_nalList);<br>
-    }<br>
+    if (m_param-><wbr>decodedPictureHashSEI)    <br>
+               writeTrailingSEIMessages();<br>
<br>
     uint64_t bytes = 0;<br>
     for (uint32_t i = 0; i < m_nalList.m_numNal; i++)<br>
@@ -1216,6 +1103,78 @@<br>
     m_endFrameTime = x265_mdate();  <br>
 }<br>
<br>
+void FrameEncoder::<wbr>initDecodedPictureHashSEI(int row, int cuAddr, int height)<br>
+{<br>
+       PicYuv *reconPic = m_frame->m_reconPic;<br>
+       uint32_t width = reconPic->m_picWidth;  <br>
+       intptr_t stride = reconPic->m_stride;<br>
+       uint32_t maxCUHeight = m_param->maxCUSize;<br>
+<br>
+       const uint32_t hChromaShift = CHROMA_H_SHIFT(m_param-><wbr>internalCsp);<br>
+       const uint32_t vChromaShift = CHROMA_V_SHIFT(m_param-><wbr>internalCsp);<br>
+<br>
+       if (m_param-><wbr>decodedPictureHashSEI == 1)<br>
+       {<br>
+               if (!row)<br>
+                       MD5Init(&m_<wbr>seiReconPictureDigest.m_state[<wbr>0]);<br>
+<br>
+               updateMD5Plane(m_<wbr>seiReconPictureDigest.m_state[<wbr>0], reconPic->getLumaAddr(cuAddr), width, height, stride);<br>
+               if (m_param->internalCsp != X265_CSP_I400)<br>
+               {<br>
+                       if (!row)<br>
+                       {<br>
+                               MD5Init(&m_<wbr>seiReconPictureDigest.m_state[<wbr>1]);<br>
+                               MD5Init(&m_<wbr>seiReconPictureDigest.m_state[<wbr>2]);<br>
+                       }<br>
+<br>
+                       width >>= hChromaShift;<br>
+                       height >>= vChromaShift;<br>
+                       stride = reconPic->m_strideC;<br>
+<br>
+                       updateMD5Plane(m_<wbr>seiReconPictureDigest.m_state[<wbr>1], reconPic->getCbAddr(cuAddr), width, height, stride);<br>
+                       updateMD5Plane(m_<wbr>seiReconPictureDigest.m_state[<wbr>2], reconPic->getCrAddr(cuAddr), width, height, stride);<br>
+               }<br>
+       }<br>
+       else if (m_param-><wbr>decodedPictureHashSEI == 2)<br>
+       {<br>
+<br>
+               if (!row)<br>
+                       m_seiReconPictureDigest.m_crc[<wbr>0] = 0xffff;<br>
+<br>
+               updateCRC(reconPic-><wbr>getLumaAddr(cuAddr), m_seiReconPictureDigest.m_crc[<wbr>0], height, width, stride);<br>
+               if (m_param->internalCsp != X265_CSP_I400)<br>
+               {<br>
+                       width >>= hChromaShift;<br>
+                       height >>= vChromaShift;<br>
+                       stride = reconPic->m_strideC;<br>
+                       m_seiReconPictureDigest.m_crc[<wbr>1] = m_seiReconPictureDigest.m_crc[<wbr>2] = 0xffff;<br>
+<br>
+                       updateCRC(reconPic->getCbAddr(<wbr>cuAddr), m_seiReconPictureDigest.m_crc[<wbr>1], height, width, stride);<br>
+                       updateCRC(reconPic->getCrAddr(<wbr>cuAddr), m_seiReconPictureDigest.m_crc[<wbr>2], height, width, stride);<br>
+               }<br>
+       }<br>
+       else if (m_param-><wbr>decodedPictureHashSEI == 3)<br>
+       {<br>
+               if (!row)<br>
+                       m_seiReconPictureDigest.m_<wbr>checksum[0] = 0;<br>
+<br>
+               updateChecksum(reconPic->m_<wbr>picOrg[0], m_seiReconPictureDigest.m_<wbr>checksum[0], height, width, stride, row, maxCUHeight);<br>
+               if (m_param->internalCsp != X265_CSP_I400)<br>
+               {<br>
+                       width >>= hChromaShift;<br>
+                       height >>= vChromaShift;<br>
+                       stride = reconPic->m_strideC;<br>
+                       maxCUHeight >>= vChromaShift;<br>
+<br>
+                       if (!row)<br>
+                               m_seiReconPictureDigest.m_<wbr>checksum[1] = m_seiReconPictureDigest.m_<wbr>checksum[2] = 0;<br>
+<br>
+                       updateChecksum(reconPic->m_<wbr>picOrg[1], m_seiReconPictureDigest.m_<wbr>checksum[1], height, width, stride, row, maxCUHeight);<br>
+                       updateChecksum(reconPic->m_<wbr>picOrg[2], m_seiReconPictureDigest.m_<wbr>checksum[2], height, width, stride, row, maxCUHeight);<br>
+               }<br>
+       }<br>
+}<br>
+<br>
 void FrameEncoder::encodeSlice(<wbr>uint32_t sliceAddr)<br>
 {<br>
     Slice* slice = m_frame->m_encData->m_slice;<br>
diff -r c258d214c978 -r 44f146176423 source/encoder/frameencoder.h<br>
--- a/source/encoder/frameencoder.<wbr>h     Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/encoder/frameencoder.<wbr>h     Fri Jul 20 20:54:23 2018 +0530<br>
@@ -129,6 +129,8 @@<br>
     /* blocks until worker thread is done, returns access unit */<br>
     Frame *getEncodedPicture(NALList& list);<br>
<br>
+       void initDecodedPictureHashSEI(int row, int cuAddr, int height);<br>
+<br>
     Event                    m_enable;<br>
     Event                    m_done;<br>
     Event                    m_completionEvent;<br>
@@ -161,9 +163,6 @@<br>
     double                   m_ssim;<br>
     uint64_t                 m_accessUnitBits;<br>
     uint32_t                 m_ssimCnt;<br>
-    MD5Context               m_state[3];<br>
-    uint32_t                 m_crc[3];<br>
-    uint32_t                 m_checksum[3];<br>
<br>
     volatile int             m_activeWorkerCount;        // count of workers currently encoding or filtering CTUs<br>
     volatile int             m_totalActiveWorkerCount;   // sum of m_activeWorkerCount sampled at end of each CTU<br>
@@ -215,7 +214,7 @@<br>
     protected:<br>
<br>
         WeightAnalysis operator=(const WeightAnalysis&);<br>
-    };<br>
+    }; <br>
<br>
 protected:<br>
<br>
@@ -230,7 +229,9 @@<br>
     void threadMain();<br>
     int  collectCTUStatistics(const CUData& ctu, FrameStats* frameLog);<br>
     void noiseReductionUpdate();<br>
-    void computeAvgTrainingData();<br>
+       void writeTrailingSEIMessages();<br>
+       void writeLeadingSEIMessages();<br>
+       bool writeToneMapInfo(x265_sei_<wbr>payload *payload);<br>
<br>
     /* Called by WaveFront::findJob() */<br>
     virtual void processRow(int row, int threadId);<br>
@@ -243,8 +244,9 @@<br>
 #if ENABLE_LIBVMAF<br>
     void vmafFrameLevelScore();<br>
 #endif<br>
-    void collectDynDataRow(CUData& ctu, FrameStats* rowStats);<br>
-    void collectDynDataFrame();<br>
+       void collectDynDataFrame();<br>
+       void computeAvgTrainingData();<br>
+    void collectDynDataRow(CUData& ctu, FrameStats* rowStats);    <br>
 };<br>
 }<br>
<br>
diff -r c258d214c978 -r 44f146176423 source/encoder/framefilter.cpp<br>
--- a/source/encoder/framefilter.<wbr>cpp    Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/encoder/framefilter.<wbr>cpp    Fri Jul 20 20:54:23 2018 +0530<br>
@@ -712,78 +712,8 @@<br>
<br>
     if (m_param->maxSlices == 1)<br>
     {<br>
-        if (m_param-><wbr>decodedPictureHashSEI == 1)<br>
-        {<br>
-            uint32_t height = m_parallelFilter[row].<wbr>getCUHeight();<br>
-            uint32_t width = reconPic->m_picWidth;<br>
-            intptr_t stride = reconPic->m_stride;<br>
-<br>
-            if (!row)<br>
-                MD5Init(&m_frameEncoder->m_<wbr>state[0]);<br>
-<br>
-            updateMD5Plane(m_frameEncoder-<wbr>>m_state[0], reconPic->getLumaAddr(cuAddr), width, height, stride);<br>
-            if (m_param->internalCsp != X265_CSP_I400)<br>
-            {<br>
-                if (!row)<br>
-                {<br>
-                    MD5Init(&m_frameEncoder->m_<wbr>state[1]);<br>
-                    MD5Init(&m_frameEncoder->m_<wbr>state[2]);<br>
-                }<br>
-<br>
-                width >>= m_hChromaShift;<br>
-                height >>= m_vChromaShift;<br>
-                stride = reconPic->m_strideC;<br>
-<br>
-                updateMD5Plane(m_frameEncoder-<wbr>>m_state[1], reconPic->getCbAddr(cuAddr), width, height, stride);<br>
-                updateMD5Plane(m_frameEncoder-<wbr>>m_state[2], reconPic->getCrAddr(cuAddr), width, height, stride);<br>
-            }<br>
-        }<br>
-        else if (m_param-><wbr>decodedPictureHashSEI == 2)<br>
-        {<br>
-            uint32_t height = m_parallelFilter[row].<wbr>getCUHeight();<br>
-            uint32_t width = reconPic->m_picWidth;<br>
-            intptr_t stride = reconPic->m_stride;<br>
-<br>
-            if (!row)<br>
-                m_frameEncoder->m_crc[0] = 0xffff;<br>
-<br>
-            updateCRC(reconPic-><wbr>getLumaAddr(cuAddr), m_frameEncoder->m_crc[0], height, width, stride);<br>
-            if (m_param->internalCsp != X265_CSP_I400)<br>
-            {<br>
-                width >>= m_hChromaShift;<br>
-                height >>= m_vChromaShift;<br>
-                stride = reconPic->m_strideC;<br>
-                m_frameEncoder->m_crc[1] = m_frameEncoder->m_crc[2] = 0xffff;<br>
-<br>
-                updateCRC(reconPic->getCbAddr(<wbr>cuAddr), m_frameEncoder->m_crc[1], height, width, stride);<br>
-                updateCRC(reconPic->getCrAddr(<wbr>cuAddr), m_frameEncoder->m_crc[2], height, width, stride);<br>
-            }<br>
-        }<br>
-        else if (m_param-><wbr>decodedPictureHashSEI == 3)<br>
-        {<br>
-            uint32_t width = reconPic->m_picWidth;<br>
-            uint32_t height = m_parallelFilter[row].<wbr>getCUHeight();<br>
-            intptr_t stride = reconPic->m_stride;<br>
-            uint32_t cuHeight = m_param->maxCUSize;<br>
-<br>
-            if (!row)<br>
-                m_frameEncoder->m_checksum[0] = 0;<br>
-<br>
-            updateChecksum(reconPic->m_<wbr>picOrg[0], m_frameEncoder->m_checksum[0], height, width, stride, row, cuHeight);<br>
-            if (m_param->internalCsp != X265_CSP_I400)<br>
-            {<br>
-                width >>= m_hChromaShift;<br>
-                height >>= m_vChromaShift;<br>
-                stride = reconPic->m_strideC;<br>
-                cuHeight >>= m_vChromaShift;<br>
-<br>
-                if (!row)<br>
-                    m_frameEncoder->m_checksum[1] = m_frameEncoder->m_checksum[2] = 0;<br>
-<br>
-                updateChecksum(reconPic->m_<wbr>picOrg[1], m_frameEncoder->m_checksum[1], height, width, stride, row, cuHeight);<br>
-                updateChecksum(reconPic->m_<wbr>picOrg[2], m_frameEncoder->m_checksum[2], height, width, stride, row, cuHeight);<br>
-            }<br>
-        }<br>
+               uint32_t height = m_parallelFilter[row].<wbr>getCUHeight();<br>
+               m_frameEncoder-><wbr>initDecodedPictureHashSEI(row, cuAddr, height);<br>
     } // end of (m_param->maxSlices == 1)<br>
<br>
     if (ATOMIC_INC(&m_frameEncoder-><wbr>m_completionCount) == 2 * (int)m_frameEncoder->m_<wbr>numRows)<br>
diff -r c258d214c978 -r 44f146176423 source/encoder/sei.cpp<br>
--- a/source/encoder/sei.cpp    Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/encoder/sei.cpp    Fri Jul 20 20:54:23 2018 +0530<br>
@@ -33,44 +33,39 @@<br>
     0x2C, 0xA2, 0xDE, 0x09, 0xB5, 0x17, 0x47, 0xDB,<br>
     0xBB, 0x55, 0xA4, 0xFE, 0x7F, 0xC2, 0xFC, 0x4E<br>
 };<br>
-/* count the size of the payload and return the size in bits */<br>
-int SEI::countPayloadSize(const SPS& sps)<br>
-{<br>
-    BitCounter counter;<br>
-    m_bitIf = &counter;<br>
-    writeSEI(sps);<br>
-    X265_CHECK(0 == (counter.<wbr>getNumberOfWrittenBits() & 7), "payload unaligned\n");<br>
-    int count = counter.<wbr>getNumberOfWrittenBits() >> 3;<br>
-    return count;<br>
-}<br>
<br>
-void SEI::alignAndSerialize(<wbr>Bitstream& bs, int lastSei, int isSingleSei, NalUnitType nalUnitType, NALList& list)<br>
+void SEI::writeSEImessages(<wbr>Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list, int isNested)<br>
 {<br>
-    if (lastSei || !isSingleSei)<br>
-    {<br>
-        bs.writeByteAlignment();<br>
-        list.serialize(nalUnitType, bs);<br>
-    }<br>
-}<br>
+       if (!isNested)<br>
+           bs.resetBits();<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>
-{<br>
-    uint32_t type = m_payloadType;<br>
-    m_bitIf = &bs;<br>
-    uint32_t payloadSize = m_payloadSize;<br>
-    if (m_payloadType == USER_DATA_UNREGISTERED)<br>
-        payloadSize = m_payloadSize + 16;<br>
-    uint32_t payloadType = m_payloadType;<br>
-    for (; payloadType >= 0xff; payloadType -= 0xff)<br>
-        WRITE_CODE(0xff, 8, "payload_type");<br>
-    WRITE_CODE(type, 8, "payload_type");<br>
-    for (; payloadSize >= 0xff; payloadSize -= 0xff)<br>
-        WRITE_CODE(0xff, 8, "payload_size");<br>
-    WRITE_CODE(payloadSize, 8, "payload_size");<br>
-    /* virtual writeSEI method, write to bs */<br>
-    writeSEI(sps);<br>
+       BitCounter counter;<br>
+       m_bitIf = &counter;<br>
+       writeSEI(sps);<br>
+       X265_CHECK(0 == (counter.<wbr>getNumberOfWrittenBits() & 7), "payload unaligned\n");<br>
+       uint32_t payloadData = counter.<wbr>getNumberOfWrittenBits() >> 3;<br>
+<br>
+       // set bitstream<br>
+       m_bitIf = &bs;  <br>
+<br>
+       uint32_t payloadType = m_payloadType;<br>
+       for (; payloadType >= 0xff; payloadType -= 0xff)<br>
+               WRITE_CODE(0xff, 8, "payload_type");<br>
+       WRITE_CODE(payloadType, 8, "payload_type");<br>
+<br>
+       uint32_t payloadSize = payloadData;<br>
+       for (; payloadSize >= 0xff; payloadSize -= 0xff)<br>
+               WRITE_CODE(0xff, 8, "payload_size");<br>
+       WRITE_CODE(payloadSize, 8, "payload_size");<br>
+<br>
+       // virtual writeSEI method, write to bs <br>
+       writeSEI(sps);<br>
+<br>
+       if (!isNested)<br>
+       {<br>
+               bs.writeByteAlignment();<br>
+               list.serialize(nalUnitType, bs);<br>
+       }<br>
 }<br>
<br>
 void SEI::writeByteAlign()<br>
@@ -91,6 +86,88 @@<br>
     m_payloadSize = size;<br>
 }<br>
<br>
+void SEIEncoder::<wbr>encodeSEIContentLightLevel(<wbr>SEIContentLightLevel& cllsei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list)<br>
+{<br>
+       cllsei.writeSEImessages(bs, sps, nalUnitType, list, isNestedSEI);<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIMasteringDisplayColor<wbr>Volume(<wbr>SEIMasteringDisplayColorVolume<wbr>& mdsei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list)<br>
+{      <br>
+       if (mdsei.parse(m_param-><wbr>masteringDisplayColorVolume))  <br>
+               mdsei.writeSEImessages(bs, sps, nalUnitType, list, isNestedSEI);<br>
+       else<br>
+               x265_log(m_param, X265_LOG_WARNING, "unable to parse mastering display color volume info\n");<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIActiveParameterSets(<wbr>SEIActiveParameterSets& sei,Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list)<br>
+{<br>
+       sei.m_selfContainedCvsFlag = true;<br>
+       sei.m_noParamSetUpdateFlag = true;<br>
+<br>
+       sei.writeSEImessages(bs, sps, nalUnitType, list, isNestedSEI);<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIBufferingPeriod(<wbr>SEIBufferingPeriod* bpSei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list)<br>
+{<br>
+       // since the temporal layer HRD is not ready, we assumed it is fixed<br>
+       bpSei->m_<wbr>auCpbRemovalDelayDelta = 1;<br>
+       bpSei->m_cpbDelayOffset = 0;<br>
+       bpSei->m_dpbDelayOffset = 0;    <br>
+<br>
+       bpSei->writeSEImessages(bs, sps, nalUnitType, list, isNestedSEI);<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIRecoveryPoint(<wbr>SEIRecoveryPoint& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list)<br>
+{      <br>
+       sei.m_recoveryPocCnt = 0;<br>
+       sei.m_exactMatchingFlag = true;<br>
+       sei.m_brokenLinkFlag = false;<br>
+<br>
+       sei.writeSEImessages(bs, sps, nalUnitType, list, isNestedSEI);<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIPictureTiming(<wbr>SEIPictureTiming *sei, Bitstream& bs, Slice* slice, NalUnitType nalUnitType, NALList& list)<br>
+{      <br>
+       const VUI vui = slice->m_sps->vuiParameters;<br>
+       int poc = slice->m_poc;<br>
+<br>
+       if (vui.<wbr>frameFieldInfoPresentFlag)<br>
+       {<br>
+               if (m_param->interlaceMode == 2)<br>
+                       sei->m_picStruct = (poc & 1) ? 1 /* top */ : 2 /* bottom */;<br>
+               else if (m_param->interlaceMode == 1)<br>
+                       sei->m_picStruct = (poc & 1) ? 2 /* bottom */ : 1 /* top */;<br>
+               else<br>
+                       sei->m_picStruct = m_param->pictureStructure;<br>
+<br>
+               sei->m_sourceScanType = m_param->interlaceMode ? 0 : 1;<br>
+<br>
+               sei->m_duplicateFlag = false;<br>
+       }<br>
+<br>
+       sei->writeSEImessages(bs, *slice->m_sps, nalUnitType, list, isNestedSEI);<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIAlternativeTransferCh<wbr>aracteristics(<wbr>SEIAlternativeTC& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list)<br>
+{<br>
+       sei.writeSEImessages(bs, sps, nalUnitType, list, isNestedSEI);<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIuserDataUnregistered(<wbr>SEIuserDataUnregistered& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list)<br>
+{<br>
+       sei.writeSEImessages(bs, sps, nalUnitType, list, isNestedSEI);<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIuserDataRegistered(<wbr>SEIuserDataRegistered& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list)<br>
+{<br>
+       sei.writeSEImessages(bs, sps, nalUnitType, list, isNestedSEI);<br>
+}<br>
+<br>
+void SEIEncoder::<wbr>encodeSEIDecodedPictureHash(<wbr>SEIDecodedPictureHash& sei, Bitstream& bs, Slice* slice, NalUnitType nalUnitType, NALList& list)<br>
+{      <br>
+       sei.writeSEImessages(bs, *slice->m_sps, nalUnitType, list, isNestedSEI && nalUnitType != NAL_UNIT_SUFFIX_SEI);<br>
+}<br>
+<br>
 /* charSet = "<wbr>ABCDEFGHIJKLMNOPQRSTUVWXYZabcd<wbr>efghijklmnopqrstuvwxyz01234567<wbr>89+/" */<br>
<br>
 char* SEI::base64Decode(char encodedString[], int base64EncodeLength)<br>
@@ -114,8 +191,8 @@<br>
                 bitstream = bitstream << 6;<br>
                 countBits += 6;<br>
             }<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>
diff -r c258d214c978 -r 44f146176423 source/encoder/sei.h<br>
--- a/source/encoder/sei.h      Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/encoder/sei.h      Fri Jul 20 20:54:23 2018 +0530<br>
@@ -28,6 +28,7 @@<br>
 #include "bitstream.h"<br>
 #include "slice.h"<br>
 #include "nal.h"<br>
+#include "md5.h"<br>
<br>
 namespace X265_NS {<br>
 // private namespace<br>
@@ -35,11 +36,9 @@<br>
 class SEI : public SyntaxElementWriter<br>
 {<br>
 public:<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>
+    /* SEI users call writeSEImessages() to marshal an SEI to a bitstream.<br>
+     * The writeSEImessages() method calls writeSEI() which encodes the header */<br>
+       void writeSEImessages(Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list, int isNested);    <br>
     void setSize(uint32_t size);<br>
     static char* base64Decode(char encodedString[], int base64EncodeLength);<br>
     virtual ~SEI() {}<br>
@@ -50,6 +49,32 @@<br>
     void writeByteAlign();<br>
 };<br>
<br>
+//<a href="mailto:seongnam.oh@samsung.com">seongnam.oh@samsung.com</a> :: for the Creative Intent Meta Data Encoding<br>
+class SEIuserDataRegistered : public SEI<br>
+{<br>
+public:<br>
+       SEIuserDataRegistered()<br>
+       {<br>
+               m_payloadType = USER_DATA_REGISTERED_ITU_T_<wbr>T35;<br>
+               m_payloadSize = 0;<br>
+       }<br>
+<br>
+       uint8_t *m_userData;<br>
+<br>
+       // <a href="mailto:daniel.vt@samsung.com">daniel.vt@samsung.com</a> :: for the Creative Intent Meta Data Encoding ( <a href="mailto:seongnam.oh@samsung.com">seongnam.oh@samsung.com</a> )<br>
+       void writeSEI(const SPS&)<br>
+       {<br>
+               if (!m_userData)<br>
+                       return;<br>
+<br>
+               uint32_t i = 0;<br>
+               for (; i < m_payloadSize; ++i)<br>
+                       WRITE_CODE(m_userData[i], 8, "creative_intent_metadata");<br>
+       }<br>
+};<br>
+<br>
+static const uint32_t ISO_IEC_11578_LEN = 16;<br>
+<br>
 class SEIuserDataUnregistered : public SEI<br>
 {<br>
 public:<br>
@@ -58,11 +83,11 @@<br>
         m_payloadType = USER_DATA_UNREGISTERED;<br>
         m_payloadSize = 0;<br>
     }<br>
-    static const uint8_t m_uuid_iso_iec_11578[16];<br>
+    static const uint8_t m_uuid_iso_iec_11578[ISO_IEC_<wbr>11578_LEN];<br>
     uint8_t *m_userData;<br>
     void writeSEI(const SPS&)<br>
     {<br>
-        for (uint32_t i = 0; i < 16; i++)<br>
+        for (uint32_t i = 0; i < ISO_IEC_11578_LEN; i++)<br>
             WRITE_CODE(m_uuid_iso_iec_<wbr>11578[i], 8, "sei.uuid_iso_iec_11578[i]");<br>
         for (uint32_t i = 0; i < m_payloadSize; i++)<br>
             WRITE_CODE(m_userData[i], 8, "user_data");<br>
@@ -136,7 +161,12 @@<br>
         CRC,<br>
         CHECKSUM,<br>
     } m_method;<br>
-    uint8_t m_digest[3][16];<br>
+<br>
+       MD5Context m_state[3];<br>
+       uint32_t   m_crc[3];<br>
+       uint32_t   m_checksum[3];<br>
+    uint8_t    m_digest[3][16];<br>
+<br>
     void writeSEI(const SPS& sps)<br>
     {<br>
         int planes = (sps.chromaFormatIdc != X265_CSP_I400) ? 3 : 1;<br>
@@ -208,8 +238,8 @@<br>
         WRITE_UVLC(0, "bp_seq_parameter_set_id");<br>
         WRITE_FLAG(0, "rap_cpb_params_present_flag")<wbr>;<br>
         WRITE_FLAG(0, "concatenation_flag");<br>
-        WRITE_CODE(m_<wbr>auCpbRemovalDelayDelta - 1,   hrd.cpbRemovalDelayLength,       "au_cpb_removal_delay_delta_<wbr>minus1");<br>
-        WRITE_CODE(m_<wbr>initialCpbRemovalDelay,       hrd.<wbr>initialCpbRemovalDelayLength,        "initial_cpb_removal_delay");<br>
+        WRITE_CODE(m_<wbr>auCpbRemovalDelayDelta - 1,   hrd.cpbRemovalDelayLength,        "au_cpb_removal_delay_delta_<wbr>minus1");<br>
+        WRITE_CODE(m_<wbr>initialCpbRemovalDelay,       hrd.<wbr>initialCpbRemovalDelayLength, "initial_cpb_removal_delay");<br>
         WRITE_CODE(m_<wbr>initialCpbRemovalDelayOffset, hrd.<wbr>initialCpbRemovalDelayLength, "initial_cpb_removal_delay_<wbr>offset");<br>
<br>
         writeByteAlign();<br>
@@ -274,30 +304,6 @@<br>
     }<br>
 };<br>
<br>
-//<a href="mailto:seongnam.oh@samsung.com">seongnam.oh@samsung.com</a> :: for the Creative Intent Meta Data Encoding<br>
-class SEICreativeIntentMeta : public SEI<br>
-{<br>
-public:<br>
-    SEICreativeIntentMeta()<br>
-    {<br>
-        m_payloadType = USER_DATA_REGISTERED_ITU_T_<wbr>T35;<br>
-        m_payloadSize = 0;<br>
-    }<br>
-<br>
-    uint8_t *m_payload;<br>
-<br>
-    // <a href="mailto:daniel.vt@samsung.com">daniel.vt@samsung.com</a> :: for the Creative Intent Meta Data Encoding ( <a href="mailto:seongnam.oh@samsung.com">seongnam.oh@samsung.com</a> )<br>
-    void writeSEI(const SPS&)<br>
-    {<br>
-        if (!m_payload)<br>
-            return;<br>
-<br>
-        uint32_t i = 0;<br>
-        for (; i < m_payloadSize; ++i)<br>
-            WRITE_CODE(m_payload[i], 8, "creative_intent_metadata");<br>
-    }<br>
-};<br>
-<br>
 class SEIAlternativeTC : public SEI<br>
 {<br>
 public:<br>
@@ -315,5 +321,30 @@<br>
        }<br>
 };<br>
<br>
+class Encoder;<br>
+<br>
+class SEIEncoder<br>
+{<br>
+public:<br>
+       x265_param*    m_param;<br>
+       int isNestedSEI;<br>
+public:<br>
+       void init(x265_param *p)<br>
+       { <br>
+               m_param = p;<br>
+               isNestedSEI = p->bSingleSeiNal;         <br>
+       }<br>
+       void encodeSEIContentLightLevel(<wbr>SEIContentLightLevel& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list);<br>
+       void encodeSEIMasteringDisplayColor<wbr>Volume(<wbr>SEIMasteringDisplayColorVolume<wbr>& mdsei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list);        <br>
+       void encodeSEIActiveParameterSets(<wbr>SEIActiveParameterSets& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list);<br>
+       void encodeSEIBufferingPeriod(<wbr>SEIBufferingPeriod* bpSei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list);<br>
+       void encodeSEIRecoveryPoint(<wbr>SEIRecoveryPoint& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list);<br>
+       void encodeSEIPictureTiming(<wbr>SEIPictureTiming *sei, Bitstream& bs, Slice* slice, NalUnitType nalUnitType, NALList& list);<br>
+       void encodeSEIAlternativeTransferCh<wbr>aracteristics(<wbr>SEIAlternativeTC& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list);<br>
+       void encodeSEIuserDataUnregistered(<wbr>SEIuserDataUnregistered& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list);<br>
+       void encodeSEIuserDataRegistered(<wbr>SEIuserDataRegistered& sei, Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list);<br>
+       void encodeSEIDecodedPictureHash(<wbr>SEIDecodedPictureHash& sei, Bitstream& bs, Slice* slice, NalUnitType nalUnitType, NALList& list);<br>
+};<br>
+<br>
 }<br>
 #endif // ifndef X265_SEI_H<br>
diff -r c258d214c978 -r 44f146176423 source/x265.h<br>
--- a/source/x265.h     Mon Jul 23 15:36:44 2018 +0530<br>
+++ b/source/x265.h     Fri Jul 20 20:54:23 2018 +0530<br>
@@ -334,6 +334,7 @@<br>
     TONE_MAPPING_INFO                    = 23,<br>
     FRAME_PACKING                        = 45,<br>
     DISPLAY_ORIENTATION                  = 47,<br>
+       GREEN_METADATA                       = 56,<br>
     SOP_DESCRIPTION                      = 128,<br>
     ACTIVE_PARAMETER_SETS                = 129,<br>
     DECODING_UNIT_INFO                   = 130,<br>
@@ -341,9 +342,20 @@<br>
     DECODED_PICTURE_HASH                 = 132,<br>
     SCALABLE_NESTING                     = 133,<br>
     REGION_REFRESH_INFO                  = 134,<br>
+       NO_DISPLAY                           = 135,<br>
+       TIME_CODE                            = 136,<br>
     MASTERING_DISPLAY_INFO               = 137,<br>
+       SEGM_RECT_FRAME_PACKING              = 138,<br>
+       EMP_MOTION_CONSTRAINED_TILE_<wbr>SETS     = 139,<br>
+       CHROMA_RESAMPLING_FILTER_HINT        = 140,<br>
+       KNEE_FUNCTION_INFO                   = 141,<br>
+       COLOUR_REMAPPING_INFO                = 142,<br>
+       DEINTERLACE_FIELD_<wbr>IDENTIFICATION     = 143, <br>
+       DEPENDENT_RAP_INDICATION             = 145, <br>
+       CODED_REGION_COMPLETION              = 146,<br>
     CONTENT_LIGHT_LEVEL_INFO             = 144,<br>
        ALTERNATIVE_TRANSFER_<wbr>CHARACTERISTICS = 147,<br>
+       AMBIENT_VIEWING_ENVIRONMENT          = 148,<br>
 } SEIPayloadType;<br>
<br>
 typedef struct x265_sei_payload<br>
</blockquote></div><br></div></div>