diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 5feb6cdb8107ae6f92ef3eaa808e08028d328098..f27d191cb33042633c8304ef4bc18d213e437841 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -3435,6 +3435,9 @@ bool EncAppCfg::xCheckParameter()
 #endif
 
   xConfirmPara(m_useBDPCM < 0 || m_useBDPCM > 2, "BDPCM must be in range 0..2");
+#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
 
 #undef xConfirmPara
   return check_failed;
@@ -3670,7 +3673,11 @@ void EncAppCfg::xPrintParameter()
     msg(VERBOSE, "MmvdDisNum:%d ", m_MmvdDisNum);
     msg(VERBOSE, "JointCbCr:%d ", m_JointCbCrMode);
   }
+#if JVET_Q0820_ACT
+  m_useColorTrans = (m_chromaFormatIDC == CHROMA_444) ? m_useColorTrans : 0u;
+#else
   m_useColorTrans = (m_chromaFormatIDC == CHROMA_444 && m_costMode != COST_LOSSLESS_CODING) ? m_useColorTrans : 0u;
+#endif
   msg(VERBOSE, "ACT:%d ", m_useColorTrans);
     m_PLTMode = ( m_chromaFormatIDC == CHROMA_444) ? m_PLTMode : 0u;
     msg(VERBOSE, "PLT:%d ", m_PLTMode);
diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp
index e1f967f14fef717a85f2c5904e8cc6377feb69eb..8320dbe7c8ae76e93689d0b7b581b5681bd9696d 100644
--- a/source/Lib/CommonLib/Buffer.cpp
+++ b/source/Lib/CommonLib/Buffer.cpp
@@ -779,7 +779,11 @@ const CPelUnitBuf PelStorage::getBuf( const UnitArea &unit ) const
 }
 
 template<>
+#if JVET_Q0820_ACT
+void UnitBuf<Pel>::colorSpaceConvert(const UnitBuf<Pel> &other, const bool forward, const ClpRng& clpRng)
+#else
 void UnitBuf<Pel>::colorSpaceConvert(const UnitBuf<Pel> &other, const bool forward)
+#endif
 {
   const Pel* pOrg0 = bufs[COMPONENT_Y].buf;
   const Pel* pOrg1 = bufs[COMPONENT_Cb].buf;
@@ -793,6 +797,9 @@ void UnitBuf<Pel>::colorSpaceConvert(const UnitBuf<Pel> &other, const bool forwa
 
   int width = bufs[COMPONENT_Y].width;
   int height = bufs[COMPONENT_Y].height;
+#if JVET_Q0820_ACT
+  int maxAbsclipBD = (1 << (clpRng.bd + 1)) - 1;
+#endif
   int r, g, b;
   int y0, cg, co;
 
@@ -810,12 +817,21 @@ void UnitBuf<Pel>::colorSpaceConvert(const UnitBuf<Pel> &other, const bool forwa
           g = pOrg0[x];
           b = pOrg1[x];
 
+#if JVET_Q0820_ACT
+          co = r - b;
+          int t = b + (co >> 1);
+          cg = g - t;
+          pDst0[x] = t + (cg >> 1);
+          pDst1[x] = cg;
+          pDst2[x] = co;
+#else
           pDst0[x] = (g << 1) + r + b;
           pDst1[x] = (g << 1) - r - b;
           pDst2[x] = ((r - b) << 1);
           pDst0[x] = (pDst0[x] + 2) >> 2;
           pDst1[x] = (pDst1[x] + 2) >> 2;
           pDst2[x] = (pDst2[x] + 2) >> 2;
+#endif
         }
         pOrg0 += strideOrg;
         pOrg1 += strideOrg;
@@ -835,9 +851,20 @@ void UnitBuf<Pel>::colorSpaceConvert(const UnitBuf<Pel> &other, const bool forwa
           cg = pOrg1[x];
           co = pOrg2[x];
 
+#if JVET_Q0820_ACT
+          y0 = Clip3((-maxAbsclipBD - 1), maxAbsclipBD, y0);
+          cg = Clip3((-maxAbsclipBD - 1), maxAbsclipBD, cg);
+          co = Clip3((-maxAbsclipBD - 1), maxAbsclipBD, co);
+
+          int t = y0 - (cg >> 1);
+          pDst0[x] = cg + t;
+          pDst1[x] = t - (co >> 1);
+          pDst2[x] = co + pDst1[x];
+#else
           pDst0[x] = (y0 + cg);
           pDst1[x] = (y0 - cg - co);
           pDst2[x] = (y0 - cg + co);
+#endif
         }
 
         pOrg0 += strideOrg;
diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h
index 9b461389d48aa12dc181aa7d4dac732a7caca5c2..0fbd97a5edcceb94333a08174c9ad91a48e0a555 100644
--- a/source/Lib/CommonLib/Buffer.h
+++ b/source/Lib/CommonLib/Buffer.h
@@ -779,7 +779,11 @@ struct UnitBuf
 
         UnitBuf<      T> subBuf (const UnitArea& subArea);
   const UnitBuf<const T> subBuf (const UnitArea& subArea) const;
+#if JVET_Q0820_ACT
+  void colorSpaceConvert(const UnitBuf<T> &other, const bool forward, const ClpRng& clpRng);
+#else
   void colorSpaceConvert(const UnitBuf<T> &other, const bool forward);
+#endif
 };
 
 typedef UnitBuf<      Pel>  PelUnitBuf;
@@ -880,13 +884,21 @@ void UnitBuf<T>::addAvg(const UnitBuf<const T> &other1, const UnitBuf<const T> &
 }
 
 template<typename T>
+#if JVET_Q0820_ACT
+void UnitBuf<T>::colorSpaceConvert(const UnitBuf<T> &other, const bool forward, const ClpRng& clpRng)
+#else
 void UnitBuf<T>::colorSpaceConvert(const UnitBuf<T> &other, const bool forward)
+#endif
 {
   THROW("Type not supported");
 }
 
 template<>
+#if JVET_Q0820_ACT
+void UnitBuf<Pel>::colorSpaceConvert(const UnitBuf<Pel> &other, const bool forward, const ClpRng& clpRng);
+#else
 void UnitBuf<Pel>::colorSpaceConvert(const UnitBuf<Pel> &other, const bool forward);
+#endif
 
 template<typename T>
 void UnitBuf<T>::extendSingleBorderPel()
diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h
index 03f20a9b04e32f75f85e45cb859e9965970ed4b1..fb83cf5b8b4b13bc96acbccc099206c2aa30b324 100644
--- a/source/Lib/CommonLib/CommonDef.h
+++ b/source/Lib/CommonLib/CommonDef.h
@@ -485,8 +485,12 @@ static const int ENC_PPS_ID_RPR =                                 3;
 static const int SCALE_RATIO_BITS =                              14;
 static const int MAX_SCALING_RATIO =                              2;  // max downsampling ratio for RPR
 static const std::pair<int, int> SCALE_1X = std::pair<int, int>( 1 << SCALE_RATIO_BITS, 1 << SCALE_RATIO_BITS );  // scale ratio 1x
+#if JVET_Q0820_ACT
+static const int DELTA_QP_ACT[4] =                  { -5, 1, 3, 1 };
+#else
 static const int DELTA_QP_FOR_Y_Cg =                             -5;
 static const int DELTA_QP_FOR_Co =                               -3;
+#endif
 
 // ====================================================================================================================
 // Macro functions
diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp
index f2ca851eae904fbfd67aee1d9ff870f6a0b0566f..5ab5c8486362ccb84df10cf2020324d8627c5f32 100644
--- a/source/Lib/CommonLib/LoopFilter.cpp
+++ b/source/Lib/CommonLib/LoopFilter.cpp
@@ -1227,8 +1227,13 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
         const TransformUnit& tuQ = *cuQ.cs->getTU(posQ, cuQ.chType);
         const TransformUnit& tuP = *cuP.cs->getTU(posP, cuP.chType); 
 
+#if JVET_Q0820_ACT
+        const QpParam cQP(tuP, ComponentID(chromaIdx + 1), -MAX_INT, false);
+        const QpParam cQQ(tuQ, ComponentID(chromaIdx + 1), -MAX_INT, false);
+#else
         const QpParam cQP(tuP, ComponentID(chromaIdx + 1));
         const QpParam cQQ(tuQ, ComponentID(chromaIdx + 1));
+#endif
         const int qpBdOffset = tuP.cs->sps->getQpBDOffset(toChannelType(ComponentID(chromaIdx + 1)));
         int baseQp_P = cQP.Qp(0) - qpBdOffset;
         int baseQp_Q = cQQ.Qp(0) - qpBdOffset;
diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp
index f30351c8ece34e456fd51111ed6408b4044da9f6..90c526ab907779ec1df3ccfa90596db7ce9370e7 100644
--- a/source/Lib/CommonLib/Quant.cpp
+++ b/source/Lib/CommonLib/Quant.cpp
@@ -70,6 +70,9 @@ QpParam::QpParam(const int           qpy,
                  const ChromaFormat  chFmt,
                  const int           dqp
               ,  const SPS           *sps
+#if JVET_Q0820_ACT
+              , const bool           applyACTQpoffset
+#endif
 )
 {
   int baseQp;
@@ -84,6 +87,12 @@ QpParam::QpParam(const int           qpy,
     baseQp = Clip3(-qpBdOffset, MAX_QP, baseQp + chromaQPOffset) + qpBdOffset;
   }
 
+#if JVET_Q0820_ACT
+  if (applyACTQpoffset)
+  {
+    baseQp += DELTA_QP_ACT[compID];
+  }
+#endif
   baseQp = Clip3( 0, MAX_QP+qpBdOffset, baseQp + dqp );
 
   Qps[0] =baseQp;
@@ -98,7 +107,11 @@ QpParam::QpParam(const int           qpy,
   rems[1] = baseQpTS % 6;
 }
 
+#if JVET_Q0820_ACT
+QpParam::QpParam(const TransformUnit& tu, const ComponentID &compIDX, const int QP /*= -MAX_INT*/, const bool allowACTQpoffset /*= true*/)
+#else
 QpParam::QpParam(const TransformUnit& tu, const ComponentID &compIDX, const int QP /*= -MAX_INT*/)
+#endif
 {
   int chromaQpOffset = 0;
   ComponentID compID = MAP_CHROMA(compIDX);
@@ -116,7 +129,12 @@ QpParam::QpParam(const TransformUnit& tu, const ComponentID &compIDX, const int
   int dqp = 0;
 
   const bool useJQP = isChroma(compID) && (abs(TU::getICTMode(tu)) == 2);
+#if JVET_Q0820_ACT
+  bool applyACTQpoffset = tu.cu->colorTransform && allowACTQpoffset;
+  *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, useJQP ? JOINT_CbCr : compID, tu.cs->sps->getQpBDOffset(toChannelType(compID)), tu.cs->sps->getMinQpPrimeTsMinus4(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp, tu.cs->sps, applyACTQpoffset);
+#else
   *this = QpParam(QP <= -MAX_INT ? tu.cu->qp : QP, useJQP ? JOINT_CbCr : compID, tu.cs->sps->getQpBDOffset(toChannelType(compID)), tu.cs->sps->getMinQpPrimeTsMinus4(toChannelType(compID)), chromaQpOffset, tu.chromaFormat, dqp, tu.cs->sps);
+#endif
 }
 
 
@@ -1255,7 +1273,11 @@ void Quant::lambdaAdjustColorTrans(bool forward)
     for (uint8_t component = 0; component < MAX_NUM_COMPONENT; component++)
     {
       ComponentID compID = (ComponentID)component;
+#if JVET_Q0820_ACT
+      int       delta_QP = DELTA_QP_ACT[compID];
+#else
       int       delta_QP = (compID == COMPONENT_Cr ? DELTA_QP_FOR_Co : DELTA_QP_FOR_Y_Cg);
+#endif
       double lamdbaAdjustRate = pow(2.0, delta_QP / 3.0);
 
       m_lambdasStore[0][component] = m_lambdas[component];
diff --git a/source/Lib/CommonLib/Quant.h b/source/Lib/CommonLib/Quant.h
index d2ffa8bbf336cd14f2ccbaf77ccd0ca0813bf71c..c5c638a8acabe25cacce59033d5ca8627acc4e05 100644
--- a/source/Lib/CommonLib/Quant.h
+++ b/source/Lib/CommonLib/Quant.h
@@ -82,11 +82,18 @@ private:
           const ChromaFormat  chFmt,
           const int           dqp
         , const SPS           *sps
+#if JVET_Q0820_ACT
+        , const bool          applyACTQpoffset
+#endif 
   );
 
 public:
 
+#if JVET_Q0820_ACT 
+  QpParam(const TransformUnit& tu, const ComponentID &compID, const int QP = -MAX_INT, const bool allowACTQpoffset = true);
+#else
   QpParam(const TransformUnit& tu, const ComponentID &compID, const int QP = -MAX_INT);
+#endif
 
   int Qp ( const bool ts ) const { return Qps [ts?1:0]; }
   int per( const bool ts ) const { return pers[ts?1:0]; }
diff --git a/source/Lib/CommonLib/RdCost.cpp b/source/Lib/CommonLib/RdCost.cpp
index 7f48f5d5ea9fca804b4e8de7f230cb99dec5add3..7c0960cb71eade8f2df88a1b26038d034d460c63 100644
--- a/source/Lib/CommonLib/RdCost.cpp
+++ b/source/Lib/CommonLib/RdCost.cpp
@@ -92,7 +92,11 @@ void RdCost::lambdaAdjustColorTrans(bool forward, ComponentID componentID)
     for (uint8_t component = 0; component < MAX_NUM_COMPONENT; component++)
     {
       ComponentID compID = (ComponentID)component;
+#if JVET_Q0820_ACT
+      int       delta_QP = DELTA_QP_ACT[compID];
+#else
       int       delta_QP = (compID == COMPONENT_Cr ? DELTA_QP_FOR_Co : DELTA_QP_FOR_Y_Cg);
+#endif
       double lamdbaAdjustRate = pow(2.0, delta_QP / 3.0);
 
       m_lambdaStore[0][component] = m_dLambda;
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index 0f33d8fecf40d2cd6f2a1ea13d8759c9ce3897e6..63025efcfc44633e902f308e55f167471affc989 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_Q0820_ACT                                    1 // JVET-Q0820: ACT bug fixes and reversible ACT transform 
+
 #define JVET_Q0353_ACT_SW_FIX                             1 // JVET-Q0353: Bug fix of ACT 
 
 #define JVET_Q0695_CHROMA_TS_JCCR                         1 // JVET-Q0695: Enabling the RD checking of chroma transform-skip mode for JCCR at encoder
diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp
index 3b96128195c8623b5fff067cdcecb0486b61cb18..88b6a9cd3d8bbfdba72c701d9968aa716927c4d7 100644
--- a/source/Lib/DecoderLib/DecCu.cpp
+++ b/source/Lib/DecoderLib/DecCu.cpp
@@ -369,12 +369,14 @@ void DecCu::xIntraRecACTBlk(TransformUnit& tu)
     PelBuf piResi = cs.getResiBuf(area);
 
     QpParam cQP(tu, compID);
+#if !JVET_Q0820_ACT
     for (int qpIdx = 0; qpIdx < 2; qpIdx++)
     {
       cQP.Qps[qpIdx] = cQP.Qps[qpIdx] + (compID == COMPONENT_Cr ? DELTA_QP_FOR_Co : DELTA_QP_FOR_Y_Cg);
       cQP.pers[qpIdx] = cQP.Qps[qpIdx] / 6;
       cQP.rems[qpIdx] = cQP.Qps[qpIdx] % 6;
     }
+#endif
 
     if (tu.jointCbCr && isChroma(compID))
     {
@@ -388,12 +390,14 @@ void DecCu::xIntraRecACTBlk(TransformUnit& tu)
         else
         {
           QpParam qpCr(tu, COMPONENT_Cr);
+#if !JVET_Q0820_ACT
           for (int qpIdx = 0; qpIdx < 2; qpIdx++)
           {
             qpCr.Qps[qpIdx] = qpCr.Qps[qpIdx] + DELTA_QP_FOR_Co;
             qpCr.pers[qpIdx] = qpCr.Qps[qpIdx] / 6;
             qpCr.rems[qpIdx] = qpCr.Qps[qpIdx] % 6;
           }
+#endif
 
           m_pcTrQuant->invTransformNxN(tu, COMPONENT_Cr, resiCr, qpCr);
         }
@@ -421,7 +425,11 @@ void DecCu::xIntraRecACTBlk(TransformUnit& tu)
     cs.setDecomp(area);
   }
 
+#if JVET_Q0820_ACT
+  cs.getResiBuf(tu).colorSpaceConvert(cs.getResiBuf(tu), false, tu.cu->cs->slice->clpRng(COMPONENT_Y));
+#else
   cs.getResiBuf(tu).colorSpaceConvert(cs.getResiBuf(tu), false);
+#endif
 
   for (int i = 0; i < getNumberValidComponents(tu.chromaFormat); i++)
   {
@@ -697,7 +705,11 @@ void DecCu::xReconInter(CodingUnit &cu)
   {
     if (cu.colorTransform)
     {
+#if JVET_Q0820_ACT
+      cs.getResiBuf(cu).colorSpaceConvert(cs.getResiBuf(cu), false, cu.cs->slice->clpRng(COMPONENT_Y));
+#else
       cs.getResiBuf(cu).colorSpaceConvert(cs.getResiBuf(cu), false);
+#endif
     }
 #if REUSE_CU_RESULTS
     const CompArea &area = cu.blocks[COMPONENT_Y];
@@ -759,6 +771,7 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
   PelBuf resiBuf  = cs.getResiBuf(area);
 
   QpParam cQP(currTU, compID);
+#if !JVET_Q0820_ACT
   if (currTU.cu->colorTransform)
   {
     for (int qpIdx = 0; qpIdx < 2; qpIdx++)
@@ -768,6 +781,7 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
       cQP.rems[qpIdx] = cQP.Qps[qpIdx] % 6;
     }
   }
+#endif
 
   if( currTU.jointCbCr && isChroma(compID) )
   {
@@ -781,6 +795,7 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
       else
       {
         QpParam qpCr(currTU, COMPONENT_Cr);
+#if !JVET_Q0820_ACT
         if (currTU.cu->colorTransform)
         {
           for (int qpIdx = 0; qpIdx < 2; qpIdx++)
@@ -790,6 +805,7 @@ void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID )
             qpCr.rems[qpIdx] = qpCr.Qps[qpIdx] % 6;
           }
         }
+#endif
         m_pcTrQuant->invTransformNxN( currTU, COMPONENT_Cr, resiCr, qpCr );
       }
       m_pcTrQuant->invTransformICT( currTU, resiBuf, resiCr );
diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp
index 40b9a733a2a7eaf282a17f1c6ea130db4a74b440..015a5461e5e49b0e5cd94b8adf746deae1fb0c11 100644
--- a/source/Lib/DecoderLib/VLCReader.cpp
+++ b/source/Lib/DecoderLib/VLCReader.cpp
@@ -1509,7 +1509,14 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS)
   }
   if (pcSPS->getChromaFormatIdc() == CHROMA_444)
   {
+#if JVET_Q0820_ACT
+    if (pcSPS->getLog2MaxTbSize() != 6)
+    {
+      READ_FLAG(uiCode, "sps_act_enabled_flag");                                pcSPS->setUseColorTrans(uiCode != 0);
+    }
+#else
     READ_FLAG(uiCode, "sps_act_enabled_flag");                                  pcSPS->setUseColorTrans(uiCode != 0);
+#endif
   }
   else
   {
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 664375b9067a73c1ed886417616ec5762d6b9fd7..e33e976488c070a10814dff2fac039994f5890c7 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -800,7 +800,12 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par
       {
         bool skipSecColorSpace = false;
         skipSecColorSpace = xCheckRDCostIntra(tempCS, bestCS, partitioner, currTestMode, (m_pcEncCfg->getRGBFormatFlag() ? true : false));
-        
+#if JVET_Q0820_ACT
+        if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING) && !m_pcEncCfg->getRGBFormatFlag())
+        {
+          skipSecColorSpace = true;
+        }
+#endif 
         if (!skipSecColorSpace && !tempCS->firstColorSpaceTestOnly)
         {
           xCheckRDCostIntra(tempCS, bestCS, partitioner, currTestMode, (m_pcEncCfg->getRGBFormatFlag() ? false : true));
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index db686f1023624cdad0c371ab2fa9f6957d994f16..5cb2192760e3cbd490b12f46305f48ab6c66c381 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -6548,8 +6548,19 @@ 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_Q0820_ACT 
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+      {
+        nNumTransformCands = 0;
+      }
+      else
+      {
+#endif
       trModes.push_back( TrMode( 0, true ) ); //DCT2
       nNumTransformCands = 1;
+#if JVET_Q0820_ACT 
+      }
+#endif
       //for a SBT-no-residual TU, the RDO process should be called once, in order to get the RD cost
       if( tsAllowed && !tu.noResidual )
       {
@@ -6579,7 +6590,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
         }
       }
 
+#if JVET_Q0820_ACT
+      if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING))
+#else
       if (colorTransFlag)
+#endif
       {
         m_pcTrQuant->lambdaAdjustColorTrans(true);
         m_pcRdCost->lambdaAdjustColorTrans(true, compID);
@@ -6629,6 +6644,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
           tu.compAlpha[compID]      = bUseCrossCPrediction ? preCalcAlpha : 0;
 
           QpParam cQP(tu, compID);  // note: uses tu.transformSkip[compID]
+#if !JVET_Q0820_ACT
           if (colorTransFlag)
           {
             for (int qpIdx = 0; qpIdx < 2; qpIdx++)
@@ -6638,6 +6654,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
               cQP.rems[qpIdx] = cQP.Qps[qpIdx] % 6;
             }
           }
+#endif
 
 #if RDOQ_CHROMA_LAMBDA
           m_pcTrQuant->selectLambda(compID);
@@ -6887,7 +6904,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
       }
 #endif
 
+#if JVET_Q0820_ACT
+      if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING))
+#else
       if (colorTransFlag)
+#endif
       {
         m_pcTrQuant->lambdaAdjustColorTrans(false);
         m_pcRdCost->lambdaAdjustColorTrans(false, compID);
@@ -6899,7 +6920,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
     {
       PelUnitBuf     orgResidual = orgResi->subBuf(relativeUnitArea);
       PelUnitBuf     invColorTransResidual = m_colorTransResiBuf[2].getBuf(relativeUnitArea);
+#if JVET_Q0820_ACT
+      csFull->getResiBuf(currArea).colorSpaceConvert(invColorTransResidual, false, slice.clpRng(COMPONENT_Y));
+#else
       csFull->getResiBuf(currArea).colorSpaceConvert(invColorTransResidual, false);
+#endif
 
       for (uint32_t c = 0; c < numTBlocks; c++)
       {
@@ -7006,7 +7031,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
         ComponentID otherCompId = (codeCompId == COMPONENT_Cr ? COMPONENT_Cb : COMPONENT_Cr);
 #endif
 
+#if JVET_Q0820_ACT
+        if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING))
+#else
         if (colorTransFlag)
+#endif
         {
           m_pcTrQuant->lambdaAdjustColorTrans(true);
           m_pcTrQuant->selectLambda(codeCompId);
@@ -7040,6 +7069,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
 
         Distortion currCompDistY = MAX_UINT64;
         QpParam qpCbCr(tu, codeCompId);
+#if !JVET_Q0820_ACT
         if (colorTransFlag)
         {
           for (int qpIdx = 0; qpIdx < 2; qpIdx++)
@@ -7049,6 +7079,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
             qpCbCr.rems[qpIdx] = qpCbCr.Qps[qpIdx] % 6;
           }
         }
+#endif
 
         tu.getCoeffs(otherCompId).fill(0);   // do we need that?
         TU::setCbfAtDepth(tu, otherCompId, tu.depth, false);
@@ -7118,7 +7149,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
           {
             PelUnitBuf     orgResidual = orgResi->subBuf(relativeUnitArea);
             PelUnitBuf     invColorTransResidual = m_colorTransResiBuf[2].getBuf(relativeUnitArea);
+#if JVET_Q0820_ACT
+            csFull->getResiBuf(currArea).colorSpaceConvert(invColorTransResidual, false, slice.clpRng(COMPONENT_Y));
+#else
             csFull->getResiBuf(currArea).colorSpaceConvert(invColorTransResidual, false);
+#endif
 
             currCompDistY = m_pcRdCost->getDistPart(orgResidual.bufs[COMPONENT_Y], invColorTransResidual.bufs[COMPONENT_Y], sps.getBitDepth(toChannelType(COMPONENT_Y)), COMPONENT_Y, DF_SSE);
             currCompDistCb = m_pcRdCost->getDistPart(orgResidual.bufs[COMPONENT_Cb], invColorTransResidual.bufs[COMPONENT_Cb], sps.getBitDepth(toChannelType(COMPONENT_Cb)), COMPONENT_Cb, DF_SSE);
@@ -7173,7 +7208,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
           csFull->getResiBuf( crArea ).copyFrom( saveCS.getResiBuf( crArea ) );
         }
 #endif
+
+#if JVET_Q0820_ACT
+        if (colorTransFlag && (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING))
+#else
         if (colorTransFlag)
+#endif
         {
           m_pcTrQuant->lambdaAdjustColorTrans(false);
         }
@@ -7488,7 +7528,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
   orgResidual.copyFrom(cs.getResiBuf());
   if (colorTransAllowed)
   {
+#if JVET_Q0820_ACT
+    cs.getResiBuf().colorSpaceConvert(colorTransResidual, true, cu.cs->slice->clpRng(COMPONENT_Y));
+#else
     cs.getResiBuf().colorSpaceConvert(colorTransResidual, true);
+#endif
   }
 
   const TempCtx ctxStart(m_CtxCache, m_CABACEstimator->getCtx());
@@ -7644,7 +7688,11 @@ void InterSearch::encodeResAndCalcRdInterCU(CodingStructure &cs, Partitioner &pa
     bestIter = iter;
     if (cu.rootCbf && cu.colorTransform)
     {
+#if JVET_Q0820_ACT
+      cs.getResiBuf(curUnitArea).colorSpaceConvert(cs.getResiBuf(curUnitArea), false, cu.cs->slice->clpRng(COMPONENT_Y));
+#else
       cs.getResiBuf(curUnitArea).colorSpaceConvert(cs.getResiBuf(curUnitArea), false);
+#endif
     }
 
     if (iter != (numAllowedColorSpace - 1))
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index 751a5c4936d12726a7494273619a8e91d56657f0..2bd485ccfe1b07e1b4d1dc7a6ebbded3ef0699f1 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -2784,7 +2784,7 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
   CHECK( tu.jointCbCr && compID == COMPONENT_Cr, "wrong combination of compID and jointCbCr" );
   bool jointCbCr = tu.jointCbCr && compID == COMPONENT_Cb;
 
-#if JVET_Q0695_CHROMA_TS_JCCR 
+#if JVET_Q0695_CHROMA_TS_JCCR || JVET_Q0820_ACT
   if (compID == COMPONENT_Y)
 #else
   if (compID == COMPONENT_Y || (isChroma(compID) && tu.cu->bdpcmModeChroma))
@@ -3145,6 +3145,9 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
 
   m_pcRdCost->setChromaFormat(cs.sps->getChromaFormatIdc());
 
+#if JVET_Q0820_ACT
+  if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif 
   m_pcTrQuant->lambdaAdjustColorTrans(true);
 
   if (jointCbCr)
@@ -3180,19 +3183,32 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
   if (isLuma(compID))
   {
     QpParam cQP(tu, compID);
+#if !JVET_Q0820_ACT 
     for (int qpIdx = 0; qpIdx < 2; qpIdx++)
     {
       cQP.Qps[qpIdx] = cQP.Qps[qpIdx] + (compID == COMPONENT_Cr ? DELTA_QP_FOR_Co : DELTA_QP_FOR_Y_Cg);
       cQP.pers[qpIdx] = cQP.Qps[qpIdx] / 6;
       cQP.rems[qpIdx] = cQP.Qps[qpIdx] % 6;
     }
+#endif
 
     if (trModes)
     {
       m_pcTrQuant->transformNxN(tu, compID, cQP, trModes, m_pcEncCfg->getMTSIntraMaxCand());
       tu.mtsIdx[compID] = trModes->at(0).first;
     }
+#if JVET_Q0820_ACT 
+    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_Q0820_ACT
+    if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[compID] == 0) && tu.cu->bdpcmMode == 0)
+    {
+      uiAbsSum = 0;
+      tu.getCoeffs(compID).fill(0);
+      TU::setCbfAtDepth(tu, compID, tu.depth, 0);
+    }
+#endif 
 
     if (uiAbsSum > 0)
     {
@@ -3208,12 +3224,14 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
     int         codedCbfMask = 0;
     ComponentID codeCompId = (tu.jointCbCr ? (tu.jointCbCr >> 1 ? COMPONENT_Cb : COMPONENT_Cr) : compID);
     QpParam qpCbCr(tu, codeCompId);
+#if !JVET_Q0820_ACT 
     for (int qpIdx = 0; qpIdx < 2; qpIdx++)
     {
       qpCbCr.Qps[qpIdx] = qpCbCr.Qps[qpIdx] + (codeCompId == COMPONENT_Cr ? DELTA_QP_FOR_Co : DELTA_QP_FOR_Y_Cg);
       qpCbCr.pers[qpIdx] = qpCbCr.Qps[qpIdx] / 6;
       qpCbCr.rems[qpIdx] = qpCbCr.Qps[qpIdx] % 6;
     }
+#endif
 
     if (tu.jointCbCr)
     {
@@ -3224,7 +3242,23 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
 
     PelBuf& codeResi = (codeCompId == COMPONENT_Cr ? crResi : piResi);
     uiAbsSum = 0;
+#if JVET_Q0820_ACT
+    if (trModes)
+    {
+      m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, trModes, m_pcEncCfg->getMTSIntraMaxCand());
+      tu.mtsIdx[codeCompId] = trModes->at(0).first;
+      if (tu.jointCbCr)
+      {
+        tu.mtsIdx[(codeCompId == COMPONENT_Cr) ? COMPONENT_Cb : COMPONENT_Cr] = MTS_DCT2_DCT2;
+      }
+    }
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && tu.mtsIdx[codeCompId] == 0) || tu.cu->bdpcmModeChroma != 0)
+    {
+      m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
+    }
+#else
     m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, uiAbsSum, m_CABACEstimator->getCtx());
+#endif
     if (uiAbsSum > 0)
     {
       m_pcTrQuant->invTransformNxN(tu, codeCompId, codeResi, qpCbCr);
@@ -3245,6 +3279,9 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
       if (tu.jointCbCr != codedCbfMask)
       {
         ruiDist = std::numeric_limits<Distortion>::max();
+#if JVET_Q0820_ACT
+        if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif 
         m_pcTrQuant->lambdaAdjustColorTrans(false);
         return;
       }
@@ -3262,6 +3299,9 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
     }
   }
 
+#if JVET_Q0820_ACT
+  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);
@@ -3462,6 +3502,23 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
     {
       nNumTransformCands = 1 + ( tsAllowed ? 1 : 0 ) + ( mtsAllowed ? 4 : 0 ); // DCT + TS + 4 MTS = 6 tests
 
+#if JVET_Q0820_ACT 
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+      {
+        nNumTransformCands = 1;
+        CHECK(!tsAllowed && !cu.bdpcmMode, "transform skip should be enabled for LS");
+        if (cu.bdpcmMode)
+        {
+          trModes.push_back(TrMode(0, true));
+        }
+        else
+        {
+          trModes.push_back(TrMode(1, true));
+        }
+      }
+      else
+      {
+#endif
       trModes.push_back( TrMode( 0, true ) ); //DCT2
       if( tsAllowed )
       {
@@ -3474,6 +3531,9 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
           trModes.push_back( TrMode( i, true ) );
         }
       }
+#if JVET_Q0820_ACT 
+      }
+#endif 
     }
 
     CHECK( !tu.Y().valid(), "Invalid TU" );
@@ -3657,7 +3717,17 @@ 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_Q0820_ACT 
+        if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif 
         singleCostTmp = MAX_DOUBLE;
+#if JVET_Q0820_ACT 
+        else
+        {
+          singleTmpFracBits = xGetIntraFracBitsQT(*csFull, partitioner, true, false, subTuCounter, ispType, &cuCtx);
+          singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
+        }
+#endif 
       }
       else
       {
@@ -3977,7 +4047,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
         piResi.subtract(piPred);
     }
 
+#if JVET_Q0820_ACT
+    resiBuf.colorSpaceConvert(orgResiBuf, true, cs.slice->clpRng(COMPONENT_Y));
+#else
     resiBuf.colorSpaceConvert(orgResiBuf, true);
+#endif
 
     // 2. luma residual optimization 
     double     dSingleCostLuma = MAX_DOUBLE;
@@ -4004,6 +4078,23 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
     }
     else
     {
+#if JVET_Q0820_ACT 
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+      {
+        nNumTransformCands = 1;
+        CHECK(!tsAllowed && !cu.bdpcmMode, "transform skip should be enabled for LS");
+        if (cu.bdpcmMode)
+        {
+          trModes.push_back(TrMode(0, true));
+        }
+        else
+        {
+          trModes.push_back(TrMode(1, true));
+        }
+      }
+      else
+      {
+#endif 
       nNumTransformCands = 1 + (tsAllowed ? 1 : 0) + (mtsAllowed ? 4 : 0); // DCT + TS + 4 MTS = 6 tests
 
       trModes.push_back(TrMode(0, true)); //DCT2
@@ -4018,6 +4109,9 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
           trModes.push_back(TrMode(i, true));
         }
       }
+#if JVET_Q0820_ACT 
+      }
+#endif
     }
 
     CodingStructure &saveLumaCS = *m_pSaveCS[0];
@@ -4042,9 +4136,16 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
     bool    cbfBestModeValid = false;
     bool    cbfDCT2 = true;
 
+#if JVET_Q0820_ACT
+    if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
     m_pcRdCost->lambdaAdjustColorTrans(true, COMPONENT_Y);
 
+#if JVET_Q0820_ACT
+    for (int modeId = firstCheckId; modeId <= ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING) ? (nNumTransformCands - 1) : lastCheckId); modeId++)
+#else
     for (int modeId = firstCheckId; modeId <= lastCheckId; modeId++)
+#endif
     {
       uint8_t transformIndex = modeId;
       csFull->getResiBuf(tu.Y()).copyFrom(csFull->getOrgResiBuf(tu.Y()));
@@ -4165,7 +4266,17 @@ 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_Q0820_ACT
+        if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
         singleCostTmp = MAX_DOUBLE;
+#if JVET_Q0820_ACT
+        else
+        {
+          singleTmpFracBits = xGetIntraFracBitsQT(*csFull, partitioner, true, false, -1, TU_NO_ISP);
+          singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma, false);
+        }
+#endif
       }
       else
       {
@@ -4180,14 +4291,22 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
           }
           else
           {
+#if JVET_Q0820_ACT
+            singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma, false);
+#else
             singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
+#endif
           }
         }
         else
 #else
         singleTmpFracBits = xGetIntraFracBitsQT(*csFull, partitioner, true, false, -1, TU_NO_ISP);
 #endif
+#if JVET_Q0820_ACT
+        singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma, false);
+#else
         singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
+#endif
       }
 
       if (singleCostTmp < dSingleCostLuma)
@@ -4219,6 +4338,9 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
       }
     }
 
+#if JVET_Q0820_ACT
+    if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif
     m_pcRdCost->lambdaAdjustColorTrans(false, COMPONENT_Y);
 
     if (sps.getUseLFNST())
@@ -4255,8 +4377,10 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
     CompArea&  cbArea = tu.blocks[COMPONENT_Cb];
     CompArea&  crArea = tu.blocks[COMPONENT_Cr];
 
+#if !JVET_Q0820_ACT
     ctxStart = m_CABACEstimator->getCtx();
     m_CABACEstimator->resetBits();
+#endif
     tu.jointCbCr = 0;
 
     bool doReshaping = (slice.getPicHeader()->getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (slice.isIntra() || m_pcReshape->getCTUFlag()) && (cbArea.width * cbArea.height > 4));
@@ -4287,16 +4411,116 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
     for (uint32_t c = COMPONENT_Cb; c < ::getNumberValidTBlocks(*csFull->pcv); c++)
     {
       const ComponentID compID = ComponentID(c);
+#if JVET_Q0820_ACT 
+      double  dSingleBestCostChroma = MAX_DOUBLE;
+      int     bestModeId = -1;
+      bool    tsAllowed = TU::isTSAllowed(tu, compID) && (m_pcEncCfg->getUseChromaTS());
+      uint8_t numTransformCands = 1 + (tsAllowed ? 1 : 0);  // DCT + TS = 2 tests
+      bool        cbfDCT2 = true;
+
+      trModes.clear();
+
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+      {
+        numTransformCands = 1;
+        CHECK(!tsAllowed && !cu.bdpcmModeChroma, "transform skip should be enabled for LS");
+        if (cu.bdpcmModeChroma)
+        {
+          trModes.push_back(TrMode(0, true));
+        }
+        else
+        {
+          trModes.push_back(TrMode(1, true));
+        }
+      }
+      else
+      {
+        trModes.push_back(TrMode(0, true));                    // DCT
+        if (tsAllowed)
+        {
+          trModes.push_back(TrMode(1, true));                  // TS
+        }
+      }
+
+      if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+        m_pcRdCost->lambdaAdjustColorTrans(true, compID);
+
+      TempCtx ctxBegin(m_CtxCache);
+      ctxBegin = m_CABACEstimator->getCtx();
+
+      for (int modeId = 0; modeId < numTransformCands; modeId++)
+      {
+        if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+        {
+          if (modeId && !cbfDCT2)
+          {
+            continue;
+          }
+          if (!trModes[modeId].second)
+          {
+            continue;
+          }
+        }
+
+        if (modeId > 0)
+        {
+          m_CABACEstimator->getCtx() = ctxBegin;
+        }
+
+        tu.mtsIdx[compID] = trModes[modeId].first;
+#endif
       Distortion singleDistChroma = 0;
+#if JVET_Q0820_ACT
+      if (numTransformCands > 1)
+      {
+        xIntraCodingACTTUBlock(tu, compID, singleDistChroma, modeId == 0 ? &trModes : nullptr, true);
+      }
+      else
+#endif 
       xIntraCodingACTTUBlock(tu, compID, singleDistChroma);
+#if JVET_Q0820_ACT
+      if (!tu.mtsIdx[compID])
+      {
+        cbfDCT2 = TU::getCbfAtDepth(tu, compID, currDepth);
+      }
+      uint64_t fracBitChroma = xGetIntraFracBitsQTChroma(tu, compID);
+      double   dSingleCostChroma = m_pcRdCost->calcRdCost(fracBitChroma, singleDistChroma, false);
+      if (dSingleCostChroma < dSingleBestCostChroma)
+      {
+        dSingleBestCostChroma = dSingleCostChroma;
+        bestModeId = modeId;
+        if (bestModeId != (numTransformCands - 1))
+        {
+          saveChromaCS.getResiBuf(tu.blocks[compID]).copyFrom(csFull->getResiBuf(tu.blocks[compID]));
+          tmpTU->copyComponentFrom(tu, compID);
+          ctxBest = m_CABACEstimator->getCtx();
+        }
+      }
+      }
+
+      if (bestModeId != (numTransformCands - 1))
+      {
+        csFull->getResiBuf(tu.blocks[compID]).copyFrom(saveChromaCS.getResiBuf(tu.blocks[compID]));
+        tu.copyComponentFrom(*tmpTU, compID);
+        m_CABACEstimator->getCtx() = ctxBest;
+      }
+
+      if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+        m_pcRdCost->lambdaAdjustColorTrans(false, compID);
+#else
       xGetIntraFracBitsQTChroma(tu, compID);
+#endif
     }
 
     Position tuPos = tu.Y();
     tuPos.relativeTo(cu.Y());
     const UnitArea relativeUnitArea(tu.chromaFormat, Area(tuPos, tu.Y().size()));
     PelUnitBuf     invColorTransResidual = m_colorTransResiBuf.getBuf(relativeUnitArea);
+#if JVET_Q0820_ACT
+    csFull->getResiBuf(tu).colorSpaceConvert(invColorTransResidual, false, cs.slice->clpRng(COMPONENT_Y));
+#else
     csFull->getResiBuf(tu).colorSpaceConvert(invColorTransResidual, false);
+#endif
 
     Distortion totalDist = 0;
     for (uint32_t c = COMPONENT_Y; c < ::getNumberValidTBlocks(*csFull->pcv); c++)
@@ -4373,7 +4597,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
       uint64_t bitsTmp = 0;
       if (distTmp < std::numeric_limits<Distortion>::max())
       {
+#if JVET_Q0820_ACT
+        csFull->getResiBuf(tu).colorSpaceConvert(invColorTransResidual, false, csFull->slice->clpRng(COMPONENT_Y));
+#else
         csFull->getResiBuf(tu).colorSpaceConvert(invColorTransResidual, false);
+#endif
         distTmp = 0;
         for (uint32_t c = COMPONENT_Y; c < ::getNumberValidTBlocks(*csFull->pcv); c++)
         {
@@ -4679,12 +4907,32 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
 #endif
       uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
       std::vector<TrMode> trModes;
+#if JVET_Q0820_ACT
+      if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING)
+      {
+        nNumTransformCands = 1;
+        CHECK(!tsAllowed && !currTU.cu->bdpcmModeChroma, "transform skip should be enabled for LS");
+        if (currTU.cu->bdpcmModeChroma)
+        {
+          trModes.push_back(TrMode(0, true));
+        }
+        else
+        {
+          trModes.push_back(TrMode(1, true));
+        }
+      }
+      else
+      {
+#endif
       trModes.push_back(TrMode(0, true)); // DCT2
 
       if (tsAllowed)
       {
           trModes.push_back(TrMode(1, true));//TS
       }
+#if JVET_Q0820_ACT 
+      }
+#endif 
       CHECK(!currTU.Cb().valid(), "Invalid TU");
 
       const int  totalModesToTest            = crossCPredictionModesToTest * nNumTransformCands;
@@ -4752,7 +5000,17 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
 
           if (((crossCPredictionModeId == 1) && (currTU.compAlpha[compID] == 0)) || ((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_Q0820_ACT
+            if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING)
+#endif 
             singleCostTmp = MAX_DOUBLE;
+#if JVET_Q0820_ACT 
+            else
+            {
+              uint64_t fracBitsTmp = xGetIntraFracBitsQTChroma(currTU, compID);
+              singleCostTmp = m_pcRdCost->calcRdCost(fracBitsTmp, singleDistCTmp);
+            }
+#endif 
           }
           else if( lumaUsesISP && bestCostSoFar != MAX_DOUBLE && c == COMPONENT_Cb )
           {
@@ -4822,7 +5080,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_Q0820_ACT 
+      if ((c == COMPONENT_Cb && bestModeId < totalModesToTest) || (c == COMPONENT_Cb && m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING))
+#else
       if ( c == COMPONENT_Cb && bestModeId < totalModesToTest)
+#endif
       {
         m_CABACEstimator->getCtx() = ctxBest;
 
diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp
index 2c97b4d446316905750b0c0e1df744f6cc157118..ab3cb102b9e66b9de389e7e644a998a66b298f40 100644
--- a/source/Lib/EncoderLib/VLCWriter.cpp
+++ b/source/Lib/EncoderLib/VLCWriter.cpp
@@ -1001,7 +1001,14 @@ void HLSWriter::codeSPS( const SPS* pcSPS )
   }
   if (pcSPS->getChromaFormatIdc() == CHROMA_444)
   {
+#if JVET_Q0820_ACT
+    if (pcSPS->getLog2MaxTbSize() != 6)
+    {
+      WRITE_FLAG(pcSPS->getUseColorTrans() ? 1 : 0, "sps_act_enabled_flag");
+    }
+#else
     WRITE_FLAG(pcSPS->getUseColorTrans() ? 1 : 0, "sps_act_enabled_flag");
+#endif
   }
   if (pcSPS->getChromaFormatIdc() == CHROMA_444)
   {