[x265] [PATCH] Refactor SEI code to handle more user SEI types
ashok at multicorewareinc.com
ashok at multicorewareinc.com
Mon Jul 23 16:39:13 CEST 2018
# HG changeset patch
# User Ashok Kumar Mishra <ashok at multicorewareinc.com>
# Date 1532100263 -19800
# Fri Jul 20 20:54:23 2018 +0530
# Node ID 3f9a9bfd927719b2d1e204af3ee7e26523bf9a77
# Parent c258d214c978a5c64ec8dd3986a3b3cc3d2381ac
Refactor SEI code to handle more user SEI types
diff -r c258d214c978 -r 3f9a9bfd9277 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 3f9a9bfd9277 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 3f9a9bfd9277 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 3f9a9bfd9277 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.encodeSEIAlternativeTransferCharacteristics(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;
- 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);
- }
+ writeLeadingSEIMessages();
- 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
@@ -890,71 +873,8 @@
{
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)
+ 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;
@@ -1802,7 +1761,7 @@
else if ((uint32_t)m_rce.encodeOrder <= 2 * (m_param->fpsNum / m_param->fpsDenom))
rowCount = X265_MIN((maxRows + 1) / 2, maxRows - 1);
else
- rowCount = X265_MIN(m_refLagRows / m_param->maxSlices, maxRows - 1);
+ rowCount = X265_MIN(m_refLagRows / m_param->maxSlices, maxRows - 1);
if (rowInSlice == rowCount)
{
@@ -1815,9 +1774,9 @@
else
{
uint32_t startAddr = m_sliceBaseRow[sliceId] * numCols;
- uint32_t finishAddr = startAddr + rowCount * numCols;
-
- for (uint32_t cuAddr = startAddr; cuAddr < finishAddr; cuAddr++)
+ uint32_t finishAddr = startAddr + rowCount * numCols;
+
+ for (uint32_t cuAddr = startAddr; cuAddr < finishAddr; cuAddr++)
m_rowSliceTotalBits[sliceId] += curEncData.m_cuStat[cuAddr].totalBits;
}
@@ -2132,7 +2091,7 @@
Frame *FrameEncoder::getEncodedPicture(NALList& output)
{
if (m_frame)
- {
+ {
/* block here until worker thread completes */
m_done.wait();
diff -r c258d214c978 -r 3f9a9bfd9277 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 computeAvgTrainingData();
+ void collectDynDataRow(CUData& ctu, FrameStats* rowStats);
};
}
diff -r c258d214c978 -r 3f9a9bfd9277 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 3f9a9bfd9277 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,46 +33,41 @@
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)
+
+void SEI::writeSEImessages(Bitstream& bs, const SPS& sps, NalUnitType nalUnitType, NALList& list, int isNested)
{
+ if (!isNested)
+ bs.resetBits();
+
BitCounter counter;
m_bitIf = &counter;
writeSEI(sps);
X265_CHECK(0 == (counter.getNumberOfWrittenBits() & 7), "payload unaligned\n");
- int count = counter.getNumberOfWrittenBits() >> 3;
- return count;
-}
+ uint32_t payloadData = counter.getNumberOfWrittenBits() >> 3;
-void SEI::alignAndSerialize(Bitstream& bs, int lastSei, int isSingleSei, NalUnitType nalUnitType, NALList& list)
-{
- if (lastSei || !isSingleSei)
+ // 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);
}
}
-/* 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);
-}
-
void SEI::writeByteAlign()
{
// TODO: expose bs.writeByteAlignment() as virtual function
@@ -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 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" */
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 3f9a9bfd9277 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,45 +304,44 @@
}
};
-//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:
int m_preferredTransferCharacteristics;
SEIAlternativeTC()
{
- m_payloadType = ALTERNATIVE_TRANSFER_CHARACTERISTICS;
- m_payloadSize = 0;
- m_preferredTransferCharacteristics = -1;
- }
-
- void writeSEI(const SPS&)
- {
- WRITE_CODE(m_preferredTransferCharacteristics, 8, "Preferred transfer characteristics");
- }
+ m_payloadType = ALTERNATIVE_TRANSFER_CHARACTERISTICS;
+ m_payloadSize = 0;
+ m_preferredTransferCharacteristics = -1;
+ }
+
+ void writeSEI(const SPS&)
+ {
+ WRITE_CODE(m_preferredTransferCharacteristics, 8, "Preferred transfer characteristics");
+ }
+};
+
+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);
};
}
diff -r c258d214c978 -r 3f9a9bfd9277 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,
+ ALTERNATIVE_TRANSFER_CHARACTERISTICS = 147,
+ AMBIENT_VIEWING_ENVIRONMENT = 148,
} SEIPayloadType;
typedef struct x265_sei_payload
-------------- next part --------------
A non-text attachment was scrubbed...
Name: x265.patch
Type: text/x-patch
Size: 57545 bytes
Desc: not available
URL: <http://mailman.videolan.org/pipermail/x265-devel/attachments/20180723/6660efe9/attachment-0001.bin>
More information about the x265-devel
mailing list