From e806d5dd7d6749fcff183c744943d82bd727cc2b Mon Sep 17 00:00:00 2001
From: Philip Cowan <cowanp@sharplabs.com>
Date: Wed, 22 Feb 2023 14:12:07 -0800
Subject: [PATCH] JVET-AC0344: Signal 2 new syntax elements,
 nnpfc_extended_patch_width_cd_delta_minus1 and
 nnpfc_extended_patch_height_cd_delta_minus1 when
 nnpfc_constant_patch_size_flag is false, and only signal
 nnpfc_patch_width_minus1 and nnpfc_patch_height_minus1 when
 nnpfc_constant_patch_size_flag is true

---
 doc/software-manual.tex              | 19 ++++++++++++++++---
 source/App/EncoderApp/EncApp.cpp     |  7 +++++++
 source/App/EncoderApp/EncAppCfg.cpp  | 10 ++++++++++
 source/App/EncoderApp/EncAppCfg.h    |  4 ++++
 source/Lib/CommonLib/SEI.h           |  8 ++++++++
 source/Lib/CommonLib/TypeDef.h       |  1 +
 source/Lib/DecoderLib/SEIread.cpp    | 22 ++++++++++++++++++++++
 source/Lib/EncoderLib/EncCfg.h       | 10 ++++++++++
 source/Lib/EncoderLib/SEIEncoder.cpp |  7 +++++++
 source/Lib/EncoderLib/SEIwrite.cpp   | 16 ++++++++++++++++
 10 files changed, 101 insertions(+), 3 deletions(-)

diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index fcf47f508..3aa53e17e 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -5849,8 +5849,6 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries
   \par
   \begin{tabular}{p{0.49\columnwidth}}
     When nnpfc_constant_patch_size_flag is true (non-zero), specifies the horizontal sample counts of the patch size required for the input to the \emph{i}-th neural network post-filter. \\
-    When nnpfc_constant_patch_size_flag is false, any positive integer multiple of ( nnpfc_patch_width_minus1 + 1 ) may be used as the horizontal sample counts of the patch size used for the input to the \emph{i}-th neural network post-filter. \\
-  \end{tabular}
   \\
   \Option{SEINNPostFilterCharacteristicsPatchHeightMinus1\emph{i}} &
   \Default{0} &
@@ -5858,7 +5856,22 @@ Specifies sii_num_units_in_shutter_interval for single entry.If multiple entries
   \par
   \begin{tabular}{p{0.49\columnwidth}}
     When nnpfc_constant_patch_size_flag is true (non-zero), specifies the vertical sample counts of the patch size required for the input to the \emph{i}-th neural network post-filter. \\
-    When nnpfc_constant_patch_size_flag is false, any positive integer multiple of ( nnpfc_patch_height_minus1 + 1 ) may be used as the vertical sample counts of the patch size used for the input to the \emph{i}-th neural network post-filter. \\
+  \end{tabular}
+  \\
+  \Option{SEINNPostFilterCharacteristicsExtendedPatchWidthCdDeltaMinus1\emph{i}} &
+  \Default{0} &
+  Specifies the extended patch width for the \emph{i}-th neural network post-filter.
+  \par
+  \begin{tabular}{p{0.49\columnwidth}}
+    When nnpfc_constant_patch_size_flag is false (zero),  nnpfc_extended_patch_width_cd_delta_minus1+1+2*nnpfc_overlap indicates a common divisor of the all allowed values of the width of an extended patch for the input to the \emph{i}-th neural network post-filter. \\
+  \end{tabular}
+  \\
+  \Option{SEINNPostFilterCharacteristicsExtendedPatchHeightCdDeltaMinus1\emph{i}} &
+  \Default{0} &
+  Specifies the extended patch height \emph{i}-th neural network post-filter.
+  \par
+  \begin{tabular}{p{0.49\columnwidth}}
+    When nnpfc_constant_patch_size_flag is false (zero),  nnpfc_extended_patch_height_cd_delta_minus1+1+2*nnpfc_overlap indicates a common divisor of the all allowed values of the height of an extended patch for the input to the \emph{i}-th neural network post-filter. \\
   \end{tabular}
   \\
   \Option{SEINNPostFilterCharacteristicsOverlap\emph{i}} &
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 090a78a13..a669321e4 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1252,6 +1252,13 @@ void EncApp::xInitLibCfg( int layerIdx )
       m_cEncLib.setNNPostFilterSEICharacteristicsConstantPatchSizeFlag   ( m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[i], i);
       m_cEncLib.setNNPostFilterSEICharacteristicsPatchWidthMinus1        ( m_nnPostFilterSEICharacteristicsPatchWidthMinus1[i], i);
       m_cEncLib.setNNPostFilterSEICharacteristicsPatchHeightMinus1       ( m_nnPostFilterSEICharacteristicsPatchHeightMinus1[i], i);
+#if JVET_AC0344_NNPFC_PATCH
+      if (m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[i] == 0)
+      {
+        m_cEncLib.setNNPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1(m_nnPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1[i], i);
+        m_cEncLib.setNNPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1(m_nnPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1[i], i);
+      }
+#endif
       m_cEncLib.setNNPostFilterSEICharacteristicsOverlap                 ( m_nnPostFilterSEICharacteristicsOverlap[i], i);
       m_cEncLib.setNNPostFilterSEICharacteristicsPaddingType             ( m_nnPostFilterSEICharacteristicsPaddingType[i], i);
       m_cEncLib.setNNPostFilterSEICharacteristicsLumaPadding             (m_nnPostFilterSEICharacteristicsLumaPadding[i], i);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 43aac474f..de75f5ad5 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1859,6 +1859,16 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     patchHeightMinus1 << "SEINNPostFilterCharacteristicsPatchHeightMinus1" << i;
     opts.addOptions()(patchHeightMinus1.str(), m_nnPostFilterSEICharacteristicsPatchHeightMinus1[i], 0u, "Specifies the vertical sample counts of a patch in the Neural Network Post Filter Characteristics SEI message");
 
+#if JVET_AC0344_NNPFC_PATCH
+    std::ostringstream extendedPatchWidthCdDeltaMinus1;
+    extendedPatchWidthCdDeltaMinus1 << "SEINNPostFilterCharacteristicsExtendedPatchWidthCdDeltaMinus1" << i;
+    opts.addOptions()(extendedPatchWidthCdDeltaMinus1.str(), m_nnPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1[i], 0u, "Specifies the extended horizontal sample counts of a patch in the Neural Network Post Filter Characteristics SEI message");
+
+    std::ostringstream extendedPatchHeightCdDeltaMinus1;
+    extendedPatchHeightCdDeltaMinus1 << "SEINNPostFilterCharacteristicsExtendedPatchHeightCdDeltaMinus1" << i;
+    opts.addOptions()(extendedPatchHeightCdDeltaMinus1.str(), m_nnPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1[i], 0u, "Specifies the extended vertical sample counts of a patch in the Neural Network Post Filter Characteristics SEI message");
+#endif
+
     std::ostringstream overlap;
     overlap << "SEINNPostFilterCharacteristicsOverlap" << i;
     opts.addOptions()(overlap.str(), m_nnPostFilterSEICharacteristicsOverlap[i], 0u, "Specifies the overlap in the Neural Network Post Filter Characteristics SEI message");
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 4b45d3d90..e9cf2f972 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -762,6 +762,10 @@ protected:
   bool                  m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[MAX_NUM_NN_POST_FILTERS];
   uint32_t              m_nnPostFilterSEICharacteristicsPatchWidthMinus1[MAX_NUM_NN_POST_FILTERS];
   uint32_t              m_nnPostFilterSEICharacteristicsPatchHeightMinus1[MAX_NUM_NN_POST_FILTERS];
+#if JVET_AC0344_NNPFC_PATCH
+  uint32_t              m_nnPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1[MAX_NUM_NN_POST_FILTERS];
+  uint32_t              m_nnPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1[MAX_NUM_NN_POST_FILTERS];
+#endif
   uint32_t              m_nnPostFilterSEICharacteristicsOverlap[MAX_NUM_NN_POST_FILTERS];
   uint32_t              m_nnPostFilterSEICharacteristicsPaddingType[MAX_NUM_NN_POST_FILTERS];
   uint32_t              m_nnPostFilterSEICharacteristicsLumaPadding[MAX_NUM_NN_POST_FILTERS];
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index 72ec1ff35..551f6036e 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -1196,6 +1196,10 @@ public:
     , m_constantPatchSizeFlag(false)
     , m_patchWidthMinus1(0)
     , m_patchHeightMinus1(0)
+#if JVET_AC0344_NNPFC_PATCH
+    , m_extendedPatchWidthCdDeltaMinus1(0)
+    , m_extendedPatchHeightCdDeltaMinus1(0)
+#endif
     , m_overlap(0)
     , m_paddingType(0)
     , m_lumaPadding(0)
@@ -1255,6 +1259,10 @@ public:
   bool           m_constantPatchSizeFlag;
   uint32_t       m_patchWidthMinus1;
   uint32_t       m_patchHeightMinus1;
+#if JVET_AC0344_NNPFC_PATCH
+  uint32_t       m_extendedPatchWidthCdDeltaMinus1;
+  uint32_t       m_extendedPatchHeightCdDeltaMinus1;
+#endif
   uint32_t       m_overlap;
   uint32_t       m_paddingType;
   uint32_t       m_lumaPadding;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 8138baa61..5d8f50344 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -63,6 +63,7 @@
 #define JVET_AC0127_BIT_MASKING_NNPFC_PURPOSE             1 
 #define JVET_AC0061_TENSOR_BITDEPTH                       1
 #define JVET_AC0062_CONSTRAINT_CHECK                      1
+#define JVET_AC0344_NNPFC_PATCH                           1
 
 
 //########### place macros to be be kept below this line ###############
diff --git a/source/Lib/DecoderLib/SEIread.cpp b/source/Lib/DecoderLib/SEIread.cpp
index da05cb96d..dbf5f4f48 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -2923,9 +2923,31 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
     CHECK(((sei.m_purpose & NNPC_PurposeType::CHROMA_UPSAMPLING) != 0)  && (sei.m_outOrderIdc == 3), "When nnpfc_purpose & 0x02 is not equal to 0, nnpfc_out_order_idc shall not be equal to 3.")
 #endif
 
+#if JVET_AC0344_NNPFC_PATCH
+    sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_overlap");
+    sei.m_overlap = val;
+#endif
+
+#if JVET_AC0344_NNPFC_PATCH
+    if (sei.m_constantPatchSizeFlag)
+    {
+#endif
     sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_constant_patch_size_flag");
     sei.m_constantPatchSizeFlag = val;
+#if JVET_AC0344_NNPFC_PATCH
+    }
+    else
+    {
+      sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_extended_patch_width_cd_delta_minus1");
+      sei.m_extendedPatchWidthCdDeltaMinus1 = val;
 
+      sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_extended_patch_height_cd_delta_minus1");
+      sei.m_extendedPatchHeightCdDeltaMinus1 = val;
+    }
+#else
+    sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_overlap");
+    sei.m_overlap = val;
+#endif
     sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_patch_width_minus1");
     sei.m_patchWidthMinus1 = val;
 
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 12093f445..d08f5ec98 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -718,6 +718,10 @@ protected:
   bool                    m_nnPostFilterSEICharacteristicsConstantPatchSizeFlag[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsPatchWidthMinus1[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsPatchHeightMinus1[MAX_NUM_NN_POST_FILTERS];
+#if JVET_AC0344_NNPFC_PATCH
+  uint32_t                m_nnPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1[MAX_NUM_NN_POST_FILTERS];
+  uint32_t                m_nnPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1[MAX_NUM_NN_POST_FILTERS];
+#endif
   uint32_t                m_nnPostFilterSEICharacteristicsOverlap[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsPaddingType[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsLumaPadding[MAX_NUM_NN_POST_FILTERS];
@@ -1970,6 +1974,12 @@ public:
   void        setNNPostFilterSEICharacteristicsPatchWidthMinus1(uint32_t patchWidthMinus1, int filterIdx)               { m_nnPostFilterSEICharacteristicsPatchWidthMinus1[filterIdx] = patchWidthMinus1; }
   uint32_t    getNNPostFilterSEICharacteristicsPatchWidthMinus1(int filterIdx) const                                    { return m_nnPostFilterSEICharacteristicsPatchWidthMinus1[filterIdx]; }
   void        setNNPostFilterSEICharacteristicsPatchHeightMinus1(uint32_t patchHeightMinus1, int filterIdx)             { m_nnPostFilterSEICharacteristicsPatchHeightMinus1[filterIdx] = patchHeightMinus1; }
+#if JVET_AC0344_NNPFC_PATCH
+  void        setNNPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1(uint32_t extendedPatchWidthCdDeltaMinus1, int filterIdx)   { m_nnPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1[filterIdx] = extendedPatchWidthCdDeltaMinus1; }
+  uint32_t    getNNPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1(int filterIdx) const                                       { return m_nnPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1[filterIdx]; }
+  void        setNNPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1(uint32_t extendedPatchHeightCdDeltaMinus1, int filterIdx) { m_nnPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1[filterIdx] = extendedPatchHeightCdDeltaMinus1; }
+  uint32_t    getNNPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1(int filterIdx) const                                      { return m_nnPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1[filterIdx]; }
+#endif
   uint32_t    getNNPostFilterSEICharacteristicsPatchHeightMinus1(int filterIdx) const                                   { return m_nnPostFilterSEICharacteristicsPatchHeightMinus1[filterIdx]; }
   void        setNNPostFilterSEICharacteristicsOverlap(uint32_t overlap, int filterIdx)                                 { m_nnPostFilterSEICharacteristicsOverlap[filterIdx] = overlap; }
   uint32_t    getNNPostFilterSEICharacteristicsOverlap(int filterIdx) const                                             { return m_nnPostFilterSEICharacteristicsOverlap[filterIdx]; }
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index 47c2ce43f..314c2fb15 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -1440,6 +1440,13 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP
     sei->m_constantPatchSizeFlag = m_pcCfg->getNNPostFilterSEICharacteristicsConstantPatchSizeFlag(filterIdx);
     sei->m_patchWidthMinus1 = m_pcCfg->getNNPostFilterSEICharacteristicsPatchWidthMinus1(filterIdx);
     sei->m_patchHeightMinus1 = m_pcCfg->getNNPostFilterSEICharacteristicsPatchHeightMinus1(filterIdx);
+#if JVET_AC0344_NNPFC_PATCH
+    if (sei->m_constantPatchSizeFlag == 0)
+    {
+      sei->m_extendedPatchWidthCdDeltaMinus1 = m_pcCfg->getNNPostFilterSEICharacteristicsExtendedPatchWidthCdDeltaMinus1(filterIdx);
+      sei->m_extendedPatchHeightCdDeltaMinus1 = m_pcCfg->getNNPostFilterSEICharacteristicsExtendedPatchHeightCdDeltaMinus1(filterIdx);
+    }
+#endif
     sei->m_overlap = m_pcCfg->getNNPostFilterSEICharacteristicsOverlap(filterIdx);
     sei->m_paddingType = m_pcCfg->getNNPostFilterSEICharacteristicsPaddingType(filterIdx);
     sei->m_lumaPadding = m_pcCfg->getNNPostFilterSEICharacteristicsLumaPadding(filterIdx);
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index aaa58d8ed..a7624a541 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -1803,10 +1803,26 @@ void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralN
     }
 
     xWriteUvlc(sei.m_outOrderIdc, "nnpfc_out_order_idc");
+#if JVET_AC0344_NNPFC_PATCH
+    xWriteUvlc(sei.m_overlap, "nnpfc_overlap");
+#endif
     xWriteFlag(sei.m_constantPatchSizeFlag, "nnpfc_constant_patch_size_flag");
+#if JVET_AC0344_NNPFC_PATCH
+    if (sei.m_constantPatchSizeFlag)
+    {
+#endif
     xWriteUvlc(sei.m_patchWidthMinus1, "nnpfc_patch_width_minus1");
     xWriteUvlc(sei.m_patchHeightMinus1, "nnpfc_patch_height_minus1");
+#if JVET_AC0344_NNPFC_PATCH
+    }
+    else
+    {
+      xWriteUvlc(sei.m_extendedPatchWidthCdDeltaMinus1, "extended_nnpfc_patch_width_cd_delta_minus1");
+      xWriteUvlc(sei.m_extendedPatchHeightCdDeltaMinus1, "extended_nnpfc_patch_height_cd_delta_minus1");
+    }
+#else
     xWriteUvlc(sei.m_overlap, "nnpfc_overlap");
+#endif
     xWriteUvlc(sei.m_paddingType, "nnpfc_padding_type");
     if (sei.m_paddingType == NNPC_PaddingType::FIXED_PADDING)
     {
-- 
GitLab