From 8c3a832b062492f5ceaeda8bae19bf51c6d2979e Mon Sep 17 00:00:00 2001
From: Maria Santamaria <maria.santamaria_gomez@nokia.com>
Date: Mon, 8 Aug 2022 16:25:36 +0000
Subject: [PATCH] JVET-AA0056: AHG9: On syntax gating in the neural-network
 post-filter characteristics SEI message

---
 ...al_network_post_filter_characteristics.cfg |  1 +
 doc/software-manual.tex                       |  4 ++
 source/App/EncoderApp/EncApp.cpp              | 48 +++++++++++++++++++
 source/App/EncoderApp/EncAppCfg.cpp           |  6 +++
 source/App/EncoderApp/EncAppCfg.h             |  3 ++
 source/Lib/CommonLib/SEI.h                    |  6 +++
 source/Lib/CommonLib/TypeDef.h                |  1 +
 source/Lib/DecoderLib/SEIread.cpp             |  7 +++
 source/Lib/EncoderLib/EncCfg.h                |  7 +++
 source/Lib/EncoderLib/SEIEncoder.cpp          |  5 ++
 source/Lib/EncoderLib/SEIwrite.cpp            |  5 ++
 11 files changed, 93 insertions(+)

diff --git a/cfg/sei_vui/neural_network_post_filter_characteristics.cfg b/cfg/sei_vui/neural_network_post_filter_characteristics.cfg
index f8ab75867..0a3b7963c 100644
--- a/cfg/sei_vui/neural_network_post_filter_characteristics.cfg
+++ b/cfg/sei_vui/neural_network_post_filter_characteristics.cfg
@@ -5,6 +5,7 @@ SEINNPostFilterCharacteristicsNumFilters:                      1
 
 SEINNPostFilterCharacteristicsId0:                             1
 SEINNPostFilterCharacteristicsModeIdc0:                        1
+SEINNPostFilterCharacteristicsPurposeAndFormattingFlag0:       1
 SEINNPostFilterCharacteristicsPurpose0:                        2
 SEINNPostFilterCharacteristicsOutSubWidthCFlag0:               1
 SEINNPostFilterCharacteristicsOutSubHeightCFlag0:              1
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index 78ff157e9..64cc080ab 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -5381,6 +5381,10 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries
   \Default{0} &
   Specifies the nnpfc_mode_idc of the \emph{i}-th neural network post-filter.
   \\
+  \Option{SEINNPostFilterCharacteristicsPurposeAndFormattingFlag\emph{i}} &
+  \Default{false} &
+  When true (non-zero) specifies, for the \emph{i}-th neural network post-filter, that the filter purpose, input formatting, output formatting and complexity are present.
+  \\
   \Option{SEINNPostFilterCharacteristicsPurpose\emph{i}} &
   \Default{0} &
   Specifies the purpose of the \emph{i}-th neural network post-filter.
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 72d1cb4ac..3d797acad 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1125,6 +1125,53 @@ void EncApp::xInitLibCfg()
   {
     m_cEncLib.setNNPostFilterSEICharacteristicsId                      (m_nnPostFilterSEICharacteristicsId[i], i);
     m_cEncLib.setNNPostFilterSEICharacteristicsModeIdc                 (m_nnPostFilterSEICharacteristicsModeIdc[i], i);
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+    m_cEncLib.setNNPostFilterSEICharacteristicsPurposeAndFormattingFlag( m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[i], i);
+    if (m_cEncLib.getNNPostFilterSEICharacteristicsPurposeAndFormattingFlag(i))
+    {
+      m_cEncLib.setNNPostFilterSEICharacteristicsPurpose                 (m_nnPostFilterSEICharacteristicsPurpose[i], i);
+      if (m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 2  || m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 4)
+      {
+        m_cEncLib.setNNPostFilterSEICharacteristicsOutSubWidthCFlag        (m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[i], i);
+        m_cEncLib.setNNPostFilterSEICharacteristicsOutSubHeightCFlag       (m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[i], i);
+      }
+      if (m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 3  || m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 4)
+      {
+        m_cEncLib.setNNPostFilterSEICharacteristicsPicWidthInLumaSamples   (m_nnPostFilterSEICharacteristicsPicWidthInLumaSamples[i], i);
+        m_cEncLib.setNNPostFilterSEICharacteristicsPicHeightInLumaSamples  (m_nnPostFilterSEICharacteristicsPicHeightInLumaSamples[i], i);
+      }
+      m_cEncLib.setNNPostFilterSEICharacteristicsComponentLastFlag       (m_nnPostFilterSEICharacteristicsComponentLastFlag[i], i);
+      m_cEncLib.setNNPostFilterSEICharacteristicsInpSampleIdc            (m_nnPostFilterSEICharacteristicsInpSampleIdc[i], i);
+      if (m_cEncLib.getNNPostFilterSEICharacteristicsInpSampleIdc(i) == 4)
+      {
+        m_cEncLib.setNNPostFilterSEICharacteristicsInpTensorBitDepthMinus8 (m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[i], i);
+      }
+      m_cEncLib.setNNPostFilterSEICharacteristicsInpOrderIdc             (m_nnPostFilterSEICharacteristicsInpOrderIdc[i], i);
+      m_cEncLib.setNNPostFilterSEICharacteristicsOutSampleIdc            (m_nnPostFilterSEICharacteristicsOutSampleIdc[i], i);
+      if (m_cEncLib.getNNPostFilterSEICharacteristicsOutSampleIdc(i) == 4)
+      {
+        m_cEncLib.setNNPostFilterSEICharacteristicsOutTensorBitDepthMinus8 (m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[i], i);
+      }
+      m_cEncLib.setNNPostFilterSEICharacteristicsOutOrderIdc             (m_nnPostFilterSEICharacteristicsOutOrderIdc[i], i);
+      m_cEncLib.setNNPostFilterSEICharacteristicsConstantPatchSizeFlag   ( m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[i], i);
+      m_cEncLib.setNNPostFilterSEICharacteristicsPatchWidthMinus1        ( m_nnPostFilterSEICharacteristicsPatchWidthMinus1[i], i);
+      m_cEncLib.setNNPostFilterSEICharacteristicsPatchHeightMinus1       ( m_nnPostFilterSEICharacteristicsPatchHeightMinus1[i], i);
+      m_cEncLib.setNNPostFilterSEICharacteristicsOverlap                 ( m_nnPostFilterSEICharacteristicsOverlap[i], i);
+      m_cEncLib.setNNPostFilterSEICharacteristicsPaddingType             ( m_nnPostFilterSEICharacteristicsPaddingType[i], i);
+      m_cEncLib.setNNPostFilterSEICharacteristicsComplexityIdc           ( m_nnPostFilterSEICharacteristicsComplexityIdc[i], i);
+      if (m_cEncLib.getNNPostFilterSEICharacteristicsComplexityIdc(i) > 0)
+      {
+        m_cEncLib.setNNPostFilterSEICharacteristicsParameterTypeFlag       ( m_nnPostFilterSEICharacteristicsParameterTypeFlag[i], i);
+        m_cEncLib.setNNPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3     ( m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[i], i);
+        m_cEncLib.setNNPostFilterSEICharacteristicsNumParametersIdc        ( m_nnPostFilterSEICharacteristicsNumParametersIdc[i], i);
+        m_cEncLib.setNNPostFilterSEICharacteristicsNumKmacOperationsIdc    ( m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[i], i);
+      }
+    }
+    if (m_cEncLib.getNNPostFilterSEICharacteristicsModeIdc(i) == 1)
+    {
+      m_cEncLib.setNNPostFilterSEICharacteristicsPayloadFilename(m_nnPostFilterSEICharacteristicsPayloadFilename[i], i);
+    }
+#else
     m_cEncLib.setNNPostFilterSEICharacteristicsPurpose                 (m_nnPostFilterSEICharacteristicsPurpose[i], i);
     m_cEncLib.setNNPostFilterSEICharacteristicsOutSubWidthCFlag        (m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[i], i);
     m_cEncLib.setNNPostFilterSEICharacteristicsOutSubHeightCFlag       (m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[i], i);
@@ -1148,6 +1195,7 @@ void EncApp::xInitLibCfg()
     m_cEncLib.setNNPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3     ( m_nnPostFilterSEICharacteristicsLog2ParameterBitLengthMinus3[i], i);
     m_cEncLib.setNNPostFilterSEICharacteristicsNumParametersIdc        ( m_nnPostFilterSEICharacteristicsNumParametersIdc[i], i);
     m_cEncLib.setNNPostFilterSEICharacteristicsNumKmacOperationsIdc    ( m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[i], i);
+#endif
   }
   m_cEncLib.setNnPostFilterSEIActivationEnabled                  (m_nnPostFilterSEIActivationEnabled);
   m_cEncLib.setNnPostFilterSEIActivationId                       (m_nnPostFilterSEIActivationId);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index ec1ded0fc..1601e61cf 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1672,6 +1672,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     modeIdc << "SEINNPostFilterCharacteristicsModeIdc" << i;
     opts.addOptions()(modeIdc.str(), m_nnPostFilterSEICharacteristicsModeIdc[i], 0u, "Specifies the Neural Network Post Filter IDC in the Neural Network Post Filter Characteristics SEI message");
 
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+    std::ostringstream purposeAndFormattingFlag;
+    purposeAndFormattingFlag << "SEINNPostFilterCharacteristicsPurposeAndFormattingFlag" << i;
+    opts.addOptions()(purposeAndFormattingFlag.str(), m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[i], false, "Specifies whether the filter purpose, input formatting, output formatting and complexity are present in the Neural Network Post Filter Characteristics SEI message");
+#endif
+
     std::ostringstream purpose;
     purpose << "SEINNPostFilterCharacteristicsPurpose" << i;
     opts.addOptions()(purpose.str(), m_nnPostFilterSEICharacteristicsPurpose[i], 0u, "Specifies the purpose in the Neural Network Post Filter Characteristics SEI message");
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 1d73ff7ab..305b979c4 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -734,6 +734,9 @@ protected:
   int                   m_nnPostFilterSEICharacteristicsNumFilters;
   uint32_t              m_nnPostFilterSEICharacteristicsId[MAX_NUM_NN_POST_FILTERS];
   uint32_t              m_nnPostFilterSEICharacteristicsModeIdc[MAX_NUM_NN_POST_FILTERS];
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+  bool                  m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[MAX_NUM_NN_POST_FILTERS];
+#endif
   uint32_t              m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS];
   bool                  m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[MAX_NUM_NN_POST_FILTERS];
   bool                  m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[MAX_NUM_NN_POST_FILTERS];
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index 2bb366284..50a7f8b43 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -1068,6 +1068,9 @@ public:
   SEINeuralNetworkPostFilterCharacteristics()
   : m_id(0)
   , m_modeIdc(0)
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+  , m_purposeAndFormattingFlag(false)
+#endif
   , m_purpose(0)
   , m_outSubWidthCFlag(false)
   , m_outSubHeightCFlag(false)
@@ -1104,6 +1107,9 @@ public:
 
   uint32_t       m_id;
   uint32_t       m_modeIdc;
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+  bool           m_purposeAndFormattingFlag;
+#endif
   uint32_t       m_purpose;
   bool           m_outSubWidthCFlag;
   bool           m_outSubHeightCFlag;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 83a042d4e..f61a7eddc 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -54,6 +54,7 @@
 
 
 //########### place macros to be removed in next cycle below this line ###############
+#define JVET_AA0056_GATING_FILTER_CHARACTERISTICS         1 // JVET-AA0056 AHG9: on syntax gating in the neural-network post-filter characteristics SEI message
 
 //########### place macros to be be kept below this line ###############
 #define JVET_X0143_ALF_APS_ID_OFFSET                      0 // A value between 0 to 7 inclusive. This macro should be kept, or to be defined as a configuration parameter if possible.
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index ada0cd057..9f38b62e4 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -2478,7 +2478,14 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
   sei_read_uvlc( pDecodedMessageOutputStream, val, "nnpfc_mode_idc" );
   sei.m_modeIdc = val;
 
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+  sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_purpose_and_formatting_flag");
+  sei.m_purposeAndFormattingFlag = val;
+
+  if (sei.m_purposeAndFormattingFlag)
+#else
   if (sei.m_modeIdc == 1)
+#endif
   {
     sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_purpose");
     sei.m_purpose = val;
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index d8890a465..9748e165c 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -666,6 +666,9 @@ protected:
   int                     m_nnPostFilterSEICharacteristicsNumFilters;
   uint32_t                m_nnPostFilterSEICharacteristicsId[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsModeIdc[MAX_NUM_NN_POST_FILTERS];
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+  bool                    m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[MAX_NUM_NN_POST_FILTERS];
+#endif
   uint32_t                m_nnPostFilterSEICharacteristicsPurpose[MAX_NUM_NN_POST_FILTERS];
   bool                    m_nnPostFilterSEICharacteristicsOutSubWidthCFlag[MAX_NUM_NN_POST_FILTERS];
   bool                    m_nnPostFilterSEICharacteristicsOutSubHeightCFlag[MAX_NUM_NN_POST_FILTERS];
@@ -1774,6 +1777,10 @@ public:
   uint32_t    getNNPostFilterSEICharacteristicsId(int filterIdx) const                                                  { return m_nnPostFilterSEICharacteristicsId[filterIdx]; }
   void        setNNPostFilterSEICharacteristicsModeIdc(uint32_t idc, int filterIdx)                                     { m_nnPostFilterSEICharacteristicsModeIdc[filterIdx] = idc; }
   uint32_t    getNNPostFilterSEICharacteristicsModeIdc(int filterIdx) const                                             { return m_nnPostFilterSEICharacteristicsModeIdc[filterIdx]; }
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+  void        setNNPostFilterSEICharacteristicsPurposeAndFormattingFlag(bool purposeAndFormattingFlag, int filterIdx)   { m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[filterIdx] = purposeAndFormattingFlag; }
+  bool        getNNPostFilterSEICharacteristicsPurposeAndFormattingFlag(int filterIdx) const                            { return m_nnPostFilterSEICharacteristicsPurposeAndFormattingFlag[filterIdx]; }
+#endif
   void        setNNPostFilterSEICharacteristicsPurpose(uint32_t purpose, int filterIdx)                                 { m_nnPostFilterSEICharacteristicsPurpose[filterIdx] = purpose; }
   uint32_t    getNNPostFilterSEICharacteristicsPurpose(int filterIdx) const                                             { return m_nnPostFilterSEICharacteristicsPurpose[filterIdx]; }
 
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index cbfa018d7..4c35d8c27 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -1158,7 +1158,12 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP
   CHECK(!(sei != nullptr), "Unspecified error");
   sei->m_id = m_pcCfg->getNNPostFilterSEICharacteristicsId(filterIdx);
   sei->m_modeIdc = m_pcCfg->getNNPostFilterSEICharacteristicsModeIdc(filterIdx);
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+  sei->m_purposeAndFormattingFlag = m_pcCfg->getNNPostFilterSEICharacteristicsPurposeAndFormattingFlag(filterIdx);
+  if (sei->m_purposeAndFormattingFlag)
+#else
   if (sei->m_modeIdc == 1)
+#endif
   {
     sei->m_purpose = m_pcCfg->getNNPostFilterSEICharacteristicsPurpose(filterIdx);
 
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index 0d3e33c50..604044cd7 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -1397,7 +1397,12 @@ void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralN
 {
   WRITE_UVLC(sei.m_id, "nnpfc_id");
   WRITE_UVLC(sei.m_modeIdc, "nnpfc_mode_idc");
+#if JVET_AA0056_GATING_FILTER_CHARACTERISTICS
+  WRITE_FLAG(sei.m_purposeAndFormattingFlag, "nnpfc_purpose_and_formatting_flag");
+  if (sei.m_purposeAndFormattingFlag)
+#else
   if (sei.m_modeIdc == 1)
+#endif
   {
     WRITE_UVLC(sei.m_purpose, "nnpfc_purpose");
 
-- 
GitLab