diff --git a/cfg/sei_vui/source_picture_timing_info.cfg b/cfg/sei_vui/source_picture_timing_info.cfg new file mode 100644 index 0000000000000000000000000000000000000000..c7078fe0145949de8d181ba95dbee34b22550a54 --- /dev/null +++ b/cfg/sei_vui/source_picture_timing_info.cfg @@ -0,0 +1,6 @@ +#======== Source Picture Timing Information SEI message ===================== +SEISourcePictureTimingInfo : 1 +SEISPTISourceTimingEqualsOutputTimingFlag : 0 +SEISPTISourceType : 0 +SEISPTITimeScale : 27000000 +SEISPTINumUnitsInElementalInterval : 1080000 \ No newline at end of file diff --git a/doc/software-manual.tex b/doc/software-manual.tex index 490e9016e7a6db4abef2541b2a829a263498857a..58190b6459691245eeacbd7f83167bfb10f8fb12 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -3978,6 +3978,7 @@ The table below lists the SEI messages defined for Version 1 and Range-Extension 211 & Neural netowrk post-filter activation & Table \ref{tab:sei-nn-post-filter-activation} \\ 212 & Phase indication & Table \ref{tab:sei-phase-indication} \\ 213 & Processing order SEI messages & Table \ref{tab:sei-processing order}\\ + 215 & Source Picture Timing Information & Table \ref{tab:sei-source-picture-timing-info}\\ \end{SEIListTable} %% %% SEI messages @@ -6082,6 +6083,28 @@ Specifies type of information the of privacy protection optimization that is app \\ \end{OptionTableNoShorthand} +\begin{OptionTableNoShorthand}{Source picture timing information SEI message encoder parameters}{tab:sei-source-picture-timing-info} +\Option{SEISourcePictureTimingInfo} & +\Default{false} & +Enables (true) or disables (false) the insertion of Source picture timing information SEI message. +\\ +\Option{SEISPTISourceTimingEqualsOutputTimingFlag} & +\Default{true} & +Indicates the timing of source pictures is the same as the timing of corresponding decoded output pictures(true) or indicates the timing of source pictures might not be the same as the timing of corresponding decoded output pictures(false). +\\ +\Option{SEISPTISourceType} & +\Default{0} & +Indicates the timing relationship between source pictures and corresponding decoded output pictures. +\\ +\Option{SEISPTITimeScale} & +\Default{27000000} & +Specifies the number of time units that pass in one second. +\\ +\Option{SEISPTINumUnitsInElementalInterval} & +\Default{1080000} & +Specifies the number of time units of a clock operating at the frequency spti_time_scale Hz that corresponds to the indicated elemental source picture interval of consecutive pictures in output order in the CLVS. +\\ +\end{OptionTableNoShorthand} %\Option{SEITimeCode} & %\Default{false} & %When true, generate time code SEI messages. diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 7b933585adeb07fbe41a1246c4794793d4bde983..dfafd548a28545b3ca9581e61d20f4024db19200 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1397,6 +1397,18 @@ void EncApp::xInitLibCfg( int layerIdx ) m_cEncLib.setPoSEIEnabled (m_poSEIEnabled); m_cEncLib.setPoSEIId (m_poSEIId); + +#if JVET_AG2034_SPTI_SEI + m_cEncLib.setSptiSEIEnabled(m_sptiSEIEnabled); + if (m_sptiSEIEnabled) + { + m_cEncLib.setmSptiSEISourceTimingEqualsOutputTimingFlag(m_sptiSourceTimingEqualsOutputTimingFlag); + m_cEncLib.setmSptiSEISourceType(m_sptiSourceType); + m_cEncLib.setmSptiSEITimeScale(m_sptiTimeScale); + m_cEncLib.setmSptiSEINumUnitsInElementalInterval(m_sptiNumUnitsInElementalInterval); + } +#endif + m_cEncLib.setPoSEINumMinus2 (m_poSEINumMinus2); m_cEncLib.setPoSEIWrappingFlag (m_poSEIWrappingFlag); m_cEncLib.setPoSEIImportanceFlag (m_poSEIImportanceFlag); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 7176d2fc81a6bad3c6616e86ca2ac4c3b713de3d..38966e4cfee66ce2d9e72d25537a6ca71d4f3586 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1460,6 +1460,13 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("SEISiiTimeScale", m_siiSEITimeScale, 27000000u, "Specifies sii_time_scale") ("SEISiiInputNumUnitsInShutterInterval", cfg_siiSEIInputNumUnitsInSI, cfg_siiSEIInputNumUnitsInSI, "Specifies sub_layer_num_units_in_shutter_interval") +#if JVET_AG2034_SPTI_SEI +("SEISourcePictureTimingInfo", m_sptiSEIEnabled, false, "Controls if source picture timing information SEI message is enabled") +("SEISPTISourceTimingEqualsOutputTimingFlag", m_sptiSourceTimingEqualsOutputTimingFlag, true, "Indicates the timing of source pictures is the same as the timing of corresponding decoded output pictures") +("SEISPTISourceType", m_sptiSourceType, 0u, "Indicates the timing relationship between source pictures and corresponding decoded output pictures.") +("SEISPTITimeScale", m_sptiTimeScale, 27000000u, "Specifies the number of time units that pass in one second.") +("SEISPTINumUnitsInElementalInterval", m_sptiNumUnitsInElementalInterval, 1080000u, "Specifies the number of time units of a clock operating at the frequency spti_time_scale Hz that corresponds to the indicated elemental source picture interval of consecutive pictures in output order in the CLVS.") +#endif #if ENABLE_TRACING ("TraceChannelsList", bTracingChannelsList, false, "List all available tracing channels") ("TraceRule", sTracingRule, std::string(""), "Tracing rule (ex: \"D_CABAC:poc==8\" or \"D_REC_CB_LUMA:poc==8\")") diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index b435d25183338273081eb6f6eafa1428ec2a1e98..4aeb297123293bf4a3194135b0b2608e6c03ef4e 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -941,6 +941,13 @@ protected: std::string m_shutterIntervalPreFileName; ///< output Pre-Filtering video int m_SII_BlendingRatio; void setBlendingRatioSII(int value) { m_SII_BlendingRatio = value; } +#if JVET_AG2034_SPTI_SEI + bool m_sptiSEIEnabled; + bool m_sptiSourceTimingEqualsOutputTimingFlag; + uint32_t m_sptiSourceType; + uint32_t m_sptiTimeScale; + uint32_t m_sptiNumUnitsInElementalInterval; +#endif #if GREEN_METADATA_SEI_ENABLED public: std::string getGMFAFile (); diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index 6bd1aeefd2e37581a9905facc2eca3edcb87b338..75cc4c3007cb5f0d150d7d1468dfd85c2ca90039 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -483,6 +483,9 @@ static const std::map<SEI::PayloadType, const char *> payloadTypeStrings = { { SEI::PayloadType::NEURAL_NETWORK_POST_FILTER_ACTIVATION, "Neural network post-filter activation" }, { SEI::PayloadType::PHASE_INDICATION, "Phase Indication" }, { SEI::PayloadType::SEI_PROCESSING_ORDER, "SEI messages Processing order" }, +#if JVET_AG2034_SPTI_SEI + { SEI::PayloadType::SOURCE_PICTURE_TIMING_INFO, "Source picture timing info" }, +#endif }; const char *SEI::getSEIMessageString(SEI::PayloadType payloadType) @@ -507,6 +510,16 @@ SEIShutterIntervalInfo::SEIShutterIntervalInfo(const SEIShutterIntervalInfo& sei m_siiFixedSIwithinCLVS = sei.m_siiFixedSIwithinCLVS; m_siiSubLayerNumUnitsInSI = sei.m_siiSubLayerNumUnitsInSI; } +#if JVET_AG2034_SPTI_SEI +SEISourcePictureTimingInfo::SEISourcePictureTimingInfo(const SEISourcePictureTimingInfo& sei) +{ + m_sptiSEIEnabled = sei.m_sptiSEIEnabled; + m_sptiSourceTimingEqualsOutputTimingFlag = sei.m_sptiSourceTimingEqualsOutputTimingFlag; + m_sptiSourceType = sei.m_sptiSourceType; + m_sptiTimeScale = sei.m_sptiTimeScale; + m_sptiNumUnitsInElementalInterval = sei.m_sptiNumUnitsInElementalInterval; +} +#endif SEIProcessingOrderInfo::SEIProcessingOrderInfo(const SEIProcessingOrderInfo& sei) { diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index d786c4e04244efff8fc65000d1f77abd32204c2b..27cac5298724827f07ad59e34eeaf355aabf16af 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -104,6 +104,9 @@ public: #if JVET_AH2006_EOI_SEI ENCODER_OPTIMIZATION_INFO = 215, #endif +#if JVET_AG2034_SPTI_SEI + SOURCE_PICTURE_TIMING_INFO = 216, +#endif }; SEI() {} @@ -155,6 +158,29 @@ public: std::vector<unsigned> m_siiSubLayerNumUnitsInSI; }; +#if JVET_AG2034_SPTI_SEI +class SEISourcePictureTimingInfo : public SEI +{ +public: + PayloadType payloadType() const { return PayloadType::SOURCE_PICTURE_TIMING_INFO; } + SEISourcePictureTimingInfo() {} + + SEISourcePictureTimingInfo(const SEISourcePictureTimingInfo& sei); + virtual ~SEISourcePictureTimingInfo() {} + + bool m_sptiSEIEnabled; + bool m_sptiSourceTimingEqualsOutputTimingFlag; + uint32_t m_sptiSourceType; + uint32_t m_sptiTimeScale; + uint32_t m_sptiNumUnitsInElementalInterval; + bool m_sptiCancelFlag; + bool m_sptiPersistenceFlag; + bool m_sptiSourceTypePresentFlag; + uint32_t m_sptiMaxSublayersMinus1; + std::vector<uint32_t> m_sptiSublayerIntervalScaleFactor; + std::vector<bool> m_sptiSublayerSynthesizedPictureFlag; +}; +#endif class SEIProcessingOrderInfo : public SEI { public: diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 0271535d9aecfb4193ce142add4f897bf9d2d996..96b4c540d8c5afb0e92b7186e8506adfded2145c 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -62,8 +62,12 @@ + #define JVET_AF2032_NNPFC_APPLICATION_INFORMATION_SIGNALING 1 // JVET-AF2032: Conditionally signal application tag URI presence flag and tag URI in the NNPFC metadata extension +#define JVET_AG2034_SPTI_SEI 1 //JVET-AE0079, JVET-AF0055, JVET-AF0069, JVET-AF0097, JVET-AG0191, JVET-AG0188 + + //########### place macros to be be kept below this line ############### #define GDR_ENABLED 1 diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp index d70e5cb9126397af800bb1fc5581ae78df7c6b4c..19f2573d36d4d55b15e6cf53b6dbdbd91c829f36 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -547,6 +547,12 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType sei = new SEIEncoderOptimizationInfo; xParseSEIEncoderOptimizationInfo((SEIEncoderOptimizationInfo &)*sei, payloadSize, pDecodedMessageOutputStream); break; +#endif +#if JVET_AG2034_SPTI_SEI + case SEI::PayloadType::SOURCE_PICTURE_TIMING_INFO: + sei = new SEISourcePictureTimingInfo; + xParseSEISourcePictureTimingInfo((SEISourcePictureTimingInfo&) *sei, payloadSize, pDecodedMessageOutputStream); + break; #endif default: for (uint32_t i = 0; i < payloadSize; i++) @@ -3332,6 +3338,57 @@ void SEIReader::xParseSEIPostFilterHint(SEIPostFilterHint &sei, uint32_t payload } } +#if JVET_AG2034_SPTI_SEI +void SEIReader::xParseSEISourcePictureTimingInfo(SEISourcePictureTimingInfo& sei, uint32_t payloadSize, + std::ostream* pDecodedMessageOutputStream) +{ + uint32_t val; + output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize); + + sei_read_flag(pDecodedMessageOutputStream, val, "spti_cancel_flag"); + sei.m_sptiCancelFlag = val; + + if (!sei.m_sptiCancelFlag) + { + sei_read_flag(pDecodedMessageOutputStream, val, "spti_persistence_flag"); + sei.m_sptiPersistenceFlag = val; + + sei_read_flag(pDecodedMessageOutputStream, val, "spti_source_timing_equals_output_timing_flag"); + sei.m_sptiSourceTimingEqualsOutputTimingFlag = val; + + if (!sei.m_sptiSourceTimingEqualsOutputTimingFlag) + { + sei_read_flag(pDecodedMessageOutputStream, val, "spti_source_type_present_flag"); + sei.m_sptiSourceTypePresentFlag = val; + + if (sei.m_sptiSourceTypePresentFlag) + { + sei_read_code(pDecodedMessageOutputStream, 16, val, "spti_source_type"); + sei.m_sptiSourceType = val; + } + sei_read_code(pDecodedMessageOutputStream, 32, val, "spti_time_scale"); + sei.m_sptiTimeScale = val; + sei_read_code(pDecodedMessageOutputStream, 32, val, "spti_num_units_in_elemental_interval"); + sei.m_sptiNumUnitsInElementalInterval = val; + + if (sei.m_sptiPersistenceFlag) + { + sei_read_code(pDecodedMessageOutputStream, 3, val, "spti_max_sublayers_minus_1"); + sei.m_sptiMaxSublayersMinus1 = val; + } + + for (int i = 0; i <= sei.m_sptiMaxSublayersMinus1; i++) + { + sei_read_uvlc(pDecodedMessageOutputStream, val, "spti_sublayer_interval_scale_factor"); + sei.m_sptiSublayerIntervalScaleFactor.push_back(val); + sei_read_flag(pDecodedMessageOutputStream, val, "spti_sublayer_synthesized_picture_flag"); + sei.m_sptiSublayerSynthesizedPictureFlag.push_back(val); + } + } + } +} +#endif + #if JVET_S0257_DUMP_360SEI_MESSAGE void SeiCfgFileDump::write360SeiDump (std::string decoded360MessageFileName, SEIMessages& seis, const SPS* sps) { diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index e35547404db179f2771b0dd715b8af87d489f5df..47d52f2d50e7c809934da87fb15273f5316484fe 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -124,6 +124,10 @@ protected: void xParseSEIProcessingOrder(SEIProcessingOrderInfo& sei, const NalUnitType nalUnitType, const uint32_t nuhLayerId, uint32_t payloadSize, const VPS* vps, const SPS* sps, HRD& hrd, std::ostream* decodedMessageOutputStream); void xParseSEIProcessingOrderNesting(SEIProcessingOrderNesting& sei, const NalUnitType nalUnitType, const uint32_t nuhLayerId, uint32_t payloadSize, const VPS* vps, const SPS* sps, HRD& hrd, std::ostream* decodedMessageOutputStream); void xParseSEIPostFilterHint(SEIPostFilterHint &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); +#if JVET_AG2034_SPTI_SEI + void xParseSEISourcePictureTimingInfo(SEISourcePictureTimingInfo& 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 length, uint32_t &ruiCode, const char *pSymbolName); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 0df5442af348f194008d7043b277914f56643dc2..699df615bdb54eb1f5e4949749a0f3904035d053 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -690,6 +690,13 @@ protected: uint32_t m_siiSEINumUnitsInShutterInterval; uint32_t m_siiSEITimeScale; std::vector<uint32_t> m_siiSEISubLayerNumUnitsInSI; +#if JVET_AG2034_SPTI_SEI + bool m_sptiSEIEnabled; + bool m_sptiSourceTimingEqualsOutputTimingFlag; + uint32_t m_sptiSourceType; + uint32_t m_sptiTimeScale; + uint32_t m_sptiNumUnitsInElementalInterval; +#endif bool m_nnPostFilterSEICharacteristicsEnabled; bool m_nnPostFilterSEICharacteristicsUseSuffixSEI; @@ -1950,6 +1957,19 @@ public: void setSiiSEISubLayerNumUnitsInSI(const std::vector<uint32_t>& b) { m_siiSEISubLayerNumUnitsInSI = b; } uint32_t getSiiSEISubLayerNumUnitsInSI(uint32_t idx) const { return m_siiSEISubLayerNumUnitsInSI[idx]; } +#if JVET_AG2034_SPTI_SEI + void setSptiSEIEnabled(bool b) { m_sptiSEIEnabled = b; } + bool getSptiSEIEnabled() { return m_sptiSEIEnabled; } + void setmSptiSEISourceTimingEqualsOutputTimingFlag(bool b) { m_sptiSourceTimingEqualsOutputTimingFlag = b; } + bool getmSptiSEISourceTimingEqualsOutputTimingFlag() { return m_sptiSourceTimingEqualsOutputTimingFlag; } + void setmSptiSEISourceType(uint32_t b) { m_sptiSourceType = b; } + uint32_t getmSptiSEISourceType() { return m_sptiSourceType; } + void setmSptiSEITimeScale(uint32_t b) { m_sptiTimeScale = b; } + uint32_t getmSptiSEITimeScale() { return m_sptiTimeScale; } + void setmSptiSEINumUnitsInElementalInterval(uint32_t b) { m_sptiNumUnitsInElementalInterval = b; } + uint32_t getmSptiSEINumUnitsInElementalInterval() { return m_sptiNumUnitsInElementalInterval; } +#endif + void setNNPostFilterSEICharacteristicsEnabled(bool enabledFlag) { m_nnPostFilterSEICharacteristicsEnabled = enabledFlag; } bool getNNPostFilterSEICharacteristicsEnabled() const { return m_nnPostFilterSEICharacteristicsEnabled; } void setNNPostFilterSEICharacteristicsUseSuffixSEI(bool suffixFlag) { m_nnPostFilterSEICharacteristicsUseSuffixSEI = suffixFlag; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index fa672a7c8c238fb1b93c1e982f4824c15f4e0277..b2c280c7c438fd0659c2bf68835f5716962147cf 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -919,6 +919,14 @@ void EncGOP::xCreateIRAPLeadingSEIMessages (SEIMessages& seiMessages, const SPS m_seiEncoder.initSEIShutterIntervalInfo(seiShutterInterval); seiMessages.push_back(seiShutterInterval); } +#if JVET_AG2034_SPTI_SEI + if (m_pcCfg->getSptiSEIEnabled()) + { + SEISourcePictureTimingInfo* seiSourcePictureTimingInfo = new SEISourcePictureTimingInfo; + m_seiEncoder.initSEISourcePictureTimingInfo(seiSourcePictureTimingInfo); + seiMessages.push_back(seiSourcePictureTimingInfo); + } +#endif if (m_pcCfg->getNNPostFilterSEICharacteristicsEnabled() && !m_pcCfg->getNNPostFilterSEICharacteristicsUseSuffixSEI()) { xCreateNNPostFilterCharacteristicsSEIMessages(seiMessages); diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 22d9333b339dba9c127bb270ae5d591c9e40ce0b..71ab049bf5eed7ad546c818941d9e55e65e8eaf2 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -572,7 +572,33 @@ void SEIEncoder::initSEIShutterIntervalInfo(SEIShutterIntervalInfo *seiShutterIn } } } +#if JVET_AG2034_SPTI_SEI +void SEIEncoder::initSEISourcePictureTimingInfo(SEISourcePictureTimingInfo* SEISourcePictureTimingInfo) +{ + CHECK(!(m_isInitialized), "Source picture timing SEI already initialized"); + CHECK(!(SEISourcePictureTimingInfo != nullptr), "Need a SEISourcePictureTimingInfo for initialization (got nullptr)"); + + SEISourcePictureTimingInfo->m_sptiSEIEnabled = m_pcCfg->getSptiSEIEnabled(); + SEISourcePictureTimingInfo->m_sptiSourceTimingEqualsOutputTimingFlag = + m_pcCfg->getmSptiSEISourceTimingEqualsOutputTimingFlag(); + SEISourcePictureTimingInfo->m_sptiSourceType = m_pcCfg->getmSptiSEISourceType(); + SEISourcePictureTimingInfo->m_sptiTimeScale = m_pcCfg->getmSptiSEITimeScale(); + SEISourcePictureTimingInfo->m_sptiNumUnitsInElementalInterval = m_pcCfg->getmSptiSEINumUnitsInElementalInterval(); + SEISourcePictureTimingInfo->m_sptiMaxSublayersMinus1 = m_pcCfg->getMaxTempLayer() - 1; + SEISourcePictureTimingInfo->m_sptiCancelFlag = 0; + SEISourcePictureTimingInfo->m_sptiPersistenceFlag = 1; + SEISourcePictureTimingInfo->m_sptiSourceTypePresentFlag = (SEISourcePictureTimingInfo->m_sptiSourceType == 0 ? 0 : 1); + SEISourcePictureTimingInfo->m_sptiSublayerSynthesizedPictureFlag = + std::vector<bool>(SEISourcePictureTimingInfo->m_sptiMaxSublayersMinus1 + 1, 0); + + for (int i = 0; i <= SEISourcePictureTimingInfo->m_sptiMaxSublayersMinus1; i++) + { + SEISourcePictureTimingInfo->m_sptiSublayerIntervalScaleFactor.push_back( + 1 << (SEISourcePictureTimingInfo->m_sptiMaxSublayersMinus1 - i)); + } +} +#endif void SEIEncoder::initSEIProcessingOrderInfo(SEIProcessingOrderInfo *seiProcessingOrderInfo, SEIProcessingOrderNesting *seiProcessingOrderNesting) { assert(m_isInitialized); diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h index 6cd2e28e8ae6e44800086b85d8a020c6fc3fd5c7..bbc2a3dbe448afba45213c2ca1a1dd4102c2eaef 100644 --- a/source/Lib/EncoderLib/SEIEncoder.h +++ b/source/Lib/EncoderLib/SEIEncoder.h @@ -93,6 +93,9 @@ public: void initSEISEIManifest(SEIManifest *seiSeiManifest, const SEIMessages &seiMessage); void initSEISEIPrefixIndication(SEIPrefixIndication *seiSeiPrefixIndications, const SEI *sei); +#if JVET_AG2034_SPTI_SEI + void initSEISourcePictureTimingInfo(SEISourcePictureTimingInfo* SEISourcePictureTimingInfo); +#endif void initSEIMultiviewViewPosition(SEIMultiviewViewPosition *sei); void initSEIShutterIntervalInfo(SEIShutterIntervalInfo *sei); void initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkPostFilterCharacteristics *sei, int filterIdx); diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index 9fc717505637f39394be7f903a293b98ad876ffa..c3417c5a34d6e5a7aa9d8cc7e5817effa330d09b 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -196,6 +196,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI &sei, HRD &h xWriteSEIEncoderOptimizationInfo(*static_cast<const SEIEncoderOptimizationInfo *>(&sei)); break; #endif +#if JVET_AG2034_SPTI_SEI + case SEI::PayloadType::SOURCE_PICTURE_TIMING_INFO: + xWriteSEISourcePictureTimingInfo(*static_cast<const SEISourcePictureTimingInfo*>(&sei)); + break; +#endif default: THROW("Trying to write unhandled SEI message"); break; @@ -1977,7 +1982,6 @@ void SEIWriter::xWriteSEIPostFilterHint(const SEIPostFilterHint &sei) } } } - #if JVET_AH2006_EOI_SEI void SEIWriter::xWriteSEIEncoderOptimizationInfo(const SEIEncoderOptimizationInfo &sei) { @@ -2012,4 +2016,40 @@ void SEIWriter::xWriteSEIEncoderOptimizationInfo(const SEIEncoderOptimizationInf } } #endif +#if JVET_AG2034_SPTI_SEI +void SEIWriter::xWriteSEISourcePictureTimingInfo(const SEISourcePictureTimingInfo& sei) +{ + xWriteFlag(sei.m_sptiCancelFlag, "spti_cancel_flag"); + + if (!sei.m_sptiCancelFlag) + { + xWriteFlag(sei.m_sptiPersistenceFlag, "spti_persistance_flag"); + xWriteFlag(sei.m_sptiSourceTimingEqualsOutputTimingFlag, "spti_source_timing_equals_output_timing_flag"); + + if (!sei.m_sptiSourceTimingEqualsOutputTimingFlag) + { + xWriteFlag(sei.m_sptiSourceTypePresentFlag, "spti_source_type_present_flag"); + + if (sei.m_sptiSourceTypePresentFlag) + { + xWriteCode(sei.m_sptiSourceType, 16, "spti_source_type"); + } + + xWriteCode(sei.m_sptiTimeScale, 32, "spti_time_scale"); + xWriteCode(sei.m_sptiNumUnitsInElementalInterval, 32, "spti_num_units_in_elemental_interval"); + + if (sei.m_sptiPersistenceFlag) + { + xWriteCode(sei.m_sptiMaxSublayersMinus1, 3, "spti_max_sublayers_minus_1"); + } + + for (int i = 0; i <= sei.m_sptiMaxSublayersMinus1; i++) + { + xWriteUvlc(sei.m_sptiSublayerIntervalScaleFactor[i], "spti_sublayer_interval_scale_factor"); + xWriteFlag(sei.m_sptiSublayerSynthesizedPictureFlag[i], "spti_sublayer_synthesized_picture_flag"); + } + } + } +} +#endif //! \} diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h index 7b18c32ce4c52b64211100acb9cd715eeb5ff201..1052b24a1f47dd77e9761ae8a36aeb21357cb99b 100644 --- a/source/Lib/EncoderLib/SEIwrite.h +++ b/source/Lib/EncoderLib/SEIwrite.h @@ -114,9 +114,13 @@ protected: void xWriteSEIGreenMetadataInfo (const SEIGreenMetadataInfo &sei); #endif void xWriteSEIPostFilterHint(const SEIPostFilterHint &sei); + #if JVET_AH2006_EOI_SEI void xWriteSEIEncoderOptimizationInfo(const SEIEncoderOptimizationInfo &sei); #endif +#if JVET_AG2034_SPTI_SEI + void xWriteSEISourcePictureTimingInfo(const SEISourcePictureTimingInfo& sei); +#endif protected: HRD m_nestingHrd; };