From 97b4a671f4d418e7b7c91f11a1b9d6ba34d0b161 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E6=9E=97=E8=B6=85=E9=80=B8?= <linchaoyi.cy@bytedance.com>
Date: Thu, 2 Feb 2023 20:55:45 +0800
Subject: [PATCH] modify code according to JVET-AC0127

---
 source/App/EncoderApp/EncApp.cpp     |  7 ++++
 source/App/EncoderApp/EncAppCfg.cpp  | 31 ++++++++++++++++-
 source/App/EncoderApp/EncAppCfg.h    |  7 ++++
 source/Lib/CommonLib/SEI.h           |  7 ++++
 source/Lib/CommonLib/TypeDef.h       |  3 ++
 source/Lib/DecoderLib/SEIread.cpp    | 52 ++++++++++++++++++++++++++--
 source/Lib/EncoderLib/EncCfg.h       | 18 +++++++++-
 source/Lib/EncoderLib/SEIEncoder.cpp | 29 +++++++++++++++-
 source/Lib/EncoderLib/SEIwrite.cpp   | 34 +++++++++++++++++-
 9 files changed, 182 insertions(+), 6 deletions(-)

diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 411e580fb9..3602b99e81 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1204,8 +1204,15 @@ void EncApp::xInitLibCfg( int layerIdx )
       }
       if (m_cEncLib.getNNPostFilterSEICharacteristicsPurpose(i) == 5)
       {
+#if JVET_AC0127
+        m_cEncLib.setNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1(m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1[i], i);
+#else
         m_cEncLib.setNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2(m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2[i], i);
+#endif
         m_cEncLib.setNNPostFilterSEICharacteristicsNumberInterpolatedPictures( m_nnPostFilterSEICharacteristicsNumberInterpolatedPictures[i], i);
+#if JVET_AC0127
+        m_cEncLib.setNNPostFilterSEICharacteristicsInputPicOutputFlag( m_nnPostFilterSEICharacteristicsInputPicOutputFlag[i], i);
+#endif    
       }
       m_cEncLib.setNNPostFilterSEICharacteristicsComponentLastFlag       (m_nnPostFilterSEICharacteristicsComponentLastFlag[i], i);
       m_cEncLib.setNNPostFilterSEICharacteristicsInpFormatIdc            (m_nnPostFilterSEICharacteristicsInpFormatIdc[i], i);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 4e0779f507..e62a403e5d 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -741,9 +741,15 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   SMultiValueInput<int32_t> cfg_postFilterHintSEIValues(INT32_MIN + 1, INT32_MAX, 1 * 1 * 1, 15 * 15 * 3);
 
   std::vector<SMultiValueInput<uint32_t>>   cfg_nnPostFilterSEICharacteristicsInterpolatedPicturesList;
+#if JVET_AC0127
+  std::vector<SMultiValueInput<bool>>   cfg_nnPostFilterSEICharacteristicsInputPicOutputFlagList;
+#endif
   for (int i = 0; i < MAX_NUM_NN_POST_FILTERS; i++)
   {
     cfg_nnPostFilterSEICharacteristicsInterpolatedPicturesList.push_back(SMultiValueInput<uint32_t>(0, std::numeric_limits<uint32_t>::max(), 1, 0));
+#if JVET_AC0127
+    cfg_nnPostFilterSEICharacteristicsInputPicOutputFlagList.push_back(SMultiValueInput<bool>(0, 1, 1, 0));
+#endif
   }
 
 #if ENABLE_TRACING
@@ -1889,12 +1895,21 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
                       "Specifies the NNR bitstream in the Neural Network Post Filter Characteristics SEI message");
 
     std::ostringstream numberDecodedInputPics;
+#if JVET_AC0127
+    numberDecodedInputPics << "SEINNPostFilterCharacteristicsNumberInputDecodedPicsMinusOne" << i;
+    opts.addOptions()(numberDecodedInputPics.str(), m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1[i], 0u, "Specifies the number of decoded output pictures used as input for the post processing filter");
+#else
     numberDecodedInputPics << "SEINNPostFilterCharacteristicsNumberInputDecodedPicsMinusTwo" << i;
     opts.addOptions()(numberDecodedInputPics.str(), m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2[i], 0u, "Specifies the number of decoded output pictures used as input for the post processing filter");
-
+#endif
     std::ostringstream numberInterpolatedPics;
     numberInterpolatedPics << "SEINNPostFilterCharacteristicsNumberInterpolatedPics" << i;
     opts.addOptions()(numberInterpolatedPics.str(), cfg_nnPostFilterSEICharacteristicsInterpolatedPicturesList[i], cfg_nnPostFilterSEICharacteristicsInterpolatedPicturesList[i], "Number of pictures to interpolate");
+#if JVET_AC0127
+    std::ostringstream InputPicOutputFlag;
+    InputPicOutputFlag << "SEINNPostFilterCharacteristicsInputPicOutputFlag" << i;
+    opts.addOptions()(InputPicOutputFlag.str(), cfg_nnPostFilterSEICharacteristicsInputPicOutputFlagList[i], cfg_nnPostFilterSEICharacteristicsInputPicOutputFlagList[i], "Indicates whether NNPF will generate a corresponding output picture for the input picture");
+#endif
 
     opts.addOptions()("SEINNPostFilterActivationEnabled", m_nnPostFilterSEIActivationEnabled, false, "Control use of the Neural Network Post Filter SEI on current picture");
     opts.addOptions()("SEINNPostFilterActivationId", m_nnPostFilterSEIActivationId , 0u,        "Id of the Neural Network Post Filter on current picture");
@@ -2422,7 +2437,18 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     {
       m_nnPostFilterSEICharacteristicsNumberInterpolatedPictures[i].push_back(0);
     }
+#if JVET_AC0127
+    CHECK(m_nnPostFilterSEICharacteristicsNumberInterpolatedPictures[i].size() < m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1[i] - 1, "Number Interpolated Pictures List must be greater than number of decoder pictures list");
+#else
     CHECK(m_nnPostFilterSEICharacteristicsNumberInterpolatedPictures[i].size() < m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2[i], "Number Interpolated Pictures List must be greater than number of decoder pictures list");
+#endif
+#if JVET_AC0127
+    m_nnPostFilterSEICharacteristicsInputPicOutputFlag[i] = cfg_nnPostFilterSEICharacteristicsInputPicOutputFlagList[i].values;
+    if (m_nnPostFilterSEICharacteristicsInputPicOutputFlag[i].size() == 0)
+    {
+      m_nnPostFilterSEICharacteristicsInputPicOutputFlag[i].push_back(0);
+    }
+#endif
   }
 
   if (isY4mFileExt(m_inputFileName))
@@ -4891,6 +4917,9 @@ bool EncAppCfg::xCheckParameter()
       xConfirmPara(m_nnPostFilterSEICharacteristicsId[i] > MAX_NNPFC_ID, "SEINNPostFilterCharacteristicsId must be in the range of 0 to 2^32-2");
       xConfirmPara(m_nnPostFilterSEICharacteristicsModeIdc[i] > 255, "SEINNPostFilterCharacteristicsModeIdc must be in the range of 0 to 255");
       xConfirmPara(m_nnPostFilterSEICharacteristicsPurpose[i] > 1023, "SEINNPostFilterCharacteristicsPurpose must be in the range of 0 to 1023");
+    #if JVET_AC0127
+      xConfirmPara(m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1[i] > 63, "SEINNPostFilterCharacteristicsNumberInputDecodedPicturesMinus1 must be in the range of 0 to 63");
+    #endif
       xConfirmPara(m_nnPostFilterSEICharacteristicsInpTensorBitDepthMinus8[i] > 24, "SEINNPostFilterCharacteristicsInpTensorBitDepthMinus8 must be in the range of 0 to 24");
       xConfirmPara(m_nnPostFilterSEICharacteristicsOutTensorBitDepthMinus8[i] > 24, "SEINNPostFilterCharacteristicsOutTensorBitDepthMinus8 must be in the range of 0 to 24");
       xConfirmPara(m_nnPostFilterSEICharacteristicsInpFormatIdc[i] > 255, "SEINNPostFilterCharacteristicsInpFormatIdc must be in the range of 0 to 255");
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index d771a4091f..f93817dd23 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -772,8 +772,15 @@ protected:
 
   bool                  m_nnPostFilterSEIActivationEnabled;
   uint32_t              m_nnPostFilterSEIActivationId;
+  #if JVET_AC0127
+  uint32_t              m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1[MAX_NUM_NN_POST_FILTERS];
+  #else
   uint32_t              m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2[MAX_NUM_NN_POST_FILTERS];
+  #endif
   std::vector<uint32_t> m_nnPostFilterSEICharacteristicsNumberInterpolatedPictures[MAX_NUM_NN_POST_FILTERS];
+  #if JVET_AC0127
+  std::vector<bool>     m_nnPostFilterSEICharacteristicsInputPicOutputFlag[MAX_NUM_NN_POST_FILTERS];
+  #endif
   bool                    m_nnPostFilterSEIActivationCancelFlag;
   bool                    m_nnPostFilterSEIActivationPersistenceFlag;
 
diff --git a/source/Lib/CommonLib/SEI.h b/source/Lib/CommonLib/SEI.h
index 18b901c893..236c01fbfb 100644
--- a/source/Lib/CommonLib/SEI.h
+++ b/source/Lib/CommonLib/SEI.h
@@ -1252,8 +1252,15 @@ public:
   uint32_t       m_numParametersIdc;
   uint32_t       m_numKmacOperationsIdc;
   uint32_t       m_totalKilobyteSize;
+#if JVET_AC0127
+  uint32_t       m_numberInputDecodedPicturesMinus1;
+#else
   uint32_t       m_numberInputDecodedPicturesMinus2;
+#endif
   std::vector<uint32_t> m_numberInterpolatedPictures;
+#if JVET_AC0127
+  std::vector<bool> m_inputPicOutputFlag;
+#endif
 };
 
 class SEINeuralNetworkPostFilterActivation : public SEI
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 8fa448a6b4..4b299ae24f 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -59,6 +59,9 @@
 #define JVET_AC0139_UNIFIED_MERGE                         1
 #define JVET_AC0096                                       1
 #define JVET_AC0154                                       1
+#define JVET_AC0127                                       1 // Combine the picture rate upsampling with other NNPF purposes
+
+
 //########### 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 d394a022ef..c698bab253 100644
--- a/source/Lib/DecoderLib/SEIread.cpp
+++ b/source/Lib/DecoderLib/SEIread.cpp
@@ -2650,6 +2650,12 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
   output_sei_message_header(sei, pDecodedMessageOutputStream, payloadSize);
   uint32_t val;
 
+#if JVET_AC0127
+    sei_read_code(pDecodedMessageOutputStream, 16, val, "nnpfc_purpose");
+    sei.m_purpose = val;
+    CHECK(sei.m_purpose >= 64 && sei.m_purpose <= 65535, "Reserved nnpfc_purpose value");
+#endif
+
   sei_read_uvlc( pDecodedMessageOutputStream, val, "nnpfc_id" );
   sei.m_id = val;
   CHECK((sei.m_id >= 256 && sei.m_id <= 511) || (sei.m_id >= (1<<31) && sei.m_id <= MAX_NNPFC_ID), "Reserved nnpfc_id value, shall ignore the SEI message");
@@ -2679,8 +2685,10 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
 
   if (sei.m_purposeAndFormattingFlag)
   {
+#if !JVET_AC0127
     sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_purpose");
     sei.m_purpose = val;
+#endif
 
     ChromaFormat chromaFormatIDC = sps->getChromaFormatIdc();
     uint8_t      subWidthC;
@@ -2700,7 +2708,17 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
       subWidthC  = 1;
       subHeightC = 1;
     }
+
+#if JVET_AC0127
+      sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_number_of_input_pictures_minus1");
+      sei.m_numberInputDecodedPicturesMinus1 = val;
+#endif
+
+#if JVET_AC0127
+    if((sei.m_purpose & 0x02) != 0)
+#else
     if(sei.m_purpose == 2 || sei.m_purpose == 4)
+#endif
     {
       sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_out_sub_c_flag");
       sei.m_outSubCFlag = val;
@@ -2726,8 +2744,14 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
       sei.m_outSubHeightC = subHeightC;
     }
 #endif
+
+#if JVET_AC0127
+    CHECK(((subWidthC == 1) && (subHeightC == 1)) && ((sei.m_purpose & 0x02) != 0),
+          "If SubWidthC is equal to 1 and SubHeightC is equal to 1, nnpfc_purpose & 0x02 shall be equal to 0");
+#else
     CHECK(((subWidthC == 1) && (subHeightC == 1)) && ((sei.m_purpose == 2) || (sei.m_purpose == 4)),
           "If SubWidthC is equal to 1 and SubHeightC is equal to 1, nnpfc_purpose shall not be equal to 2 or 4");
+#endif
 
 #if JVET_AC0154
     if((sei.m_purpose & NNPC_PurposeType::COLOURIZATION) != 0)
@@ -2750,19 +2774,32 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
     }
 #endif
 
+#if JVET_AC0127
+    if((sei.m_purpose & 0x04) != 0)
+#else
     if(sei.m_purpose == 3 || sei.m_purpose == 4)
+#endif
     {
       sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_pic_width_in_luma_samples");
       sei.m_picWidthInLumaSamples = val;
       sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_pic_height_in_luma_samples");
       sei.m_picHeightInLumaSamples = val;
     }
-    
-    if (sei.m_purpose == NNPC_PurposeType::FRAME_RATE_UPSAMPLING)
+
+#if JVET_AC0127
+    if((sei.m_purpose & 0x08) != 0)
+#else
+    if(sei.m_purpose == NNPC_PurposeType::FRAME_RATE_UPSAMPLING)
+#endif
     {
+#if JVET_AC0127
+      CHECK(sei.m_numberInputDecodedPicturesMinus1 <= 0, "If nnpfc_purpose is FRAME_RATE_UPSAMPLING, nnpfc_num_input_pics_minus1 shall be greater than 0");
+      sei.m_numberInterpolatedPictures.resize(sei.m_numberInputDecodedPicturesMinus1);
+#else
       sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_number_of_input_pictures_minus2");
       sei.m_numberInputDecodedPicturesMinus2 = val;
       sei.m_numberInterpolatedPictures.resize(sei.m_numberInputDecodedPicturesMinus2 + 1);
+#endif
 #if JVET_AC0154
       bool allZeroFlag = false;
       for (int i = 0; i < sei.m_numberInterpolatedPictures.size(); i++)
@@ -2782,6 +2819,14 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
         sei.m_numberInterpolatedPictures[i] = val;
       }
 #endif
+
+#if JVET_AC0127
+      for (int i = 0; i <= sei.m_numberInterpolatedPictures.size(); i++)
+      {
+        sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_input_pic_output_flag");
+        sei.m_inputPicOutputFlag[i] = val;
+      }
+#endif
     }
 
     sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_component_last_flag");
@@ -2823,6 +2868,9 @@ void SEIReader::xParseSEINNPostFilterCharacteristics(SEINeuralNetworkPostFilterC
 
     sei_read_uvlc(pDecodedMessageOutputStream, val, "nnpfc_out_order_idc");
     sei.m_outOrderIdc = val;
+#if JVET_AC0127
+    CHECK(((sei.m_purpose & 0x02) != 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
 
     sei_read_flag(pDecodedMessageOutputStream, val, "nnpfc_constant_patch_size_flag");
     sei.m_constantPatchSizeFlag = val;
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 31cfb14c29..12b082279f 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -725,8 +725,15 @@ protected:
   uint32_t                m_nnPostFilterSEICharacteristicsNumParametersIdc[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsNumKmacOperationsIdc[MAX_NUM_NN_POST_FILTERS];
   uint32_t                m_nnPostFilterSEICharacteristicsTotalKilobyteSize[MAX_NUM_NN_POST_FILTERS];
-  uint32_t                m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2[MAX_NUM_NN_POST_FILTERS];
+#if JVET_AC0127
+    uint32_t              m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1[MAX_NUM_NN_POST_FILTERS];
+#else
+    uint32_t                m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2[MAX_NUM_NN_POST_FILTERS];
+#endif
   std::vector<uint32_t>   m_nnPostFilterSEICharacteristicsNumberInterpolatedPictures[MAX_NUM_NN_POST_FILTERS];
+#if JVET_AC0127
+  std::vector<bool>       m_nnPostFilterSEICharacteristicsInputPicOutputFlag[MAX_NUM_NN_POST_FILTERS];
+#endif
 
   bool                    m_nnPostFilterSEIActivationEnabled;
   uint32_t                m_nnPostFilterSEIActivationId;
@@ -1973,10 +1980,19 @@ public:
 
   void        setNNPostFilterSEICharacteristicsPayloadFilename(std::string payloadFilename, int filterIdx)              { m_nnPostFilterSEICharacteristicsPayloadFilename[filterIdx] = payloadFilename; }
   std::string getNNPostFilterSEICharacteristicsPayloadFilename(int filterIdx) const                                     { return m_nnPostFilterSEICharacteristicsPayloadFilename[filterIdx]; }
+#if JVET_AC0127
+  void        setNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1(uint32_t value, int filterIdx)          { m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1[filterIdx] = value; }
+  uint32_t    getNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1(int filterIdx) const                    { return m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1[filterIdx]; }
+#else
   void        setNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2(uint32_t value, int filterIdx)          { m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2[filterIdx] = value; }
   uint32_t    getNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2(int filterIdx) const                    { return m_nnPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2[filterIdx]; }
+#endif
   void        setNNPostFilterSEICharacteristicsNumberInterpolatedPictures(std::vector<uint32_t> value, int filterIdx)   { m_nnPostFilterSEICharacteristicsNumberInterpolatedPictures[filterIdx] = value; }
   const       std::vector<uint32_t>& getNNPostFilterSEICharacteristicsNumberInterpolatedPictures(int filterIdx)         { return m_nnPostFilterSEICharacteristicsNumberInterpolatedPictures[filterIdx]; }
+#if JVET_AC0127
+  void        setNNPostFilterSEICharacteristicsInputPicOutputFlag(std::vector<bool> value, int filterIdx)   { m_nnPostFilterSEICharacteristicsInputPicOutputFlag[filterIdx] = value; }
+  const       std::vector<bool>& getNNPostFilterSEICharacteristicsInputPicOutputFlag(int filterIdx)         { return m_nnPostFilterSEICharacteristicsInputPicOutputFlag[filterIdx]; }
+#endif
   void        setNnPostFilterSEIActivationEnabled(bool enabledFlag)                                                     { m_nnPostFilterSEIActivationEnabled = enabledFlag; }
   bool        getNnPostFilterSEIActivationEnabled() const                                                               { return m_nnPostFilterSEIActivationEnabled; }
   void        setNnPostFilterSEIActivationId(uint32_t id)                                                               { m_nnPostFilterSEIActivationId = id; }
diff --git a/source/Lib/EncoderLib/SEIEncoder.cpp b/source/Lib/EncoderLib/SEIEncoder.cpp
index 6f92e4ed78..3962a6b91f 100644
--- a/source/Lib/EncoderLib/SEIEncoder.cpp
+++ b/source/Lib/EncoderLib/SEIEncoder.cpp
@@ -1296,6 +1296,9 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP
 {
   CHECK(!(m_isInitialized), "Unspecified error");
   CHECK(!(sei != nullptr), "Unspecified error");
+#if JVET_AC0127
+  sei->m_purpose = m_pcCfg->getNNPostFilterSEICharacteristicsPurpose(filterIdx);
+#endif
   sei->m_id = m_pcCfg->getNNPostFilterSEICharacteristicsId(filterIdx);
   sei->m_modeIdc = m_pcCfg->getNNPostFilterSEICharacteristicsModeIdc(filterIdx);
   if (sei->m_modeIdc == POST_FILTER_MODE::URI)
@@ -1306,9 +1309,20 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP
   sei->m_purposeAndFormattingFlag = m_pcCfg->getNNPostFilterSEICharacteristicsPurposeAndFormattingFlag(filterIdx);
   if (sei->m_purposeAndFormattingFlag)
   {
-    sei->m_purpose = m_pcCfg->getNNPostFilterSEICharacteristicsPurpose(filterIdx);
+#if !JVET_AC0127
+  sei->m_purpose = m_pcCfg->getNNPostFilterSEICharacteristicsPurpose(filterIdx);
+#endif
 
+#if JVET_AC0127
+      sei->m_numberInputDecodedPicturesMinus1 = m_pcCfg->getNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus1(filterIdx);
+      CHECK(sei->m_numberInputDecodedPicturesMinus1 <= 0, "If nnpfc_purpose is FRAME_RATE_UPSAMPLING, m_numberInputDecodedPicturesMinus1 shall be greater than 0");
+#endif
+
+#if JVET_AC0127
+    if(sei->m_purpose & 0x02 != 0)
+#else
     if(sei->m_purpose == 2 || sei->m_purpose == 4)
+#endif
     {
       sei->m_outSubCFlag = m_pcCfg->getNNPostFilterSEICharacteristicsOutSubCFlag(filterIdx);
     }
@@ -1318,7 +1332,11 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP
       sei->m_outColourFormatIdc = m_pcCfg->getNNPostFilterSEICharacteristicsOutColourFormatIdc(filterIdx);
     }
 #endif
+#if JVET_AC0127
+    if(sei->m_purpose & 0x04 != 0)
+#else
     if(sei->m_purpose == 3 || sei->m_purpose == 4)
+#endif
     {
       sei->m_picWidthInLumaSamples = m_pcCfg->getNNPostFilterSEICharacteristicsPicWidthInLumaSamples(filterIdx);
       sei->m_picHeightInLumaSamples = m_pcCfg->getNNPostFilterSEICharacteristicsPicHeightInLumaSamples(filterIdx);
@@ -1352,10 +1370,19 @@ void SEIEncoder::initSEINeuralNetworkPostFilterCharacteristics(SEINeuralNetworkP
       CHECK(!(sei->m_picWidthInLumaSamples >= croppedWidth && sei->m_picWidthInLumaSamples <= croppedWidth * 16 - 1), "m_picWidthInLumaSamples shall be in the range of croppedWidth to croppedWidth * 16 - 1");
       CHECK(!(sei->m_picHeightInLumaSamples >= croppedHeight && sei->m_picHeightInLumaSamples <= croppedHeight * 16 - 1), "m_picHeightInLumaSamples shall be in the range of croppedHeight to croppedHeight * 16 - 1");
     }
+#if JVET_AC0127
+    if(sei->m_purpose & 0x08 != 0)
+#else
     if (sei->m_purpose == NNPC_PurposeType::FRAME_RATE_UPSAMPLING)
+#endif
     {
+#if !JVET_AC0127
       sei->m_numberInputDecodedPicturesMinus2 = m_pcCfg->getNNPostFilterSEICharacteristicsNumberInputDecodedPicturesMinus2(filterIdx);
+#endif
       sei->m_numberInterpolatedPictures = m_pcCfg->getNNPostFilterSEICharacteristicsNumberInterpolatedPictures(filterIdx);
+#if JVET_AC0127
+      sei->m_inputPicOutputFlag = m_pcCfg->getNNPostFilterSEICharacteristicsInputPicOutputFlag(filterIdx);
+#endif
     }
 
     sei->m_componentLastFlag = m_pcCfg->getNNPostFilterSEICharacteristicsComponentLastFlag(filterIdx);
diff --git a/source/Lib/EncoderLib/SEIwrite.cpp b/source/Lib/EncoderLib/SEIwrite.cpp
index 5be7b918e5..ef49ba0737 100644
--- a/source/Lib/EncoderLib/SEIwrite.cpp
+++ b/source/Lib/EncoderLib/SEIwrite.cpp
@@ -1680,6 +1680,9 @@ void SEIWriter::xWriteSEIGreenMetadataInfo(const SEIGreenMetadataInfo& sei)
 
 void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralNetworkPostFilterCharacteristics &sei)
 {
+#if JVET_AC0127
+  xWriteCode(sei.m_purpose, 16, "nnpfc_purpose");
+#endif
   xWriteUvlc(sei.m_id, "nnpfc_id");
   xWriteUvlc(sei.m_modeIdc, "nnpfc_mode_idc");
   if (sei.m_modeIdc == POST_FILTER_MODE::URI)
@@ -1694,9 +1697,18 @@ void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralN
   xWriteFlag(sei.m_purposeAndFormattingFlag, "nnpfc_purpose_and_formatting_flag");
   if (sei.m_purposeAndFormattingFlag)
   {
+#if !JVET_AC0127
     xWriteUvlc(sei.m_purpose, "nnpfc_purpose");
+#endif
+#if JVET_AC0127
+    xWriteUvlc(sei.m_numberInputDecodedPicturesMinus1, "nnpfc_number_of_input_pictures_minus1");
+#endif
 
+#if JVET_AC0127
+    if((sei.m_purpose & 0x02) != 0)
+#else
     if(sei.m_purpose == 2 || sei.m_purpose == 4)
+#endif
     {
       xWriteFlag(sei.m_outSubCFlag, "nnpfc_out_sub_c_flag");
     }
@@ -1706,18 +1718,38 @@ void SEIWriter::xWriteSEINeuralNetworkPostFilterCharacteristics(const SEINeuralN
       xWriteCode(uint32_t(sei.m_outColourFormatIdc), 2, "nnpfc_out_colour_format_idc");
     }
 #endif
+#if JVET_AC0127
+    if((sei.m_purpose & 0x04) != 0)
+#else
     if(sei.m_purpose == 3 || sei.m_purpose == 4)
+#endif
     {
       xWriteUvlc(sei.m_picWidthInLumaSamples, "nnpfc_pic_width_in_luma_samples");
       xWriteUvlc(sei.m_picHeightInLumaSamples, "nnpfc_pic_height_in_luma_samples");
     }
-    if (sei.m_purpose == NNPC_PurposeType::CHROMA_UPSAMPLING) 
+
+#if JVET_AC0127
+    if((sei.m_purpose & 0x08) != 0)
+#else
+    if (sei.m_purpose == NNPC_PurposeType::FRAME_RATE_UPSAMPLING) 
+#endif
     {
+#if JVET_AC0127
+      for (int i = 0; i < sei.m_numberInputDecodedPicturesMinus1; ++i)
+      {
+        xWriteUvlc(sei.m_numberInterpolatedPictures[i], "nnpfc_interpolated_pictures");
+      }
+      for (int i = 0; i <= sei.m_numberInputDecodedPicturesMinus1; ++i)
+      {
+        xWriteFlag(sei.m_inputPicOutputFlag[i], "nnpfc_input_pic_output_flag");
+      }
+#else
       xWriteUvlc(sei.m_numberInputDecodedPicturesMinus2, "nnpfc_number_of_input_pictures_minus2");
       for (int i = 0; i <= sei.m_numberInputDecodedPicturesMinus2; ++i)
       {
         xWriteUvlc(sei.m_numberInterpolatedPictures[i], "nnpfc_interpolated_pictures");
       }
+#endif
     }
 
     xWriteFlag(sei.m_componentLastFlag, "nnpfc_component_last_flag");
-- 
GitLab