From 9c481a075e4de75cc47ea67984ff267381ac3e5d Mon Sep 17 00:00:00 2001
From: Alican <analci@qti.qualcomm.com>
Date: Thu, 30 Jan 2020 15:59:49 -0800
Subject: [PATCH] Slice-level switch between TS residual coding and regular
 residual coding for lossless coding as in JVET-Q0089. One SPS flag that
 controls both luma and chroma BDPCM simultaneously as under JVET-Q0089
 (meeting notes) - removed chroma BDPCM flag. Modified the .cfg files to
 reflect high-level chroma BDPCM changes. Fix: Disabled CCALF in lossless.cfg
 (necessary) CCALF cannot be used if ALF is disabled (disabled in
 lossless.cfg)

---
 cfg/444/yuv444.cfg                    |  2 +-
 cfg/lossless/lossless.cfg             |  1 +
 cfg/per-class/classF.cfg              |  2 +-
 source/App/EncoderApp/EncApp.cpp      |  4 ++++
 source/App/EncoderApp/EncAppCfg.cpp   |  6 ++++++
 source/App/EncoderApp/EncAppCfg.h     |  4 ++++
 source/Lib/CommonLib/Slice.cpp        | 10 ++++++++++
 source/Lib/CommonLib/Slice.h          | 16 ++++++++++++++++
 source/Lib/CommonLib/TypeDef.h        |  4 ++++
 source/Lib/CommonLib/UnitTools.cpp    |  4 ++++
 source/Lib/DecoderLib/CABACReader.cpp |  4 ++++
 source/Lib/DecoderLib/VLCReader.cpp   | 10 ++++++++--
 source/Lib/EncoderLib/CABACWriter.cpp |  8 ++++++++
 source/Lib/EncoderLib/EncCfg.h        |  9 +++++++++
 source/Lib/EncoderLib/EncLib.cpp      |  4 ++++
 source/Lib/EncoderLib/EncSlice.cpp    | 10 ++++++++++
 source/Lib/EncoderLib/IntraSearch.cpp |  4 ++++
 source/Lib/EncoderLib/VLCWriter.cpp   | 13 +++++++++++++
 18 files changed, 111 insertions(+), 4 deletions(-)

diff --git a/cfg/444/yuv444.cfg b/cfg/444/yuv444.cfg
index c64afd759..ca0f331fb 100644
--- a/cfg/444/yuv444.cfg
+++ b/cfg/444/yuv444.cfg
@@ -1 +1 @@
-BDPCM: 2
+BDPCM: 1
diff --git a/cfg/lossless/lossless.cfg b/cfg/lossless/lossless.cfg
index a0a00a933..583b2ca2b 100644
--- a/cfg/lossless/lossless.cfg
+++ b/cfg/lossless/lossless.cfg
@@ -12,6 +12,7 @@ JointCbCr                    : 0
 LoopFilterDisable            : 1
 SAO                          : 0
 ALF                          : 0
+CCALF                        : 0
 DMVR                         : 0
 BIO                          : 0
 PROF                         : 0
diff --git a/cfg/per-class/classF.cfg b/cfg/per-class/classF.cfg
index 7646377dc..8acfe6899 100644
--- a/cfg/per-class/classF.cfg
+++ b/cfg/per-class/classF.cfg
@@ -1,3 +1,3 @@
 IBC : 1
 HashME : 1
-BDPCM: 2
+BDPCM: 1
\ No newline at end of file
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 49eafcf8c..e5ebd2ca1 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -236,7 +236,11 @@ void EncApp::xInitLibCfg()
 #endif
   m_cEncLib.setNoLadfConstraintFlag                              ( !m_LadfEnabed );
   m_cEncLib.setNoTransformSkipConstraintFlag                     ( !m_useTransformSkip );
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  m_cEncLib.setNoBDPCMConstraintFlag                             ( !m_useBDPCM );
+#else
   m_cEncLib.setNoBDPCMConstraintFlag                             ( m_useBDPCM == 0 );
+#endif
   m_cEncLib.setNoJointCbCrConstraintFlag                         (!m_JointCbCrMode);
   m_cEncLib.setNoQpDeltaConstraintFlag                           ( m_bNoQpDeltaConstraintFlag );
   m_cEncLib.setNoDepQuantConstraintFlag                          ( !m_depQuantEnabledFlag);
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 8baddf032..46fe17c54 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -1123,7 +1123,11 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("TransformSkipFast",                               m_useTransformSkipFast,                           false, "Fast encoder search for transform skipping, winner takes it all mode.")
   ("TransformSkipLog2MaxSize",                        m_log2MaxTransformSkipBlockSize,                     5U, "Specify transform-skip maximum size. Minimum 2, Maximum 5. (not valid in V1 profiles)")
   ("ChromaTS",                                        m_useChromaTS,                                    false, "Enable encoder search of chromaTS")
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  ("BDPCM",                                           m_useBDPCM,                                       false, "BDPCM (0:off, 1:luma and chroma)")
+#else
   ("BDPCM",                                           m_useBDPCM,                                           0, "BDPCM (0:off, 1:lumaonly, 2:lumachroma")
+#endif
   ("ISPFast",                                         m_useFastISP,                                     false, "Fast encoder search for ISP")
   ("ImplicitResidualDPCM",                            m_rdpcmEnabledFlag[RDPCM_SIGNAL_IMPLICIT],        false, "Enable implicitly signalled residual DPCM for intra (also known as sample-adaptive intra predict) (not valid in V1 profiles)")
   ("ExplicitResidualDPCM",                            m_rdpcmEnabledFlag[RDPCM_SIGNAL_EXPLICIT],        false, "Enable explicitly signalled residual DPCM for inter (not valid in V1 profiles)")
@@ -3512,7 +3516,9 @@ bool EncAppCfg::xCheckParameter()
   check_failed |= m_ext360.verifyParameters();
 #endif
 
+#if !JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
   xConfirmPara(m_useBDPCM < 0 || m_useBDPCM > 2, "BDPCM must be in range 0..2");
+#endif
 #if JVET_Q0820_ACT
   xConfirmPara(m_useColorTrans && (m_log2MaxTbSize == 6), "Log2MaxTbSize must be less than 6 when ACT is enabled, otherwise ACT needs to be disabled");
 #endif
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index f49621074..2bfc49058 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -210,7 +210,11 @@ protected:
   uint32_t      m_log2SaoOffsetScale[MAX_NUM_CHANNEL_TYPE];       ///< number of bits for the upward bit shift operation on the decoded SAO offsets
   bool      m_useTransformSkip;                               ///< flag for enabling intra transform skipping
   bool      m_useTransformSkipFast;                           ///< flag for enabling fast intra transform skipping
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  bool      m_useBDPCM;
+#else
   int       m_useBDPCM;
+#endif
   uint32_t      m_log2MaxTransformSkipBlockSize;                  ///< transform-skip maximum size (minimum of 2)
   bool      m_transformSkipRotationEnabledFlag;               ///< control flag for transform-skip/transquant-bypass residual rotation
   bool      m_transformSkipContextEnabledFlag;                ///< control flag for transform-skip/transquant-bypass single significance map context
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index df9936f98..225770e99 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -73,6 +73,9 @@ Slice::Slice()
 , m_deblockingFilterCrBetaOffsetDiv2( 0 )
 , m_deblockingFilterCrTcOffsetDiv2  ( 0 )
 #endif
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+, m_tsResidualCodingDisabledFlag  ( false )
+#endif
 , m_pendingRasInit                ( false )
 , m_bCheckLDC                     ( false )
 , m_biDirPred                    ( false )
@@ -769,6 +772,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
   m_deblockingFilterCrBetaOffsetDiv2  = pSrc->m_deblockingFilterCrBetaOffsetDiv2;
   m_deblockingFilterCrTcOffsetDiv2    = pSrc->m_deblockingFilterCrTcOffsetDiv2;
 #endif
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  m_tsResidualCodingDisabledFlag      = pSrc->m_tsResidualCodingDisabledFlag;
+#endif
 
   for (i = 0; i < NUM_REF_PIC_LIST_01; i++)
   {
@@ -1861,7 +1867,11 @@ SPS::SPS()
 , m_bLongTermRefsPresent      (false)
 // Tool list
 , m_transformSkipEnabledFlag  (false)
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+, m_BDPCMEnabledFlag          (false)
+#else
 , m_BDPCMEnabled              (0)
+#endif
 , m_JointCbCrEnabledFlag      (false)
 , m_sbtmvpEnabledFlag         (false)
 , m_bdofEnabledFlag           (false)
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index 4fb4fb24d..fa7fa5788 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -1102,7 +1102,11 @@ private:
   // Tool list
 
   bool              m_transformSkipEnabledFlag;
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  bool              m_BDPCMEnabledFlag;
+#else
   int               m_BDPCMEnabled;
+#endif
   bool              m_JointCbCrEnabledFlag;
   // Parameter
   BitDepths         m_bitDepths;
@@ -1310,8 +1314,13 @@ public:
   uint32_t                    getMaxCodingDepth() const                                                       { return  m_uiMaxCodingDepth;                                          }
   bool                    getTransformSkipEnabledFlag() const                                                 { return m_transformSkipEnabledFlag;                                   }
   void                    setTransformSkipEnabledFlag( bool b )                                               { m_transformSkipEnabledFlag = b;                                      }
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  bool                    getBDPCMEnabledFlag() const                                                         { return m_BDPCMEnabledFlag;                                           }
+  void                    setBDPCMEnabledFlag( bool b )                                                       { m_BDPCMEnabledFlag = b;                                              }
+#else
   int                     getBDPCMEnabled() const                                                             { return m_BDPCMEnabled;                                               }
   void                    setBDPCMEnabled(int val)                                                            { m_BDPCMEnabled = val;                                                }
+#endif
   void                    setBitsForPOC( uint32_t u )                                                         { m_uiBitsForPOC = u;                                                  }
   uint32_t                    getBitsForPOC() const                                                           { return m_uiBitsForPOC;                                               }
   void                    setNumReorderPics(int i, uint32_t tlayer)                                           { m_numReorderPics[tlayer] = i;                                        }
@@ -2274,6 +2283,9 @@ private:
   int                        m_iSliceQp;
   int                        m_iSliceQpBase;
   bool                       m_ChromaQpAdjEnabled;
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  bool                       m_tsResidualCodingDisabledFlag;
+#endif
   bool                       m_deblockingFilterDisable;
   bool                       m_deblockingFilterOverrideFlag;      //< offsets for deblocking filter inherit from PPS
   int                        m_deblockingFilterBetaOffsetDiv2;    //< beta offset for deblocking filter
@@ -2456,6 +2468,10 @@ public:
   void                        setSliceQpDelta( int i )                               { m_iSliceQpDelta     = i;                                      }
   void                        setSliceChromaQpDelta( ComponentID compID, int i )     { m_iSliceChromaQpDelta[compID] = isLuma(compID) ? 0 : i;       }
   void                        setUseChromaQpAdj( bool b )                            { m_ChromaQpAdjEnabled = b;                                     }
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  void                        setTSResidualCodingDisabledFlag( bool b )              { m_tsResidualCodingDisabledFlag = b; }
+  bool                        getTSResidualCodingDisabledFlag() const                { return m_tsResidualCodingDisabledFlag; }
+#endif
   void                        setDeblockingFilterDisable( bool b )                   { m_deblockingFilterDisable= b;                                 }
   void                        setDeblockingFilterOverrideFlag( bool b )              { m_deblockingFilterOverrideFlag = b;                           }
   void                        setDeblockingFilterBetaOffsetDiv2( int i )             { m_deblockingFilterBetaOffsetDiv2 = i;                         }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 756850b86..615e5e55d 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM     1 // JVET-Q0089: RRC slice-level switch for lossless coding and one SPS flag for luma and chroma BDPCM.
+
 #define JVET_Q0110_Q0785_CHROMA_BDPCM_420                 1 // JVET-Q0110/Q0785: Enable chroma BDPCM for 420, separate contexts for chroma BDPCM and bug-fixes.
 
 #define JVET_Q0512_ENC_CHROMA_TS_ACT                      1 // JVET-Q0512: encoder-side improvement on enabling chroma transform-skip for ACT
@@ -334,12 +336,14 @@ typedef       uint64_t        Distortion;        ///< distortion measurement
 // Enumeration
 // ====================================================================================================================
 
+#if !JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
 enum BDPCMControl
 {
   BDPCM_INACTIVE = 0,
   BDPCM_LUMAONLY = 1,
   BDPCM_LUMACHROMA = 2,
 };
+#endif
 
 enum ApsType
 {
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index ece0dcac6..023d7796f 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -3837,8 +3837,12 @@ bool CU::bdpcmAllowed( const CodingUnit& cu, const ComponentID compID )
 {
   SizeType transformSkipMaxSize = 1 << cu.cs->pps->getLog2MaxTransformSkipBlockSize();
 
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  bool bdpcmAllowed = cu.cs->sps->getBDPCMEnabledFlag();
+#else
   bool bdpcmAllowed = cu.cs->sps->getBDPCMEnabled();
        bdpcmAllowed &= (isLuma(compID) || cu.cs->sps->getBDPCMEnabled() == BDPCM_LUMACHROMA);
+#endif
        bdpcmAllowed &= CU::isIntra( cu );
        if (isLuma(compID))
            bdpcmAllowed &= (cu.lwidth() <= transformSkipMaxSize && cu.lheight() <= transformSkipMaxSize);
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 5f9043eab..5207a1d64 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -2958,7 +2958,11 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx&
   ts_flag            ( tu, compID );
   explicit_rdpcm_mode( tu, compID );
 
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  if( tu.mtsIdx[compID] == MTS_SKIP && !tu.cs->slice->getTSResidualCodingDisabledFlag() )
+#else
   if (tu.mtsIdx[compID] == MTS_SKIP)
+#endif
   {
     residual_codingTS( tu, compID );
     return;
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 48752f8cc..a89e6ab4c 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -1504,6 +1504,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   READ_FLAG(uiCode, "sps_transform_skip_enabled_flag"); pcSPS->setTransformSkipEnabledFlag(uiCode ? true : false);
   if (pcSPS->getTransformSkipEnabledFlag())
   {
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+    READ_FLAG(uiCode, "sps_bdpcm_enabled_flag"); pcSPS->setBDPCMEnabledFlag(uiCode ? true : false);
+#else
       READ_FLAG(uiCode, "sps_bdpcm_enabled_flag");
 #if JVET_Q0110_Q0785_CHROMA_BDPCM_420
       if( uiCode )
@@ -1515,6 +1518,7 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
           uiCode++;
       }
       pcSPS->setBDPCMEnabled(uiCode);
+#endif
   }
 
   READ_FLAG(uiCode, "sps_ref_wraparound_enabled_flag");                  pcSPS->setWrapAroundEnabledFlag( uiCode ? true : false );
@@ -3313,7 +3317,6 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, Par
 #endif
     }
 
-
     if (pps->getDeblockingFilterControlPresentFlag())
     {
       if( pps->getDeblockingFilterOverrideEnabledFlag() && !picHeader->getDeblockingFilterOverridePresentFlag() )
@@ -3386,7 +3389,10 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, Par
 #endif
     }
 
-
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+	READ_FLAG(uiCode, "slice_ts_residual_coding_disabled_flag");
+	pcSlice->setTSResidualCodingDisabledFlag(uiCode != 0);
+#endif
 
   if( pcSlice->getFirstCtuRsAddrInSlice() == 0 )
   {
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index 5b851d934..6cfe6d532 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -815,7 +815,11 @@ void CABACWriter::pred_mode( const CodingUnit& cu )
 }
 void CABACWriter::bdpcm_mode( const CodingUnit& cu, const ComponentID compID )
 {
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  if( !cu.cs->sps->getBDPCMEnabledFlag() ) return;
+#else
   if( cu.cs->sps->getBDPCMEnabled() == 0 ) return;
+#endif
   if( !CU::bdpcmAllowed( cu, compID ) ) return;
 
   int bdpcmMode = isLuma(compID) ? cu.bdpcmMode : cu.bdpcmModeChroma;
@@ -2707,7 +2711,11 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID,
   ts_flag            ( tu, compID );
   explicit_rdpcm_mode( tu, compID );
 
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  if( tu.mtsIdx[compID] == MTS_SKIP && !tu.cs->slice->getTSResidualCodingDisabledFlag() )
+#else
   if (tu.mtsIdx[compID] == MTS_SKIP)
+#endif
   {
     residual_codingTS( tu, compID );
     return;
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 6b66f9ff6..b795a2a41 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -460,7 +460,11 @@ protected:
   bool      m_useTransformSkip;
   bool      m_useTransformSkipFast;
   bool      m_useChromaTS;
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  bool      m_useBDPCM;
+#else
   int       m_useBDPCM;
+#endif
   uint32_t      m_log2MaxTransformSkipBlockSize;
   bool      m_transformSkipRotationEnabledFlag;
   bool      m_transformSkipContextEnabledFlag;
@@ -1350,8 +1354,13 @@ public:
   void setTransformSkipContextEnabledFlag              (const bool value)  { m_transformSkipContextEnabledFlag = value; }
   bool getUseChromaTS                                  ()       { return m_useChromaTS; }
   void setUseChromaTS                                  (bool b) { m_useChromaTS = b; }
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  bool getUseBDPCM                                     ()         { return m_useBDPCM; }
+  void setUseBDPCM                                     ( bool b ) { m_useBDPCM  = b;   }
+#else
   int  getUseBDPCM                                     ()         { return m_useBDPCM; }
   void setUseBDPCM                                     ( int b )  { m_useBDPCM = b;    }
+#endif
   bool getUseJointCbCr                                 ()         { return m_JointCbCrMode; }
   void setUseJointCbCr                                 (bool b)   { m_JointCbCrMode = b; }
   bool getPersistentRiceAdaptationEnabledFlag          ()                 const { return m_persistentRiceAdaptationEnabledFlag;  }
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index 4595b865a..6352d8b3e 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -1128,7 +1128,11 @@ void EncLib::xInitSPS( SPS& sps, VPS& vps )
   CHECK(m_uiMaxMTTHierarchyDepthIChroma > 2 * (floorLog2(sps.getCTUSize()) - sps.getLog2MinCodingBlockSize()), "sps_max_mtt_hierarchy_depth_intra_slice_chroma shall be in the range 0 to 2*(ctbLog2SizeY - log2MinCUSize)");
 
   sps.setTransformSkipEnabledFlag(m_useTransformSkip);
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  sps.setBDPCMEnabledFlag(m_useBDPCM);
+#else
   sps.setBDPCMEnabled(m_useBDPCM);
+#endif
 
   sps.setSPSTemporalMVPEnabledFlag((getTMVPModeId() == 2 || getTMVPModeId() == 1));
 
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 979743ec4..525656424 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -343,6 +343,16 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr
     picHeader->setPicOutputFlag(true);
   }
   rpcSlice->setPOC( pocCurr );
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  if( m_pcCfg->getCostMode() == COST_LOSSLESS_CODING )
+  {
+    rpcSlice->setTSResidualCodingDisabledFlag(true);
+  }
+  else
+  {
+    rpcSlice->setTSResidualCodingDisabledFlag(false);
+  }
+#endif
 
 #if SHARP_LUMA_DELTA_QP
   pcPic->fieldPic = isField;
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index ecacd5094..432360f38 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -448,7 +448,11 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c
     }
   }
 
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+  const bool testBDPCM = sps.getBDPCMEnabledFlag() && CU::bdpcmAllowed(cu, ComponentID(partitioner.chType)) && cu.mtsFlag == 0 && cu.lfnstIdx == 0;
+#else
   const bool testBDPCM = (sps.getBDPCMEnabled()!=0) && CU::bdpcmAllowed(cu, ComponentID(partitioner.chType)) && cu.mtsFlag == 0 && cu.lfnstIdx == 0;
+#endif
   static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiHadModeList;
   static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandCostList;
   static_vector<double, FAST_UDI_MAX_RDMODE_NUM> CandHadList;
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index a4e36d773..6e2a884e0 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -961,6 +961,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   WRITE_FLAG(pcSPS->getTransformSkipEnabledFlag() ? 1 : 0, "sps_transform_skip_enabled_flag");
   if (pcSPS->getTransformSkipEnabledFlag())
   {
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+    WRITE_FLAG(pcSPS->getBDPCMEnabledFlag() ? 1 : 0, "sps_bdpcm_enabled_flag");
+#else
       WRITE_FLAG(pcSPS->getBDPCMEnabled() ? 1 : 0, "sps_bdpcm_enabled_flag");
 #if JVET_Q0110_Q0785_CHROMA_BDPCM_420
       if( pcSPS->getBDPCMEnabled() )
@@ -975,11 +978,16 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
       {
         CHECK(pcSPS->getBDPCMEnabled() == BDPCM_LUMACHROMA, "BDPCM for chroma can be used for 444 only.")
       }
+#endif
 #endif
   }
   else
   {
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+    CHECK(pcSPS->getBDPCMEnabledFlag(), "BDPCM cannot be used when transform skip is disabled");
+#else
     CHECK(pcSPS->getBDPCMEnabled()!=0, "BDPCM cannot be used when transform skip is disabled");
+#endif
   }
 
   WRITE_FLAG( pcSPS->getWrapAroundEnabledFlag() ? 1 : 0,                              "sps_ref_wraparound_enabled_flag" );
@@ -2265,6 +2273,7 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
 #endif
       }
     }
+	
 
     if (pcSlice->getPPS()->getDeblockingFilterControlPresentFlag())
     {
@@ -2317,6 +2326,10 @@ void HLSWriter::codeSliceHeader         ( Slice* pcSlice )
 #endif
     }
 
+#if JVET_Q0089_SLICE_LOSSLESS_CODING_CHROMA_BDPCM
+	WRITE_FLAG(pcSlice->getTSResidualCodingDisabledFlag() ? 1 : 0, "slice_ts_residual_coding_disabled_flag");
+#endif
+
   if(pcSlice->getPPS()->getSliceHeaderExtensionPresentFlag())
   {
     WRITE_UVLC(0,"slice_segment_header_extension_length");
-- 
GitLab