From 2d15ef72ddcd3273ed9122197bbac661478112cc Mon Sep 17 00:00:00 2001
From: "moonmo.koo" <moonmo.koo@lge.com>
Date: Sat, 24 Aug 2019 10:50:13 +0900
Subject: [PATCH] JVET_O0299: Support for user defined Scaling List Matrices in
 the APS - This merge request provides the implementation for JVET_O0299,
 i.e., Support for user defined Scaling List Matrics in the APS.

---
 source/Lib/CommonLib/CodingStructure.cpp |  3 +
 source/Lib/CommonLib/CodingStructure.h   |  3 +
 source/Lib/CommonLib/Picture.cpp         | 16 +++++
 source/Lib/CommonLib/Picture.h           |  4 ++
 source/Lib/CommonLib/Slice.cpp           | 19 ++++++
 source/Lib/CommonLib/Slice.h             | 31 ++++++++++
 source/Lib/CommonLib/TypeDef.h           |  5 ++
 source/Lib/DecoderLib/DecLib.cpp         | 63 ++++++++++++++++++++
 source/Lib/DecoderLib/DecSlice.cpp       |  3 +
 source/Lib/DecoderLib/VLCReader.cpp      | 39 +++++++++++++
 source/Lib/DecoderLib/VLCReader.h        |  3 +
 source/Lib/EncoderLib/EncGOP.cpp         | 52 +++++++++++++++++
 source/Lib/EncoderLib/EncGOP.h           |  3 +
 source/Lib/EncoderLib/EncLib.cpp         | 74 +++++++++++++++++++++++-
 source/Lib/EncoderLib/EncLib.h           |  7 +++
 source/Lib/EncoderLib/VLCWriter.cpp      | 28 +++++++++
 source/Lib/EncoderLib/VLCWriter.h        |  3 +
 17 files changed, 354 insertions(+), 2 deletions(-)

diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index 93faa5f5aa..2df5fd5627 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -1026,6 +1026,9 @@ void CodingStructure::initSubStructure( CodingStructure& subStruct, const Channe
   memcpy(subStruct.alfApss, alfApss, sizeof(alfApss));
 
   subStruct.lmcsAps = lmcsAps;
+#if JVET_O0299_APS_SCALINGLIST
+  subStruct.scalinglistAps = scalinglistAps;
+#endif
 
   subStruct.slice     = slice;
   subStruct.baseQP    = baseQP;
diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h
index 082238419a..d3c5c248f2 100644
--- a/source/Lib/CommonLib/CodingStructure.h
+++ b/source/Lib/CommonLib/CodingStructure.h
@@ -107,6 +107,9 @@ public:
   APS*       alfApss[MAX_NUM_APS];
 #endif
   APS *      lmcsAps;
+#if JVET_O0299_APS_SCALINGLIST
+  APS *      scalinglistAps;
+#endif
   const VPS *vps;
   const PreCalcValues* pcv;
 
diff --git a/source/Lib/CommonLib/Picture.cpp b/source/Lib/CommonLib/Picture.cpp
index 776b2fa956..73d3e108ad 100644
--- a/source/Lib/CommonLib/Picture.cpp
+++ b/source/Lib/CommonLib/Picture.cpp
@@ -886,7 +886,11 @@ const CPelUnitBuf Picture::getRecoBuf(const UnitArea &unit, bool wrap)     const
        PelUnitBuf Picture::getRecoBuf(bool wrap)                                 { return M_BUFS(scheduler.getSplitPicId(), wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION); }
 const CPelUnitBuf Picture::getRecoBuf(bool wrap)                           const { return M_BUFS(scheduler.getSplitPicId(), wrap ? PIC_RECON_WRAP : PIC_RECONSTRUCTION); }
 
+#if JVET_O0299_APS_SCALINGLIST
+void Picture::finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS& lmcsAps, APS& scalingListAps )
+#else
 void Picture::finalInit(const SPS& sps, const PPS& pps, APS** alfApss, APS& lmcsAps)
+#endif
 {
   for( auto &sei : SEIs )
   {
@@ -927,6 +931,9 @@ void Picture::finalInit(const SPS& sps, const PPS& pps, APS** alfApss, APS& lmcs
   cs->pps     = &pps;
   memcpy(cs->alfApss, alfApss, sizeof(cs->alfApss));
   cs->lmcsAps = &lmcsAps;
+#if JVET_O0299_APS_SCALINGLIST  
+  cs->scalinglistAps = &scalingListAps;
+#endif
 
   cs->pcv     = pps.pcv;
 
@@ -947,6 +954,9 @@ void Picture::allocateNewSlice()
   memcpy(slice.getAlfAPSs(), cs->alfApss, sizeof(cs->alfApss));
 
   slice.setLmcsAPS(cs->lmcsAps);
+#if JVET_O0299_APS_SCALINGLIST
+  slice.setscalingListAPS( cs->scalinglistAps );
+#endif
 
   slice.setPPS( cs->pps);
   slice.setSPS( cs->sps);
@@ -964,6 +974,9 @@ Slice *Picture::swapSliceObject(Slice * p, uint32_t i)
   p->setAlfAPSs(cs->alfApss);
 
   p->setLmcsAPS(cs->lmcsAps);
+#if JVET_O0299_APS_SCALINGLIST
+  p->setscalingListAPS( cs->scalinglistAps );
+#endif
 
   Slice * pTmp = slices[i];
   slices[i] = p;
@@ -976,6 +989,9 @@ Slice *Picture::swapSliceObject(Slice * p, uint32_t i)
 #endif
 
   pTmp->setLmcsAPS(0);
+#if JVET_O0299_APS_SCALINGLIST
+  pTmp->setscalingListAPS( 0 );
+#endif
   return pTmp;
 }
 
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index ae97b1d917..f8e62a92c0 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -237,7 +237,11 @@ struct Picture : public UnitArea
   const CPelUnitBuf getBuf(const UnitArea &unit,     const PictureType &type) const;
 
   void extendPicBorder();
+#if JVET_O0299_APS_SCALINGLIST
+  void finalInit( const SPS& sps, const PPS& pps, APS** alfApss, APS& lmcsAps, APS& scalingListAps );
+#else
   void finalInit(const SPS& sps, const PPS& pps, APS** alfApss, APS& lmcsAps);
+#endif
 
   int  getPOC()                               const { return poc; }
   void setBorderExtension( bool bFlag)              { m_bIsBorderExtended = bFlag;}
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index d068d5c875..9c75bcf3cb 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -125,6 +125,11 @@ Slice::Slice()
 , m_lmcsAps                      (nullptr)
 , m_tileGroupLmcsEnabledFlag     (false)
 , m_tileGroupLmcsChromaResidualScaleFlag (false)
+#if JVET_O0299_APS_SCALINGLIST
+, m_scalingListApsId             ( -1 )
+, m_scalingListAps               ( nullptr )
+, m_tileGroupscalingListPresentFlag ( false )
+#endif
 {
   for(uint32_t i=0; i<NUM_REF_PIC_LIST_01; i++)
   {
@@ -734,6 +739,12 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
   m_tileGroupLmcsChromaResidualScaleFlag = pSrc->m_tileGroupLmcsChromaResidualScaleFlag;
   m_lmcsAps = pSrc->m_lmcsAps;
   m_lmcsApsId = pSrc->m_lmcsApsId;
+
+#if JVET_O0299_APS_SCALINGLIST
+  m_tileGroupscalingListPresentFlag = pSrc->m_tileGroupscalingListPresentFlag;
+  m_scalingListAps                  = pSrc->m_scalingListAps;
+  m_scalingListApsId                = pSrc->m_scalingListApsId;
+#endif
 }
 
 
@@ -2298,7 +2309,11 @@ uint32_t PreCalcValues::getMinQtSize( const Slice &slice, const ChannelType chTy
 }
 
 #if JVET_O1164_RPR
+#if JVET_O0299_APS_SCALINGLIST
+void Slice::scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS& lmcsAps, APS& scalingListAps, const bool isDecoder )
+#else
 void Slice::scaleRefPicList( Picture *scaledRefPic[], APS** apss, APS& lmcsAps, const bool isDecoder )
+#endif
 {
   int i;
   const SPS* sps = getSPS();
@@ -2373,7 +2388,11 @@ void Slice::scaleRefPicList( Picture *scaledRefPic[], APS** apss, APS& lmcsAps,
             scaledRefPic[j]->reconstructed = false;
             scaledRefPic[j]->referenced = true;
 
+#if JVET_O0299_APS_SCALINGLIST
+            scaledRefPic[ j ]->finalInit( *sps, *pps, apss, lmcsAps, scalingListAps );
+#else
             scaledRefPic[j]->finalInit( *sps, *pps, apss, lmcsAps );
+#endif
 
             scaledRefPic[j]->poc = -1;
 
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index ab8699180a..8af8b24927 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1065,10 +1065,12 @@ public:
 
   bool                    getScalingListFlag() const                                                      { return m_scalingListEnabledFlag;                                     }
   void                    setScalingListFlag( bool b )                                                    { m_scalingListEnabledFlag  = b;                                       }
+#if !JVET_O0299_APS_SCALINGLIST          // remove from SPS
   bool                    getScalingListPresentFlag() const                                               { return m_scalingListPresentFlag;                                     }
   void                    setScalingListPresentFlag( bool b )                                             { m_scalingListPresentFlag  = b;                                       }
   ScalingList&            getScalingList()                                                                { return m_scalingList; }
   const ScalingList&      getScalingList() const                                                          { return m_scalingList; }
+#endif
   uint32_t                    getMaxDecPicBuffering(uint32_t tlayer) const                                        { return m_uiMaxDecPicBuffering[tlayer];                               }
   void                    setMaxDecPicBuffering( uint32_t ui, uint32_t tlayer )                                   { CHECK(tlayer >= MAX_TLAYER, "Invalid T-layer"); m_uiMaxDecPicBuffering[tlayer] = ui;    }
   uint32_t                    getMaxLatencyIncreasePlus1(uint32_t tlayer) const                                   { return m_uiMaxLatencyIncreasePlus1[tlayer];                          }
@@ -1315,8 +1317,10 @@ private:
   bool             m_ppsDeblockingFilterDisabledFlag;
   int              m_deblockingFilterBetaOffsetDiv2;    //< beta offset for deblocking filter
   int              m_deblockingFilterTcOffsetDiv2;      //< tc offset for deblocking filter
+#if !JVET_O0299_APS_SCALINGLIST     // PPS
   bool             m_scalingListPresentFlag;
   ScalingList      m_scalingList;                       //!< ScalingList class
+#endif
   bool             m_listsModificationPresentFlag;
   uint32_t             m_log2ParallelMergeLevelMinus2;
   int              m_numExtraSliceHeaderBits;
@@ -1473,10 +1477,12 @@ public:
   int                    getDeblockingFilterBetaOffsetDiv2() const                        { return m_deblockingFilterBetaOffsetDiv2;      } //!< get beta offset for deblocking filter
   void                   setDeblockingFilterTcOffsetDiv2(int val)                         { m_deblockingFilterTcOffsetDiv2 = val;         } //!< set tc offset for deblocking filter
   int                    getDeblockingFilterTcOffsetDiv2() const                          { return m_deblockingFilterTcOffsetDiv2;        } //!< get tc offset for deblocking filter
+#if! JVET_O0299_APS_SCALINGLIST           // PPS
   bool                   getScalingListPresentFlag() const                                { return m_scalingListPresentFlag;              }
   void                   setScalingListPresentFlag( bool b )                              { m_scalingListPresentFlag  = b;                }
   ScalingList&           getScalingList()                                                 { return m_scalingList;                         }
   const ScalingList&     getScalingList() const                                           { return m_scalingList;                         }
+#endif
   bool                   getListsModificationPresentFlag() const                          { return m_listsModificationPresentFlag;        }
   void                   setListsModificationPresentFlag( bool b )                        { m_listsModificationPresentFlag = b;           }
   uint32_t                   getLog2ParallelMergeLevelMinus2() const                          { return m_log2ParallelMergeLevelMinus2;        }
@@ -1521,6 +1527,9 @@ private:
   int                    m_APSType;                  // aps_params_type
   AlfParam               m_alfAPSParam;
   SliceReshapeInfo       m_reshapeAPSInfo;
+#if JVET_O0299_APS_SCALINGLIST
+  ScalingList            m_scalingListApsInfo;
+#endif
 
 public:
   APS();
@@ -1539,6 +1548,10 @@ public:
 
   void                   setReshaperAPSInfo(SliceReshapeInfo& reshapeAPSInfo)             { m_reshapeAPSInfo = reshapeAPSInfo;            }
   SliceReshapeInfo&      getReshaperAPSInfo()                                             { return m_reshapeAPSInfo;                      }
+#if JVET_O0299_APS_SCALINGLIST
+  void                   setScalingList( ScalingList& scalingListAPSInfo )                { m_scalingListApsInfo = scalingListAPSInfo;    }
+  ScalingList&           getScalingList()                                                 { return m_scalingListApsInfo;                  }
+#endif
 };
 struct WPScalingParam
 {
@@ -1706,6 +1719,11 @@ private:
   APS*                       m_lmcsAps;
   bool                       m_tileGroupLmcsEnabledFlag;
   bool                       m_tileGroupLmcsChromaResidualScaleFlag;
+#if JVET_O0299_APS_SCALINGLIST
+  int                        m_scalingListApsId;
+  APS*                       m_scalingListAps;
+  bool                       m_tileGroupscalingListPresentFlag;
+#endif
 public:
                               Slice();
   virtual                     ~Slice();
@@ -1734,6 +1752,15 @@ public:
   void                        setLmcsChromaResidualScaleFlag(bool b)                 { m_tileGroupLmcsChromaResidualScaleFlag = b;                  }
   bool                        getLmcsChromaResidualScaleFlag()                       { return m_tileGroupLmcsChromaResidualScaleFlag;               }
   const bool                  getLmcsChromaResidualScaleFlag()                 const { return m_tileGroupLmcsChromaResidualScaleFlag;               }
+#if JVET_O0299_APS_SCALINGLIST
+  void                        setscalingListAPS( APS* scalingListAps )               { m_scalingListAps = scalingListAps; m_scalingListApsId = ( scalingListAps ) ? scalingListAps->getAPSId() : -1; }
+  APS*                        getscalingListAPS()                                    { return m_scalingListAps;                                     }
+  void                        setscalingListAPSId( int scalingListApsId )            { m_scalingListApsId = scalingListApsId;                       }
+  int                         getscalingListAPSId()                            const { return m_scalingListApsId;                                   }
+  void                        setscalingListPresentFlag( bool b )                    { m_tileGroupscalingListPresentFlag = b;                       }
+  bool                        getscalingListPresentFlag()                            { return m_tileGroupscalingListPresentFlag;                    }
+  const bool                  getscalingListPresentFlag()                      const { return m_tileGroupLmcsEnabledFlag;                           }
+#endif
   void                        setPicOutputFlag( bool b   )                           { m_PicOutputFlag = b;                                          }
   bool                        getPicOutputFlag() const                               { return m_PicOutputFlag;                                       }
   void                        setSaoEnabledFlag(ChannelType chType, bool s)          {m_saoEnabledFlag[chType] =s;                                   }
@@ -2003,7 +2030,11 @@ public:
   void                        setDisableSATDForRD(bool b) { m_disableSATDForRd = b; }
   bool                        getDisableSATDForRD() { return m_disableSATDForRd; }
 #if JVET_O1164_RPR
+#if JVET_O0299_APS_SCALINGLIST
+  void                        scaleRefPicList( Picture *scaledRefPic[ ], APS** apss, APS& lmcsAps, APS& scalingListAps, const bool isDecoder );
+#else
   void                        scaleRefPicList( Picture *scaledRefPic[], APS** apss, APS& lmcsAps, const bool isDecoder );
+#endif
   void                        freeScaledRefPicList( Picture *scaledRefPic[] );
   bool                        checkRPR();
   const std::pair<int, int>&  getScalingRatio( const RefPicList refPicList, const int refIdx )  const { return m_scalingRatio[refPicList][refIdx]; }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 88063fe2c0..0b81ef8e0c 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_O0299_APS_SCALINGLIST                        1 // JVET-O0299: Scaling List Matrices Support in APS
+
 #define JVET_O1164_RPR                                    1  // JVET-O1164: Reference picture resampling
 #if JVET_O1164_RPR
 #define JVET_O1164_PS                                     1
@@ -493,6 +495,9 @@ enum ApsTypeValues
 {
   ALF_APS = 0,
   LMCS_APS = 1,
+#if JVET_O0299_APS_SCALINGLIST
+  SCALING_LIST_APS = 2,
+#endif
 };
 
 enum QuantFlags
diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp
index e820fbfcf3..b85e9bc583 100644
--- a/source/Lib/DecoderLib/DecLib.cpp
+++ b/source/Lib/DecoderLib/DecLib.cpp
@@ -838,6 +838,24 @@ void DecLib::xActivateParameterSets()
       }
     }
 
+#if JVET_O0299_APS_SCALINGLIST
+    APS* scalinglistAPS = NULL;
+    if( m_apcSlicePilot->getscalingListAPSId() != -1 )
+    {
+      scalinglistAPS = m_parameterSetManager.getAPS( m_apcSlicePilot->getscalingListAPSId(), SCALING_LIST_APS );
+      CHECK( scalinglistAPS == 0, "No SCALING LIST APS present" );
+    }
+
+    if( scalinglistAPS )
+    {
+      m_parameterSetManager.clearAPSChangedFlag( m_apcSlicePilot->getscalingListAPSId(), SCALING_LIST_APS );
+      if( false == m_parameterSetManager.activateAPS( m_apcSlicePilot->getscalingListAPSId(), SCALING_LIST_APS ) )
+      {
+        THROW( "SCALING LIST APS activation failed!" );
+      }
+    }
+#endif
+
     xParsePrefixSEImessages();
 
 #if RExt__HIGH_BIT_DEPTH_SUPPORT==0
@@ -851,7 +869,11 @@ void DecLib::xActivateParameterSets()
     m_pcPic = xGetNewPicBuffer (*sps, *pps, m_apcSlicePilot->getTLayer());
 
     m_apcSlicePilot->applyReferencePictureListBasedMarking(m_cListPic, m_apcSlicePilot->getRPL0(), m_apcSlicePilot->getRPL1());
+#if JVET_O0299_APS_SCALINGLIST
+    m_pcPic->finalInit( *sps, *pps, apss, *lmcsAPS, *scalinglistAPS );
+#else
     m_pcPic->finalInit(*sps, *pps, apss, *lmcsAPS);
+#endif
     m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId())->setNumBricksInPic((int)m_pcPic->brickMap->bricks.size());
     m_pcPic->createTempBuffers( m_pcPic->cs->pps->pcv->maxCUWidth );
     m_pcPic->cs->createCoeffs();
@@ -874,6 +896,9 @@ void DecLib::xActivateParameterSets()
     m_pcPic->cs->pps   = pps;
     memcpy(m_pcPic->cs->alfApss, apss, sizeof(m_pcPic->cs->alfApss));
     m_pcPic->cs->lmcsAps = lmcsAPS;
+#if JVET_O0299_APS_SCALINGLIST
+    m_pcPic->cs->scalinglistAps = scalinglistAPS;
+#endif
 
     m_pcPic->cs->pcv   = pps->pcv;
 
@@ -957,6 +982,9 @@ void DecLib::xActivateParameterSets()
     const PPS *pps = pSlice->getPPS();
     APS** apss = pSlice->getAlfAPSs();
     APS *lmcsAPS = pSlice->getLmcsAPS();
+#if JVET_O0299_APS_SCALINGLIST
+    APS *scalinglistAPS = pSlice->getscalingListAPS();
+#endif
 
     // fix Parameter Sets, now that we have the real slice
     m_pcPic->cs->slice = pSlice;
@@ -964,6 +992,9 @@ void DecLib::xActivateParameterSets()
     m_pcPic->cs->pps   = pps;
     memcpy(m_pcPic->cs->alfApss, apss, sizeof(m_pcPic->cs->alfApss));
     m_pcPic->cs->lmcsAps = lmcsAPS;
+#if JVET_O0299_APS_SCALINGLIST
+    m_pcPic->cs->scalinglistAps = scalinglistAPS;
+#endif
 
     m_pcPic->cs->pcv   = pps->pcv;
 
@@ -993,6 +1024,12 @@ void DecLib::xActivateParameterSets()
     {
       EXIT("Error - a new LMCS APS has been decoded while processing a picture");
     }
+#if JVET_O0299_APS_SCALINGLIST
+    if( scalinglistAPS && m_parameterSetManager.getAPSChangedFlag( scalinglistAPS->getAPSId(), SCALING_LIST_APS ) )
+    {
+      EXIT( "Error - a new SCALING LIST APS has been decoded while processing a picture" );
+    }
+#endif
 
     xParsePrefixSEImessages();
 
@@ -1269,7 +1306,11 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
   pcSlice->constructRefPicList(m_cListPic);
 
 #if JVET_O1164_RPR
+#if JVET_O0299_APS_SCALINGLIST
+  pcSlice->scaleRefPicList( scaledRefPic, m_parameterSetManager.getAPSs(), *pcSlice->getLmcsAPS(), *pcSlice->getscalingListAPS(), true );
+#else
   pcSlice->scaleRefPicList( scaledRefPic, m_parameterSetManager.getAPSs(), *pcSlice->getLmcsAPS(), true );
+#endif
 #endif
 
     if (!pcSlice->isIntra())
@@ -1405,6 +1446,27 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
 
   Quant *quant = m_cTrQuant.getQuant();
 
+#if JVET_O0299_APS_SCALINGLIST
+  if( pcSlice->getSPS()->getScalingListFlag() )
+  {
+    ScalingList scalingList;
+    if( pcSlice->getscalingListPresentFlag() )
+    {
+      APS* scalingListAPS = pcSlice->getscalingListAPS();
+      scalingList = scalingListAPS->getScalingList();
+    }
+    else
+    {
+      scalingList.setDefaultScalingList();
+    }
+    quant->setScalingListDec( scalingList );
+    quant->setUseScalingList( true );
+  }
+  else
+  {
+    quant->setUseScalingList( false );
+  }
+#else
   if(pcSlice->getSPS()->getScalingListFlag())
   {
     ScalingList scalingList;
@@ -1427,6 +1489,7 @@ bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDispl
   {
     quant->setUseScalingList(false);
   }
+#endif
 
 
   if (pcSlice->getSPS()->getUseReshaper())
diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp
index 42b66acdae..909f680967 100644
--- a/source/Lib/DecoderLib/DecSlice.cpp
+++ b/source/Lib/DecoderLib/DecSlice.cpp
@@ -88,6 +88,9 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb
   memcpy(cs.alfApss, slice->getAlfAPSs(), sizeof(cs.alfApss));
 
   cs.lmcsAps = slice->getLmcsAPS();
+#if JVET_O0299_APS_SCALINGLIST
+  cs.scalinglistAps   = slice->getscalingListAPS();
+#endif
 
   cs.pcv              = slice->getPPS()->pcv;
   cs.chromaQpAdj      = 0;
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index ac9997d2ee..adafe8c56c 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -670,11 +670,13 @@ void HLSyntaxReader::parsePPS( PPS* pcPPS, ParameterSetManager *parameterSetMana
     }
   }
 
+#if !JVET_O0299_APS_SCALINGLIST
   READ_FLAG( uiCode, "pps_scaling_list_data_present_flag" );           pcPPS->setScalingListPresentFlag( uiCode ? true : false );
   if(pcPPS->getScalingListPresentFlag ())
   {
     parseScalingList( &(pcPPS->getScalingList()) );
   }
+#endif
 
 
   READ_UVLC( uiCode, "log2_parallel_merge_level_minus2");
@@ -804,6 +806,20 @@ void HLSyntaxReader::parseAPS( APS* aps )
 
   READ_CODE(3, code, "aps_params_type");
   aps->setAPSType(code);
+#if JVET_O0299_APS_SCALINGLIST
+  if( code == ALF_APS )
+  {
+    parseAlfAps( aps );
+  }
+  else if( code == LMCS_APS )
+  {
+    parseLmcsAps( aps );
+  }
+  else if( code == SCALING_LIST_APS )
+  {
+    parseScalingListAps( aps );
+  }
+#else
   if (code == ALF_APS)
   {
     parseAlfAps(aps);
@@ -812,6 +828,7 @@ void HLSyntaxReader::parseAPS( APS* aps )
   {
     parseLmcsAps(aps);
   }
+#endif
   READ_FLAG(code, "aps_extension_flag");
   if (code)
   {
@@ -946,6 +963,13 @@ void HLSyntaxReader::parseLmcsAps( APS* aps )
   aps->setReshaperAPSInfo(info);
 }
 
+#if JVET_O0299_APS_SCALINGLIST
+void HLSyntaxReader::parseScalingListAps( APS* aps )
+{
+  ScalingList& info = aps->getScalingList();
+  parseScalingList( &info );
+}
+#endif
 
 void  HLSyntaxReader::parseVUI(VUI* pcVUI, SPS *pcSPS)
 {
@@ -1484,6 +1508,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
 
   // KJS: remove scaling lists?
   READ_FLAG( uiCode, "scaling_list_enabled_flag" );                 pcSPS->setScalingListFlag ( uiCode );
+#if !JVET_O0299_APS_SCALINGLIST
   if(pcSPS->getScalingListFlag())
   {
     READ_FLAG( uiCode, "sps_scaling_list_data_present_flag" );                 pcSPS->setScalingListPresentFlag ( uiCode );
@@ -1492,6 +1517,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
       parseScalingList( &(pcSPS->getScalingList()) );
     }
   }
+#endif
 
   TimingInfo *timingInfo = pcSPS->getTimingInfo();
   READ_FLAG(       uiCode, "timing_info_present_flag");         timingInfo->setTimingInfoPresentFlag      (uiCode ? true : false);
@@ -2414,6 +2440,19 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, ParameterSetManager *para
       }
     }
 
+#if JVET_O0299_APS_SCALINGLIST
+      if( sps->getScalingListFlag() )
+      {
+        READ_FLAG( uiCode, "slice_scaling_list_present_flag" );
+        pcSlice->setscalingListPresentFlag( uiCode );
+      }
+      if( pcSlice->getscalingListPresentFlag() )
+      {
+        READ_CODE( 3, uiCode, "slice_scaling_list_aps_id" );
+        pcSlice->setscalingListAPSId( uiCode );
+      }
+#endif
+
     if( pcSlice->getSliceCurStartBrickIdx() == 0 )
   {
     pcSlice->setDefaultClpRng( *sps );
diff --git a/source/Lib/DecoderLib/VLCReader.h b/source/Lib/DecoderLib/VLCReader.h
index fb11bd8807..9bf0f8a1cd 100644
--- a/source/Lib/DecoderLib/VLCReader.h
+++ b/source/Lib/DecoderLib/VLCReader.h
@@ -153,6 +153,9 @@ public:
   void  parseAPS            ( APS* pcAPS );
   void  parseAlfAps         ( APS* pcAPS );
   void  parseLmcsAps        ( APS* pcAPS );
+#if JVET_O0299_APS_SCALINGLIST
+  void  parseScalingListAps ( APS* pcAPS );
+#endif
   void  parseVUI            ( VUI* pcVUI, SPS* pcSPS );
   void  parseConstraintInfo   (ConstraintInfo *cinfo);
   void  parseProfileTierLevel ( ProfileTierLevel *ptl, int maxNumSubLayersMinus1);
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 5835f3c649..1d94bcdda8 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2069,8 +2069,12 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     //  Set reference list
     pcSlice->constructRefPicList(rcListPic);
 #if JVET_O1164_RPR
+#if JVET_O0299_APS_SCALINGLIST
+    pcSlice->scaleRefPicList( scaledRefPic, m_pcEncLib->getApss(), *pcSlice->getLmcsAPS(), *pcSlice->getscalingListAPS(), false );
+#else
     pcSlice->scaleRefPicList( scaledRefPic, m_pcEncLib->getApss(), *pcSlice->getLmcsAPS(), false );
 #endif
+#endif
 
 #if JVET_O1164_PS
     xPicInitHashME( pcPic, pcSlice->getPPS(), rcListPic );
@@ -2499,6 +2503,20 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 
     xPicInitLMCS(pcPic, pcSlice);
 
+#if JVET_O0299_APS_SCALINGLIST
+    if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ )
+    {
+      pcSlice->setscalingListPresentFlag( true );
+      int apsId = 0;
+      pcSlice->setscalingListAPSId( apsId );
+
+      ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap();
+      APS*  scalingListAPS = apsMap->getPS( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS );
+      assert( scalingListAPS != NULL );
+      pcSlice->setscalingListAPS( scalingListAPS );
+    }
+#endif
+
     if( encPic )
     // now compress (trial encode) the various slice segments (slices, and dependent slices)
     {
@@ -2599,6 +2617,23 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
       }
 #endif
 
+#if JVET_O0299_APS_SCALINGLIST
+      if( pcSlice->getSPS()->getScalingListFlag() && m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ )
+      {
+        pcSlice->setscalingListPresentFlag( true );
+        int apsId = 0;
+        pcSlice->setscalingListAPSId( apsId );
+      }
+      for( int s = 0; s < uiNumSliceSegments; s++ )
+      {
+        pcPic->slices[ s ]->setscalingListPresentFlag( pcSlice->getscalingListPresentFlag() );
+        if( pcSlice->getscalingListPresentFlag() )
+        {
+          pcPic->slices[ s ]->setscalingListAPSId( pcSlice->getscalingListAPSId() );
+        }
+      }
+#endif
+
       // SAO parameter estimation using non-deblocked pixels for CTU bottom and right boundary areas
       if( pcSlice->getSPS()->getSAOEnabledFlag() && m_pcCfg->getSaoCtuBoundary() )
       {
@@ -2769,6 +2804,23 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         }
       }
 
+#if JVET_O0299_APS_SCALINGLIST
+      // only 1 SCALING LIST data for 1 picture    
+      if( pcSlice->getSPS()->getScalingListFlag() && ( m_pcCfg->getUseScalingListId() == SCALING_LIST_FILE_READ ) )
+      {
+        int apsId = pcSlice->getscalingListAPSId();
+        ParameterSetMap<APS> *apsMap = m_pcEncLib->getApsMap();
+        APS* aps = apsMap->getPS( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS );
+        bool writeAPS = aps && apsMap->getChangedFlag( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS );
+        if( writeAPS )
+        {
+          actualTotalBits += xWriteAPS( accessUnit, aps );
+          apsMap->clearChangedFlag( ( apsId << NUM_APS_TYPE_LEN ) + SCALING_LIST_APS );
+          CHECK( aps != pcSlice->getscalingListAPS(), "Wrong SCALING LIST APS pointer in compressGOP" );
+        }
+      }
+#endif
+
       if (pcSlice->getSPS()->getALFEnabledFlag() && pcSlice->getTileGroupAlfEnabledFlag(COMPONENT_Y))
       {
 #if JVET_O_MAX_NUM_ALF_APS_8
diff --git a/source/Lib/EncoderLib/EncGOP.h b/source/Lib/EncoderLib/EncGOP.h
index 9d0785afc3..aa0eda372f 100644
--- a/source/Lib/EncoderLib/EncGOP.h
+++ b/source/Lib/EncoderLib/EncGOP.h
@@ -127,6 +127,9 @@ private:
   bool                    m_bFirst;
   int                     m_iLastRecoveryPicPOC;
   int                     m_lastRasPoc;
+#if JVET_O0299_APS_SCALINGLIST
+  ScalingListMode         m_ScalingListId;
+#endif
 
   //  Access channel
   EncLib*                 m_pcEncLib;
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 963cd63e6f..3332d894b5 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -66,6 +66,9 @@ EncLib::EncLib()
   , m_cacheModel()
 #endif
   , m_lmcsAPS(nullptr)
+#if JVET_O0299_APS_SCALINGLIST
+  , m_scalinglistAPS( nullptr )
+#endif
 #if JVET_O0119_BASE_PALETTE_444
   , m_doPlt( true )
 #endif
@@ -241,6 +244,11 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
 
   SPS &sps0=*(m_spsMap.allocatePS(0)); // NOTE: implementations that use more than 1 SPS need to be aware of activation issues.
   PPS &pps0=*(m_ppsMap.allocatePS(0));
+#if JVET_O0299_APS_SCALINGLIST
+  APS &aps0 = *( m_apsMap.allocatePS( SCALING_LIST_APS ) );
+  aps0.setAPSId( 0 );
+  aps0.setAPSType( SCALING_LIST_APS );
+#endif
 
   // initialize SPS
   xInitSPS(sps0);
@@ -438,18 +446,31 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
 #if ER_CHROMA_QP_WCG_PPS
   if( m_wcgChromaQpControl.isEnabled() )
   {
+#if JVET_O0299_APS_SCALINGLIST  
+    xInitScalingLists( sps0, *m_apsMap.getPS( 1 ) );
+    xInitScalingLists( sps0, aps0 );
+#else
     xInitScalingLists( sps0, *m_ppsMap.getPS(1) );
     xInitScalingLists( sps0, pps0 );
+#endif
   }
   else
 #endif
   {
+#if JVET_O0299_APS_SCALINGLIST
+    xInitScalingLists( sps0, aps0 );
+#else
     xInitScalingLists( sps0, pps0 );
+#endif
   }
 #if JVET_O1164_RPR
   if( m_rprEnabled )
   {
+#if JVET_O0299_APS_SCALINGLIST
+    xInitScalingLists( sps0, *m_apsMap.getPS( ENC_PPS_ID_RPR ) );
+#else
     xInitScalingLists( sps0, *m_ppsMap.getPS( ENC_PPS_ID_RPR ) );
+#endif
   }
 #endif
 #if ENABLE_WPP_PARALLELISM
@@ -464,7 +485,11 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
     picBg->create(sps0.getChromaFormatIdc(), Size(sps0.getPicWidthInLumaSamples(), sps0.getPicHeightInLumaSamples()), sps0.getMaxCUWidth(), sps0.getMaxCUWidth() + 16, false);
 #endif
     picBg->getRecoBuf().fill(0);
+#if JVET_O0299_APS_SCALINGLIST
+    picBg->finalInit( sps0, pps0, m_apss, *m_lmcsAPS, *m_scalinglistAPS );
+#else
     picBg->finalInit(sps0, pps0, m_apss, *m_lmcsAPS);
+#endif
     pps0.setNumBricksInPic((int)picBg->brickMap->bricks.size());
     picBg->allocateNewSlice();
     picBg->createSpliceIdx(pps0.pcv->sizeInCtus);
@@ -480,14 +505,18 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf )
   }
 }
 
+#if JVET_O0299_APS_SCALINGLIST
+void EncLib::xInitScalingLists( SPS &sps, APS &aps )
+#else
 void EncLib::xInitScalingLists(SPS &sps, PPS &pps)
+#endif
 {
   // Initialise scaling lists
   // The encoder will only use the SPS scaling lists. The PPS will never be marked present.
   const int maxLog2TrDynamicRange[MAX_NUM_CHANNEL_TYPE] =
   {
-      sps.getMaxLog2TrDynamicRange(CHANNEL_TYPE_LUMA),
-      sps.getMaxLog2TrDynamicRange(CHANNEL_TYPE_CHROMA)
+    sps.getMaxLog2TrDynamicRange(CHANNEL_TYPE_LUMA),
+    sps.getMaxLog2TrDynamicRange(CHANNEL_TYPE_CHROMA)
   };
 
   Quant* quant = getTrQuant()->getQuant();
@@ -503,16 +532,23 @@ void EncLib::xInitScalingLists(SPS &sps, PPS &pps)
       getTrQuant( jId )->getQuant()->setUseScalingList( false );
     }
 #endif
+#if !JVET_O0299_APS_SCALINGLIST
     sps.setScalingListPresentFlag(false);
     pps.setScalingListPresentFlag(false);
+#endif
   }
   else if(getUseScalingListId() == SCALING_LIST_DEFAULT)
   {
+#if JVET_O0299_APS_SCALINGLIST
+    aps.getScalingList().setDefaultScalingList ();
+    quant->setScalingList( &( aps.getScalingList() ), maxLog2TrDynamicRange, sps.getBitDepths() );
+#else
     sps.getScalingList().setDefaultScalingList ();
     sps.setScalingListPresentFlag(false);
     pps.setScalingListPresentFlag(false);
 
     quant->setScalingList(&(sps.getScalingList()), maxLog2TrDynamicRange, sps.getBitDepths());
+#endif
     quant->setUseScalingList(true);
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
     for( int jId = 1; jId < m_numCuEncStacks; jId++ )
@@ -523,6 +559,19 @@ void EncLib::xInitScalingLists(SPS &sps, PPS &pps)
   }
   else if(getUseScalingListId() == SCALING_LIST_FILE_READ)
   {
+#if JVET_O0299_APS_SCALINGLIST 
+    aps.getScalingList().setDefaultScalingList();
+    if( aps.getScalingList().xParseScalingList( getScalingListFileName() ) )
+    {
+      THROW( "parse scaling list" );
+    }
+    aps.getScalingList().checkDcOfMatrix();
+    if( aps.getScalingList().checkDefaultScalingList() == false )
+    {
+      setUseScalingListId( SCALING_LIST_DEFAULT );
+    }
+    quant->setScalingList( &( aps.getScalingList() ), maxLog2TrDynamicRange, sps.getBitDepths() );
+#else
     sps.getScalingList().setDefaultScalingList ();
     if(sps.getScalingList().xParseScalingList(getScalingListFileName()))
     {
@@ -533,6 +582,7 @@ void EncLib::xInitScalingLists(SPS &sps, PPS &pps)
     pps.setScalingListPresentFlag(false);
 
     quant->setScalingList(&(sps.getScalingList()), maxLog2TrDynamicRange, sps.getBitDepths());
+#endif
     quant->setUseScalingList(true);
 #if ENABLE_SPLIT_PARALLELISM || ENABLE_WPP_PARALLELISM
     for( int jId = 1; jId < m_numCuEncStacks; jId++ )
@@ -546,7 +596,11 @@ void EncLib::xInitScalingLists(SPS &sps, PPS &pps)
     THROW("error : ScalingList == " << getUseScalingListId() << " not supported\n");
   }
 
+#if JVET_O0299_APS_SCALINGLIST 
+  if( getUseScalingListId() == SCALING_LIST_FILE_READ )
+#else
   if (getUseScalingListId() == SCALING_LIST_FILE_READ && sps.getScalingListPresentFlag())
+#endif
   {
     // Prepare delta's:
     for (uint32_t sizeId = SCALING_LIST_2x2; sizeId <= SCALING_LIST_64x64; sizeId++)
@@ -558,7 +612,11 @@ void EncLib::xInitScalingLists(SPS &sps, PPS &pps)
         {
           continue;
         }
+#if JVET_O0299_APS_SCALINGLIST 
+        aps.getScalingList().checkPredMode( sizeId, listId );
+#else
         sps.getScalingList().checkPredMode( sizeId, listId );
+#endif
       }
     }
   }
@@ -621,7 +679,11 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru
     const SPS *sps = m_spsMap.getPS(pps->getSPSId());
 
     picCurr->M_BUFS(0, PIC_ORIGINAL).copyFrom(m_cGOPEncoder.getPicBg()->getRecoBuf());
+#if JVET_O0299_APS_SCALINGLIST
+    picCurr->finalInit( *sps, *pps, m_apss, *m_lmcsAPS, *m_scalinglistAPS );
+#else
     picCurr->finalInit(*sps, *pps, m_apss, *m_lmcsAPS);
+#endif
     picCurr->poc = m_iPOCLast - 1;
     m_iPOCLast -= 2;
     if (getUseAdaptiveQP())
@@ -717,7 +779,11 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* cPicYuvTru
       pcPicCurr->M_BUFS( 0, PIC_TRUE_ORIGINAL ).swap(*cPicYuvTrueOrg );
 #endif
 
+#if JVET_O0299_APS_SCALINGLIST
+      pcPicCurr->finalInit( *pSPS, *pPPS, m_apss, *m_lmcsAPS, *m_scalinglistAPS );
+#else
       pcPicCurr->finalInit(*pSPS, *pPPS, m_apss, *m_lmcsAPS);
+#endif
       PPS *ptrPPS = (ppsID<0) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS(ppsID);
       ptrPPS->setNumBricksInPic((int)pcPicCurr->brickMap->bricks.size());
     }
@@ -816,7 +882,11 @@ void EncLib::encode( bool flush, PelStorage* pcPicYuvOrg, PelStorage* pcPicYuvTr
         int ppsID=-1; // Use default PPS ID
         const PPS *pPPS=(ppsID<0) ? m_ppsMap.getFirstPS() : m_ppsMap.getPS(ppsID);
         const SPS *pSPS=m_spsMap.getPS(pPPS->getSPSId());
+#if JVET_O0299_APS_SCALINGLIST
+        pcField->finalInit( *pSPS, *pPPS, m_apss, *m_lmcsAPS, *m_scalinglistAPS );
+#else
         pcField->finalInit(*pSPS, *pPPS, m_apss, *m_lmcsAPS);
+#endif
       }
 
       pcField->poc = m_iPOCLast;
diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h
index 69bfefeb20..0aa443cd76 100644
--- a/source/Lib/EncoderLib/EncLib.h
+++ b/source/Lib/EncoderLib/EncLib.h
@@ -145,6 +145,9 @@ private:
 #endif
 
   APS*                      m_lmcsAPS;
+#if JVET_O0299_APS_SCALINGLIST
+  APS*                      m_scalinglistAPS;
+#endif
 
   EncHRD                    m_encHRD;
 
@@ -172,7 +175,11 @@ protected:
   void  xInitSPS          (SPS &sps);                 ///< initialize SPS from encoder options
   void  xInitPPS          (PPS &pps, const SPS &sps); ///< initialize PPS from encoder options
   void  xInitAPS          (APS &aps);                 ///< initialize APS from encoder options
+#if JVET_O0299_APS_SCALINGLIST
+  void  xInitScalingLists ( SPS &sps, APS &aps );     ///< initialize scaling lists
+#else
   void  xInitScalingLists (SPS &sps, PPS &pps);   ///< initialize scaling lists
+#endif
   void  xInitPPSforLT(PPS& pps);
   void  xInitHrdParameters(SPS &sps);                 ///< initialize HRDParameters parameters
 
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index a6f1441865..7ca2dec687 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -396,11 +396,13 @@ void HLSWriter::codePPS( const PPS* pcPPS )
     }
   }
 
+#if !JVET_O0299_APS_SCALINGLIST
   WRITE_FLAG( pcPPS->getScalingListPresentFlag() ? 1 : 0,                          "pps_scaling_list_data_present_flag" );
   if( pcPPS->getScalingListPresentFlag() )
   {
     codeScalingList( pcPPS->getScalingList() );
   }
+#endif
   WRITE_UVLC( pcPPS->getLog2ParallelMergeLevelMinus2(), "log2_parallel_merge_level_minus2");
   WRITE_FLAG( pcPPS->getSliceHeaderExtensionPresentFlag() ? 1 : 0, "slice_segment_header_extension_present_flag");
 
@@ -508,6 +510,12 @@ void HLSWriter::codeAPS( APS* pcAPS )
   {
     codeLmcsAps (pcAPS);
   }
+#if JVET_O0299_APS_SCALINGLIST
+  else if( pcAPS->getAPSType() == SCALING_LIST_APS )
+  {
+    codeScalingListAps( pcAPS );
+  }
+#endif
   WRITE_FLAG(0, "aps_extension_flag");   //Implementation when this flag is equal to 1 should be added when it is needed. Currently in the spec we don't have case when this flag is equal to 1
   xWriteRbspTrailingBits();
 }
@@ -610,6 +618,14 @@ void HLSWriter::codeLmcsAps( APS* pcAPS )
   }
 }
 
+#if JVET_O0299_APS_SCALINGLIST
+void HLSWriter::codeScalingListAps( APS* pcAPS )
+{
+  ScalingList param = pcAPS->getScalingList();
+  codeScalingList( param );
+}
+#endif
+
 void HLSWriter::codeVUI( const VUI *pcVUI, const SPS* pcSPS )
 {
 #if ENABLE_TRACING
@@ -1038,6 +1054,7 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
 
   // KJS: remove scaling lists?
   WRITE_FLAG( pcSPS->getScalingListFlag() ? 1 : 0,                                   "scaling_list_enabled_flag" );
+#if !JVET_O0299_APS_SCALINGLIST
   if(pcSPS->getScalingListFlag())
   {
     WRITE_FLAG( pcSPS->getScalingListPresentFlag() ? 1 : 0,                          "sps_scaling_list_data_present_flag" );
@@ -1046,6 +1063,7 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
       codeScalingList( pcSPS->getScalingList() );
     }
   }
+#endif
 
   const TimingInfo *timingInfo = pcSPS->getTimingInfo();
   WRITE_FLAG(timingInfo->getTimingInfoPresentFlag(),          "timing_info_present_flag");
@@ -1691,6 +1709,16 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
       }
     }
 
+#if JVET_O0299_APS_SCALINGLIST
+    if( pcSlice->getSPS()->getScalingListFlag() )
+    {
+      WRITE_FLAG( pcSlice->getscalingListPresentFlag() ? 1 : 0, "slice_scaling_list_present_flag" );
+      if( pcSlice->getscalingListPresentFlag() )
+      {
+        WRITE_CODE( pcSlice->getscalingListAPSId(), 3, "slice_scaling_list_aps_id" );
+      }
+    }
+#endif
   if(pcSlice->getPPS()->getSliceHeaderExtensionPresentFlag())
   {
     WRITE_UVLC(0,"slice_segment_header_extension_length");
diff --git a/source/Lib/EncoderLib/VLCWriter.h b/source/Lib/EncoderLib/VLCWriter.h
index cca3346414..e18ab25ff9 100644
--- a/source/Lib/EncoderLib/VLCWriter.h
+++ b/source/Lib/EncoderLib/VLCWriter.h
@@ -132,6 +132,9 @@ public:
   void  codeAPS                 ( APS* pcAPS );
   void  codeAlfAps              ( APS* pcAPS );
   void  codeLmcsAps             ( APS* pcAPS );
+#if JVET_O0299_APS_SCALINGLIST
+  void  codeScalingListAps      ( APS* pcAPS );
+#endif
   void  codeVPS                 ( const VPS* pcVPS );
   void  codeDPS                 ( const DPS* dps );
   void  codeSliceHeader         ( Slice* pcSlice );
-- 
GitLab