diff --git a/cfg/sei_vui/ai_marker_info.cfg b/cfg/sei_vui/ai_marker_info.cfg new file mode 100644 index 0000000000000000000000000000000000000000..1d8a20d8a3bc8a33baaa055ec009512d6fb90cb6 --- /dev/null +++ b/cfg/sei_vui/ai_marker_info.cfg @@ -0,0 +1,6 @@ +#======== Exif metadata SEI message ===================== +SEIAIMarkerEnabled : 1 # enable to use AI Marker SEI message. +SEIAIMarkerCancelFlag : 0 # to cancel an active AI Marker SEI message +SEIAIMarkerPersistenceFlag : 1 # to enable persistence beyond a single picture; otherwise 0 for per-picture persistence +SEIAIMarkerInfo : The pictures in this video were created or edited using AI technology + diff --git a/doc/software-manual.tex b/doc/software-manual.tex index d0945d53f721a3f7a6ef3216d691ce4acc28ea33..7f54fa5b65ff76cbf6c4c794092437595f500cb0 100644 --- a/doc/software-manual.tex +++ b/doc/software-manual.tex @@ -3994,6 +3994,7 @@ The table below lists the SEI messages defined for Version 1 and Range-Extension 213 & Processing order SEI messages & Table \ref{tab:sei-processing order}\\ 215 & Multiplane image information & Table \ref{tab:sei-mpii}\\ TDB & Copyright information & Table \ref{tab:sei-ci}\\ + TDB & AI marking & Table \ref{tab:sei-ai}\\ \end{SEIListTable} %% %% SEI messages @@ -6235,6 +6236,25 @@ An example file can be found in cfg/sei_vui/object_mask_infos/intra/mask_info_0. \\ \end{OptionTableNoShorthand} +\begin{OptionTableNoShorthand}{AI marking SEI message encoder parameters}{tab:sei-ai} + \Option{SEIAIMarkerEnabled} & + \Default{false} & + Enables (true) or disables (false) the insertion of AI marking SEI message. + \\ + \Option{SEIAIMarkerCancelFlag} & + \Default{false} & + Indicates that the AI marking SEI message cancels the persistence (true) or follows (false). + \\ + \Option{SEIAIMarkerPersistenceFlag} & + \Default{false} & + Specifies the persistence of the AI marking SEI message for the current layer. + \\ + \Option{SEIAIMarkerInfo} & + \Default{} & + Specifies AI marking information string. + \\ +\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 2d0911fb0112742174153df67a43f10f3d2cc0d3..255b70eddb51ca9aa3134381a97879ed6cb14961 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1378,6 +1378,12 @@ void EncApp::xInitLibCfg( int layerIdx ) m_cEncLib.setCopyrightInfoSEICancelFlag ( m_copyrightCancelFlag ); m_cEncLib.setCopyrightInfoSEIPersistenceFlag ( m_copyrightPersistenceFlag ); #endif +#if JVET_AG0045_AI_MARKER_SEI + m_cEncLib.setAIMarkerInfoSEIEnabled (m_aiMarkerSeiEnabled); + m_cEncLib.setAIMarkerInfoSEIAIMarkerInfoData(m_aiMarkerInfoData); + m_cEncLib.setAIMarkerInfoSEICancelFlag (m_aiMarkerCancelFlag); + m_cEncLib.setAIMarkerInfoSEIPersistenceFlag (m_aiMarkerPersistenceFlag); +#endif m_cEncLib.setPoSEIEnabled (m_poSEIEnabled); m_cEncLib.setPoSEINumMinus2 (m_poSEINumMinus2); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 05012b4f6e3b08a0f15666efafe92d08833b459d..771caf93f27c1207a243f35ac9c1b7bed2bee4c5 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -2005,6 +2005,15 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) opts.addOptions()("SEICopyrightPersistenceFlag", m_copyrightPersistenceFlag, false, "Specifies that Copyright SEI persists beyond the scope of a single picture"); opts.addOptions()("SEICopyrightInfo", m_copyrightInfoData, std::string(""), "The Copyright message to be stored in the SEI"); #endif +#if JVET_AG0045_AI_MARKER_SEI + opts.addOptions()("SEIAIMarkerEnabled", m_aiMarkerSeiEnabled, false, "Specifies if AI marker info SEI is active"); + opts.addOptions()("SEIAIMarkerCancelFlag", m_aiMarkerCancelFlag, false, + "Specifies if AI marker info SEI should be cancelled"); + opts.addOptions()("SEIAIMarkerPersistenceFlag", m_aiMarkerPersistenceFlag, false, + "Specifies that AI marker SEI persists beyond the scope of a single picture"); + opts.addOptions()("SEIAIMarkerInfo", m_aiMarkerInfoData, std::string(""), + "The AI marker message to be stored in the SEI"); +#endif po::setDefaults(opts); po::ErrorReporter err; diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 781aae3f0b37ce0390572c79da99225792e572e8..c8cd2948c5cb2cc3891bf7e5d60a3312275f2ad1 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -1084,6 +1084,12 @@ protected: bool m_copyrightPersistenceFlag; std::string m_copyrightInfoData; #endif +#if JVET_AG0045_AI_MARKER_SEI + bool m_aiMarkerSeiEnabled; + bool m_aiMarkerCancelFlag; + bool m_aiMarkerPersistenceFlag; + std::string m_aiMarkerInfoData; +#endif // internal member functions bool xCheckParameter (); ///< check validity of configuration values diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp index 2c54223e29086296a779bdf6fe39ed433d931c0e..4ae8024001af12c612745ad599c10b30070a523f 100644 --- a/source/Lib/CommonLib/SEI.cpp +++ b/source/Lib/CommonLib/SEI.cpp @@ -541,6 +541,9 @@ static const std::map<SEI::PayloadType, const char *> payloadTypeStrings = { #if JVET_AG0044_COPYRIGHT_SEI { SEI::PayloadType::COPYRIGHT_INFO, "Copyright information" }, #endif +#if JVET_AG0045_AI_MARKER_SEI + { SEI::PayloadType::AI_MARKER_INFO, "AI marker information" }, +#endif }; const char *SEI::getSEIMessageString(SEI::PayloadType payloadType) @@ -1275,3 +1278,11 @@ SEICopyrightInfo::SEICopyrightInfo(const SEICopyrightInfo& sei) m_copyrightInfoData = sei.m_copyrightInfoData; } #endif +#if JVET_AG0045_AI_MARKER_SEI +SEIAIMarkerInfo::SEIAIMarkerInfo(const SEIAIMarkerInfo& sei) +{ + m_persistenceFlag = sei.m_persistenceFlag; + m_cancelFlag = sei.m_cancelFlag; + m_aiMarkerInfoData = sei.m_aiMarkerInfoData; +} +#endif diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h index b0d530d6262afb997ff37fbbd5787a170e89bd69..b3b874625cfb38b8ca1b44a7eee27bdb2f3a756d 100644 --- a/source/Lib/CommonLib/SEI.h +++ b/source/Lib/CommonLib/SEI.h @@ -106,6 +106,9 @@ public: #if JVET_AG0044_COPYRIGHT_SEI COPYRIGHT_INFO, // value to be confirmed by JVET #endif +#if JVET_AG0045_AI_MARKER_SEI + AI_MARKER_INFO, // value to be confirmed by JVET +#endif #if JVET_AF0167_MULTI_PLANE_IMAGE_INFO_SEI MULTIPLANE_IMAGE_INFO, // payload_type value TBD #endif @@ -1490,3 +1493,19 @@ public: std::string m_copyrightInfoData; }; #endif +#if JVET_AG0045_AI_MARKER_SEI +class SEIAIMarkerInfo : public SEI +{ +public: + PayloadType payloadType() const { return PayloadType::AI_MARKER_INFO; } + + SEIAIMarkerInfo() : m_persistenceFlag(false), m_cancelFlag(false), m_aiMarkerInfoData("") {} + SEIAIMarkerInfo(const SEIAIMarkerInfo& sei); + + virtual ~SEIAIMarkerInfo() {} + + bool m_persistenceFlag; + bool m_cancelFlag; + std::string m_aiMarkerInfoData; +}; +#endif diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 286f0e5aeb66bfd641a63da9b7a50f814d72e6b1..a4debbbd0ba6d80aea8650d5e71f2054567aa27a 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -76,6 +76,8 @@ #define JVET_AG0044_COPYRIGHT_SEI 1 +#define JVET_AG0045_AI_MARKER_SEI 1 + //########### 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 497e04c1147c0264e4d81ff2157ff9942f106996..d31887cab2717bff618c7b17da262ca964e98e6f 100644 --- a/source/Lib/DecoderLib/SEIread.cpp +++ b/source/Lib/DecoderLib/SEIread.cpp @@ -550,6 +550,12 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType sei = new SEICopyrightInfo(); xParseSEICopyrightInfo((SEICopyrightInfo &) *sei, payloadSize, pDecodedMessageOutputStream); break; +#endif +#if JVET_AG0045_AI_MARKER_SEI + case SEI::PayloadType::AI_MARKER_INFO: + sei = new SEIAIMarkerInfo(); + xParseSEIAIMarkerInfo((SEIAIMarkerInfo &) *sei, payloadSize, pDecodedMessageOutputStream); + break; #endif default: for (uint32_t i = 0; i < payloadSize; i++) @@ -3773,4 +3779,23 @@ void SEIReader::xParseSEICopyrightInfo(SEICopyrightInfo& sei, uint32_t payLoadSi } } #endif +#if JVET_AG0045_AI_MARKER_SEI +void SEIReader::xParseSEIAIMarkerInfo(SEIAIMarkerInfo& sei, uint32_t payLoadSize, + std::ostream* pDecodedMessageOutputStream) +{ + output_sei_message_header(sei, pDecodedMessageOutputStream, payLoadSize); + uint32_t val; + sei_read_flag(pDecodedMessageOutputStream, val, "ai_marker_cancel_flag"); + sei.m_cancelFlag = val; + if (!sei.m_cancelFlag) + { + sei_read_flag(pDecodedMessageOutputStream, val, "ai_marker_persistence_flag"); + sei.m_persistenceFlag = val; + + std::string info; + sei_read_string(pDecodedMessageOutputStream, info, "ai_mark_information"); + sei.m_aiMarkerInfoData = info; + } +} +#endif //! \} diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h index f907d720621c0730c2c6e3d42dadecd166bf3b10..45f5ff109534cf8b318381e3d14a0e8748ec5ebc 100644 --- a/source/Lib/DecoderLib/SEIread.h +++ b/source/Lib/DecoderLib/SEIread.h @@ -121,6 +121,9 @@ protected: void xParseSEIPhaseIndication(SEIPhaseIndication& sei, uint32_t payloadSize, std::ostream* pDecodedMessageOutputStream); 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 xParseSEIPostFilterHint(SEIPostFilterHint &sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream); +#if JVET_AG0045_AI_MARKER_SEI + void xParseSEIAIMarkerInfo (SEIAIMarkerInfo & sei,uint32_t payLoadSize, std::ostream *pDecodedMessageOutputStream); +#endif #if JVET_AG0044_COPYRIGHT_SEI void xParseSEICopyrightInfo(SEICopyrightInfo & sei,uint32_t payLoadSize, std::ostream *pDecodedMessageOutputStream); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index e25008a9c9052767d77149627faf7fa5b1e4e051..b4b402fc63511241fa3d0ede854cd9cc0a096f17 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -923,6 +923,13 @@ protected: std::string m_copyrightInfoSEIData; #endif +#if JVET_AG0045_AI_MARKER_SEI + bool m_aiMarkerInfoSEIEnabled; + bool m_aiMarkerInfoSEICancelFlag; + bool m_aiMarkerInfoSEIPersistenceFlag; + std::string m_aiMarkerInfoSEIData; +#endif + bool m_constrainedRaslEncoding; //====== Weighted Prediction ======== @@ -2654,6 +2661,16 @@ public: std::string getCopyrightInfoSEICopyrightInfoData() { return m_copyrightInfoSEIData; } void setCopyrightInfoSEICopyrightInfoData(std::string s) { m_copyrightInfoSEIData = s; } #endif +#if JVET_AG0045_AI_MARKER_SEI + bool getAIMarkerInfoSEIEnabled() const { return m_aiMarkerInfoSEIEnabled; } + void setAIMarkerInfoSEIEnabled(bool b) { m_aiMarkerInfoSEIEnabled = b; } + bool getAIMarkerInfoSEICancelFlag() const { return m_aiMarkerInfoSEICancelFlag; } + void setAIMarkerInfoSEICancelFlag(bool b) { m_aiMarkerInfoSEICancelFlag = b; } + bool getAIMarkerInfoSEIPersistenceFlag() const { return m_aiMarkerInfoSEIPersistenceFlag; } + void setAIMarkerInfoSEIPersistenceFlag(bool b) { m_aiMarkerInfoSEIPersistenceFlag = b; } + std::string getAIMarkerInfoSEIAIMarkerInfoData() { return m_aiMarkerInfoSEIData; } + void setAIMarkerInfoSEIAIMarkerInfoData(std::string s) { m_aiMarkerInfoSEIData = s; } +#endif void setUseWP ( bool b ) { m_useWeightedPred = b; } void setWPBiPred ( bool b ) { m_useWeightedBiPred = b; } diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index 7e6307e15fcb58b253716d7aef3820377e9dd362..4ba140a1b4d0a30e30355c3ca81140c2627652ad 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -1056,11 +1056,21 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage if (m_pcCfg->getCopyrightInfoSEIEnabled()) { SEICopyrightInfo *pCopyrightSEI = new SEICopyrightInfo; - + m_seiEncoder.initSEICopyrightInfo(pCopyrightSEI); seiMessages.push_back(pCopyrightSEI); } #endif + +#if JVET_AG0045_AI_MARKER_SEI + if (m_pcCfg->getAIMarkerInfoSEIEnabled()) + { + SEIAIMarkerInfo *pAIMarkerSEI = new SEIAIMarkerInfo; + + m_seiEncoder.initSEIAIMarkerInfo(pAIMarkerSEI); + seiMessages.push_back(pAIMarkerSEI); + } +#endif } void EncGOP::xCreateNNPostFilterCharacteristicsSEIMessages(SEIMessages& seiMessages) diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp index 589741e535b5f6b6273355c400f31cf6d49e4414..78f9c22bb099f9531d712f3ac342f3570965ca43 100644 --- a/source/Lib/EncoderLib/SEIEncoder.cpp +++ b/source/Lib/EncoderLib/SEIEncoder.cpp @@ -1819,5 +1819,16 @@ void SEIEncoder::initSEICopyrightInfo(SEICopyrightInfo *sei) sei->m_copyrightInfoData = m_pcCfg->getCopyrightInfoSEICopyrightInfoData(); } #endif +#if JVET_AG0045_AI_MARKER_SEI +void SEIEncoder::initSEIAIMarkerInfo(SEIAIMarkerInfo* sei) +{ + CHECK(!m_isInitialized, "AI marker information SEI already initialized"); + CHECK(sei == nullptr, "Need a SEICopyrightInfo for initialization (got nullptr)"); + + sei->m_persistenceFlag = m_pcCfg->getAIMarkerInfoSEIPersistenceFlag(); + sei->m_cancelFlag = m_pcCfg->getAIMarkerInfoSEICancelFlag(); + sei->m_aiMarkerInfoData = m_pcCfg->getAIMarkerInfoSEIAIMarkerInfoData(); +} +#endif //! \} diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h index 3748916387e7eda78624ef7416e29226f63e5c7c..26e2849975537aeeb69fcadd11a924fe82ce7b02 100644 --- a/source/Lib/EncoderLib/SEIEncoder.h +++ b/source/Lib/EncoderLib/SEIEncoder.h @@ -113,6 +113,9 @@ public: void initSEICopyrightInfo(SEICopyrightInfo *sei); #endif +#if JVET_AG0045_AI_MARKER_SEI + void initSEIAIMarkerInfo(SEIAIMarkerInfo *sei); +#endif private: EncCfg* m_pcCfg; EncLib* m_pcEncLib; diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp index 336d2d874dd68956729046dd8fe01b274006cdcc..00634e05808962937200239724f2726d6381fc3d 100644 --- a/source/Lib/EncoderLib/SEIwrite.cpp +++ b/source/Lib/EncoderLib/SEIwrite.cpp @@ -202,6 +202,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI &sei, HRD &h case SEI::PayloadType::COPYRIGHT_INFO: xWriteSEICopyrightInfo(*static_cast<const SEICopyrightInfo*>(&sei)); break; +#endif +#if JVET_AG0045_AI_MARKER_SEI + case SEI::PayloadType::AI_MARKER_INFO: + xWriteSEIAIMarkerInfo(*static_cast<const SEIAIMarkerInfo*>(&sei)); + break; #endif default: THROW("Trying to write unhandled SEI message"); @@ -1702,6 +1707,17 @@ void SEIWriter::xWriteSEICopyrightInfo(const SEICopyrightInfo& sei) } } #endif +#if JVET_AG0045_AI_MARKER_SEI +void SEIWriter::xWriteSEIAIMarkerInfo(const SEIAIMarkerInfo& sei) +{ + xWriteFlag(sei.m_cancelFlag, "ai_marker_cancel_flag"); + if (!sei.m_cancelFlag) + { + xWriteFlag(sei.m_persistenceFlag, "ai_marker_persistence_flag"); + xWriteString(sei.m_aiMarkerInfoData, "ai_mark_information"); + } +} +#endif void SEIWriter::xWriteSEIProcessingOrder(OutputBitstream& bs, const SEIProcessingOrderInfo& sei) { diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h index 12fafa8c33621c47977a252ed921c2047d0fd13a..a79bcdf636d5c9d564d4dec650cbd1bec108d42b 100644 --- a/source/Lib/EncoderLib/SEIwrite.h +++ b/source/Lib/EncoderLib/SEIwrite.h @@ -121,6 +121,9 @@ protected: #if JVET_AG0044_COPYRIGHT_SEI void xWriteSEICopyrightInfo(const SEICopyrightInfo &sei); #endif +#if JVET_AG0045_AI_MARKER_SEI + void xWriteSEIAIMarkerInfo(const SEIAIMarkerInfo &sei); +#endif protected: HRD m_nestingHrd; };