From 213cae31b1c65ebbad16ba300be130ea0fc5c865 Mon Sep 17 00:00:00 2001
From: Hendry <hendry197@gmail.com>
Date: Sat, 15 Jun 2024 11:56:31 -0700
Subject: [PATCH] Implementation of Encoder Optimization Information SEI
 message that is currently in JVET-AH2006

---
 cfg/sei_vui/encoder_optimization_info.cfg | 14 ++++++
 source/App/EncoderApp/EncApp.cpp          | 14 ++++++
 source/App/EncoderApp/EncAppCfg.cpp       | 16 +++++++
 source/App/EncoderApp/EncAppCfg.h         | 15 +++++++
 source/Lib/CommonLib/SEI.cpp              | 20 +++++++++
 source/Lib/CommonLib/SEI.h                | 41 ++++++++++++++++++
 source/Lib/CommonLib/TypeDef.h            | 15 +++++++
 source/Lib/DecoderLib/SEIread.cpp         | 53 +++++++++++++++++++++++
 source/Lib/DecoderLib/SEIread.h           |  3 ++
 source/Lib/EncoderLib/EncCfg.h            | 42 ++++++++++++++++++
 source/Lib/EncoderLib/EncGOP.cpp          |  9 ++++
 source/Lib/EncoderLib/SEIEncoder.cpp      | 34 +++++++++++++++
 source/Lib/EncoderLib/SEIEncoder.h        |  3 ++
 source/Lib/EncoderLib/SEIwrite.cpp        | 40 +++++++++++++++++
 source/Lib/EncoderLib/SEIwrite.h          |  3 ++
 15 files changed, 322 insertions(+)
 create mode 100644 cfg/sei_vui/encoder_optimization_info.cfg

diff --git a/cfg/sei_vui/encoder_optimization_info.cfg b/cfg/sei_vui/encoder_optimization_info.cfg
new file mode 100644
index 000000000..73b4f601b
--- /dev/null
+++ b/cfg/sei_vui/encoder_optimization_info.cfg
@@ -0,0 +1,14 @@
+#========Encoder Optimization Information SEI message =====================
+
+SEIEOIEnabled:           1
+SEIEOICancelFlag:          0
+SEIEOIPersistenceFlag:          1
+SEIEOIForHumanViewingIdc:          1
+SEIEOIForMachineAnalysisIdc:          3
+SEIEOIType:          39
+SEIEOIObjectBasedIdc: 1
+SEIEOITemporalResamplingTypeFlag: 1
+SEIEOINumIntPics: 4
+SEIEOISpatialResamplingTypeFlag: 1
+SEIEOIPrivacyProtectionTypeIdc: 3
+SEIEOIPrivacyProtectedInfoType: 3
\ No newline at end of file
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index b468c425e..9f848f1f8 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1112,6 +1112,20 @@ void EncApp::xInitLibCfg( int layerIdx )
   {
     m_cEncLib.setCtiSEILut(m_ctiSEILut[i], i);
   }
+#if JVET_AH2006_EOI_SEI
+  m_cEncLib.setEOISEIEnabled(m_eoiSEIEnabled);
+  m_cEncLib.setEOISEICancelFlag(m_eoiSEICancelFlag);
+  m_cEncLib.setEOISEIPersistenceFlag(m_eoiSEIPersistenceFlag);
+  m_cEncLib.setEOISEIForHumanViewingIdc(m_eoiSEIForHumanViewingIdc);
+  m_cEncLib.setEOISEIForMachineAnalysisIdc(m_eoiSEIForMachineAnalysisIdc);
+  m_cEncLib.setEOISEIType(m_eoiSEIType);
+  m_cEncLib.setEOISEIObjectBasedIdc(m_eoiSEIObjectBasedIdc);
+  m_cEncLib.setEOISEITemporalResamplingTypeFlag(m_eoiSEITemporalResamplingTypeFlag);
+  m_cEncLib.setEOISEINumIntPics(m_eoiSEINumIntPics);
+  m_cEncLib.setEOISEISpatialResamplingTypeFlag(m_eoiSEISpatialResamplingTypeFlag);
+  m_cEncLib.setEOISEIPrivacyProtectionTypeIdc(m_eoiSEIPrivacyProtectionTypeIdc);
+  m_cEncLib.setEOISEIPrivacyProtectedInfoType(m_eoiSEIPrivacyProtectedInfoType);
+#endif
   // content colour volume SEI
   m_cEncLib.setCcvSEIEnabled                                     (m_ccvSEIEnabled);
   m_cEncLib.setCcvSEICancelFlag                                  (m_ccvSEICancelFlag);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index f21df7f73..7a67427a8 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1465,6 +1465,22 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 ("TraceRule", sTracingRule, std::string(""), "Tracing rule (ex: \"D_CABAC:poc==8\" or \"D_REC_CB_LUMA:poc==8\")")
 ("TraceFile", sTracingFile, std::string(""), "Tracing file")
 #endif
+
+#if JVET_AH2006_EOI_SEI
+("SEIEOIEnabled", m_eoiSEIEnabled, false, "Control use of the Encoder Optimization Information SEI")
+("SEIEOICancelFlag", m_eoiSEICancelFlag, false, "Specifies that the persistence of the previous applied optimization")
+("SEIEOIPersistenceFlag", m_eoiSEIPersistenceFlag, false, "Specifies the persistence of the optimization the current layer")
+("SEIEOIForHumanViewingIdc", m_eoiSEIForHumanViewingIdc, 0u, "Indicates the level of optimization for human viewing")
+("SEIEOIForMachineAnalysisIdc", m_eoiSEIForMachineAnalysisIdc, 0u, "Indicates the level of optimization for  machine analsysis")
+("SEIEOIType", m_eoiSEIType, 0u, "Indicates the types of optimization method")
+("SEIEOIObjectBasedIdc", m_eoiSEIObjectBasedIdc, 0u, "Indicates the type of object-based optimization")
+("SEIEOITemporalResamplingTypeFlag", m_eoiSEITemporalResamplingTypeFlag, false, "specifies the type of the temporal resampling optimization.")
+("SEIEOINumIntPics", m_eoiSEINumIntPics, 0u, "indicates that the count of pictures that the encoding system excluded or added between each pair of coded pictures in output order within the persistence of this SEI message is constant")
+("SEIEOISpatialResamplingTypeFlag", m_eoiSEISpatialResamplingTypeFlag, false, "specifies the type of the spatial resampling optimization.")
+("SEIEOIPrivacyProtectionTypeIdc", m_eoiSEIPrivacyProtectionTypeIdc, 0u, "indicates the type of privacy protection optimization")
+("SEIEOIPrivacyProtectedInfoType", m_eoiSEIPrivacyProtectedInfoType, 0u, "indicates the types of protected information")
+#endif 
+
 // film grain characteristics SEI
   ("SEIFGCEnabled",                                   m_fgcSEIEnabled,                                   false, "Control generation of the film grain characteristics SEI message")
   ("SEIFGCCancelFlag",                                m_fgcSEICancelFlag,                                 true, "Specifies the persistence of any previous film grain characteristics SEI message in output order.")
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index b2ec7e087..a984aafa2 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -540,6 +540,21 @@ protected:
   int       m_selfContainedClvsFlag;
   int       m_preferredTransferCharacteristics;
 
+#if JVET_AH2006_EOI_SEI
+  bool  m_eoiSEIEnabled;
+  bool  m_eoiSEICancelFlag;
+  bool  m_eoiSEIPersistenceFlag;
+  uint32_t m_eoiSEIForHumanViewingIdc;
+  uint32_t m_eoiSEIForMachineAnalysisIdc;
+  uint32_t m_eoiSEIType;
+  uint32_t m_eoiSEIObjectBasedIdc;
+  bool m_eoiSEITemporalResamplingTypeFlag;
+  uint32_t m_eoiSEINumIntPics;
+  bool m_eoiSEISpatialResamplingTypeFlag;
+  uint32_t m_eoiSEIPrivacyProtectionTypeIdc;
+  uint32_t m_eoiSEIPrivacyProtectedInfoType;
+#endif 
+
   // film grain characterstics sei
   bool      m_fgcSEIEnabled;
   bool      m_fgcSEICancelFlag;
diff --git a/source/Lib/CommonLib/SEI.cpp b/source/Lib/CommonLib/SEI.cpp
index 1aec07c4b..775816ef3 100644
--- a/source/Lib/CommonLib/SEI.cpp
+++ b/source/Lib/CommonLib/SEI.cpp
@@ -1115,3 +1115,23 @@ SEINeuralNetworkPostFilterCharacteristics* getSuperResolutionNnpfc(const SEIMess
   }
   return nullptr;
 }
+
+#if JVET_AH2006_EOI_SEI
+SEIEncoderOptimizationInfo::SEIEncoderOptimizationInfo(
+  const SEIEncoderOptimizationInfo& sei)
+{
+  m_cancelFlag = sei.m_cancelFlag;
+  m_persistenceFlag = sei.m_persistenceFlag;
+  m_forHumanViewingIdc = sei.m_forHumanViewingIdc;
+  m_forMachineAnalysisIdc = sei.m_forMachineAnalysisIdc;
+  m_type = sei.m_type;
+  m_objectBasedIdc = sei.m_objectBasedIdc;
+  m_temporalResamplingTypeFlag = sei.m_temporalResamplingTypeFlag;
+  m_numIntPics = sei.m_numIntPics;
+  m_spatialResamplingTypeFlag = sei.m_spatialResamplingTypeFlag;
+  m_privacyProtectionTypeIdc = sei.m_privacyProtectionTypeIdc;
+  m_privacyProtectedInfoType = sei.m_privacyProtectedInfoType;
+
+}
+#endif
+
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index 53545f868..a28f8097c 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -101,6 +101,9 @@ public:
 
     SEI_PROCESSING_ORDER = 213,
     SEI_PROCESSING_ORDER_NESTING = 214,
+#if JVET_AH2006_EOI_SEI
+    ENCODER_OPTIMIZATION_INFO = 215,
+#endif 
   };
 
   SEI() {}
@@ -1453,6 +1456,44 @@ public:
 
 SEINeuralNetworkPostFilterCharacteristics* getNnpfcWithGivenId(const SEIMessages &seiList, uint32_t nnpfaTargetId);
 SEINeuralNetworkPostFilterCharacteristics* getSuperResolutionNnpfc(const SEIMessages &seiList);
+
+#if JVET_AH2006_EOI_SEI
+class SEIEncoderOptimizationInfo : public SEI
+{
+public:
+  PayloadType payloadType() const { return PayloadType::ENCODER_OPTIMIZATION_INFO; }
+  SEIEncoderOptimizationInfo()
+    : m_cancelFlag(false)
+    , m_persistenceFlag(false)
+    , m_forHumanViewingIdc(0)
+    , m_forMachineAnalysisIdc(0)
+    , m_type(0)
+    , m_objectBasedIdc(0)
+    , m_temporalResamplingTypeFlag(false)
+    , m_numIntPics(0)
+    , m_spatialResamplingTypeFlag(false)
+    , m_privacyProtectionTypeIdc(0)
+    , m_privacyProtectedInfoType(0)
+  {}
+  SEIEncoderOptimizationInfo(const SEIEncoderOptimizationInfo& sei);
+
+  virtual ~SEIEncoderOptimizationInfo() {}
+
+  bool     m_cancelFlag;
+  bool     m_persistenceFlag;
+  uint32_t m_forHumanViewingIdc;
+  uint32_t m_forMachineAnalysisIdc;
+  uint32_t m_type;
+  uint32_t m_objectBasedIdc;
+  bool     m_temporalResamplingTypeFlag;
+  uint32_t m_numIntPics;
+  bool     m_spatialResamplingTypeFlag;
+  uint32_t m_privacyProtectionTypeIdc;
+  uint32_t m_privacyProtectedInfoType;
+
+};
+
+#endif
 //! \}
 
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 6db760e8e..a975826df 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -82,6 +82,8 @@
 
 #define JVET_AD0067_INCLUDE_SYNTAX                        1 // include nnpfc_full_range_flag syntax element in the nnpfc sei message when nnpfc_separate_colour_description_present_flag is equal to 1 and when nnpfc_out_format_idc is equal to 1.
 
+#define JVET_AH2006_EOI_SEI                               1 // Implementation of Encoder Optimizaion Information SEI message 
+
 #define REUSE_CU_RESULTS                                  1
 #if REUSE_CU_RESULTS
 #define REUSE_CU_RESULTS_WITH_MULTIPLE_TUS                1
@@ -769,6 +771,19 @@ enum SAOEOClasses
   NUM_SAO_EO_CLASSES,
 };
 
+#if JVET_AH2006_EOI_SEI
+enum EOI_OptimizationType
+{
+  UNDEFINED = 0,
+  OBJECT_BASED_OPTIMIZATION = 1,
+  TEMPORAL_RESAMPLING = 2,
+  SPATIAL_RESAMPLING = 4,
+  TEMPORAL_QUALITY_OPTIMIZATION = 8,
+  SPATIAL_QUALITY_OPTIMIZATION = 16,
+  PRIVACY_PROTECTION_OPTIMIZATION = 32,
+};
+#endif 
+
 enum NNPC_PaddingType
 {
   ZERO_PADDING = 0,
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index 2acb373c6..0df1f5e2b 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -542,6 +542,12 @@ bool SEIReader::xReadSEImessage(SEIMessages& seis, const NalUnitType nalUnitType
       sei = new SEIPostFilterHint;
       xParseSEIPostFilterHint((SEIPostFilterHint &) *sei, payloadSize, pDecodedMessageOutputStream);
       break;
+#if JVET_AH2006_EOI_SEI
+    case SEI::PayloadType::ENCODER_OPTIMIZATION_INFO:
+      sei = new SEIEncoderOptimizationInfo;
+      xParseSEIEncoderOptimizationInfo((SEIEncoderOptimizationInfo &)*sei, payloadSize, pDecodedMessageOutputStream);
+      break;
+#endif
     default:
       for (uint32_t i = 0; i < payloadSize; i++)
       {
@@ -1838,6 +1844,53 @@ void SEIReader::xParseSEIAnnotatedRegions(SEIAnnotatedRegions& sei, uint32_t pay
   }
 }
 
+#if JVET_AH2006_EOI_SEI
+void SEIReader::xParseSEIEncoderOptimizationInfo(SEIEncoderOptimizationInfo& sei, uint32_t payloadSize, std::ostream* pDecodedMessageOutputStream)
+{
+  uint32_t val;
+  output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
+  sei_read_flag(pDecodedMessageOutputStream, val, "eoi_cancel_flag");
+  sei.m_cancelFlag = val;
+  if (!sei.m_cancelFlag)
+  {
+    sei_read_flag(pDecodedMessageOutputStream, val, "eoi_persistence_flag");
+    sei.m_persistenceFlag = val;
+    sei_read_code(pDecodedMessageOutputStream, 2, val, "eoi_for_human_viewing_idc");
+    sei.m_forHumanViewingIdc = val;
+    sei_read_code(pDecodedMessageOutputStream, 2, val, "eoi_for_machine_analysis_idc");
+    sei.m_forMachineAnalysisIdc = val;
+    sei_read_code(pDecodedMessageOutputStream, 16, val, "eoi_type");
+    sei.m_type = val;
+    if ((sei.m_type & EOI_OptimizationType::OBJECT_BASED_OPTIMIZATION) != 0)
+    {
+      sei_read_uvlc(pDecodedMessageOutputStream, val, "eoi_object_based_idc");
+      sei.m_objectBasedIdc = val;
+    }
+    if ((sei.m_type & EOI_OptimizationType::TEMPORAL_RESAMPLING) != 0)
+    {
+      sei_read_flag(pDecodedMessageOutputStream, val, "eoi_temporal_resampling_type_flag");
+      sei.m_temporalResamplingTypeFlag = val;
+      sei_read_uvlc(pDecodedMessageOutputStream, val, "eoi_num_int_pics");
+      sei.m_numIntPics = val;
+    }
+
+    if ((sei.m_type & EOI_OptimizationType::SPATIAL_RESAMPLING) != 0)
+    {
+      sei_read_flag(pDecodedMessageOutputStream, val, "eoi_spatial_resampling_type_flag");
+      sei.m_spatialResamplingTypeFlag = val;
+    }
+    
+    if ((sei.m_type & EOI_OptimizationType::PRIVACY_PROTECTION_OPTIMIZATION) != 0)
+    {
+      sei_read_code(pDecodedMessageOutputStream, 4, val, "eoi_privacy_protection_type_idc");
+      sei.m_privacyProtectionTypeIdc = val;
+      sei_read_code(pDecodedMessageOutputStream, 8, val, "eoi_privacy_protected_info_type");
+      sei.m_privacyProtectedInfoType = val;
+    }
+  }
+}
+#endif 
+
 void SEIReader::xParseSEIFrameFieldinfo(SEIFrameFieldInfo& sei, uint32_t payloadSize, std::ostream *pDecodedMessageOutputStream)
 {
   output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
diff --git a/source/Lib/DecoderLib/SEIread.h b/source/Lib/DecoderLib/SEIread.h
index bc7ee2afc..e35547404 100644
--- a/source/Lib/DecoderLib/SEIread.h
+++ b/source/Lib/DecoderLib/SEIread.h
@@ -90,6 +90,9 @@ protected:
   void xParseSEIMasteringDisplayColourVolume  (SEIMasteringDisplayColourVolume& sei,  uint32_t payloadSize,                     std::ostream *pDecodedMessageOutputStream);
   void xParseSEIAnnotatedRegions              (SEIAnnotatedRegions& sei,              uint32_t payloadSize,                     std::ostream *pDecodedMessageOutputStream);
   void xParseSEIAlternativeTransferCharacteristics(SEIAlternativeTransferCharacteristics& sei,              uint32_t payLoadSize,                     std::ostream *pDecodedMessageOutputStream);
+#if JVET_AH2006_EOI_SEI
+  void xParseSEIEncoderOptimizationInfo(SEIEncoderOptimizationInfo& sei, uint32_t payloadSize, std::ostream* pDecodedMessageOutputStream);
+#endif 
   void xParseSEIEquirectangularProjection     (SEIEquirectangularProjection &sei,     uint32_t payloadSize,                     std::ostream *pDecodedMessageOutputStream);
   void xParseSEISphereRotation                (SEISphereRotation &sei,                uint32_t payloadSize,                     std::ostream *pDecodedMessageOutputStream);
   void xParseSEIOmniViewport                  (SEIOmniViewport& sei,                  uint32_t payloadSize,                     std::ostream *pDecodedMessageOutputStream);
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 22e75b316..320744fa3 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -759,6 +759,22 @@ protected:
   bool                    m_nnPostFilterSEIActivationPersistenceFlag;
   std::vector<bool>       m_nnPostFilterSEIActivationOutputflag;
 
+#if JVET_AH2006_EOI_SEI
+  // Encoder Optimization Information SEI
+  bool  m_eoiSEIEnabled;
+  bool  m_eoiSEICancelFlag;
+  bool  m_eoiSEIPersistenceFlag;
+  uint32_t  m_eoiSEIForHumanViewingIdc;
+  uint32_t  m_eoiSEIForMachineAnalysisIdc;
+  uint32_t m_eoiSEIType;
+  uint32_t m_eoiSEIObjectBasedIdc;
+  bool m_eoiSEITemporalResamplingTypeFlag;
+  uint32_t m_eoiSEINumIntPics;
+  bool m_eoiSEISpatialResamplingTypeFlag;
+  uint32_t m_eoiSEIPrivacyProtectionTypeIdc;
+  uint32_t m_eoiSEIPrivacyProtectedInfoType;
+#endif 
+
   // film grain characterstics sei
   bool      m_fgcSEIEnabled;
   bool      m_fgcSEICancelFlag;
@@ -2326,6 +2342,32 @@ public:
   void  setSEIPreferredTransferCharacteristics(uint8_t v)              { m_preferredTransferCharacteristics = v;    }
   uint8_t getSEIPreferredTransferCharacteristics() const               { return m_preferredTransferCharacteristics; }
   const SEIMasteringDisplay &getMasteringDisplaySEI() const          { return m_masteringDisplay; }
+#if JVET_AH2006_EOI_SEI
+  void setEOISEIEnabled(bool enabledFlag) { m_eoiSEIEnabled = enabledFlag; }
+  bool getEOISEIEnabled() const { return m_eoiSEIEnabled; }
+  void setEOISEICancelFlag(bool cancelFlag) { m_eoiSEICancelFlag = cancelFlag; }
+  bool getEOISEICancelFlag() const { return m_eoiSEICancelFlag; }
+  void setEOISEIPersistenceFlag(bool persistenceFlag) { m_eoiSEIPersistenceFlag = persistenceFlag; }
+  bool getEOISEIPersistenceFlag() const { return m_eoiSEIPersistenceFlag; }
+  void setEOISEIForHumanViewingIdc(uint32_t forHumanViewingIdc) { m_eoiSEIForHumanViewingIdc = forHumanViewingIdc; }
+  uint32_t getEOISEIForHumanViewingIdc() const { return m_eoiSEIForHumanViewingIdc; }
+  void setEOISEIForMachineAnalysisIdc(uint32_t forMachineAnalysisIdc) { m_eoiSEIForMachineAnalysisIdc = forMachineAnalysisIdc; }
+  uint32_t getEOISEIForMachineAnalysisIdc() const { return m_eoiSEIForMachineAnalysisIdc; }
+  void setEOISEIType(uint32_t eoiType) { m_eoiSEIType = eoiType; }
+  uint32_t getEOISEIType() const { return m_eoiSEIType; }
+  void setEOISEIObjectBasedIdc(uint32_t objectBasedIdc) { m_eoiSEIObjectBasedIdc = objectBasedIdc; }
+  uint32_t getEOISEIObjectBasedIdc() const { return m_eoiSEIObjectBasedIdc; }
+  void setEOISEITemporalResamplingTypeFlag(bool temporalResamplingTypeFlag) { m_eoiSEITemporalResamplingTypeFlag = temporalResamplingTypeFlag; }
+  bool getEOISEITemporalResamplingTypeFlag() const { return m_eoiSEITemporalResamplingTypeFlag; }
+  void setEOISEINumIntPics(uint32_t numIntPics) { m_eoiSEINumIntPics = numIntPics; }
+  uint32_t getEOISEINumIntPics() const { return m_eoiSEINumIntPics; }
+  void setEOISEISpatialResamplingTypeFlag(bool spatialResamplingTypeFlag) { m_eoiSEISpatialResamplingTypeFlag = spatialResamplingTypeFlag; }
+  bool getEOISEISpatialResamplingTypeFlag() const { return m_eoiSEISpatialResamplingTypeFlag; }
+  void setEOISEIPrivacyProtectionTypeIdc(uint32_t privacyProtectionTypeIdc) { m_eoiSEIPrivacyProtectionTypeIdc = privacyProtectionTypeIdc; }
+  uint32_t getEOISEIPrivacyProtectionTypeIdc() const { return m_eoiSEIPrivacyProtectionTypeIdc; }
+  void setEOISEIPrivacyProtectedInfoType(uint32_t privacyProtectedInfoType) { m_eoiSEIPrivacyProtectedInfoType = privacyProtectedInfoType; }
+  uint32_t getEOISEIPrivacyProtectedInfoType() const { return m_eoiSEIPrivacyProtectedInfoType; }
+#endif 
   // film grain SEI
   void  setFilmGrainCharactersticsSEIEnabled (bool b)                { m_fgcSEIEnabled = b; }
   bool  getFilmGrainCharactersticsSEIEnabled()                       { return m_fgcSEIEnabled; }
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 8b617ec08..fa672a7c8 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -1012,6 +1012,15 @@ void EncGOP::xCreatePerPictureSEIMessages (int picInGOP, SEIMessages& seiMessage
     seiMessages.push_back(fgcSEI);
   }
 
+#if JVET_AH2006_EOI_SEI
+  if (m_pcCfg->getEOISEIEnabled())
+  {
+    SEIEncoderOptimizationInfo *eoiSEI = new SEIEncoderOptimizationInfo;
+    m_seiEncoder.initSEIEncoderOptimizationInfo(eoiSEI);
+    seiMessages.push_back(eoiSEI);
+  }
+#endif
+
   if (m_pcCfg->getNnPostFilterSEIActivationEnabled() && !m_pcCfg->getNnPostFilterSEIActivationUseSuffixSEI())
   {
     xCreateNNPostFilterActivationSEIMessage(seiMessages, slice);
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index 533607018..bb0703b24 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -1535,5 +1535,39 @@ void SEIEncoder::initSEINeuralNetworkPostFilterActivation(SEINeuralNetworkPostFi
   }
 }
 
+#if JVET_AH2006_EOI_SEI
+void SEIEncoder::initSEIEncoderOptimizationInfo(SEIEncoderOptimizationInfo *sei)
+{
+  CHECK(!(m_isInitialized), "Unspecified error");
+  CHECK(!(sei != nullptr), "Unspecified error");
+  sei->m_cancelFlag = m_pcCfg->getEOISEICancelFlag();
+  if (!sei->m_cancelFlag)
+  {
+    sei->m_persistenceFlag = m_pcCfg->getEOISEIPersistenceFlag();
+    sei->m_forHumanViewingIdc = m_pcCfg->getEOISEIForHumanViewingIdc();
+    sei->m_forMachineAnalysisIdc = m_pcCfg->getEOISEIForMachineAnalysisIdc();
+    CHECK(sei->m_forHumanViewingIdc ==1  && sei->m_forMachineAnalysisIdc ==1 , "the value of eoi_for_human_viewing_idc and eoi_for_machine_analysis_idc shall not be both equal to 1");
+    sei->m_type = m_pcCfg->getEOISEIType();
+    if ((sei->m_type & EOI_OptimizationType::OBJECT_BASED_OPTIMIZATION) != 0)
+    {
+      sei->m_objectBasedIdc = m_pcCfg->getEOISEIObjectBasedIdc();
+    }
+    if ((sei->m_type & EOI_OptimizationType::TEMPORAL_RESAMPLING) != 0)
+    {
+      sei->m_temporalResamplingTypeFlag = m_pcCfg->getEOISEITemporalResamplingTypeFlag();
+      sei->m_numIntPics = m_pcCfg->getEOISEINumIntPics();
+    }
+    if ((sei->m_type & EOI_OptimizationType::SPATIAL_RESAMPLING) != 0)
+    {
+      sei->m_spatialResamplingTypeFlag = m_pcCfg->getEOISEISpatialResamplingTypeFlag();
+    }
+    if ((sei->m_type & EOI_OptimizationType::PRIVACY_PROTECTION_OPTIMIZATION) != 0)
+    {
+      sei->m_privacyProtectionTypeIdc = m_pcCfg->getEOISEIPrivacyProtectionTypeIdc();
+      sei->m_privacyProtectedInfoType = m_pcCfg->getEOISEIPrivacyProtectedInfoType();
+    }
+  }
+}
+#endif
 
 //! \}
diff --git a/source/Lib/EncoderLib/SEIEncoder.h b/source/Lib/EncoderLib/SEIEncoder.h
index baf33f494..6cd2e28e8 100644
--- a/source/Lib/EncoderLib/SEIEncoder.h
+++ b/source/Lib/EncoderLib/SEIEncoder.h
@@ -99,6 +99,9 @@ public:
   void initSEINeuralNetworkPostFilterActivation(SEINeuralNetworkPostFilterActivation *sei);
   void initSEIProcessingOrderInfo(SEIProcessingOrderInfo *seiProcessingOrderInfo, SEIProcessingOrderNesting *seiProcessingOrderNesting);
   void initSEIPostFilterHint(SEIPostFilterHint *sei);
+#if JVET_AH2006_EOI_SEI
+  void initSEIEncoderOptimizationInfo(SEIEncoderOptimizationInfo *sei);
+#endif 
 #if GREEN_METADATA_SEI_ENABLED
   void initSEIGreenMetadataInfo(SEIGreenMetadataInfo *sei, FeatureCounterStruct featureCounter, SEIQualityMetrics metrics, SEIComplexityMetrics greenMetadata);
 #endif
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index 69bcce2b7..4f2b75417 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -191,6 +191,11 @@ void SEIWriter::xWriteSEIpayloadData(OutputBitstream &bs, const SEI &sei, HRD &h
   case SEI::PayloadType::POST_FILTER_HINT:
     xWriteSEIPostFilterHint(*static_cast<const SEIPostFilterHint *>(&sei));
     break;
+#if JVET_AH2006_EOI_SEI
+  case SEI::PayloadType::ENCODER_OPTIMIZATION_INFO:
+    xWriteSEIEncoderOptimizationInfo(*static_cast<const SEIEncoderOptimizationInfo *>(&sei));
+    break;
+#endif 
   default:
     THROW("Trying to write unhandled SEI message");
     break;
@@ -1951,4 +1956,39 @@ void SEIWriter::xWriteSEIPostFilterHint(const SEIPostFilterHint &sei)
     }
   }
 }
+
+#if JVET_AH2006_EOI_SEI
+void SEIWriter::xWriteSEIEncoderOptimizationInfo(const SEIEncoderOptimizationInfo &sei)
+{
+  xWriteFlag(sei.m_cancelFlag, "eoi_cancel_flag");
+  if (!sei.m_cancelFlag)
+  {
+    xWriteFlag(sei.m_persistenceFlag, "eoi_persistence_flag");
+    xWriteCode(sei.m_forHumanViewingIdc,2, "eoi_for_human_viewing_idc");
+    xWriteCode(sei.m_forMachineAnalysisIdc,2, "eoi_for_machine_analysis_idc");
+    xWriteCode(sei.m_type, 16, "eoi_type");
+
+    if ((sei.m_type & EOI_OptimizationType::OBJECT_BASED_OPTIMIZATION) != 0)
+    {
+      xWriteUvlc(sei.m_objectBasedIdc, "eoi_object_based_idc");
+
+    }
+    if ((sei.m_type & EOI_OptimizationType::TEMPORAL_RESAMPLING) != 0)
+    {
+      xWriteFlag(sei.m_temporalResamplingTypeFlag, "eoi_temporal_resampling_type_flag");
+      xWriteUvlc(sei.m_numIntPics, "eoi_num_int_pics");
+
+    }
+    if ((sei.m_type & EOI_OptimizationType::SPATIAL_RESAMPLING) != 0)
+    {
+      xWriteFlag(sei.m_spatialResamplingTypeFlag, "eoi_spatial_resampling_type_flag");
+    }
+    if ((sei.m_type & EOI_OptimizationType::PRIVACY_PROTECTION_OPTIMIZATION) != 0)
+    {
+      xWriteCode(sei.m_privacyProtectionTypeIdc, 4, "eoi_privacy_protection_type_idc");
+      xWriteCode(sei.m_privacyProtectedInfoType, 8, "eoi_privacy_protected_info_type");
+    }
+  }
+}
+#endif
 //! \}
diff --git a/source/Lib/EncoderLib/SEIwrite.h b/source/Lib/EncoderLib/SEIwrite.h
index c222e8c03..7b18c32ce 100644
--- a/source/Lib/EncoderLib/SEIwrite.h
+++ b/source/Lib/EncoderLib/SEIwrite.h
@@ -114,6 +114,9 @@ protected:
   void xWriteSEIGreenMetadataInfo                 (const SEIGreenMetadataInfo &sei);
 #endif
   void xWriteSEIPostFilterHint(const SEIPostFilterHint &sei);
+#if JVET_AH2006_EOI_SEI
+  void xWriteSEIEncoderOptimizationInfo(const SEIEncoderOptimizationInfo &sei);
+#endif
 protected:
   HRD m_nestingHrd;
 };
-- 
GitLab