From 4a25ab06ea964012e3179cd5c6a66d0404696654 Mon Sep 17 00:00:00 2001
From: Mohammed Golam Sarwer <m.sarwer@alibaba-inc.com>
Date: Sat, 9 May 2020 05:56:44 +0200
Subject: [PATCH] JVET-R0110: Mixed lossy/lossless coding

---
 cfg/lossless/lossless.cfg                     |   1 +
 cfg/lossless/lossless_mixed.cfg               |  46 ++++++
 doc/software-manual.tex                       |   6 +
 source/App/EncoderApp/EncApp.cpp              |   3 +
 source/App/EncoderApp/EncAppCfg.cpp           |  40 ++++-
 source/App/EncoderApp/EncAppCfg.h             |   3 +
 source/Lib/CommonLib/Picture.h                |   9 +-
 source/Lib/CommonLib/QuantRDOQ.cpp            |   5 +
 source/Lib/CommonLib/RdCost.cpp               |   6 +-
 source/Lib/CommonLib/RdCost.h                 |   7 +
 source/Lib/CommonLib/Slice.cpp                |   3 +
 source/Lib/CommonLib/Slice.h                  |   7 +
 source/Lib/CommonLib/TypeDef.h                |   2 +
 .../Lib/EncoderLib/EncAdaptiveLoopFilter.cpp  |  19 +++
 source/Lib/EncoderLib/EncAdaptiveLoopFilter.h |   3 +
 source/Lib/EncoderLib/EncCfg.h                |   8 +-
 source/Lib/EncoderLib/EncCu.cpp               |   4 +
 source/Lib/EncoderLib/EncGOP.cpp              |  75 ++++++++-
 source/Lib/EncoderLib/EncSlice.cpp            |  36 +++++
 source/Lib/EncoderLib/EncSlice.h              |   3 +
 source/Lib/EncoderLib/InterSearch.cpp         |  39 ++++-
 source/Lib/EncoderLib/IntraSearch.cpp         | 143 ++++++++++++++++--
 22 files changed, 435 insertions(+), 33 deletions(-)
 create mode 100644 cfg/lossless/lossless_mixed.cfg

diff --git a/cfg/lossless/lossless.cfg b/cfg/lossless/lossless.cfg
index 793b2bedb..2ab513b33 100644
--- a/cfg/lossless/lossless.cfg
+++ b/cfg/lossless/lossless.cfg
@@ -21,4 +21,5 @@ PROF                         : 0
 Log2MaxTbSize                : 5
 InternalBitDepth             : 0
 TSRCdisableLL                : 1
+SliceLosslessArray           : 1
 
diff --git a/cfg/lossless/lossless_mixed.cfg b/cfg/lossless/lossless_mixed.cfg
new file mode 100644
index 000000000..c53046585
--- /dev/null
+++ b/cfg/lossless/lossless_mixed.cfg
@@ -0,0 +1,46 @@
+CostMode                     : lossless
+BDPCM                        : 1
+ChromaTS                     : 1
+BDPCM                        : 1
+DepQuant                     : 0
+RDOQ                         : 1
+RDOQTS                       : 1
+SBT                          : 0
+LMCSEnable                   : 0
+ISP                          : 0
+MTS                          : 0
+LFNST                        : 0
+JointCbCr                    : 0
+LoopFilterDisable            : 0
+SAO                          : 1
+ALF                          : 1
+CCALF                        : 0
+DMVR                         : 0
+BIO                          : 0
+PROF                         : 0
+Log2MaxTbSize                : 5
+InternalBitDepth             : 0
+TSRCdisableLL                : 1
+
+# Configuration to achieve mixed-lossy lossless coding
+QP                           : 55          # Quantization parameter for lossy slices
+CbQpOffset                   : 0
+CrQpOffset                   : 0
+SliceLevelDblk               : 1
+SliceLevelAlf                : 1
+SliceLevelSao                : 1
+SignHideFlag                 : 0
+SliceLosslessArray           : 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 0 1 
+
+#============ Tiles / Slices ================
+EnablePicPartitioning         : 1                         # Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
+
+TileColumnWidthArray          : 3 3 3 3 3 3               # Tile column widths in units of CTUs. Last column width will be repeated uniformly to cover any remaining picture width
+TileRowHeightArray            : 3 3 3 3                   # Tile row heights in units of CTUs. Last row height will be repeated uniformly to cover any remaining picture height  
+RasterScanSlices              : 0                         # Raster-scan or rectangular slices (0: rectangular, 1: raster-scan)
+RectSliceFixedWidth           : 1                         # Fixed rectangular slice width in units of tiles (0: disable this feature and use RectSlicePositions instead)
+RectSliceFixedHeight          : 1                         # Fixed rectangular slice height in units of tiles (0: disable this feature and use RectSlicePositions instead)
+DisableLoopFilterAcrossTiles  : 1                         # Loop filtering (DBLK/SAO/ALF) applied across tile boundaries or not (0: filter across tile boundaries  1: do not filter across tile boundaries)
+DisableLoopFilterAcrossSlices : 1                         # Loop filtering (DBLK/SAO/ALF) applied across slice boundaries or not (0: filter across slice boundaries 1: do not filter across slice boundaries)
+
+
diff --git a/doc/software-manual.tex b/doc/software-manual.tex
index aa01684f0..9b5c193ca 100644
--- a/doc/software-manual.tex
+++ b/doc/software-manual.tex
@@ -2024,6 +2024,12 @@ Allow signalling of entry points for WPP in slice header.
 Note that when a slice contains more than one tile, entry point offsets for tile are always present in the slice header.
 \\
 
+\Option{SliceLosslessArray} &
+%\ShortOption{\None} &
+\Default{0} &
+Define pattern of lossless coding in unit of slices, 0 means lossy slice; 1 means lossless slice. Example:  1 1 0 0 means first 2 slices are lossless coded and rest of the slices are lossy coded. Default is all slices are lossy coded.
+\\
+
 \end{OptionTableNoShorthand}
 
 %%
diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index 2b50392d1..db141a6fa 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -559,6 +559,9 @@ void EncApp::xInitLibCfg()
 
   //====== Parallel Merge Estimation ========
   m_cEncLib.setLog2ParallelMergeLevelMinus2(m_log2ParallelMergeLevel - 2);
+#if JVET_R0110_MIXED_LOSSLESS
+  m_cEncLib.setSliceLosslessArray(m_sliceLosslessArray);
+#endif
 
   //====== Tiles and Slices ========
   m_cEncLib.setNoPicPartitionFlag( !m_picPartitionFlag );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 0faec54b6..c07e8e978 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -606,7 +606,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 
 
   SMultiValueInput<double> cfg_adIntraLambdaModifier         (0, std::numeric_limits<double>::max(), 0, MAX_TLAYER); ///< Lambda modifier for Intra pictures, one for each temporal layer. If size>temporalLayer, then use [temporalLayer], else if size>0, use [size()-1], else use m_adLambdaModifier.
-
+#if JVET_R0110_MIXED_LOSSLESS
+  SMultiValueInput<uint32_t>  cfgSliceLosslessArray(0, std::numeric_limits<uint32_t>::max(), 0, std::numeric_limits<uint32_t>::max());
+#endif
 #if SHARP_LUMA_DELTA_QP
   const int defaultLumaLevelTodQp_QpChangePoints[]   =  {-3,  -2,  -1,   0,   1,   2,   3,   4,   5,   6};
   const int defaultLumaLevelTodQp_LumaChangePoints[] =  { 0, 301, 367, 434, 501, 567, 634, 701, 767, 834};
@@ -1081,6 +1083,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("SAOLcuBoundary",                                  m_saoCtuBoundary,                                 false, "0: right/bottom CTU boundary areas skipped from SAO parameter estimation, 1: non-deblocked pixels are used for those areas")
   ("SAOGreedyEnc",                                    m_saoGreedyMergeEnc,                              false, "SAO greedy merge encoding algorithm")
   ("EnablePicPartitioning",                           m_picPartitionFlag,                               false, "Enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)")
+#if JVET_R0110_MIXED_LOSSLESS
+  ("SliceLosslessArray", cfgSliceLosslessArray, cfgSliceLosslessArray, " Lossless slice array Last lossless flag in the  list will be repeated uniformly to cover any remaining slice")
+#endif 
   ("TileColumnWidthArray",                            cfgTileColumnWidth,                  cfgTileColumnWidth, "Tile column widths in units of CTUs. Last column width in list will be repeated uniformly to cover any remaining picture width")
   ("TileRowHeightArray",                              cfgTileRowHeight,                      cfgTileRowHeight, "Tile row heights in units of CTUs. Last row height in list will be repeated uniformly to cover any remaining picture height")
   ("RasterScanSlices",                                m_rasterSliceFlag,                                false, "Indicates if using raster-scan or rectangular slices (0: rectangular, 1: raster-scan)")
@@ -1610,6 +1615,34 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
     }
   }
 
+#if JVET_R0110_MIXED_LOSSLESS
+  // store slice lossless array 
+  const int maxSlicesPerPicture = 600; // the maximum number of slices per picture is 600
+  m_sliceLosslessArray.resize(maxSlicesPerPicture);
+  if (cfgSliceLosslessArray.values.size() == 0)
+  {
+    // Default all slices are lossy
+    for (uint32_t i = 0; i < maxSlicesPerPicture; i++)
+    {
+      m_sliceLosslessArray[i] = 0;
+    }
+  }
+  else
+  {
+    for (uint32_t i = 0; i < cfgSliceLosslessArray.values.size(); i++)
+    {
+      m_sliceLosslessArray[i] = cfgSliceLosslessArray.values[i];
+    }
+    for (uint32_t i = (uint32_t)cfgSliceLosslessArray.values.size(); i < maxSlicesPerPicture; i++)
+    {
+      if (cfgSliceLosslessArray.values.size() > 0)
+        m_sliceLosslessArray[i] = cfgSliceLosslessArray.values[cfgSliceLosslessArray.values.size() - 1];
+      else
+        m_sliceLosslessArray[i] = 0;
+    }
+  }
+#endif
+
   if( m_picPartitionFlag )
   {
     // store tile column widths
@@ -2220,11 +2253,16 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
 #endif
 #endif // ENABLE_QPA
 
+#if JVET_R0110_MIXED_LOSSLESS
+  if (m_costMode == COST_LOSSLESS_CODING && m_sliceLosslessArray[0]) // if first slice is lossless 
+#else
   if( m_costMode == COST_LOSSLESS_CODING )
+#endif
   {
     m_iQP = LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP - ( ( m_internalBitDepth[CHANNEL_TYPE_LUMA] - 8 ) * 6 );
   }
 
+
   m_uiMaxCUWidth = m_uiMaxCUHeight = m_uiCTUSize;
 
   // check validity of input parameters
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 0263cb3ba..14cf20b36 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -440,6 +440,9 @@ protected:
   bool      m_bUseCbfFastMode;                                ///< flag for using Cbf Fast PU Mode Decision
   bool      m_useEarlySkipDetection;                          ///< flag for using Early SKIP Detection
   bool      m_picPartitionFlag;                               ///< enable picture partitioning (0: single tile, single slice, 1: multiple tiles/slices can be used)
+#if JVET_R0110_MIXED_LOSSLESS
+  std::vector<uint32_t> m_sliceLosslessArray;                    ///< Slice lossless array
+#endif
   std::vector<uint32_t> m_tileColumnWidth;                    ///< tile column widths in units of CTUs (last column width will be repeated uniformly to cover any remaining picture width)
   std::vector<uint32_t> m_tileRowHeight;                      ///< tile row heights in units of CTUs (last row height will be repeated uniformly to cover any remaining picture height)
   bool      m_rasterSliceFlag;                                ///< indicates if using raster-scan or rectangular slices (0: rectangular, 1: raster-scan)
diff --git a/source/Lib/CommonLib/Picture.h b/source/Lib/CommonLib/Picture.h
index 4a0b4ab8b..6f4b5b6da 100644
--- a/source/Lib/CommonLib/Picture.h
+++ b/source/Lib/CommonLib/Picture.h
@@ -155,6 +155,11 @@ struct Picture : public UnitArea
   void setBorderExtension( bool bFlag)              { m_bIsBorderExtended = bFlag;}
   Pel* getOrigin( const PictureType &type, const ComponentID compID ) const;
 
+#if JVET_R0110_MIXED_LOSSLESS
+  void setLossyQPValue(int i)                 { m_lossyQP = i; }
+  int getLossyQPValue()                       const { return m_lossyQP; }
+#endif
+
   int           getSpliceIdx(uint32_t idx) const { return m_spliceIdx[idx]; }
   void          setSpliceIdx(uint32_t idx, int poc) { m_spliceIdx[idx] = poc; }
   void          createSpliceIdx(int nums);
@@ -211,7 +216,9 @@ public:
 
   int* m_spliceIdx;
   int  m_ctuNums;
-
+#if JVET_R0110_MIXED_LOSSLESS
+  int m_lossyQP;
+#endif
   bool interLayerRefPicFlag;
 
 #if ENABLE_SPLIT_PARALLELISM
diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp
index 881f0178c..26a17c99d 100644
--- a/source/Lib/CommonLib/QuantRDOQ.cpp
+++ b/source/Lib/CommonLib/QuantRDOQ.cpp
@@ -527,6 +527,11 @@ void QuantRDOQ::quant(TransformUnit &tu, const ComponentID &compID, const CCoeff
     useRDOQ &= uiHeight > 2;
   }
 
+#if  JVET_R0110_MIXED_LOSSLESS
+  if (tu.cs->slice->isLossless())
+    useRDOQ = false;
+#endif
+
   if (useRDOQ && (isLuma(compID) || RDOQ_CHROMA))
   {
 #if T0196_SELECTIVE_RDOQ
diff --git a/source/Lib/CommonLib/RdCost.cpp b/source/Lib/CommonLib/RdCost.cpp
index 81eec7926..4f4cdb585 100644
--- a/source/Lib/CommonLib/RdCost.cpp
+++ b/source/Lib/CommonLib/RdCost.cpp
@@ -65,7 +65,11 @@ double RdCost::calcRdCost( uint64_t fracBits, Distortion distortion, bool useUna
 double RdCost::calcRdCost( uint64_t fracBits, Distortion distortion )
 #endif
 {
-  if( m_costMode == COST_LOSSLESS_CODING && 0 != distortion )
+#if JVET_R0110_MIXED_LOSSLESS  
+  if (m_costMode == COST_LOSSLESS_CODING && 0 != distortion && m_isLosslessRDCost)
+#else
+  if( m_costMode == COST_LOSSLESS_CODING && 0 != distortion)
+#endif
   {
     return MAX_DOUBLE;
   }
diff --git a/source/Lib/CommonLib/RdCost.h b/source/Lib/CommonLib/RdCost.h
index 15a2c5c74..3cf776c1a 100644
--- a/source/Lib/CommonLib/RdCost.h
+++ b/source/Lib/CommonLib/RdCost.h
@@ -114,6 +114,10 @@ private:
   CostMode                m_costMode;
   double                  m_distortionWeight[MAX_NUM_COMPONENT]; // only chroma values are used.
   double                  m_dLambda;
+#if JVET_R0110_MIXED_LOSSLESS
+  bool                   m_isLosslessRDCost;
+#endif
+
 #if WCG_EXT
   double                  m_dLambda_unadjusted; // TODO: check is necessary
   double                  m_DistScaleUnadjusted;
@@ -164,6 +168,9 @@ public:
 #endif
 
   void          setCostMode(CostMode m) { m_costMode = m; }
+#if JVET_R0110_MIXED_LOSSLESS
+  void          setLosslessRDCost(bool m) { m_isLosslessRDCost = m; }
+#endif
 
   // Distortion Functions
   void          init();
diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp
index 948a5a3b0..d28342e43 100644
--- a/source/Lib/CommonLib/Slice.cpp
+++ b/source/Lib/CommonLib/Slice.cpp
@@ -1019,6 +1019,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
   m_tileGroupLumaApsId            = pSrc->m_tileGroupLumaApsId;
   m_tileGroupChromaApsId          = pSrc->m_tileGroupChromaApsId;
   m_disableSATDForRd              = pSrc->m_disableSATDForRd;
+#if JVET_R0110_MIXED_LOSSLESS
+  m_isLossless = pSrc->m_isLossless;
+#endif
 
   if( cpyAlmostAll ) m_encCABACTableIdx  = pSrc->m_encCABACTableIdx;
   for( int i = 0; i < NUM_REF_PIC_LIST_01; i ++ )
diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h
index a9e092631..3b9109cc6 100644
--- a/source/Lib/CommonLib/Slice.h
+++ b/source/Lib/CommonLib/Slice.h
@@ -2588,6 +2588,9 @@ private:
   int                        m_tileGroupCcAlfCbApsId;
   int                        m_tileGroupCcAlfCrApsId;
   bool                       m_disableSATDForRd;
+#if JVET_R0110_MIXED_LOSSLESS
+  bool                       m_isLossless;
+#endif
 public:
                               Slice();
   virtual                     ~Slice();
@@ -2877,6 +2880,10 @@ public:
   int  getTileGroupCcAlfCrApsId() { return m_tileGroupCcAlfCrApsId; }
   void                        setDisableSATDForRD(bool b) { m_disableSATDForRd = b; }
   bool                        getDisableSATDForRD() { return m_disableSATDForRd; }
+#if JVET_R0110_MIXED_LOSSLESS
+  void                        setLossless(bool b) { m_isLossless = b; }
+  bool                        isLossless() const { return m_isLossless; }
+#endif
   void                        scaleRefPicList( Picture *scaledRefPic[ ], PicHeader *picHeader, APS** apss, APS* lmcsAps, APS* scalingListAps, const bool isDecoder );
   void                        freeScaledRefPicList( Picture *scaledRefPic[] );
   bool                        checkRPR();
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 3ba52903d..99e8bcb6b 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -85,6 +85,8 @@
 
 #define JVET_R0437_BS_DERIVATION                          1 // JVET-R0437: fix the bS derivation for palette mode
 
+#define JVET_R0110_MIXED_LOSSLESS                         1 // JVET-R0110: Slice level mixed lossy/lossless coding: encoder only method
+
 #define JVET_R0330_CRS_CLIP_REM                           1 // JVET-R0330: Remove redundant clipping in chroma residual scaling factor derivation
 
 #define JVET_R0059_RPL_CLEANUP                            1 // JVET-R0059 aspect 2: Condition the signalling of ltrp_in_header_flag[ listIdx ][ rplsIdx ].
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
index 111872fb0..76ce5f0da 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.cpp
@@ -886,6 +886,9 @@ void EncAdaptiveLoopFilter::xSetupCcAlfAPS( CodingStructure &cs )
 void EncAdaptiveLoopFilter::ALFProcess(CodingStructure& cs, const double *lambdas
 #if ENABLE_QPA
                                        , const double lambdaChromaWeight
+#endif
+#if JVET_R0110_MIXED_LOSSLESS
+                                       , Picture* pcPic, uint32_t numSliceSegments
 #endif
                                       )
 {
@@ -1049,6 +1052,22 @@ void EncAdaptiveLoopFilter::ALFProcess(CodingStructure& cs, const double *lambda
 #endif
   );
 
+#if  JVET_R0110_MIXED_LOSSLESS
+  for (int s = 0; s < numSliceSegments; s++)
+  {
+    if (pcPic->slices[s]->isLossless())
+    {
+      for (uint32_t ctuIdx = 0; ctuIdx < pcPic->slices[s]->getNumCtuInSlice(); ctuIdx++)
+      {
+        uint32_t ctuRsAddr = pcPic->slices[s]->getCtuAddrInSlice(ctuIdx);
+        m_ctuEnableFlag[COMPONENT_Y][ctuRsAddr] = 0;
+        m_ctuEnableFlag[COMPONENT_Cb][ctuRsAddr] = 0;
+        m_ctuEnableFlag[COMPONENT_Cr][ctuRsAddr] = 0;
+      }
+    }
+  }
+#endif
+
   alfReconstructor(cs, recYuv);
 
   // Do not transmit CC ALF if it is unchanged
diff --git a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
index db4c7d313..cecff4c84 100644
--- a/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
+++ b/source/Lib/EncoderLib/EncAdaptiveLoopFilter.h
@@ -293,6 +293,9 @@ public:
   void ALFProcess(CodingStructure& cs, const double *lambdas
 #if ENABLE_QPA
     , const double lambdaChromaWeight
+#endif
+#if JVET_R0110_MIXED_LOSSLESS
+    , Picture* pcPic, uint32_t numSliceSegments
 #endif
   );
   int getNewCcAlfApsId(CodingStructure &cs, int cIdx);
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 40e2516d8..6c64775ab 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -472,6 +472,9 @@ protected:
   bool      m_bUseBLambdaForNonKeyLowDelayPictures;
   bool      m_gopBasedTemporalFilterEnabled;
   bool      m_noPicPartitionFlag;                             ///< no picture partitioning flag (single tile, single slice)
+#if JVET_R0110_MIXED_LOSSLESS
+  std::vector<uint32_t> m_sliceLosslessArray;                    ///< Slice lossless array
+#endif
   std::vector<uint32_t> m_tileColumnWidth;                    ///< tile column widths in units of CTUs (last column width will be repeated uniformly to cover any remaining picture width)
   std::vector<uint32_t> m_tileRowHeight;                      ///< tile row heights in units of CTUs (last row height will be repeated uniformly to cover any remaining picture height)
   bool      m_rectSliceFlag;                                  ///< indicates if using rectangular or raster-scan slices
@@ -1355,7 +1358,10 @@ public:
   const int* getdQPs                        () const { return m_aidQP;       }
   uint32_t      getDeltaQpRD                    () const { return m_uiDeltaQpRD; }
   bool      getFastDeltaQp                  () const { return m_bFastDeltaQP; }
-
+#if JVET_R0110_MIXED_LOSSLESS
+  void      setSliceLosslessArray(std::vector<uint32_t> sliceLosslessArray) { m_sliceLosslessArray = sliceLosslessArray; }
+  const     std::vector<uint32_t>*   getSliceLosslessArray() const { return &m_sliceLosslessArray; }
+#endif
   //====== Tiles and Slices ========
   void      setNoPicPartitionFlag( bool b )                                { m_noPicPartitionFlag = b;              }
   bool      getNoPicPartitionFlag()                                        { return m_noPicPartitionFlag;           }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index ff9addd27..8e63c8799 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -775,7 +775,11 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par
       {
         bool skipSecColorSpace = false;
         skipSecColorSpace = xCheckRDCostIntra(tempCS, bestCS, partitioner, currTestMode, (m_pcEncCfg->getRGBFormatFlag() ? true : false));
+#if JVET_R0110_MIXED_LOSSLESS        
+        if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()) && !m_pcEncCfg->getRGBFormatFlag())
+#else
         if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING) && !m_pcEncCfg->getRGBFormatFlag())
+#endif
         {
           skipSecColorSpace = true;
         }
diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp
index 78a98415c..1d508ce9b 100644
--- a/source/Lib/EncoderLib/EncGOP.cpp
+++ b/source/Lib/EncoderLib/EncGOP.cpp
@@ -2663,6 +2663,9 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
     // now compress (trial encode) the various slice segments (slices, and dependent slices)
     {
       DTRACE_UPDATE( g_trace_ctx, ( std::make_pair( "poc", pocCurr ) ) );
+#if JVET_R0110_MIXED_LOSSLESS
+      const std::vector<uint32_t> sliceLosslessArray = *(m_pcCfg->getSliceLosslessArray());
+#endif
 
       for(uint32_t sliceIdx = 0; sliceIdx < pcPic->cs->pps->getNumSlicesInPic(); sliceIdx++ )
       {
@@ -2705,6 +2708,16 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
             }
           }
         }
+
+#if JVET_R0110_MIXED_LOSSLESS
+        bool isLossless = false;
+        if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
+        {
+          isLossless = (sliceLosslessArray[sliceIdx] != 0);
+        }
+        m_pcSliceEncoder->setLosslessSlice(pcPic, isLossless);
+#endif
+
         m_pcSliceEncoder->precompressSlice( pcPic );
         m_pcSliceEncoder->compressSlice   ( pcPic, false, false );
 
@@ -2799,7 +2812,18 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         }
   #endif
       }
-
+#if JVET_R0110_MIXED_LOSSLESS
+      if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING) 
+      {
+        for (int s = 0; s < uiNumSliceSegments; s++)
+        {
+          if (pcPic->slices[s]->isLossless())
+          {
+            pcPic->slices[s]->setDeblockingFilterDisable(true);
+          }
+        }
+      }
+#endif
       m_pcLoopFilter->loopFilterPic( cs );
 
       CS::setRefinedMotionField(cs);
@@ -2815,11 +2839,26 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
 #endif
                              m_pcCfg->getTestSAODisableAtPictureLevel(), m_pcCfg->getSaoEncodingRate(), m_pcCfg->getSaoEncodingRateChroma(), m_pcCfg->getSaoCtuBoundary(), m_pcCfg->getSaoGreedyMergeEnc() );
         //assign SAO slice header
-        for(int s=0; s< uiNumSliceSegments; s++)
+        for (int s = 0; s < uiNumSliceSegments; s++)
         {
-          pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]);
-          CHECK(!(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]), "Unspecified error");
-          pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]);
+
+#if  JVET_R0110_MIXED_LOSSLESS
+          if (pcPic->slices[s]->isLossless() && m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
+          {
+            pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, false);
+            pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, false);
+          }
+          else
+          {
+#endif          
+            pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_LUMA, sliceEnabled[COMPONENT_Y]);
+            CHECK(!(sliceEnabled[COMPONENT_Cb] == sliceEnabled[COMPONENT_Cr]), "Unspecified error");
+            pcPic->slices[s]->setSaoEnabledFlag(CHANNEL_TYPE_CHROMA, sliceEnabled[COMPONENT_Cb]);
+
+#if  JVET_R0110_MIXED_LOSSLESS
+        }
+#endif
+
         }
       }
 
@@ -2836,15 +2875,35 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic,
         m_pcALF->ALFProcess(cs, pcSlice->getLambdas()
 #if ENABLE_QPA
           , (m_pcCfg->getUsePerceptQPA() && !m_pcCfg->getUseRateCtrl() && pcSlice->getPPS()->getUseDQP() ? m_pcEncLib->getRdCost(PARL_PARAM0(0))->getChromaWeight() : 0.0)
+#endif
+#if JVET_R0110_MIXED_LOSSLESS
+          , pcPic, uiNumSliceSegments
 #endif
         );
 
         //assign ALF slice header
         for (int s = 0; s < uiNumSliceSegments; s++)
         {
-          pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y));
-          pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cb, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb));
-          pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cr, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr));
+#if JVET_R0110_MIXED_LOSSLESS
+           //For the first slice, even if it is lossless, slice level ALF is not disabled and ALF-APS is signaled so that the later lossy slices can use APS of the first slice. 
+           //However, if the first slice is lossless, the ALF process is disabled for all of the CTUs ( m_ctuEnableFlag == 0) of that slice which is implemented in the function void EncAdaptiveLoopFilter::ALFProcess.         
+      
+          if (pcPic->slices[s]->isLossless() && s && m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
+          {
+            pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, false);
+            pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cb, false);
+            pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cr, false);
+          }
+          else
+          {
+#endif          
+            pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Y, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Y));
+            pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cb, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cb));
+            pcPic->slices[s]->setTileGroupAlfEnabledFlag(COMPONENT_Cr, cs.slice->getTileGroupAlfEnabledFlag(COMPONENT_Cr));
+
+#if JVET_R0110_MIXED_LOSSLESS
+          }
+#endif
           if (pcPic->slices[s]->getTileGroupAlfEnabledFlag(COMPONENT_Y))
           {
             pcPic->slices[s]->setTileGroupNumAps(cs.slice->getTileGroupNumAps());
diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp
index 599701109..46aa69ba7 100644
--- a/source/Lib/EncoderLib/EncSlice.cpp
+++ b/source/Lib/EncoderLib/EncSlice.cpp
@@ -628,6 +628,9 @@ void EncSlice::initEncSlice(Picture* pcPic, const int pocLast, const int pocCurr
 
   rpcSlice->setSliceQp           ( iQP );
   rpcSlice->setSliceQpDelta      ( 0 );
+#if JVET_R0110_MIXED_LOSSLESS
+  pcPic->setLossyQPValue(iQP);
+#endif
 #if !W0038_CQP_ADJ
   rpcSlice->setSliceChromaQpDelta( COMPONENT_Cb, 0 );
   rpcSlice->setSliceChromaQpDelta( COMPONENT_Cr, 0 );
@@ -1135,6 +1138,36 @@ void EncSlice::setSearchRange( Slice* pcSlice )
   }
 }
 
+#if JVET_R0110_MIXED_LOSSLESS
+void EncSlice::setLosslessSlice(Picture* pcPic, bool islossless) 
+{
+  Slice* slice = pcPic->slices[getSliceSegmentIdx()];
+  slice->setLossless(islossless);
+
+  if (m_pcCfg->getCostMode() == COST_LOSSLESS_CODING)
+  {
+    if (islossless)
+    {
+      int losslessQp = LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP - ((slice->getSPS()->getBitDepth(CHANNEL_TYPE_LUMA) - 8) * 6);
+      slice->setSliceQp(losslessQp); // update the slice/base QPs
+
+#if JVET_R0143_TSRCdisableLL
+     slice->setTSResidualCodingDisabledFlag(m_pcCfg->getTSRCdisableLL() ? true : false);
+#else
+     slice->setTSResidualCodingDisabledFlag(true);
+#endif 
+
+    }
+    else
+    {
+        slice->setSliceQp(pcPic->getLossyQPValue());
+        slice->setTSResidualCodingDisabledFlag(false);
+    }
+  }
+}
+#endif
+
+
 /**
  Multi-loop slice encoding for different slice QP
 
@@ -1441,6 +1474,9 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons
   RdCost*         pRdCost         = pEncLib->getRdCost( PARL_PARAM0( dataId ) );
   EncCfg*         pCfg            = pEncLib;
   RateCtrl*       pRateCtrl       = pEncLib->getRateCtrl();
+#if JVET_R0110_MIXED_LOSSLESS
+  pRdCost->setLosslessRDCost(pcSlice->isLossless());
+#endif
 #if RDOQ_CHROMA_LAMBDA
   pTrQuant    ->setLambdas( pcSlice->getLambdas() );
 #else
diff --git a/source/Lib/EncoderLib/EncSlice.h b/source/Lib/EncoderLib/EncSlice.h
index 53fadab31..aeff8eb1c 100644
--- a/source/Lib/EncoderLib/EncSlice.h
+++ b/source/Lib/EncoderLib/EncSlice.h
@@ -128,6 +128,9 @@ public:
   void    precompressSlice    ( Picture* pcPic                                     );      ///< precompress slice for multi-loop slice-level QP opt.
   void    compressSlice       ( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP );      ///< analysis stage of slice
   void    calCostSliceI       ( Picture* pcPic );
+#if JVET_R0110_MIXED_LOSSLESS
+  void    setLosslessSlice(Picture* pcPic, bool b);      ///< Set if the slice is lossless or not
+#endif
 
   void    encodeSlice         ( Picture* pcPic, OutputBitstream* pcSubstreams, uint32_t &numBinsCoded );
   void    encodeCtus          ( Picture* pcPic, const bool bCompressEntireSlice, const bool bFastDeltaQP, EncLib* pcEncLib );
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index bea5d61e5..ad660bb8f 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -6533,7 +6533,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 
       uint8_t nNumTransformCands = 1 + ( tsAllowed ? 1 : 0 ) + ( mtsAllowed ? 4 : 0 ); // DCT + TS + 4 MTS = 6 tests
       std::vector<TrMode> trModes;
+#if JVET_R0110_MIXED_LOSSLESS      
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
+#else
       if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+#endif
       {
         nNumTransformCands = 0;
       }
@@ -6570,8 +6574,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 #endif
         }
       }
-
+#if JVET_R0110_MIXED_LOSSLESS      
+      if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless()))
+#else     
       if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING))
+#endif
       {
         m_pcTrQuant->lambdaAdjustColorTrans(true);
         m_pcRdCost->lambdaAdjustColorTrans(true, compID);
@@ -6588,7 +6595,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
           m_CABACEstimator->resetBits();
 
           {
-            if( !( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING ) )
+#if JVET_R0110_MIXED_LOSSLESS            
+            if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()))
+#else
+            if( !( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING) )
+#endif
             {
             if (bestTU.mtsIdx[compID] == MTS_SKIP && m_pcEncCfg->getUseTransformSkipFast())
             {
@@ -6636,7 +6647,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
               m_pcTrQuant->transformNxN( tu, compID, cQP, &trModes, m_pcEncCfg->getMTSInterMaxCand() );
               tu.mtsIdx[compID] = trModes[0].first;
             }
+#if JVET_R0110_MIXED_LOSSLESS            
+            if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0))
+#else
             if( !( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0 ) )
+#endif
             {
               m_pcTrQuant->transformNxN( tu, compID, cQP, currAbsSum, m_CABACEstimator->getCtx(), true );
             }
@@ -6684,8 +6699,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
           {
             *puiZeroDist += nonCoeffDist; // initialized with zero residual distortion
           }
-
+#if JVET_R0110_MIXED_LOSSLESS          
+          if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0)
+#else
           if( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0 )
+#endif
           {
             currAbsSum = 0;
           }
@@ -6784,8 +6802,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
         // copy component
         tu.copyComponentFrom( bestTU, compID );
         csFull->getResiBuf( compArea ).copyFrom( saveCS.getResiBuf( compArea ) );
-
+#if JVET_R0110_MIXED_LOSSLESS        
+      if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless()))
+#else
       if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING))
+#endif
       {
         m_pcTrQuant->lambdaAdjustColorTrans(false);
         m_pcRdCost->lambdaAdjustColorTrans(false, compID);
@@ -6887,8 +6908,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
         tu.mtsIdx[codeCompId]  = trModes[modeId].first;
         tu.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
         int         codedCbfMask = 0;
-
+#if JVET_R0110_MIXED_LOSSLESS 
+        if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless()))
+#else
         if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING))
+#endif
         {
           m_pcTrQuant->lambdaAdjustColorTrans(true);
           m_pcTrQuant->selectLambda(codeCompId);
@@ -7026,8 +7050,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
           }
         }
 
-
+#if JVET_R0110_MIXED_LOSSLESS        
+        if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless()))
+#else
         if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING))
+#endif
         {
           m_pcTrQuant->lambdaAdjustColorTrans(false);
         }
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index b8b296650..29be70ab3 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -1766,7 +1766,11 @@ void IntraSearch::preCalcPLTIndexRD(CodingStructure& cs, Partitioner& partitione
   CodingUnit &cu = *cs.getCU(partitioner.chType);
   uint32_t height = cu.block(compBegin).height;
   uint32_t width = cu.block(compBegin).width;
+#if JVET_R0110_MIXED_LOSSLESS
+  bool lossless = (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && cs.slice->isLossless());
+#else
   bool lossless = (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING);
+#endif
 
   CPelBuf   orgBuf[3];
   for (int comp = compBegin; comp < (compBegin + numComp); comp++)
@@ -2270,7 +2274,11 @@ void IntraSearch::calcPixelPred(CodingStructure& cs, Partitioner& partitioner, u
 {
   CodingUnit    &cu = *cs.getCU(partitioner.chType);
   TransformUnit &tu = *cs.getTU(partitioner.chType);
+#if JVET_R0110_MIXED_LOSSLESS 
+  bool lossless = (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && cs.slice->isLossless());
+#else
   bool lossless = (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING);
+#endif
 
   CPelBuf   orgBuf[3];
   for (int comp = compBegin; comp < (compBegin + numComp); comp++)
@@ -2357,7 +2365,11 @@ void IntraSearch::derivePLTLossy(CodingStructure& cs, Partitioner& partitioner,
   CodingUnit &cu = *cs.getCU(partitioner.chType);
   const int channelBitDepth_L = cs.sps->getBitDepth(CHANNEL_TYPE_LUMA);
   const int channelBitDepth_C = cs.sps->getBitDepth(CHANNEL_TYPE_CHROMA);
+#if JVET_R0110_MIXED_LOSSLESS  
+  bool lossless        = (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && cs.slice->isLossless());
+#else
   bool lossless        = (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING);
+#endif
   int  pcmShiftRight_L = (channelBitDepth_L - PLT_ENCBITDEPTH);
   int  pcmShiftRight_C = (channelBitDepth_C - PLT_ENCBITDEPTH);
   if (lossless)
@@ -3162,7 +3174,11 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
       m_pcTrQuant->transformNxN(tu, compID, cQP, trModes, m_pcEncCfg->getMTSIntraMaxCand());
       tu.mtsIdx[compID] = trModes->at(0).first;
     }
+#if JVET_R0110_MIXED_LOSSLESS   
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmMode != 0)
+#else
     if( !( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0 ) || tu.cu->bdpcmMode != 0 )
+#endif
     {
       m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
     }
@@ -3176,8 +3192,11 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
     ruiDist = MAX_INT;
     return;
   }
-
+#if JVET_R0110_MIXED_LOSSLESS 
+  if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) && 0 == tu.cu->bdpcmMode)
+#else
   if( ( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0 ) && 0 == tu.cu->bdpcmMode )
+#endif
   {
     uiAbsSum = 0;
     tu.getCoeffs( compID ).fill( 0 );
@@ -3219,12 +3238,19 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
         }
     }
     // encoder bugfix: Set loadTr to aovid redundant transform process
+#if JVET_R0110_MIXED_LOSSLESS
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmModeChroma != 0)
+#else
     if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmModeChroma != 0)
+#endif
     {
         m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
     }
-
+#if JVET_R0110_MIXED_LOSSLESS
+    if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) && 0 == tu.cu->bdpcmModeChroma)
+#else
     if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0) && 0 == tu.cu->bdpcmModeChroma)
+#endif
     {
         uiAbsSum = 0;
         tu.getCoeffs(compID).fill(0);
@@ -3343,8 +3369,11 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
   bool jointCbCr = tu.jointCbCr && compID == COMPONENT_Cb;
 
   m_pcRdCost->setChromaFormat(cs.sps->getChromaFormatIdc());
-
+#if JVET_R0110_MIXED_LOSSLESS
+  if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
   if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
   m_pcTrQuant->lambdaAdjustColorTrans(true);
 
   if (jointCbCr)
@@ -3386,9 +3415,17 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
       m_pcTrQuant->transformNxN(tu, compID, cQP, trModes, m_pcEncCfg->getMTSIntraMaxCand());
       tu.mtsIdx[compID] = trModes->at(0).first;
     }
+#if JVET_R0110_MIXED_LOSSLESS  
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmMode != 0)
+#else
     if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmMode != 0)
+#endif
     m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
+#if JVET_R0110_MIXED_LOSSLESS    
+    if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) && tu.cu->bdpcmMode == 0)
+#else
     if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0) && tu.cu->bdpcmMode == 0)
+#endif
     {
       uiAbsSum = 0;
       tu.getCoeffs(compID).fill(0);
@@ -3428,7 +3465,11 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
         tu.mtsIdx[(codeCompId == COMPONENT_Cr) ? COMPONENT_Cb : COMPONENT_Cr] = MTS_DCT2_DCT2;
       }
     }
+#if JVET_R0110_MIXED_LOSSLESS    
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[codeCompId] == 0) || tu.cu->bdpcmModeChroma != 0)
+#else
     if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[codeCompId] == 0) || tu.cu->bdpcmModeChroma != 0)
+#endif
     {
       m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
     }
@@ -3452,7 +3493,11 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
       if (tu.jointCbCr != codedCbfMask)
       {
         ruiDist = std::numeric_limits<Distortion>::max();
+#if JVET_R0110_MIXED_LOSSLESS        
+        if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
         if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
         m_pcTrQuant->lambdaAdjustColorTrans(false);
         return;
       }
@@ -3469,8 +3514,11 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
       crResi.scaleSignal(tu.getChromaAdj(), 0, slice.clpRng(COMPONENT_Cr));
     }
   }
-
+#if JVET_R0110_MIXED_LOSSLESS
+  if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
   if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
   m_pcTrQuant->lambdaAdjustColorTrans(false);
 
   ruiDist += m_pcRdCost->getDistPart(piOrgResi, piResi, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE);
@@ -3604,6 +3652,9 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
   bool bCheckSplit         = false;
   bCheckFull               = !partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
   bCheckSplit              = partitioner.canSplit( TU_MAX_TR_SPLIT, cs );
+#if JVET_R0110_MIXED_LOSSLESS
+  const Slice           &slice = *cs.slice;
+#endif
 
   if( cu.ispMode )
   {
@@ -3667,8 +3718,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
     else
     {
       nNumTransformCands = 1 + ( tsAllowed ? 1 : 0 ) + ( mtsAllowed ? 4 : 0 ); // DCT + TS + 4 MTS = 6 tests
-
+#if JVET_R0110_MIXED_LOSSLESS      
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
+#else
       if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+#endif
       {
         nNumTransformCands = 1;
         CHECK(!tsAllowed && !cu.bdpcmMode, "transform skip should be enabled for LS");
@@ -3746,7 +3800,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
       }
       else
       {
-        if( !( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING ) )
+#if JVET_R0110_MIXED_LOSSLESS        
+        if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()))
+#else
+        if( !( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING) )
+#endif
         {
         if( !cbfDCT2 || ( m_pcEncCfg->getUseTransformSkipFast() && bestModeId[ COMPONENT_Y ] == MTS_SKIP))
         {
@@ -3873,7 +3931,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
       if( ( sps.getUseLFNST() ? ( modeId == lastCheckId && modeId != 0 && checkTransformSkip ) : ( trModes[ modeId ].first != 0 ) ) && !TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ) )
       {
         //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
+#if JVET_R0110_MIXED_LOSSLESS
+        if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
         if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
         singleCostTmp = MAX_DOUBLE;
         else
         {
@@ -4222,7 +4284,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
     }
     else
     {
+#if JVET_R0110_MIXED_LOSSLESS      
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
+#else
       if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+#endif
       {
         nNumTransformCands = 1;
         CHECK(!tsAllowed && !cu.bdpcmMode, "transform skip should be enabled for LS");
@@ -4275,11 +4341,17 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
     bool    cbfBestMode = false;
     bool    cbfBestModeValid = false;
     bool    cbfDCT2 = true;
-
+#if JVET_R0110_MIXED_LOSSLESS    
+    if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
     if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
     m_pcRdCost->lambdaAdjustColorTrans(true, COMPONENT_Y);
-
+#if JVET_R0110_MIXED_LOSSLESS    
+    for (int modeId = firstCheckId; modeId <= ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()) ? (nNumTransformCands - 1) : lastCheckId); modeId++)
+#else
     for (int modeId = firstCheckId; modeId <= ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING) ? (nNumTransformCands - 1) : lastCheckId); modeId++)
+#endif
     {
       uint8_t transformIndex = modeId;
       csFull->getResiBuf(tu.Y()).copyFrom(csFull->getOrgResiBuf(tu.Y()));
@@ -4300,7 +4372,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
       }
       else
       {
+#if JVET_R0110_MIXED_LOSSLESS
+        if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()))
+#else
         if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING))
+#endif
         {
         if (!cbfDCT2 || (m_pcEncCfg->getUseTransformSkipFast() && bestLumaModeId == 1))
         {
@@ -4394,7 +4470,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
       if ((sps.getUseLFNST() ? (modeId == lastCheckId && modeId != 0 && checkTransformSkip) : (trModes[modeId].first != 0)) && !TU::getCbfAtDepth(tu, COMPONENT_Y, currDepth))
       {
         //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
+#if JVET_R0110_MIXED_LOSSLESS       
+        if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
         if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
         singleCostTmp = MAX_DOUBLE;
         else
         {
@@ -4449,8 +4529,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
         }
       }
     }
-
+#if JVET_R0110_MIXED_LOSSLESS
+    if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
     if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
     m_pcRdCost->lambdaAdjustColorTrans(false, COMPONENT_Y);
 
     if (sps.getUseLFNST())
@@ -4524,8 +4607,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
       bool        cbfDCT2 = true;
 
       trModes.clear();
-
+#if JVET_R0110_MIXED_LOSSLESS     
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
+#else
       if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+#endif
       {
         numTransformCands = 1;
         CHECK(!tsAllowed && !cu.bdpcmModeChroma, "transform skip should be enabled for LS");
@@ -4546,8 +4632,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
           trModes.push_back(TrMode(1, true));                  // TS
         }
       }
-
+#if JVET_R0110_MIXED_LOSSLESS
+      if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
       if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
         m_pcRdCost->lambdaAdjustColorTrans(true, compID);
 
       TempCtx ctxBegin(m_CtxCache);
@@ -4555,7 +4644,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
 
       for (int modeId = 0; modeId < numTransformCands; modeId++)
       {
+#if JVET_R0110_MIXED_LOSSLESS        
+        if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
         if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
         {
           if (modeId && !cbfDCT2)
           {
@@ -4605,8 +4698,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
         tu.copyComponentFrom(*tmpTU, compID);
         m_CABACEstimator->getCtx() = ctxBest;
       }
-
+#if JVET_R0110_MIXED_LOSSLESS    
+      if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else
       if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
         m_pcRdCost->lambdaAdjustColorTrans(false, compID);
     }
 
@@ -4885,7 +4981,9 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
   UnitArea currArea                   = partitioner.currArea();
   const bool keepResi                 = cs.sps->getUseLMChroma() || KEEP_PRED_AND_RESI_SIGNALS;
   if( !currArea.Cb().valid() ) return ChromaCbfs( false );
-
+#if JVET_R0110_MIXED_LOSSLESS
+  const Slice           &slice = *cs.slice;
+#endif 
 
   TransformUnit &currTU               = *cs.getTU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
   const PredictionUnit &pu            = *cs.getPU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
@@ -5018,7 +5116,11 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
       const bool tsAllowed = TU::isTSAllowed(currTU, compID) && m_pcEncCfg->getUseChromaTS() && !currTU.cu->lfnstIdx;
       uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
       std::vector<TrMode> trModes;
+#if JVET_R0110_MIXED_LOSSLESS     
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
+#else
       if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+#endif
       {
         nNumTransformCands = 1;
         CHECK(!tsAllowed && !currTU.cu->bdpcmModeChroma, "transform skip should be enabled for LS");
@@ -5067,8 +5169,11 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
 
           const bool isFirstMode = (currModeId == 1);
           const bool isLastMode  = false; // Always store output to saveCS and tmpTU
-
-          if( !( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING ) )
+#if JVET_R0110_MIXED_LOSSLESS          
+          if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()))
+#else
+          if( !( m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING) )
+#endif
           {
            //if DCT2's cbf==0, skip ts search
           if (!cbfDCT2 && trModes[modeId].first == MTS_SKIP)
@@ -5099,7 +5204,11 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
 
           if (((currTU.mtsIdx[compID] == MTS_SKIP && !currTU.cu->bdpcmModeChroma) && !TU::getCbf(currTU, compID))) //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
           {
+#if JVET_R0110_MIXED_LOSSLESS            
+            if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
+#else           
             if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
             singleCostTmp = MAX_DOUBLE;
             else
             {
@@ -5174,7 +5283,11 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
       }
 
       // Done with one component of separate coding of Cr and Cb, just switch to the best Cb contexts if Cr coding is still to be done
+#if JVET_R0110_MIXED_LOSSLESS
+      if ((c == COMPONENT_Cb && bestModeId < totalModesToTest) || (c == COMPONENT_Cb && m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()))
+#else
       if ((c == COMPONENT_Cb && bestModeId < totalModesToTest) || (c == COMPONENT_Cb && m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING))
+#endif
       {
         m_CABACEstimator->getCtx() = ctxBest;
 
-- 
GitLab