From cd41499e80d85966178838ddbd3d0915696d67da Mon Sep 17 00:00:00 2001
From: Karsten Suehring <karsten.suehring@hhi.fraunhofer.de>
Date: Tue, 19 Nov 2019 23:59:17 +0100
Subject: [PATCH] JVET-P0588/P0452: Suffix APS (based on !1090)

---
 source/App/EncoderApp/EncApp.cpp |  5 +++++
 source/App/Parcat/parcat.cpp     |  9 ++++++++
 source/Lib/CommonLib/Rom.cpp     | 10 +++++++++
 source/Lib/CommonLib/TypeDef.h   | 17 ++++++++++++---
 source/Lib/DecoderLib/DecLib.cpp |  5 +++++
 source/Lib/EncoderLib/EncGOP.cpp | 36 +++++++++++++++++++++++++++++---
 source/Lib/EncoderLib/EncGOP.h   |  6 +++++-
 7 files changed, 81 insertions(+), 7 deletions(-)

diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 34e3951a0..8023735a7 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -1181,7 +1181,12 @@ void EncApp::rateStatsAccum(const AccessUnit& au, const std::vector<uint32_t>& a
     case NAL_UNIT_VPS:
     case NAL_UNIT_SPS:
     case NAL_UNIT_PPS:
+#if JVET_P0588_SUFFIX_APS
+    case NAL_UNIT_PREFIX_APS:
+    case NAL_UNIT_SUFFIX_APS:
+#else
     case NAL_UNIT_APS:
+#endif
       m_essentialBytes += *it_stats;
       break;
     default:
diff --git a/source/App/Parcat/parcat.cpp b/source/App/Parcat/parcat.cpp
index 470e4f696..f614dcc1a 100644
--- a/source/App/Parcat/parcat.cpp
+++ b/source/App/Parcat/parcat.cpp
@@ -200,7 +200,12 @@ const char * NALU_TYPE[] =
     "NAL_UNIT_VPS",
     "NAL_UNIT_SPS",
     "NAL_UNIT_PPS",
+#if JVET_P0588_SUFFIX_APS
+    "NAL_UNIT_PREFIX_APS",
+    "NAL_UNIT_SUFFIX_APS",
+#else
     "NAL_UNIT_APS",
+#endif
     "NAL_UNIT_PH",
     "NAL_UNIT_ACCESS_UNIT_DELIMITER",
     "NAL_UNIT_EOS",
@@ -393,7 +398,11 @@ std::vector<uint8_t> filter_segment(const std::vector<uint8_t> & v, int idx, int
       idr_found = true;
     }
 
+#if JVET_P0588_SUFFIX_APS
+    if( ( idx > 1 && ( nalu_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu_type == NAL_UNIT_CODED_SLICE_IDR_N_LP ) ) || ( ( idx > 1 && !idr_found ) && ( nalu_type == NAL_UNIT_DPS || nalu_type == NAL_UNIT_VPS || nalu_type == NAL_UNIT_SPS || nalu_type == NAL_UNIT_PPS || nalu_type == NAL_UNIT_PREFIX_APS || nalu_type == NAL_UNIT_SUFFIX_APS || nalu_type == NAL_UNIT_ACCESS_UNIT_DELIMITER ) )
+#else
     if((idx > 1 && (nalu_type == NAL_UNIT_CODED_SLICE_IDR_W_RADL || nalu_type == NAL_UNIT_CODED_SLICE_IDR_N_LP)) || ((idx > 1 && !idr_found) && (nalu_type == NAL_UNIT_DPS || nalu_type == NAL_UNIT_VPS ||nalu_type == NAL_UNIT_SPS || nalu_type == NAL_UNIT_PPS || nalu_type == NAL_UNIT_APS || nalu_type == NAL_UNIT_ACCESS_UNIT_DELIMITER))
+#endif
       || (nalu_type == NAL_UNIT_SUFFIX_SEI && skip_next_sei))
     {
     }
diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp
index 4762f063b..61891f4b8 100644
--- a/source/Lib/CommonLib/Rom.cpp
+++ b/source/Lib/CommonLib/Rom.cpp
@@ -75,7 +75,12 @@ const char* nalUnitTypeToString(NalUnitType type)
   case NAL_UNIT_VPS:                    return "VPS";
   case NAL_UNIT_SPS:                    return "SPS";
   case NAL_UNIT_PPS:                    return "PPS";
+#if JVET_P0588_SUFFIX_APS
+  case NAL_UNIT_PREFIX_APS:             return "Prefix APS";
+  case NAL_UNIT_SUFFIX_APS:             return "Suffix APS";
+#else
   case NAL_UNIT_APS:                    return "APS";
+#endif
   case NAL_UNIT_PH:                     return "PH";
   case NAL_UNIT_ACCESS_UNIT_DELIMITER:  return "AUD";
   case NAL_UNIT_EOS:                    return "EOS";
@@ -90,7 +95,12 @@ const char* nalUnitTypeToString(NalUnitType type)
   case NAL_UNIT_ACCESS_UNIT_DELIMITER:  return "AUD";
   case NAL_UNIT_PREFIX_SEI:             return "Prefix SEI";
   case NAL_UNIT_SUFFIX_SEI:             return "Suffix SEI";
+#if JVET_P0588_SUFFIX_APS
+  case NAL_UNIT_PREFIX_APS:             return "Prefix APS";
+  case NAL_UNIT_SUFFIX_APS:             return "Suffix APS";
+#else
   case NAL_UNIT_APS:                    return "APS";
+#endif
   case NAL_UNIT_CODED_SLICE_TRAIL:      return "TRAIL";
   case NAL_UNIT_CODED_SLICE_STSA:       return "STSA";
   case NAL_UNIT_CODED_SLICE_RADL:       return "RADL";
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 7c0026daa..a9ae67945 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -71,6 +71,9 @@
 #define JVET_P0371_CHROMA_SCALING_OFFSET                  1 // JVET-P0371: Signalling offset for chroma residual scaling
 
 #define JVET_P0469_QP_OUT_VAL                             1 // JVET-P0469: Coding delta_qp_diff_val instead of delta_qp_out_val
+
+#define JVET_P0588_SUFFIX_APS                             1 // JVET-P0588/P0452: suffix APS NUT
+
 #define JVET_P0803_COMBINED_MIP_CLEANUP                   1 // JVET-P0803: Several MIP cleanups
 #define JVET_P0199_P0289_P0303_MIP_FULLMATRIX             1 // JVET-P0199/P0289/P0303: Full matrix multiplication for all MIP block shapes
 
@@ -969,9 +972,12 @@ enum NalUnitType
   NAL_UNIT_VPS,                     // 14
   NAL_UNIT_SPS,                     // 15
   NAL_UNIT_PPS,                     // 16
-  NAL_UNIT_APS,                     // Todo: Remove this line after prefix and suffix APS have been implemented
-  //NAL_UNIT_PREFIX_APS,              // 17
-  //NAL_UNIT_SUFFIX_APS,              // 18
+#if JVET_P0588_SUFFIX_APS
+  NAL_UNIT_PREFIX_APS,              // 17
+  NAL_UNIT_SUFFIX_APS,              // 18
+#else
+  NAL_UNIT_APS,
+#endif
   NAL_UNIT_PH,                      // 19
   NAL_UNIT_ACCESS_UNIT_DELIMITER,   // 20
   NAL_UNIT_EOS,                     // 21
@@ -1015,7 +1021,12 @@ enum NalUnitType
 
   NAL_UNIT_SPS,                     // 16
   NAL_UNIT_PPS,                     // 17
+#if JVET_P0588_SUFFIX_APS
+  NAL_UNIT_PREFIX_APS,              // 17
+  NAL_UNIT_SUFFIX_APS,              // 18
+#else
   NAL_UNIT_APS,                     // 18
+#endif
   NAL_UNIT_ACCESS_UNIT_DELIMITER,   // 19
   NAL_UNIT_EOS,                     // 20
   NAL_UNIT_EOB,                     // 21
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index bd3a3f817..473455a21 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -1773,7 +1773,12 @@ bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay)
     case NAL_UNIT_PPS:
       xDecodePPS( nalu );
       return false;
+#if JVET_P0588_SUFFIX_APS
+    case NAL_UNIT_PREFIX_APS:
+    case NAL_UNIT_SUFFIX_APS:
+#else
     case NAL_UNIT_APS:
+#endif
       xDecodeAPS(nalu);
       return false;
 
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 7710ee6f3..275bb7434 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -355,9 +355,15 @@ int EncGOP::xWritePPS( AccessUnit &accessUnit, const PPS *pps, const SPS *sps, c
   return (int)(accessUnit.back()->m_nalUnitData.str().size()) * 8;
 }
 
+#if JVET_P0588_SUFFIX_APS
+int EncGOP::xWriteAPS( AccessUnit &accessUnit, APS *aps, const int layerId, const bool isPrefixNUT )
+{
+  OutputNALUnit nalu( isPrefixNUT ? NAL_UNIT_PREFIX_APS : NAL_UNIT_SUFFIX_APS );
+#else
 int EncGOP::xWriteAPS( AccessUnit &accessUnit, APS *aps, const int layerId )
 {
   OutputNALUnit nalu(NAL_UNIT_APS);
+#endif
   m_HLSWriter->setBitstream(&nalu.m_Bitstream);
   nalu.m_nuhLayerId = layerId;
   nalu.m_temporalId = aps->getTemporalId();
@@ -2967,9 +2973,17 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         if (writeAPS)
         {
 #if JVET_N0278_FIXES
+#if JVET_P0588_SUFFIX_APS
+          actualTotalBits += xWriteAPS( accessUnit, aps, m_pcEncLib->getLayerId(), false );
+#else
           actualTotalBits += xWriteAPS( accessUnit, aps, m_pcEncLib->getLayerId() );
+#endif
+#else
+#if JVET_P0588_SUFFIX_APS
+          actualTotalBits += xWriteAPS(accessUnit, aps, 0, false );
 #else
-          actualTotalBits += xWriteAPS(accessUnit, aps);
+          actualTotalBits += xWriteAPS(accessUnit, aps, 0 );
+#endif
 #endif
           apsMap->clearChangedFlag((apsId << NUM_APS_TYPE_LEN) + LMCS_APS);
           CHECK(aps != pcSlice->getLmcsAPS(), "Wrong LMCS APS pointer in compressGOP");
@@ -2986,9 +3000,17 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         if( writeAPS )
         {
 #if JVET_N0278_FIXES
+#if JVET_P0588_SUFFIX_APS
+          actualTotalBits += xWriteAPS( accessUnit, aps, m_pcEncLib->getLayerId(), false );
+#else
           actualTotalBits += xWriteAPS( accessUnit, aps, m_pcEncLib->getLayerId() );
+#endif
+#else
+#if JVET_P0588_SUFFIX_APS
+          actualTotalBits += xWriteAPS( accessUnit, aps, 0, false );
 #else
-          actualTotalBits += xWriteAPS( accessUnit, aps );
+          actualTotalBits += xWriteAPS( accessUnit, aps, 0 );
+#endif
 #endif
           apsMap->clearChangedFlag( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS );
           CHECK( aps != pcSlice->getscalingListAPS(), "Wrong SCALING LIST APS pointer in compressGOP" );
@@ -3014,9 +3036,17 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
           if (writeAPS )
           {
 #if JVET_N0278_FIXES
+#if JVET_P0588_SUFFIX_APS
+            actualTotalBits += xWriteAPS( accessUnit, aps, m_pcEncLib->getLayerId(), false );
+#else
             actualTotalBits += xWriteAPS( accessUnit, aps, m_pcEncLib->getLayerId() );
+#endif
+#else
+#if JVET_P0588_SUFFIX_APS
+            actualTotalBits += xWriteAPS( accessUnit, aps, 0, false );
 #else
-            actualTotalBits += xWriteAPS(accessUnit, aps);
+            actualTotalBits += xWriteAPS(accessUnit, aps, 0);
+#endif
 #endif
             apsMap->clearChangedFlag((apsId << NUM_APS_TYPE_LEN) + ALF_APS);
             CHECK(aps != pcSlice->getAlfAPSs()[apsId], "Wrong APS pointer in compressGOP");
diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h
index fd3628bee..f49e2c773 100644
--- a/source/Lib/EncoderLib/EncGOP.h
+++ b/source/Lib/EncoderLib/EncGOP.h
@@ -324,7 +324,11 @@ protected:
   int xWriteDPS (AccessUnit &accessUnit, const DPS *dps);
   int xWriteSPS (AccessUnit &accessUnit, const SPS *sps);
   int xWritePPS( AccessUnit &accessUnit, const PPS *pps, const SPS *sps, const int layerId = 0 );
-  int xWriteAPS( AccessUnit &accessUnit, APS *aps, const int layerId = 0 );
+#if JVET_P0588_SUFFIX_APS
+  int xWriteAPS( AccessUnit &accessUnit, APS *aps, const int layerId, const bool isPrefixNUT );
+#else
+  int xWriteAPS( AccessUnit &accessUnit, APS *aps, const int layerId );
+#endif
   int xWriteParameterSets (AccessUnit &accessUnit, Slice *slice, const bool bSeqFirst);
 
   void applyDeblockingFilterMetric( Picture* pcPic, uint32_t uiNumSlices );
-- 
GitLab