[x265] [PATCH] Refactor SEI code to handle more user SEI types

Ashok Kumar Mishra ashok at multicorewareinc.com
Mon Jul 23 16:38:52 CEST 2018


Kindly ignore this patch. Resending the patch after removing whitespaces.

On Mon, Jul 23, 2018 at 6:47 PM, <ashok at multicorewareinc.com> wrote:

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


More information about the x265-devel mailing list