[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