From 1b9c0119f7c0c1b82bad58ab3e02af18535ef10f Mon Sep 17 00:00:00 2001 From: PengJian Yang <yangpengjian.pj666@bytedance.com> Date: Wed, 21 Jul 2021 16:46:37 +0800 Subject: [PATCH] JVET-T0056: SEI manifest & SEI prefix indication --- cfg/sei_vui/JVET_T0056.cfg | 5 + source/App/EncoderApp/EncApp.cpp | 8 + source/App/EncoderApp/EncAppCfg.cpp | 9 + source/App/EncoderApp/EncAppCfg.h | 7 + source/Lib/CommonLib/SEI.cpp | 53 ++++++ source/Lib/CommonLib/SEI.h | 52 ++++++ source/Lib/CommonLib/TypeDef.h | 3 + source/Lib/DecoderLib/SEIread.cpp | 71 ++++++++ source/Lib/DecoderLib/SEIread.h | 6 + source/Lib/EncoderLib/EncCfg.h | 19 +++ source/Lib/EncoderLib/EncGOP.cpp | 52 ++++++ source/Lib/EncoderLib/SEIEncoder.cpp | 30 ++++ source/Lib/EncoderLib/SEIEncoder.h | 7 + source/Lib/EncoderLib/SEIwrite.cpp | 241 +++++++++++++++++++++++++-- source/Lib/EncoderLib/SEIwrite.h | 48 +++++- 15 files changed, 593 insertions(+), 18 deletions(-) create mode 100644 cfg/sei_vui/JVET_T0056.cfg diff --git a/cfg/sei_vui/JVET_T0056.cfg b/cfg/sei_vui/JVET_T0056.cfg new file mode 100644 index 000000000..c221d4525 --- /dev/null +++ b/cfg/sei_vui/JVET_T0056.cfg @@ -0,0 +1,5 @@ +# Controls if SEI Manifest SEI messages | enabled +SEISMEnabled: 1 + +# Controls if SEI Prefix Indication SEI messages | enabled +SEISPIEnabled: 1 diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index b3d1be536..25a86994a 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1175,6 +1175,14 @@ void EncApp::xInitLibCfg() m_cEncLib.setCropOffsetBottom (m_cropOffsetBottom); m_cEncLib.setCalculateHdrMetrics (m_calculateHdrMetrics); #endif + +#if JVET_T0056_SEI_MANIFEST + m_cEncLib.setSEIManifestEnabled(m_SEIManifestEnabled); +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + m_cEncLib.setSEIPrefixIndicationEnabled(m_SEIPrefixIndicationEnabled); +#endif + m_cEncLib.setOPIEnabled ( m_OPIEnabled ); if (m_OPIEnabled) { diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 2cf136192..fe2f96e9f 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1497,6 +1497,15 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("SEIDRINonlinearNumMinus1", m_driSEINonlinearNumMinus1, 0, "Specifies the number of piece-wise linear segments minus 2 for mapping of depth values to a scale that is uniformly quantized in terms of disparity in the depth representation information SEI message") ("SEIDRINonlinearModel", cfg_driSEINonlinearModel, cfg_driSEINonlinearModel, "List of the piece-wise linear segments for mapping of decoded luma sample values of an auxiliary picture to a scale that is uniformly quantized in terms of disparity in the depth representation information SEI message") +#if JVET_T0056_SEI_MANIFEST + //SEI manifest + ("SEISMEnabled", m_SEIManifestEnabled, false, "Controls if SEI Manifest SEI messages enabled") +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + //SEI prefix indication + ("SEISPIEnabled", m_SEIPrefixIndicationEnabled, false, "Controls if SEI Prefix Indications SEI messages enabled") +#endif + ("DebugBitstream", m_decodeBitstreams[0], string( "" ), "Assume the frames up to POC DebugPOC will be the same as in this bitstream. Load those frames from the bitstream instead of encoding them." ) ("DebugPOC", m_switchPOC, -1, "If DebugBitstream is present, load frames up to this POC from this bitstream. Starting with DebugPOC, return to normal encoding." ) ("DecodeBitstream1", m_decodeBitstreams[0], string( "" ), "Assume the frames up to POC DebugPOC will be the same as in this bitstream. Load those frames from the bitstream instead of encoding them." ) diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 87e914ecc..fbaaaaca8 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -700,6 +700,13 @@ protected: int m_sariSarWidth; int m_sariSarHeight; +#if JVET_T0056_SEI_MANIFEST + bool m_SEIManifestEnabled; +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + bool m_SEIPrefixIndicationEnabled; +#endif + bool m_MCTSEncConstraint; // weighted prediction diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index 008c8748b..326cff734 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -414,6 +414,53 @@ bool SEIMultiviewAcquisitionInfo::isMAISameContent(SEIMultiviewAcquisitionInfo * return true; } +#if JVET_T0056_SEI_MANIFEST +SEIManifest::SEIManifestDescription SEIManifest::getSEIMessageDescription(const PayloadType payloadType) +{ + std::vector<PayloadType> nessary = { FRAME_PACKING, EQUIRECTANGULAR_PROJECTION, GENERALIZED_CUBEMAP_PROJECTION, + SPHERE_ROTATION, REGION_WISE_PACKING }; + + std::vector<PayloadType> undetermined = { USER_DATA_REGISTERED_ITU_T_T35, USER_DATA_UNREGISTERED }; + + for (auto pt : nessary) { + if (payloadType == pt) + return NESSARY_SEI_MESSAGE; + } + for (auto pt: undetermined) + { + if (payloadType == pt) + return UNDETERMINED_SEI_MESSAGE; + } + return UNNESSARY_SEI_MESSAGE; +} +#endif + +#if JVET_T0056_SEI_PREFIX_INDICATION +uint8_t SEIPrefixIndication::getNumsOfSeiPrefixIndications(const SEI *sei) +{ + PayloadType payloadType = sei->payloadType(); + CHECK((payloadType == SEI_MANIFEST), "SEI_SPI should not include SEI_manfest"); + CHECK((payloadType == SEI_PREFIX_INDICATION), "SEI_SPI should not include itself"); + + //Unable to determine how many indicators are needed, it will be determined in xWriteSEIPrefixIndication() return 3 + std::vector<PayloadType> indicationN = { REGION_WISE_PACKING }; + // Need two indicators to finish writing the SEI prefix indication message(return 2) + std::vector<PayloadType> indication2 = { SPHERE_ROTATION }; + + for (auto pt: indicationN) + { + if (payloadType == pt) + return 3; + } + for (auto pt: indication2) + { + if (payloadType == pt) + return 2; + } + return 1; +} +#endif + // Static member const char *SEI::getSEIMessageString(SEI::PayloadType payloadType) { @@ -453,6 +500,12 @@ const char *SEI::getSEIMessageString(SEI::PayloadType payloadType) case SEI::ANNOTATED_REGIONS: return "Annotated Region"; case SEI::SCALABILITY_DIMENSION_INFO: return "Scalability dimension information"; case SEI::EXTENDED_DRAP_INDICATION: return "Extended DRAP indication"; +#if JVET_T0056_SEI_MANIFEST + case SEI::SEI_MANIFEST: return "SEI manifest"; +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + case SEI::SEI_PREFIX_INDICATION: return "SEI prefix indication"; +#endif default: return "Unknown"; } } diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index 43223bf51..e945a38c3 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -84,6 +84,12 @@ public: ALTERNATIVE_TRANSFER_CHARACTERISTICS = 147, AMBIENT_VIEWING_ENVIRONMENT = 148, CONTENT_COLOUR_VOLUME = 149, +#if JVET_T0056_SEI_MANIFEST + SEI_MANIFEST = 200, +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + SEI_PREFIX_INDICATION = 201, +#endif ANNOTATED_REGIONS = 202, SCALABILITY_DIMENSION_INFO = 205, EXTENDED_DRAP_INDICATION = 206, @@ -889,6 +895,52 @@ public: std::vector<std::vector<std::vector<int>>> m_refLevelFraction; }; +#if JVET_T0056_SEI_MANIFEST +class SEIManifest : public SEI +{ +public: + PayloadType payloadType() const { return SEI_MANIFEST; } + + SEIManifest() {} + virtual ~SEIManifest() {} + + enum SEIManifestDescription + { + NO_SEI_MESSAGE = 0, + NESSARY_SEI_MESSAGE = 1, + UNNESSARY_SEI_MESSAGE = 2, + UNDETERMINED_SEI_MESSAGE = 3, + + NUM_OF_DESCROPTION = 255, + }; + uint16_t m_manifestNumSeiMsgTypes; + std::vector<uint16_t> m_manifestSeiPayloadType; + std::vector<uint8_t> m_manifestSeiDescription; + + SEIManifestDescription getSEIMessageDescription(const PayloadType payloadType); +}; +#endif + +#if JVET_T0056_SEI_PREFIX_INDICATION +class SEIPrefixIndication : public SEI +{ +public: + PayloadType payloadType() const { return SEI_PREFIX_INDICATION; } + + SEIPrefixIndication() {} + virtual ~SEIPrefixIndication() {} + + uint16_t m_prefixSeiPayloadType; + uint8_t m_numSeiPrefixIndicationsMinus1; + std::vector<uint16_t> m_numBitsInPrefixIndicationMinus1; + std::vector<std::vector<int>> m_seiPrefixDataBit; + int m_byteAlignmentBitEqualToOne; + const SEI* m_payload; + + uint8_t getNumsOfSeiPrefixIndications(const SEI *sei); +}; +#endif + class SEIAnnotatedRegions : public SEI { public: diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 998d64f0a..ab34d9e04 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -52,6 +52,9 @@ // clang-format off +#define JVET_T0056_SEI_MANIFEST 1 // JVET-T0056: SEI manifest SEI message +#define JVET_T0056_SEI_PREFIX_INDICATION 1 // JVET-T0056: SEI prefix indication SEI message + //########### place macros to be removed in next cycle below this line ############### //########### place macros to be be kept below this line ############### diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index 97b62ddb6..059119c0d 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -328,6 +328,18 @@ void SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType sei = new SEIColourTransformInfo; xParseSEIColourTransformInfo((SEIColourTransformInfo&)*sei, payloadSize, pDecodedMessageOutputStream); break; +#if JVET_T0056_SEI_MANIFEST + case SEI::SEI_MANIFEST: + sei = new SEIManifest; + xParseSEISeiManifest((SEIManifest&) *sei, payloadSize, pDecodedMessageOutputStream); + break; +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + case SEI::SEI_PREFIX_INDICATION: + sei = new SEIPrefixIndication; + xParseSEISeiPrefixIndication((SEIPrefixIndication&) *sei, payloadSize, pDecodedMessageOutputStream); + break; +#endif default: for (uint32_t i = 0; i < payloadSize; i++) { @@ -2148,4 +2160,63 @@ void SeiCfgFileDump::xDumpSEIGeneralizedCubemapProjection (SEIGeneralizedCubema #endif +#if JVET_T0056_SEI_MANIFEST +void SEIReader::xParseSEISeiManifest(SEIManifest &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream) +{ + output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); + unsigned int val; + sei_read_code(pDecodedMessageOutputStream, 16, val, "manifest_num_sei_msg_types"); + sei.m_manifestNumSeiMsgTypes = val; + if (sei.m_manifestNumSeiMsgTypes > 0) + { + sei.m_manifestSeiPayloadType.resize(sei.m_manifestNumSeiMsgTypes); + sei.m_manifestSeiDescription.resize(sei.m_manifestNumSeiMsgTypes); + for (int i = 0; i < sei.m_manifestNumSeiMsgTypes; i++) + { + sei_read_code(pDecodedMessageOutputStream, 16, val, "manifest_sei_payload_types"); + sei.m_manifestSeiPayloadType[i] = val; + sei_read_code(pDecodedMessageOutputStream, 8, val, "manifest_sei_description"); + sei.m_manifestSeiDescription[i] = val; + } + } +} +#endif + +#if JVET_T0056_SEI_PREFIX_INDICATION +void SEIReader::xParseSEISeiPrefixIndication(SEIPrefixIndication &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream) +{ + output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); + unsigned int val; + unsigned int bitsRead = 0; + sei_read_code(pDecodedMessageOutputStream, 16, val, "prefix_sei_payload_type"); + sei.m_prefixSeiPayloadType = val; + sei_read_code(pDecodedMessageOutputStream, 8, val, "num_sei_prefix_indications_minus1"); + sei.m_numSeiPrefixIndicationsMinus1 = val; + if (sei.m_numSeiPrefixIndicationsMinus1 >= 0) + { + sei.m_numBitsInPrefixIndicationMinus1.resize(sei.m_numSeiPrefixIndicationsMinus1 + 1); + sei.m_seiPrefixDataBit.resize(sei.m_numSeiPrefixIndicationsMinus1 + 1); + for (int i = 0; i <= sei.m_numSeiPrefixIndicationsMinus1; i++) + { + sei_read_code(pDecodedMessageOutputStream, 16, val, "num_bits_in_prefix_indication_minus1"); + sei.m_numBitsInPrefixIndicationMinus1[i] = val; + sei.m_seiPrefixDataBit[i].resize(sei.m_numBitsInPrefixIndicationMinus1[i] + 1); + for (int j = 0; j <= sei.m_numBitsInPrefixIndicationMinus1[i]; j++) + { + sei_read_code(pDecodedMessageOutputStream, 1, val, "sei_prefix_data_bit"); + sei.m_seiPrefixDataBit[i][j] = val; + bitsRead += 1; + } + while (bitsRead % 8 != 0) + { + sei_read_code(pDecodedMessageOutputStream, 1, val, "byte_alignment_bit_equal_to_one"); + sei.m_byteAlignmentBitEqualToOne = val; + CHECK(!sei.m_byteAlignmentBitEqualToOne, "error to read/write SEI_prefix_indication::byte_alignment_bit_equal_to_one"); + bitsRead += 1; + } + } + } +} +#endif + //! \} diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index de75eb3d5..0c421606b 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -95,6 +95,12 @@ protected: void xParseSEIContentColourVolume (SEIContentColourVolume& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); void xParseSEIExtendedDrapIndication (SEIExtendedDrapIndication& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); void xParseSEIColourTransformInfo (SEIColourTransformInfo& sei, uint32_t payloadSize, std::ostream* pDecodedMessageOutputStream); + #if JVET_T0056_SEI_MANIFEST + void xParseSEISeiManifest (SEIManifest& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + void xParseSEISeiPrefixIndication (SEIPrefixIndication& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); +#endif void sei_read_scode(std::ostream *pOS, uint32_t length, int& code, const char *pSymbolName); void sei_read_code(std::ostream *pOS, uint32_t uiLength, uint32_t& ruiCode, const char *pSymbolName); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 238d0cd00..ebb55f1b1 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -735,6 +735,13 @@ protected: int m_driSEINonlinearNumMinus1; std::vector<uint32_t> m_driSEINonlinearModel; std::string m_arSEIFileRoot; // Annotated region SEI - initialized from external file + +#if JVET_T0056_SEI_MANIFEST + bool m_SEIManifestEnabled; +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + bool m_SEIPrefixIndicationEnabled; +#endif //====== Weighted Prediction ======== bool m_useWeightedPred; //< Use of Weighting Prediction (P_SLICE) bool m_useWeightedBiPred; //< Use of Bi-directional Weighting Prediction (B_SLICE) @@ -2004,6 +2011,18 @@ public: int getDriSEINonlinearNumMinus1() const { return m_driSEINonlinearNumMinus1; } void setDriSEINonlinearModel(const std::vector<uint32_t>& driSEINonLinearModel) { m_driSEINonlinearModel = driSEINonLinearModel; } uint32_t getDriSEINonlinearModel(int idx) const { return m_driSEINonlinearModel[idx]; } + +#if JVET_T0056_SEI_MANIFEST + //SEI manifest + void setSEIManifestEnabled(bool b) { m_SEIManifestEnabled = b; } + bool getSmSeiManifestSeiEnabled() { return m_SEIManifestEnabled; } +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + //SEI prefix indication + void setSEIPrefixIndicationEnabled(bool b) { m_SEIPrefixIndicationEnabled = b; } + bool getSpiPrefixIndicationSeiEnabled() { return m_SEIPrefixIndicationEnabled; } +#endif + void setUseWP ( bool b ) { m_useWeightedPred = b; } void setWPBiPred ( bool b ) { m_useWeightedBiPred = b; } bool getUseWP () { return m_useWeightedPred; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index c9c1e274e..2ebfa2116 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -546,6 +546,26 @@ void EncGOP::xWriteLeadingSEIOrdered (SEIMessages& seiMessages, SEIMessages& duI #endif // The case that a specific SEI is not present is handled in xWriteSEI (empty list) +#if JVET_T0056_SEI_MANIFEST + // When SEI Manifest SEI message is present in an SEI NAL unit, the SEI Manifest SEI message shall be the first SEI + // message in the SEI NAL unit (D3.45 in ISO/IEC 23008-2). + if (m_pcCfg->getSmSeiManifestSeiEnabled()) + { + currentMessages = extractSeisByType(localMessages, SEI::SEI_MANIFEST); + CHECK(!(currentMessages.size() <= 1), "Unspecified error"); + xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId); + xClearSEIs(currentMessages, !testWrite); + } +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + if (m_pcCfg->getSpiPrefixIndicationSeiEnabled()) + { + //There may be multiple SEI prefix indication messages at the same time + currentMessages = extractSeisByType(localMessages, SEI::SEI_PREFIX_INDICATION); + xWriteSEI(NAL_UNIT_PREFIX_SEI, currentMessages, accessUnit, itNalu, temporalId); + xClearSEIs(currentMessages, !testWrite); + } +#endif // Buffering period SEI must always be following active parameter sets currentMessages = extractSeisByType(localMessages, SEI::BUFFERING_PERIOD); @@ -807,6 +827,38 @@ void EncGOP::xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const SPS m_seiEncoder.initSEIColourTransformInfo(seiCTI); seiMessages.push_back(seiCTI); } + +#if JVET_T0056_SEI_MANIFEST + // Make sure that sei_manifest and sei_prefix are the last two initialized sei_msg, otherwise it will cause these two + // Sei messages to not be able to enter all SEI messages + if (m_pcCfg->getSmSeiManifestSeiEnabled()) + { + SEIManifest *seiSEIManifest = new SEIManifest; + m_seiEncoder.initSEISeiManifest(seiSEIManifest, seiMessages); + seiMessages.push_back(seiSEIManifest); + } +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + if (m_pcCfg->getSpiPrefixIndicationSeiEnabled()) + { + int NumOfSEIPrefixMsg = 0; + for (auto &it: seiMessages) + { + NumOfSEIPrefixMsg++; + } + for (auto &it: seiMessages) + { + if (NumOfSEIPrefixMsg == 0 || it->payloadType() == 200) + { + break; + } + SEIPrefixIndication *seiSEIPrefixIndication = new SEIPrefixIndication; + m_seiEncoder.initSEISeiPrefixIndication(seiSEIPrefixIndication, it); + seiMessages.push_back(seiSEIPrefixIndication); + NumOfSEIPrefixMsg--; + } + } +#endif } void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessages, SEIMessages& nestedSeiMessages, Slice *slice) diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 31a2795d4..870426846 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -1096,5 +1096,35 @@ void SEIEncoder::initSEISubpictureLevelInfo(SEISubpicureLevelInfo *sei, const SP } } +#if JVET_T0056_SEI_MANIFEST +void SEIEncoder::initSEISeiManifest(SEIManifest *seiSeiManifest, const SEIMessages &seiMessages) +{ + assert(m_isInitialized); + assert(seiSeiManifest != NULL); + seiSeiManifest->m_manifestNumSeiMsgTypes = 0; + int i = 0; + for (auto &it: seiMessages) + { + seiSeiManifest->m_manifestNumSeiMsgTypes += 1; + auto tempPayloadType = it->payloadType(); + seiSeiManifest->m_manifestSeiPayloadType.push_back(tempPayloadType); + auto description = seiSeiManifest->getSEIMessageDescription(tempPayloadType); + seiSeiManifest->m_manifestSeiDescription.push_back(description); + i++; + } + CHECK(seiSeiManifest->m_manifestNumSeiMsgTypes == 0, "No SEI messages available"); +} +#endif + +#if JVET_T0056_SEI_PREFIX_INDICATION +void SEIEncoder::initSEISeiPrefixIndication(SEIPrefixIndication *seiSeiPrefixIndications, const SEI *sei) +{ + assert(m_isInitialized); + assert(seiSeiPrefixIndications != NULL); + seiSeiPrefixIndications->m_prefixSeiPayloadType = sei->payloadType(); + seiSeiPrefixIndications->m_numSeiPrefixIndicationsMinus1 = seiSeiPrefixIndications->getNumsOfSeiPrefixIndications(sei) - 1; + seiSeiPrefixIndications->m_payload = sei; +} +#endif //! \} diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h index 76232b8f5..c93c97335 100644 --- a/source/Lib/EncoderLib/SEIEncoder.h +++ b/source/Lib/EncoderLib/SEIEncoder.h @@ -94,6 +94,13 @@ public: bool initSEIAnnotatedRegions(SEIAnnotatedRegions *sei, int currPOC); void initSEIColourTransformInfo(SEIColourTransformInfo* sei); void readAnnotatedRegionSEI(std::istream &fic, SEIAnnotatedRegions *seiAnnoRegion, bool &failed); +#if JVET_T0056_SEI_MANIFEST + void initSEISeiManifest(SEIManifest *seiSeiManifest, const SEIMessages &seiMessage); +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + void initSEISeiPrefixIndication(SEIPrefixIndication *seiSeiPrefixIndications, const SEI *sei); +#endif + private: EncCfg* m_pcCfg; EncLib* m_pcEncLib; diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index 0f554a7ff..05c2e581e 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -41,7 +41,11 @@ //! \ingroup EncoderLib //! \{ -void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &hrd, const uint32_t temporalId) +void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &hrd, const uint32_t temporalId +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx +#endif +) { const SEIBufferingPeriod *bp = NULL; switch (sei.payloadType()) @@ -81,7 +85,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &h xWriteSEIEdrapIndication(*static_cast<const SEIExtendedDrapIndication*>(&sei)); break; case SEI::FRAME_PACKING: - xWriteSEIFramePacking(*static_cast<const SEIFramePacking*>(&sei)); + xWriteSEIFramePacking(*static_cast<const SEIFramePacking*>(&sei) +#if JVET_T0056_SEI_PREFIX_INDICATION + , SEIPrefixIndicationIdx +#endif + ); break; case SEI::DISPLAY_ORIENTATION: xWriteSEIDisplayOrientation(*static_cast<const SEIDisplayOrientation*>(&sei)); @@ -98,19 +106,35 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &h break; #endif case SEI::EQUIRECTANGULAR_PROJECTION: - xWriteSEIEquirectangularProjection(*static_cast<const SEIEquirectangularProjection*>(&sei)); + xWriteSEIEquirectangularProjection(*static_cast<const SEIEquirectangularProjection*>(&sei) +#if JVET_T0056_SEI_PREFIX_INDICATION + , SEIPrefixIndicationIdx +#endif + ); break; case SEI::SPHERE_ROTATION: - xWriteSEISphereRotation(*static_cast<const SEISphereRotation*>(&sei)); + xWriteSEISphereRotation(*static_cast<const SEISphereRotation*>(&sei) +#if JVET_T0056_SEI_PREFIX_INDICATION + , SEIPrefixIndicationIdx +#endif + ); break; case SEI::OMNI_VIEWPORT: xWriteSEIOmniViewport(*static_cast<const SEIOmniViewport*>(&sei)); break; case SEI::REGION_WISE_PACKING: - xWriteSEIRegionWisePacking(*static_cast<const SEIRegionWisePacking*>(&sei)); + xWriteSEIRegionWisePacking(*static_cast<const SEIRegionWisePacking*>(&sei) +#if JVET_T0056_SEI_PREFIX_INDICATION + , SEIPrefixIndicationIdx +#endif + ); break; case SEI::GENERALIZED_CUBEMAP_PROJECTION: - xWriteSEIGeneralizedCubemapProjection(*static_cast<const SEIGeneralizedCubemapProjection*>(&sei)); + xWriteSEIGeneralizedCubemapProjection(*static_cast<const SEIGeneralizedCubemapProjection*>(&sei) +#if JVET_T0056_SEI_PREFIX_INDICATION + , SEIPrefixIndicationIdx +#endif + ); break; case SEI::SCALABILITY_DIMENSION_INFO: xWriteSEIScalabilityDimensionInfo(*static_cast<const SEIScalabilityDimensionInfo*>(&sei)); @@ -151,10 +175,29 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &h case SEI::ANNOTATED_REGIONS: xWriteSEIAnnotatedRegions(*static_cast<const SEIAnnotatedRegions*>(&sei)); break; +#if JVET_T0056_SEI_MANIFEST + case SEI::SEI_MANIFEST: + CHECK((SEIPrefixIndicationIdx), "wrong SEI prefix indication message"); + xWriteSEIManifest(*static_cast<const SEIManifest *>(&sei)); + break; +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + case SEI::SEI_PREFIX_INDICATION: + CHECK((SEIPrefixIndicationIdx), "wrong SEI prefix indication message"); + xWriteSEIPrefixIndication(bs, *static_cast<const SEIPrefixIndication *>(&sei), hrd, temporalId); + break; +#endif + default: THROW("Trying to write unhandled SEI message"); break; } +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx) + { + return; + } +#endif xWriteByteAlign(); } @@ -577,16 +620,38 @@ void SEIWriter::xWriteSEIScalableNesting(OutputBitstream& bs, const SEIScalableN writeSEImessages(bs, sei.m_nestedSEIs, m_nestingHrd, true, 0); } -void SEIWriter::xWriteSEIFramePacking(const SEIFramePacking& sei) +void SEIWriter::xWriteSEIFramePacking(const SEIFramePacking& sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx +#endif +) { +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx) + { + int numBits = 0; + numBits += getUESENumBits("ue", sei.m_arrangementId); + if (!sei.m_arrangementCancelFlag) + numBits += 9; + else + numBits += 2; + WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); + } +#endif + WRITE_UVLC( sei.m_arrangementId, "fp_arrangement_id" ); WRITE_FLAG( sei.m_arrangementCancelFlag, "fp_arrangement_cancel_flag" ); if( sei.m_arrangementCancelFlag == 0 ) { WRITE_CODE( sei.m_arrangementType, 7, "fp_arrangement_type" ); - WRITE_FLAG( sei.m_quincunxSamplingFlag, "fp_quincunx_sampling_flag" ); +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx) + { + return; + } +#endif WRITE_CODE( sei.m_contentInterpretationType, 6, "fp_content_interpretation_type" ); WRITE_FLAG( sei.m_spatialFlippingFlag, "fp_spatial_flipping_flag" ); WRITE_FLAG( sei.m_frame0FlippedFlag, "fp_frame0_flipped_flag" ); @@ -647,6 +712,67 @@ void SEIWriter::xWriteSEIMasteringDisplayColourVolume(const SEIMasteringDisplayC WRITE_CODE( sei.values.minLuminance, 32, "mdcv_min_display_mastering_luminance" ); } +#if JVET_T0056_SEI_MANIFEST +void SEIWriter::xWriteSEIManifest(const SEIManifest &sei) +{ + WRITE_CODE(sei.m_manifestNumSeiMsgTypes, 16, "manifest_num_sei_msg_types"); + for (int i = 0; i < sei.m_manifestNumSeiMsgTypes; i++) + { + WRITE_CODE(sei.m_manifestSeiPayloadType[i], 16, "manifest_sei_payload_types"); + WRITE_CODE(sei.m_manifestSeiDescription[i], 8, "manifest_sei_description"); + } +} +#endif + +#if JVET_T0056_SEI_PREFIX_INDICATION +//SEI prefix indication +void SEIWriter::xWriteSEIPrefixIndication(OutputBitstream &bs, const SEIPrefixIndication &sei, HRD &hrd, const uint32_t temporalId) +{ + + WRITE_CODE(sei.m_prefixSeiPayloadType, 16, "prefix_sei_payload_type"); + int idx = sei.m_numSeiPrefixIndicationsMinus1 + 1; + //If num_sei_prefix_indication cannot be determined during initialization, then determine when writing prefix databits + if (idx <= 1) { + WRITE_CODE(sei.m_numSeiPrefixIndicationsMinus1, 8, "num_sei_prefix_indications_minus1"); + } + // By writing SEI prefix indication recursively, you only need to pass in SEIPrefixIndicationIdx in the corresponding + // function and add the SEI prefix syntax elements. At present, only part of SEI can be written in SEI prefix + // indication. If it needs to be added later, the corresponding databit should be determined + xWriteSEIpayloadData(bs, *static_cast<const SEI *>(sei.m_payload), hrd, temporalId, idx); + xWriteSPIByteAlign(); +} +int SEIWriter::getUESENumBits(std::string str, int codeNum) { + CHECK(!(str == "ue" || str == "se"), "Unknown type of codeNum"); + if (str == "ue") { + if (codeNum <= 0) + return 1; + else if (codeNum <= 2) + return 3; + else if (codeNum <= 6) + return 5; + else if (codeNum <= 14) + return 7; + else if (codeNum <= 30) + return 9; + else + return 11; + } + else if (str == "se") + { + return getUESENumBits("ue", 2 * std::abs(codeNum)); + } + assert(0); + return -1; +} +void SEIWriter::xWriteSPIByteAlign() { + while (m_pcBitIf->getNumberOfWrittenBits() % 8 != 0) + { + WRITE_FLAG(1, "byte_alignment_bit_equal_to_one"); + } +} +// ~SEI prefix indication +#endif + void SEIWriter::xWriteSEIAnnotatedRegions(const SEIAnnotatedRegions &sei) { WRITE_FLAG(sei.m_hdr.m_cancelFlag, "ar_cancel_flag"); @@ -756,8 +882,22 @@ void SEIWriter::xWriteSEIAlternativeTransferCharacteristics(const SEIAlternative } #endif -void SEIWriter::xWriteSEIEquirectangularProjection(const SEIEquirectangularProjection &sei) +void SEIWriter::xWriteSEIEquirectangularProjection(const SEIEquirectangularProjection &sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx +#endif +) { +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx) + { + int numBits = 5; + if (sei.m_erpGuardBandFlag) + numBits += 19; + WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); + } +#endif + WRITE_FLAG( sei.m_erpCancelFlag, "erp_cancel_flag" ); if( !sei.m_erpCancelFlag ) { @@ -773,13 +913,40 @@ void SEIWriter::xWriteSEIEquirectangularProjection(const SEIEquirectangularProje } } -void SEIWriter::xWriteSEISphereRotation(const SEISphereRotation &sei) +void SEIWriter::xWriteSEISphereRotation(const SEISphereRotation &sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx +#endif +) { +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx) + { + if (sei.m_sphereRotationCancelFlag) + { + WRITE_CODE(0, 8, "num_sei_prefix_indications_minus1"); + } + else + { + WRITE_CODE(1, 8, "num_sei_prefix_indications_minus1"); + } + int numBits = 8; + WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); + } +#endif WRITE_FLAG( sei.m_sphereRotationCancelFlag, "sphere_rotation_cancel_flag" ); if( !sei.m_sphereRotationCancelFlag ) { WRITE_FLAG( sei.m_sphereRotationPersistenceFlag, "sphere_rotation_persistence_flag" ); WRITE_CODE( 0, 6, "sphere_rotation_reserved_zero_6bits" ); +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx >= 2) + { + xWriteSPIByteAlign(); + int numBits2 = 32 + 32 + 32; + WRITE_CODE(numBits2 - 1, 16, "num_bits_in_prefix_indication_minus1"); + } +#endif WRITE_SCODE(sei.m_sphereRotationYaw, 32, "sphere_rotation_yaw" ); WRITE_SCODE(sei.m_sphereRotationPitch, 32, "sphere_rotation_pitch" ); WRITE_SCODE(sei.m_sphereRotationRoll, 32, "sphere_rotation_roll" ); @@ -807,8 +974,29 @@ void SEIWriter::xWriteSEIOmniViewport(const SEIOmniViewport &sei) } } -void SEIWriter::xWriteSEIRegionWisePacking(const SEIRegionWisePacking &sei) +void SEIWriter::xWriteSEIRegionWisePacking(const SEIRegionWisePacking &sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx +#endif +) { +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx) + { + if (sei.m_rwpCancelFlag) + { + WRITE_CODE(0, 8, "num_sei_prefix_indications_minus1"); + } + else + { + WRITE_CODE(sei.m_numPackedRegions, 8, "num_sei_prefix_indications_minus1"); + } + int numBits = 1; + if (!sei.m_rwpCancelFlag) + numBits += 111; + WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); + } +#endif WRITE_FLAG( sei.m_rwpCancelFlag, "rwp_cancel_flag" ); if(!sei.m_rwpCancelFlag) { @@ -822,6 +1010,15 @@ void SEIWriter::xWriteSEIRegionWisePacking(const SEIRegionWisePacking &sei) WRITE_CODE( (uint32_t)sei.m_packedPictureHeight, 16, "rwp_packed_picture_height" ); for( int i=0; i < sei.m_numPackedRegions; i++ ) { +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx >= 2) + { + int numBits = 200; + if (sei.m_rwpGuardBandFlag[i]) + numBits += 48; + WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); + } +#endif WRITE_CODE( 0, 4, "rwp_reserved_zero_4bits" ); WRITE_CODE( (uint32_t)sei.m_rwpTransformType[i], 3, "rwp_transform_type" ); WRITE_FLAG( sei.m_rwpGuardBandFlag[i], "rwp_guard_band_flag" ); @@ -850,14 +1047,34 @@ void SEIWriter::xWriteSEIRegionWisePacking(const SEIRegionWisePacking &sei) } } -void SEIWriter::xWriteSEIGeneralizedCubemapProjection(const SEIGeneralizedCubemapProjection &sei) +void SEIWriter::xWriteSEIGeneralizedCubemapProjection(const SEIGeneralizedCubemapProjection &sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx +#endif +) { +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx) + { + int numBits = 1; + if (!sei.m_gcmpCancelFlag) + numBits += 6; + WRITE_CODE(numBits - 1, 16, "num_bits_in_prefix_indication_minus1"); + } +#endif + WRITE_FLAG( sei.m_gcmpCancelFlag, "gcmp_cancel_flag" ); if (!sei.m_gcmpCancelFlag) { WRITE_FLAG( sei.m_gcmpPersistenceFlag, "gcmp_persistence_flag" ); WRITE_CODE( sei.m_gcmpPackingType, 3, "gcmp_packing_type" ); WRITE_CODE( sei.m_gcmpMappingFunctionType, 2, "gcmp_mapping_function_type" ); +#if JVET_T0056_SEI_PREFIX_INDICATION + if (SEIPrefixIndicationIdx == 1) + { + return; + } +#endif int numFace = sei.m_gcmpPackingType == 4 || sei.m_gcmpPackingType == 5 ? 5 : 6; for (int i = 0; i < numFace; i++) { diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h index 55cff4a49..edc360331 100644 --- a/source/Lib/EncoderLib/SEIwrite.h +++ b/source/Lib/EncoderLib/SEIwrite.h @@ -61,18 +61,38 @@ protected: void xWriteSEIDependentRAPIndication(const SEIDependentRAPIndication& sei); void xWriteSEIEdrapIndication(const SEIExtendedDrapIndication& sei); void xWriteSEIScalableNesting(OutputBitstream& bs, const SEIScalableNesting& sei); - void xWriteSEIFramePacking(const SEIFramePacking& sei); + void xWriteSEIFramePacking(const SEIFramePacking& sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx = 0 +#endif + ); void xWriteSEIDisplayOrientation(const SEIDisplayOrientation& sei); void xWriteSEIParameterSetsInclusionIndication(const SEIParameterSetsInclusionIndication& sei); void xWriteSEIMasteringDisplayColourVolume( const SEIMasteringDisplayColourVolume& sei); #if U0033_ALTERNATIVE_TRANSFER_CHARACTERISTICS_SEI void xWriteSEIAlternativeTransferCharacteristics(const SEIAlternativeTransferCharacteristics& sei); #endif - void xWriteSEIEquirectangularProjection (const SEIEquirectangularProjection &sei); - void xWriteSEISphereRotation (const SEISphereRotation &sei); + void xWriteSEIEquirectangularProjection (const SEIEquirectangularProjection &sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx = 0 +#endif + ); + void xWriteSEISphereRotation (const SEISphereRotation &sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx = 0 +#endif + ); void xWriteSEIOmniViewport (const SEIOmniViewport& sei); - void xWriteSEIRegionWisePacking (const SEIRegionWisePacking &sei); - void xWriteSEIGeneralizedCubemapProjection (const SEIGeneralizedCubemapProjection &sei); + void xWriteSEIRegionWisePacking (const SEIRegionWisePacking &sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx = 0 +#endif + ); + void xWriteSEIGeneralizedCubemapProjection (const SEIGeneralizedCubemapProjection &sei +#if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx = 0 +#endif + ); void xWriteSEIScalabilityDimensionInfo (const SEIScalabilityDimensionInfo& sei); void xWriteSEIMultiviewAcquisitionInfo (const SEIMultiviewAcquisitionInfo& sei); void xWriteSEIAlphaChannelInfo (const SEIAlphaChannelInfo& sei); @@ -86,9 +106,25 @@ protected: void xWriteSEIContentLightLevelInfo(const SEIContentLightLevelInfo& sei); void xWriteSEIAmbientViewingEnvironment(const SEIAmbientViewingEnvironment& sei); void xWriteSEIContentColourVolume(const SEIContentColourVolume &sei); + +#if JVET_T0056_SEI_MANIFEST + //SEI manifest + void xWriteSEIManifest(const SEIManifest &sei); +#endif +#if JVET_T0056_SEI_PREFIX_INDICATION + //SEI prefix indication + void xWriteSEIPrefixIndication(OutputBitstream &bs, const SEIPrefixIndication &sei, HRD &hrd, const uint32_t temporalId); + int getUESENumBits(std::string str, int codeNum); + void xWriteSPIByteAlign(); +#endif + void xWriteSEIColourTransformInfo(const SEIColourTransformInfo& sei); void xWriteSEIAnnotatedRegions (const SEIAnnotatedRegions& sei); - void xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &hrd, const uint32_t temporalId); + void xWriteSEIpayloadData(OutputBitstream &bs, const SEI& sei, HRD &hrd, const uint32_t temporalId + #if JVET_T0056_SEI_PREFIX_INDICATION + , int SEIPrefixIndicationIdx = 0 +#endif + ); void xWriteByteAlign(); protected: HRD m_nestingHrd; -- GitLab