From 329279589a6a3111f7fc2a5a070c7a05e1d1c85d Mon Sep 17 00:00:00 2001
From: Frank Bossen <fbossen@gmail.com>
Date: Wed, 31 Aug 2022 15:56:47 -0400
Subject: [PATCH] Use enumeration for BDPCM mode

---
 source/Lib/CommonLib/ContextModelling.cpp     |   3 +-
 source/Lib/CommonLib/ContextModelling.h       |  19 +--
 source/Lib/CommonLib/DeblockingFilter.cpp     |  10 +-
 source/Lib/CommonLib/IntraPrediction.cpp      |  14 ++-
 source/Lib/CommonLib/IntraPrediction.h        |   2 +-
 source/Lib/CommonLib/Quant.cpp                |  10 +-
 source/Lib/CommonLib/QuantRDOQ.cpp            |  30 ++---
 source/Lib/CommonLib/QuantRDOQ.h              |   2 +-
 source/Lib/CommonLib/TrQuant.cpp              |   2 +-
 source/Lib/CommonLib/TypeDef.h                |   7 ++
 source/Lib/CommonLib/Unit.cpp                 |   4 +-
 source/Lib/CommonLib/Unit.h                   |   6 +-
 source/Lib/CommonLib/UnitTools.cpp            |  10 +-
 source/Lib/CommonLib/UnitTools.h              |   3 +-
 .../Lib/CommonLib/dtrace_blockstatistics.cpp  |   9 +-
 source/Lib/DecoderLib/CABACReader.cpp         |  77 ++++++-------
 source/Lib/DecoderLib/CABACReader.h           |   2 +-
 source/Lib/EncoderLib/CABACWriter.cpp         |  76 ++++++------
 source/Lib/EncoderLib/CABACWriter.h           |   2 +-
 source/Lib/EncoderLib/EncCu.cpp               |   6 +-
 source/Lib/EncoderLib/InterSearch.cpp         |  26 +++--
 source/Lib/EncoderLib/IntraSearch.cpp         | 109 ++++++++++--------
 source/Lib/EncoderLib/IntraSearch.h           |  13 ++-
 23 files changed, 233 insertions(+), 209 deletions(-)

diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp
index 85d8097f97..317ad46982 100644
--- a/source/Lib/CommonLib/ContextModelling.cpp
+++ b/source/Lib/CommonLib/ContextModelling.cpp
@@ -42,7 +42,8 @@
 
 const int CoeffCodingContext::prefixCtx[8] = { 0, 0, 0, 3, 6, 10, 15, 21 };
 
-CoeffCodingContext::CoeffCodingContext(const TransformUnit &tu, ComponentID component, bool signHide, bool bdpcm)
+CoeffCodingContext::CoeffCodingContext(const TransformUnit &tu, ComponentID component, bool signHide,
+                                       const BdpcmMode bdpcm)
   : m_compID(component)
   , m_chType(toChannelType(m_compID))
   , m_width(tu.block(m_compID).width)
diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h
index 0da935f935..e56515b81b 100644
--- a/source/Lib/CommonLib/ContextModelling.h
+++ b/source/Lib/CommonLib/ContextModelling.h
@@ -53,7 +53,8 @@ struct CoeffCodingContext
 public:
   static const int prefixCtx[8];
 
-  CoeffCodingContext( const TransformUnit& tu, ComponentID component, bool signHide, bool bdpcm = false );
+  CoeffCodingContext(const TransformUnit &tu, ComponentID component, bool signHide, const BdpcmMode bdpcm);
+
 public:
   void  initSubblock     ( int SubsetId, bool sigGroupFlag = false );
 public:
@@ -97,7 +98,7 @@ public:
   int             numCtxBins      ()                        const { return   m_remainingContextBins;      }
   void            setNumCtxBins   ( int n )                       {          m_remainingContextBins  = n; }
   unsigned        sigGroupCtxId   ( bool ts = false     )   const { return ts ? m_sigGroupCtxIdTS : m_sigGroupCtxId; }
-  bool            bdpcm           ()                        const { return m_bdpcm; }
+  BdpcmMode       bdpcm() const { return m_bdpcm; }
 
   void            decimateNumCtxBins(int n) { m_remainingContextBins -= n; }
   void            increaseNumCtxBins(int n) { m_remainingContextBins += n; }
@@ -355,7 +356,7 @@ public:
   unsigned parityCtxIdAbsTS   ()                  const { return m_tsParFlagCtxSet(      0 ); }
   unsigned greaterXCtxIdAbsTS ( uint8_t offset )  const { return m_tsGtxFlagCtxSet( offset ); }
 
-  unsigned lrg1CtxIdAbsTS(int scanPos, const TCoeff* coeff, int bdpcm)
+  unsigned lrg1CtxIdAbsTS(int scanPos, const TCoeff *coeff, const BdpcmMode bdpcm)
   {
     const uint32_t  posY = m_scan[scanPos].y;
     const uint32_t  posX = m_scan[scanPos].x;
@@ -364,7 +365,7 @@ public:
     int             numPos = 0;
 #define UPDATE(x) {TCoeff a=abs(x);numPos+=int(!!a);}
 
-    if (bdpcm)
+    if (bdpcm != BdpcmMode::NONE)
     {
       numPos = 3;
     }
@@ -384,7 +385,7 @@ public:
     return m_tsLrg1FlagCtxSet(numPos);
   }
 
-  unsigned signCtxIdAbsTS(int scanPos, const TCoeff* coeff, int bdpcm)
+  unsigned signCtxIdAbsTS(int scanPos, const TCoeff *coeff, const BdpcmMode bdpcm)
   {
     const uint32_t  posY = m_scan[scanPos].y;
     const uint32_t  posX = m_scan[scanPos].x;
@@ -414,7 +415,7 @@ public:
     {
       signCtx = 2;
     }
-    if (bdpcm)
+    if (bdpcm != BdpcmMode::NONE)
     {
       signCtx += 3;
     }
@@ -439,7 +440,7 @@ public:
     }
   }
 
-  int deriveModCoeff(int rightPixel, int belowPixel, TCoeff absCoeff, int bdpcm = 0)
+  int deriveModCoeff(int rightPixel, int belowPixel, TCoeff absCoeff, const bool bdpcm)
   {
 
     if (absCoeff == 0)
@@ -450,7 +451,7 @@ public:
 
     int absCoeffMod = int(absCoeff);
 
-    if (bdpcm == 0)
+    if (!bdpcm)
     {
       pred1 = std::max(absBelow, absRight);
 
@@ -556,7 +557,7 @@ private:
   CtxSet                    m_tsSignFlagCtxSet;
   int                       m_remainingContextBins;
   std::bitset<MLS_GRP_NUM>  m_sigCoeffGroupFlag;
-  const bool                m_bdpcm;
+  const BdpcmMode           m_bdpcm;
   int                       m_cctxBaseLevel;
   TCoeff                    m_histValue;
   bool                      m_updateHist;
diff --git a/source/Lib/CommonLib/DeblockingFilter.cpp b/source/Lib/CommonLib/DeblockingFilter.cpp
index 5880c3b43b..57b3b2eb1a 100644
--- a/source/Lib/CommonLib/DeblockingFilter.cpp
+++ b/source/Lib/CommonLib/DeblockingFilter.cpp
@@ -762,12 +762,18 @@ DeblockingFilter::EdgeStrengths DeblockingFilter::xGetBoundaryStrengthSingle(con
   {
     if (isLuma(chType))
     {
-      const int bsY = CU::isIntra(cuP) && cuP.bdpcmMode && CU::isIntra(cuQ) && cuQ.bdpcmMode ? 0 : 2;
+      const int bsY =
+        CU::isIntra(cuP) && cuP.bdpcmMode != BdpcmMode::NONE && CU::isIntra(cuQ) && cuQ.bdpcmMode != BdpcmMode::NONE
+          ? 0
+          : 2;
       return EdgeStrengths().setBoundaryStrength(COMPONENT_Y, bsY);
     }
     else
     {
-      const int bsC = CU::isIntra(cuP) && cuP.bdpcmModeChroma && CU::isIntra(cuQ) && cuQ.bdpcmModeChroma ? 0 : 2;
+      const int bsC = CU::isIntra(cuP) && cuP.bdpcmModeChroma != BdpcmMode::NONE && CU::isIntra(cuQ)
+                          && cuQ.bdpcmModeChroma != BdpcmMode::NONE
+                        ? 0
+                        : 2;
       return EdgeStrengths().setBoundaryStrength(COMPONENT_Cb, bsC).setBoundaryStrength(COMPONENT_Cr, bsC);
     }
   }
diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp
index 393f509a42..34098add7e 100644
--- a/source/Lib/CommonLib/IntraPrediction.cpp
+++ b/source/Lib/CommonLib/IntraPrediction.cpp
@@ -221,7 +221,7 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co
   CHECK(width == 2, "Width of 2 is not supported");
   CHECK(PU::isMIP(pu, toChannelType(compId)), "We should not get here for MIP.");
   const uint32_t dirMode =
-    (isLuma(compId) ? pu.cu->bdpcmMode : pu.cu->bdpcmModeChroma) ? BDPCM_IDX : PU::getFinalIntraMode(pu, channelType);
+    pu.cu->getBdpcmMode(compID) != BdpcmMode::NONE ? BDPCM_IDX : PU::getFinalIntraMode(pu, channelType);
 
   CHECK(floorLog2(width) < 2 && pu.cs->pcv->noChroma2x2, "Size not allowed");
   CHECK(floorLog2(width) > MAX_CU_DEPTH, "Size not allowed");
@@ -236,7 +236,9 @@ void IntraPrediction::predIntraAng( const ComponentID compId, PelBuf &piPred, co
   {
     case(PLANAR_IDX): xPredIntraPlanar(srcBuf, piPred); break;
     case(DC_IDX):     xPredIntraDc(srcBuf, piPred, channelType, false); break;
-    case(BDPCM_IDX):  xPredIntraBDPCM(srcBuf, piPred, isLuma(compID) ? pu.cu->bdpcmMode : pu.cu->bdpcmModeChroma, clpRng); break;
+    case BDPCM_IDX:
+      xPredIntraBDPCM(srcBuf, piPred, pu.cu->getBdpcmMode(compID), clpRng);
+      break;
     default:          xPredIntraAng(srcBuf, piPred, channelType, clpRng); break;
   }
 
@@ -412,7 +414,7 @@ void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompA
 
   // high level conditions and DC intra prediction
   if (isLuma(chType) && !useISP && !PU::isMIP(pu, chType) && m_ipaParam.multiRefIndex == 0 && DC_IDX != dirMode
-      && !pu.cu->bdpcmMode)
+      && pu.cu->bdpcmMode == BdpcmMode::NONE)
   {
     if (dirMode == PLANAR_IDX)   // Planar intra prediction
     {
@@ -636,7 +638,7 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch
   }
 }
 
-void IntraPrediction::xPredIntraBDPCM(const CPelBuf &pSrc, PelBuf &pDst, const uint32_t dirMode, const ClpRng& clpRng )
+void IntraPrediction::xPredIntraBDPCM(const CPelBuf &pSrc, PelBuf &pDst, const BdpcmMode dirMode, const ClpRng &clpRng)
 {
   const int wdt = pDst.width;
   const int hgt = pDst.height;
@@ -644,10 +646,10 @@ void IntraPrediction::xPredIntraBDPCM(const CPelBuf &pSrc, PelBuf &pDst, const u
   const int strideP = pDst.stride;
   const int strideS = pSrc.stride;
 
-  CHECK( !( dirMode == 1 || dirMode == 2 ), "Incorrect BDPCM mode parameter." );
+  CHECK(dirMode != BdpcmMode::HOR && dirMode != BdpcmMode::VER, "Incorrect BDPCM mode parameter.");
 
   Pel* pred = &pDst.buf[0];
-  if( dirMode == 1 )
+  if (dirMode == BdpcmMode::HOR)
   {
     Pel  val;
     for( int y = 0; y < hgt; y++ )
diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h
index 99fb89c8f4..cd2c5e8dd6 100644
--- a/source/Lib/CommonLib/IntraPrediction.h
+++ b/source/Lib/CommonLib/IntraPrediction.h
@@ -129,7 +129,7 @@ protected:
 
   static bool isIntegerSlope(const int absAng) { return (0 == (absAng & 0x1F)); }
 
-  void xPredIntraBDPCM            ( const CPelBuf &pSrc, PelBuf &pDst, const uint32_t dirMode, const ClpRng& clpRng );
+  void xPredIntraBDPCM(const CPelBuf &pSrc, PelBuf &pDst, BdpcmMode dirMode, const ClpRng &clpRng);
   Pel  xGetPredValDc              ( const CPelBuf &pSrc, const Size &dstSize );
 
   void xFillReferenceSamples      ( const CPelBuf &recoBuf,      Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu );
diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp
index 2e5f77d206..49ad24ac92 100644
--- a/source/Lib/CommonLib/Quant.cpp
+++ b/source/Lib/CommonLib/Quant.cpp
@@ -153,7 +153,7 @@ void invResDPCM( const TransformUnit &tu, const ComponentID &compID, CoeffBuf &d
   const TCoeff* coef = &coeffs.buf[0];
   TCoeff* dst = &dstBuf.buf[0];
 
-  if( isLuma(compID) ? tu.cu->bdpcmMode == 1 : tu.cu->bdpcmModeChroma == 1)
+  if (tu.cu->getBdpcmMode(compID) == BdpcmMode::HOR)
   {
     for( int y = 0; y < hgt; y++ )
     {
@@ -193,7 +193,7 @@ void fwdResDPCM( TransformUnit &tu, const ComponentID &compID )
 
   TCoeff* coef = &coeffs.buf[0];
 
-  if( isLuma(compID) ? tu.cu->bdpcmMode == 1 : tu.cu->bdpcmModeChroma == 1)
+  if (tu.cu->getBdpcmMode(compID) == BdpcmMode::HOR)
   {
     for( int y = 0; y < hgt; y++ )
     {
@@ -377,7 +377,7 @@ void Quant::dequant(const TransformUnit &tu,
   const int             channelBitDepth    = sps->getBitDepth(toChannelType(compID));
 
   const TCoeff          *coef;
-  if ((tu.cu->bdpcmMode && isLuma(compID)) || ( tu.cu->bdpcmModeChroma && isChroma(compID) ))
+  if (tu.cu->getBdpcmMode(compID) != BdpcmMode::NONE)
   {
     invResDPCM( tu, compID, dstCoeff );
     coef = piCoef;
@@ -941,7 +941,7 @@ void Quant::quant(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf
   const int  maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange(toChannelType(compID));
 
   {
-    CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag());
+    CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag(), tu.cu->getBdpcmMode(compID));
     const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange);
     const TCoeff entropyCodingMaximum =  (1 << maxLog2TrDynamicRange) - 1;
 
@@ -996,7 +996,7 @@ void Quant::quant(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf
 
       piQCoef.buf[uiBlockPos] = Clip3<TCoeff>( entropyCodingMinimum, entropyCodingMaximum, quantisedCoefficient );
     } // for n
-    if ((tu.cu->bdpcmMode && isLuma(compID)) || (tu.cu->bdpcmModeChroma && isChroma(compID)) )
+    if (cctx.bdpcm() != BdpcmMode::NONE)
     {
       fwdResDPCM( tu, compID );
     }
diff --git a/source/Lib/CommonLib/QuantRDOQ.cpp b/source/Lib/CommonLib/QuantRDOQ.cpp
index 989b83ff5b..53d62043d5 100644
--- a/source/Lib/CommonLib/QuantRDOQ.cpp
+++ b/source/Lib/CommonLib/QuantRDOQ.cpp
@@ -538,7 +538,7 @@ void QuantRDOQ::quant(TransformUnit &tu, const ComponentID &compID, const CCoeff
     {
       if( useTransformSkip )
       {
-        if( (tu.cu->bdpcmMode && isLuma(compID)) || (isChroma(compID) && tu.cu->bdpcmModeChroma ) )
+        if (tu.cu->getBdpcmMode(compID) != BdpcmMode::NONE)
         {
           forwardBDPCM(tu, compID, pSrc, absSum, cQP, ctx);
         }
@@ -642,7 +642,7 @@ void QuantRDOQ::xRateDistOptQuant(TransformUnit &tu, const ComponentID &compID,
   const TCoeff entropyCodingMinimum = -(1 << maxLog2TrDynamicRange);
   const TCoeff entropyCodingMaximum =  (1 << maxLog2TrDynamicRange) - 1;
 
-  CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag());
+  CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag(), tu.cu->getBdpcmMode(compID));
   int baseLevel = cctx.getBaseLevel();
   if (tu.cs->slice->getSPS()->getSpsRangeExtension().getPersistentRiceAdaptationEnabledFlag())
   {
@@ -1235,7 +1235,7 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI
   memset( m_pdCostCoeff,  0, sizeof( double ) *  maxNumCoeff );
   memset( m_pdCostSig,    0, sizeof( double ) *  maxNumCoeff );
 
-  m_bdpcm = 0;
+  m_bdpcm = BdpcmMode::NONE;
 
   const bool   needsSqrt2Scale = TU::needsSqrt2Scale( tu, compID );  // should always be false - transform-skipped blocks don't require sqrt(2) compensation.
   const bool   isTransformSkip = (tu.mtsIdx[compID] == MTS_SKIP);
@@ -1248,7 +1248,7 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI
   uint32_t coeffLevels[3];
   double   coeffLevelError[4];
 
-  CoeffCodingContext cctx( tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag() );
+  CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag(), m_bdpcm);
   const int sbSizeM1    = ( 1 << cctx.log2CGSize() ) - 1;
   double    baseCost    = 0;
   uint32_t  goRiceParam = 0;
@@ -1303,7 +1303,7 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI
       int rightPixel, belowPixel, predPixel;
 
       cctx.neighTS(rightPixel, belowPixel, scanPos, dstCoeff);
-      predPixel = cctx.deriveModCoeff(rightPixel, belowPixel, upAbsLevel, 0);
+      predPixel = cctx.deriveModCoeff(rightPixel, belowPixel, upAbsLevel, false);
 
       if (upAbsLevel != roundAbsLevel && upAbsLevel != minAbsLevel && predPixel == 1)
       {
@@ -1326,13 +1326,13 @@ void QuantRDOQ::xRateDistOptQuantTS( TransformUnit &tu, const ComponentID &compI
       {
         goRiceParam = goRiceParam + tu.cu->slice->getTsrcIndex();
       }
-      unsigned ctxIdSign = cctx.signCtxIdAbsTS(scanPos, dstCoeff, 0);
+      unsigned          ctxIdSign    = cctx.signCtxIdAbsTS(scanPos, dstCoeff, m_bdpcm);
       const BinFracBits fracBitsSign = fracBits.getFracBitsArray(ctxIdSign);
       const uint8_t     sign         = srcCoeff[ blkPos ] < 0 ? 1 : 0;
 
       DTRACE_COND( ( coeffLevels[0] != 0 ), g_trace_ctx, D_RDOQ_MORE, " uiCtxSig=%d", ctxIdSig );
 
-      unsigned gt1CtxId = cctx.lrg1CtxIdAbsTS(scanPos, dstCoeff, 0);
+      unsigned          gt1CtxId    = cctx.lrg1CtxIdAbsTS(scanPos, dstCoeff, m_bdpcm);
       const BinFracBits fracBitsGr1 = fracBits.getFracBitsArray(gt1CtxId);
 
       const BinFracBits fracBitsSig = fracBits.getFracBitsArray( ctxIdSig );
@@ -1438,7 +1438,7 @@ void QuantRDOQ::forwardBDPCM(TransformUnit &tu, const ComponentID &compID, const
 
   const bool extendedPrecision = sps.getSpsRangeExtension().getExtendedPrecisionProcessingFlag();
   const int  maxLog2TrDynamicRange = sps.getMaxLog2TrDynamicRange(chType);
-  const int  dirMode = isLuma(compID) ? tu.cu->bdpcmMode : tu.cu->bdpcmModeChroma;
+  const BdpcmMode dirMode               = tu.cu->getBdpcmMode(compID);
   int transformShift = getTransformShift(channelBitDepth, rect.size(), maxLog2TrDynamicRange);
 
   if (extendedPrecision)
@@ -1480,7 +1480,7 @@ void QuantRDOQ::forwardBDPCM(TransformUnit &tu, const ComponentID &compID, const
   uint32_t coeffLevels[3];
   double   coeffLevelError[4];
 
-  CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag());
+  CoeffCodingContext cctx(tu, compID, tu.cs->slice->getSignDataHidingEnabledFlag(), dirMode);
   const int sbSizeM1 = (1 << cctx.log2CGSize()) - 1;
   double    baseCost = 0;
   uint32_t  goRiceParam = 0;
@@ -1515,8 +1515,9 @@ void QuantRDOQ::forwardBDPCM(TransformUnit &tu, const ComponentID &compID, const
 
       const int posX = cctx.posX(scanPos);
       const int posY = cctx.posY(scanPos);
-      const int posS = (1 == dirMode) ? posX : posY;
-      const int posNb = (1 == dirMode) ? (posX - 1) + posY * coeffs.stride : posX + (posY - 1) * coeffs.stride;
+      const int posS = (BdpcmMode::HOR == dirMode) ? posX : posY;
+      const int posNb =
+        (BdpcmMode::HOR == dirMode) ? (posX - 1) + posY * coeffs.stride : posX + (posY - 1) * coeffs.stride;
       TCoeff predCoeff = (0 != posS) ? m_fullCoeff[posNb] : 0;
 
       // set coeff
@@ -1630,8 +1631,9 @@ void QuantRDOQ::forwardBDPCM(TransformUnit &tu, const ComponentID &compID, const
 
           const int posX = cctx.posX(scanPos);
           const int posY = cctx.posY(scanPos);
-          const int posS = (1 == dirMode) ? posX : posY;
-          const int posNb = (1 == dirMode) ? (posX - 1) + posY * coeffs.stride : posX + (posY - 1) * coeffs.stride;
+          const int posS = (BdpcmMode::HOR == dirMode) ? posX : posY;
+          const int posNb =
+            (BdpcmMode::HOR == dirMode) ? (posX - 1) + posY * coeffs.stride : posX + (posY - 1) * coeffs.stride;
           m_fullCoeff[scanPos] = (0 != posS) ? m_fullCoeff[posNb] : 0;
 
           if (dstCoeff[blkPos])
@@ -1750,7 +1752,7 @@ inline uint32_t QuantRDOQ::xGetCodedLevelTSPred(double&            rd64CodedCost
     int modAbsLevel = absLevel;
     if (cctx.numCtxBins() >= 4)
     {
-      modAbsLevel = cctx.deriveModCoeff(rightPixel, belowPixel, absLevel, m_bdpcm);
+      modAbsLevel = cctx.deriveModCoeff(rightPixel, belowPixel, absLevel, m_bdpcm != BdpcmMode::NONE);
     }
     int numCtxBins = 0;
     double dCurrCost = coeffLevelError[errorInd] + xGetICost(xGetICRateTS(modAbsLevel, fracBitsPar, cctx, fracBitsAccess, fracBitsSign, fracBitsGt1, numCtxBins, sign, ricePar, useLimitedPrefixLength, maxLog2TrDynamicRange));
diff --git a/source/Lib/CommonLib/QuantRDOQ.h b/source/Lib/CommonLib/QuantRDOQ.h
index da229e8782..4ff86f1672 100644
--- a/source/Lib/CommonLib/QuantRDOQ.h
+++ b/source/Lib/CommonLib/QuantRDOQ.h
@@ -169,7 +169,7 @@ private:
   int    m_sigRateDelta       [MAX_TB_SIZEY * MAX_TB_SIZEY];
   TCoeff m_deltaU             [MAX_TB_SIZEY * MAX_TB_SIZEY];
   TCoeff m_fullCoeff          [MAX_TB_SIZEY * MAX_TB_SIZEY];
-  int   m_bdpcm;
+  BdpcmMode m_bdpcm;
   int   m_testedLevels;
 };// END CLASS DEFINITION QuantRDOQ
 
diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp
index bdbd7b0b0a..d3e769c088 100644
--- a/source/Lib/CommonLib/TrQuant.cpp
+++ b/source/Lib/CommonLib/TrQuant.cpp
@@ -988,7 +988,7 @@ void TrQuant::transformNxN(TransformUnit &tu, const ComponentID &compID, const Q
     return;
   }
 
-  if ((tu.cu->bdpcmMode && isLuma(compID)) || (!isLuma(compID) && tu.cu->bdpcmModeChroma))
+  if (tu.cu->getBdpcmMode(compID) != BdpcmMode::NONE)
   {
     tu.mtsIdx[compID] = MTS_SKIP;
   }
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index b271f60b65..99c817f0d9 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -378,6 +378,13 @@ enum SbtMode
   NUMBER_SBT_MODE
 };
 
+enum class BdpcmMode : uint8_t
+{
+  NONE = 0,
+  HOR,
+  VER
+};
+
 /// supported slice type
 enum SliceType
 {
diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp
index 841f0cd981..5d842b09b0 100644
--- a/source/Lib/CommonLib/Unit.cpp
+++ b/source/Lib/CommonLib/Unit.cpp
@@ -331,8 +331,8 @@ void CodingUnit::initData()
   affineType        = 0;
   colorTransform = false;
   geoFlag           = false;
-  bdpcmMode         = 0;
-  bdpcmModeChroma   = 0;
+  bdpcmMode         = BdpcmMode::NONE;
+  bdpcmModeChroma   = BdpcmMode::NONE;
   qp                = 0;
   chromaQpAdj       = 0;
   rootCbf           = true;
diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h
index c5ec0e3004..4be76be95b 100644
--- a/source/Lib/CommonLib/Unit.h
+++ b/source/Lib/CommonLib/Unit.h
@@ -311,8 +311,8 @@ struct CodingUnit : public UnitArea
   int            affineType;
   bool           colorTransform;
   bool           geoFlag;
-  int            bdpcmMode;
-  int            bdpcmModeChroma;
+  BdpcmMode      bdpcmMode;
+  BdpcmMode      bdpcmModeChroma;
   uint8_t        imv;
   bool           rootCbf;
   uint8_t        sbtInfo;
@@ -363,6 +363,8 @@ struct CodingUnit : public UnitArea
   const bool        isLocalSepTree() const;
   const bool        isConsInter() const { return modeType == MODE_TYPE_INTER; }
   const bool        isConsIntra() const { return modeType == MODE_TYPE_INTRA; }
+
+  BdpcmMode getBdpcmMode(const ComponentID compId) const { return isLuma(compId) ? bdpcmMode : bdpcmModeChroma; }
 };
 
 // ---------------------------------------------------------------------------
diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp
index 09d7a166ed..f7ffd81dbe 100644
--- a/source/Lib/CommonLib/UnitTools.cpp
+++ b/source/Lib/CommonLib/UnitTools.cpp
@@ -761,11 +761,6 @@ int PU::getLMSymbolList(const PredictionUnit &pu, int *modeList)
   return idx;
 }
 
-bool PU::isChromaIntraModeCrossCheckMode( const PredictionUnit &pu )
-{
-  return !pu.cu->bdpcmModeChroma && pu.intraDir[CHANNEL_TYPE_CHROMA] == DM_CHROMA_IDX;
-}
-
 uint32_t PU::getFinalIntraMode( const PredictionUnit &pu, const ChannelType &chType )
 {
   uint32_t intraMode = pu.intraDir[chType];
@@ -4715,7 +4710,7 @@ bool CU::isMTSAllowed(const CodingUnit &cu, const ComponentID compID)
   mtsAllowed &= cuWidth <= maxSize && cuHeight <= maxSize;
   mtsAllowed &= !cu.ispMode;
   mtsAllowed &= !cu.sbtInfo;
-  mtsAllowed &= !(cu.bdpcmMode && cuWidth <= tsMaxSize && cuHeight <= tsMaxSize);
+  mtsAllowed &= !(cu.bdpcmMode != BdpcmMode::NONE && cuWidth <= tsMaxSize && cuHeight <= tsMaxSize);
   return mtsAllowed;
 }
 
@@ -4756,8 +4751,7 @@ bool TU::isTSAllowed(const TransformUnit &tu, const ComponentID compID)
   bool tsAllowed = tu.cs->sps->getTransformSkipEnabledFlag();
   tsAllowed &= ( !tu.cu->ispMode || !isLuma(compID) );
   SizeType transformSkipMaxSize = 1 << maxSize;
-  tsAllowed &= !(tu.cu->bdpcmMode && isLuma(compID));
-  tsAllowed &= !(tu.cu->bdpcmModeChroma && isChroma(compID));
+  tsAllowed &= tu.cu->getBdpcmMode(compID) == BdpcmMode::NONE;
   tsAllowed &= tu.blocks[compID].width <= transformSkipMaxSize && tu.blocks[compID].height <= transformSkipMaxSize;
   tsAllowed &= !tu.cu->sbtInfo;
 
diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h
index aa485dce44..2b34156aa1 100644
--- a/source/Lib/CommonLib/UnitTools.h
+++ b/source/Lib/CommonLib/UnitTools.h
@@ -193,8 +193,7 @@ namespace PU
   void restrictBiPredMergeCandsOne    (PredictionUnit &pu);
 
   bool isLMCMode                      (                          unsigned mode);
-  bool isLMCModeEnabled               (const PredictionUnit &pu, unsigned mode);
-  bool isChromaIntraModeCrossCheckMode(const PredictionUnit &pu);
+  bool isLMCModeEnabled(const PredictionUnit &pu, unsigned mode);
   void getGeoMergeCandidates          (const PredictionUnit &pu, MergeCtx &GeoMrgCtx);
   void spanGeoMotionInfo(PredictionUnit &pu, const MergeCtx &GeoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0,
                          const uint8_t candIdx1);
diff --git a/source/Lib/CommonLib/dtrace_blockstatistics.cpp b/source/Lib/CommonLib/dtrace_blockstatistics.cpp
index 61977c7239..6fe0036f72 100644
--- a/source/Lib/CommonLib/dtrace_blockstatistics.cpp
+++ b/source/Lib/CommonLib/dtrace_blockstatistics.cpp
@@ -556,8 +556,10 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea)
           DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::SkipFlag), cu.skip);
         }
 
-        DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::BDPCM), cu.bdpcmMode);
-        DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::BDPCMChroma), cu.bdpcmModeChroma);
+        DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::BDPCM),
+                            to_underlying(cu.bdpcmMode));
+        DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::BDPCMChroma),
+                            to_underlying(cu.bdpcmModeChroma));
         DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::TileIdx), cu.tileIdx);
         DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::IndependentSliceIdx), cu.slice->getIndependentSliceIdx());
         DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::LFNSTIdx), cu.lfnstIdx);
@@ -573,7 +575,8 @@ void writeAllData(const CodingStructure& cs, const UnitArea& ctuArea)
         DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::QP_Chroma), cu.qp);
         DTRACE_BLOCK_SCALAR_CHROMA(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::SplitSeries_Chroma), (int)cu.splitSeries);
 
-        DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::BDPCMChroma), cu.bdpcmModeChroma);
+        DTRACE_BLOCK_SCALAR(g_trace_ctx, D_BLOCK_STATISTICS_ALL, cu, GetBlockStatisticName(BlockStatistic::BDPCMChroma),
+                            to_underlying(cu.bdpcmModeChroma));
       }
 
 
diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp
index 56eae9bc15..747b582e07 100644
--- a/source/Lib/DecoderLib/CABACReader.cpp
+++ b/source/Lib/DecoderLib/CABACReader.cpp
@@ -1194,27 +1194,30 @@ void CABACReader::bdpcm_mode( CodingUnit& cu, const ComponentID compID )
   {
     if (isLuma(compID))
     {
-      cu.bdpcmMode = 0;
+      cu.bdpcmMode = BdpcmMode::NONE;
       if (!CS::isDualITree(*cu.cs))
       {
-        cu.bdpcmModeChroma = 0;
+        cu.bdpcmModeChroma = BdpcmMode::NONE;
       }
     }
     else
     {
-      cu.bdpcmModeChroma = 0;
+      cu.bdpcmModeChroma = BdpcmMode::NONE;
     }
     return;
   }
 
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2( STATS__CABAC_BITS__BDPCM_MODE, cu.block(compID).lumaSize(), compID );
 
+  BdpcmMode bdpcmMode;
   unsigned ctxId = isLuma( compID ) ? 0 : 2;
-
-  int bdpcmMode = m_binDecoder.decodeBin(Ctx::BDPCMMode(ctxId));
-  if (bdpcmMode)
+  if (m_binDecoder.decodeBin(Ctx::BDPCMMode(ctxId)))
+  {
+    bdpcmMode = m_binDecoder.decodeBin(Ctx::BDPCMMode(ctxId + 1)) ? BdpcmMode::VER : BdpcmMode::HOR;
+  }
+  else
   {
-    bdpcmMode += m_binDecoder.decodeBin(Ctx::BDPCMMode(ctxId + 1));
+    bdpcmMode = BdpcmMode::NONE;
   }
   if (isLuma(compID))
   {
@@ -1340,7 +1343,7 @@ void CABACReader::xReadTruncBinCode(uint32_t& symbol, uint32_t maxSymbol)
 
 void CABACReader::extend_ref_line(CodingUnit& cu)
 {
-  if (!cu.Y().valid() || !CU::isIntra(cu) || !isLuma(cu.chType) || cu.bdpcmMode)
+  if (!cu.Y().valid() || !CU::isIntra(cu) || !isLuma(cu.chType) || cu.bdpcmMode != BdpcmMode::NONE)
   {
     cu.firstPU->multiRefIdx = 0;
     return;
@@ -1388,9 +1391,9 @@ void CABACReader::intra_luma_pred_modes( CodingUnit &cu )
     return;
   }
 
-  if( cu.bdpcmMode )
+  if (cu.bdpcmMode != BdpcmMode::NONE)
   {
-    cu.firstPU->intraDir[0] = cu.bdpcmMode == 2? VER_IDX : HOR_IDX;
+    cu.firstPU->intraDir[0] = cu.bdpcmMode == BdpcmMode::VER ? VER_IDX : HOR_IDX;
     return;
   }
 
@@ -1488,9 +1491,9 @@ void CABACReader::intra_chroma_pred_modes( CodingUnit& cu )
     return;
   }
 
-  if( cu.bdpcmModeChroma )
+  if (cu.bdpcmModeChroma != BdpcmMode::NONE)
   {
-    cu.firstPU->intraDir[1] = cu.bdpcmModeChroma == 2 ? VER_IDX : HOR_IDX;
+    cu.firstPU->intraDir[1] = cu.bdpcmModeChroma == BdpcmMode::VER ? VER_IDX : HOR_IDX;
     return;
   }
   PredictionUnit *pu = cu.firstPU;
@@ -2658,37 +2661,24 @@ void CABACReader::transform_tree( CodingStructure &cs, Partitioner &partitioner,
   }
 }
 
-bool CABACReader::cbf_comp( CodingStructure& cs, const CompArea& area, unsigned depth, const bool prevCbf, const bool useISP )
+bool CABACReader::cbf_comp(const CompArea &area, unsigned depth, const bool prevCbf, const bool useISP,
+                           const BdpcmMode bdpcmMode)
 {
   unsigned  ctxId = DeriveCtx::CtxQtCbf(area.compID, prevCbf, useISP && isLuma(area.compID));
   const CtxSet&   ctxSet  = Ctx::QtCbf[ area.compID ];
 
   RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE2(STATS__CABAC_BITS__QT_CBF, area.size(), area.compID);
 
-  unsigned  cbf = 0;
-  if( (area.compID == COMPONENT_Y && cs.getCU(area.pos(), toChannelType(area.compID))->bdpcmMode)
-   || (area.compID != COMPONENT_Y && cs.getCU(area.pos(), toChannelType(area.compID))->bdpcmModeChroma))
-  {
-    if (area.compID == COMPONENT_Y)
-    {
-      ctxId = 1;
-    }
-    else if (area.compID == COMPONENT_Cb)
-    {
-      ctxId = 1;
-    }
-    else
-    {
-      ctxId = 2;
-    }
-    cbf = m_binDecoder.decodeBin(ctxSet(ctxId));
-  }
-  else
+  if (bdpcmMode != BdpcmMode::NONE)
   {
-    cbf = m_binDecoder.decodeBin(ctxSet(ctxId));
+    ctxId = area.compID == COMPONENT_Cr ? 2 : 1;
   }
 
-  DTRACE( g_trace_ctx, D_SYNTAX, "cbf_comp() etype=%d pos=(%d,%d) ctx=%d cbf=%d\n", area.compID, area.x, area.y, ctxId, cbf );
+  const bool cbf = m_binDecoder.decodeBin(ctxSet(ctxId)) != 0;
+
+  DTRACE(g_trace_ctx, D_SYNTAX, "cbf_comp() etype=%d pos=(%d,%d) ctx=%d cbf=%d\n", area.compID, area.x, area.y, ctxId,
+         cbf ? 1 : 0);
+
   return cbf;
 }
 
@@ -2762,7 +2752,6 @@ void CABACReader::transform_unit( TransformUnit& tu, CUCtx& cuCtx, Partitioner&
   const UnitArea&         area = partitioner.currArea();
   const unsigned          trDepth = partitioner.currTrDepth;
 
-  CodingStructure&  cs = *tu.cs;
   CodingUnit&       cu = *tu.cu;
   ChromaCbfs        chromaCbfs;
   chromaCbfs.Cb = chromaCbfs.Cr = false;
@@ -2775,12 +2764,12 @@ void CABACReader::transform_unit( TransformUnit& tu, CUCtx& cuCtx, Partitioner&
     const int cbfDepth = chromaCbfISP ? trDepth - 1 : trDepth;
     if (!(cu.sbtInfo && tu.noResidual))
     {
-      chromaCbfs.Cb = cbf_comp(cs, area.blocks[COMPONENT_Cb], cbfDepth);
+      chromaCbfs.Cb = cbf_comp(area.blocks[COMPONENT_Cb], cbfDepth, false, false, cu.bdpcmModeChroma);
     }
 
     if (!(cu.sbtInfo && tu.noResidual))
     {
-      chromaCbfs.Cr = cbf_comp(cs, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb);
+      chromaCbfs.Cr = cbf_comp(area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb, false, cu.bdpcmModeChroma);
     }
   }
   else if (cu.isSepTree())
@@ -2831,7 +2820,7 @@ void CABACReader::transform_unit( TransformUnit& tu, CUCtx& cuCtx, Partitioner&
           previousCbf = TU::getPrevTuCbfAtDepth(tu, COMPONENT_Y, trDepth);
         }
       }
-      bool cbfY = lastCbfIsInferred ? true : cbf_comp(cs, tu.Y(), trDepth, previousCbf, cu.ispMode);
+      bool cbfY = lastCbfIsInferred ? true : cbf_comp(tu.Y(), trDepth, previousCbf, cu.ispMode, cu.bdpcmMode);
       TU::setCbfAtDepth(tu, COMPONENT_Y, trDepth, (cbfY ? 1 : 0));
     }
   }
@@ -2976,7 +2965,7 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx&
   bool signHiding = cu.cs->slice->getSignDataHidingEnabledFlag();
 
   // init coeff coding context
-  CoeffCodingContext  cctx    ( tu, compID, signHiding );
+  CoeffCodingContext  cctx(tu, compID, signHiding, cu.getBdpcmMode(compID));
   TCoeff*             coeff   = tu.getCoeffs( compID ).buf;
 
   // parse last coeff position
@@ -3036,7 +3025,7 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx&
 
 void CABACReader::ts_flag( TransformUnit& tu, ComponentID compID )
 {
-  int tsFlag = ( (tu.cu->bdpcmMode && isLuma(compID)) || (tu.cu->bdpcmModeChroma && isChroma(compID)) ) ? 1 : tu.mtsIdx[compID] == MTS_SKIP ? 1 : 0;
+  int tsFlag = tu.cu->getBdpcmMode(compID) != BdpcmMode::NONE || tu.mtsIdx[compID] == MTS_SKIP ? 1 : 0;
   int ctxIdx = isLuma(compID) ? 0 : 1;
 
   if( TU::isTSAllowed ( tu, compID ) )
@@ -3086,7 +3075,9 @@ void CABACReader::mts_idx( CodingUnit& cu, CUCtx& cuCtx )
 
 void CABACReader::isp_mode( CodingUnit& cu )
 {
-  if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || !cu.cs->sps->getUseISP() || cu.bdpcmMode || !CU::canUseISP( cu, getFirstComponentOfChannel( cu.chType ) ) || cu.colorTransform )
+  if (!CU::isIntra(cu) || !isLuma(cu.chType) || cu.firstPU->multiRefIdx || !cu.cs->sps->getUseISP()
+      || cu.bdpcmMode != BdpcmMode::NONE || !CU::canUseISP(cu, getFirstComponentOfChannel(cu.chType))
+      || cu.colorTransform)
   {
     cu.ispMode = NOT_INTRA_SUBPARTITIONS;
     return;
@@ -3421,7 +3412,7 @@ void CABACReader::residual_codingTS( TransformUnit& tu, ComponentID compID )
   DTRACE( g_trace_ctx, D_SYNTAX, "residual_codingTS() etype=%d pos=(%d,%d) size=%dx%d\n", tu.blocks[compID].compID, tu.blocks[compID].x, tu.blocks[compID].y, tu.blocks[compID].width, tu.blocks[compID].height );
 
   // init coeff coding context
-  CoeffCodingContext  cctx    ( tu, compID, false, isLuma(compID) ? tu.cu->bdpcmMode : tu.cu->bdpcmModeChroma);
+  CoeffCodingContext  cctx(tu, compID, false, tu.cu->getBdpcmMode(compID));
   TCoeff*             coeff   = tu.getCoeffs( compID ).buf;
   int maxCtxBins = (cctx.maxNumCoeff() * 7) >> 2;
   cctx.setNumCtxBins(maxCtxBins);
@@ -3592,7 +3583,7 @@ void CABACReader::residual_coding_subblockTS(CoeffCodingContext &cctx, TCoeff *c
         sigBlkPos[numNonZero++] = blkPos;
       }
     }
-    if (!cctx.bdpcm() && cutoffVal)
+    if (cctx.bdpcm() == BdpcmMode::NONE && cutoffVal)
     {
       if (tcoeff > 0)
       {
diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h
index b7c730c083..0ea5df2816 100644
--- a/source/Lib/DecoderLib/CABACReader.h
+++ b/source/Lib/DecoderLib/CABACReader.h
@@ -123,7 +123,7 @@ public:
 
   // transform tree (clause 7.3.8.8)
   void        transform_tree            ( CodingStructure&              cs, Partitioner&    pm, CUCtx& cuCtx, const PartSplit ispType = TU_NO_ISP, const int subTuIdx = -1 );
-  bool        cbf_comp                  ( CodingStructure&              cs,     const CompArea& area,     unsigned depth, const bool prevCbf = false, const bool useISP = false );
+  bool cbf_comp(const CompArea &area, unsigned depth, bool prevCbf, bool useISP, BdpcmMode bdpcmMode);
 
   // mvd coding (clause 7.3.8.9)
   void        mvd_coding                ( Mv &rMvd );
diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp
index e5ac58b952..4b2fc21b9a 100644
--- a/source/Lib/EncoderLib/CABACWriter.cpp
+++ b/source/Lib/EncoderLib/CABACWriter.cpp
@@ -832,14 +832,14 @@ void CABACWriter::bdpcm_mode( const CodingUnit& cu, const ComponentID compID )
     return;
   }
 
-  int bdpcmMode = isLuma(compID) ? cu.bdpcmMode : cu.bdpcmModeChroma;
+  const BdpcmMode bdpcmMode = cu.getBdpcmMode(compID);
 
   unsigned ctxId = isLuma(compID) ? 0 : 2;
-  m_binEncoder.encodeBin(bdpcmMode > 0 ? 1 : 0, Ctx::BDPCMMode(ctxId));
+  m_binEncoder.encodeBin(bdpcmMode != BdpcmMode::NONE ? 1 : 0, Ctx::BDPCMMode(ctxId));
 
-  if (bdpcmMode)
+  if (bdpcmMode != BdpcmMode::NONE)
   {
-    m_binEncoder.encodeBin(bdpcmMode > 1 ? 1 : 0, Ctx::BDPCMMode(ctxId + 1));
+    m_binEncoder.encodeBin(bdpcmMode != BdpcmMode::HOR ? 1 : 0, Ctx::BDPCMMode(ctxId + 1));
   }
   if (isLuma(compID))
   {
@@ -961,7 +961,7 @@ void CABACWriter::extend_ref_line(const PredictionUnit& pu)
 {
 
   const CodingUnit& cu = *pu.cu;
-  if (!cu.Y().valid() || !CU::isIntra(cu) || !isLuma(cu.chType) || cu.bdpcmMode)
+  if (!cu.Y().valid() || !CU::isIntra(cu) || !isLuma(cu.chType) || cu.bdpcmMode != BdpcmMode::NONE)
   {
     return;
   }
@@ -987,7 +987,7 @@ void CABACWriter::extend_ref_line(const PredictionUnit& pu)
 
 void CABACWriter::extend_ref_line(const CodingUnit& cu)
 {
-  if (!cu.Y().valid() || !CU::isIntra(cu) || !isLuma(cu.chType) || cu.bdpcmMode)
+  if (!cu.Y().valid() || !CU::isIntra(cu) || !isLuma(cu.chType) || cu.bdpcmMode != BdpcmMode::NONE)
   {
     return;
   }
@@ -1026,9 +1026,9 @@ void CABACWriter::intra_luma_pred_modes( const CodingUnit& cu )
     return;
   }
 
-  if( cu.bdpcmMode )
+  if (cu.bdpcmMode != BdpcmMode::NONE)
   {
-    cu.firstPU->intraDir[0] = cu.bdpcmMode == 2? VER_IDX : HOR_IDX;
+    cu.firstPU->intraDir[0] = cu.bdpcmMode == BdpcmMode::VER ? VER_IDX : HOR_IDX;
     return;
   }
 
@@ -1139,7 +1139,7 @@ void CABACWriter::intra_luma_pred_modes( const CodingUnit& cu )
 
 void CABACWriter::intra_luma_pred_mode( const PredictionUnit& pu )
 {
-  if (pu.cu->bdpcmMode)
+  if (pu.cu->bdpcmMode != BdpcmMode::NONE)
   {
     return;
   }
@@ -1226,9 +1226,9 @@ void CABACWriter::intra_chroma_pred_modes( const CodingUnit& cu )
     return;
   }
 
-  if( cu.bdpcmModeChroma )
+  if (cu.bdpcmModeChroma != BdpcmMode::NONE)
   {
-    cu.firstPU->intraDir[1] = cu.bdpcmModeChroma == 2 ? VER_IDX : HOR_IDX;
+    cu.firstPU->intraDir[1] = cu.bdpcmModeChroma == BdpcmMode::VER ? VER_IDX : HOR_IDX;
     return;
   }
   const PredictionUnit* pu = cu.firstPU;
@@ -2323,34 +2323,21 @@ void CABACWriter::transform_tree( const CodingStructure& cs, Partitioner& partit
   }
 }
 
-void CABACWriter::cbf_comp( const CodingStructure& cs, bool cbf, const CompArea& area, unsigned depth, const bool prevCbf, const bool useISP )
+void CABACWriter::cbf_comp(bool cbf, const CompArea &area, unsigned depth, const bool prevCbf, const bool useISP,
+                           const BdpcmMode bdpcmMode)
 {
   unsigned  ctxId = DeriveCtx::CtxQtCbf(area.compID, prevCbf, useISP && isLuma(area.compID));
   const CtxSet&   ctxSet  = Ctx::QtCbf[ area.compID ];
 
-  if ((area.compID == COMPONENT_Y && cs.getCU(area.pos(), toChannelType(area.compID))->bdpcmMode)
-      || (area.compID != COMPONENT_Y && cs.getCU(area.pos(), toChannelType(area.compID)) != nullptr
-          && cs.getCU(area.pos(), toChannelType(area.compID))->bdpcmModeChroma))
+  if (bdpcmMode != BdpcmMode::NONE)
   {
-    if (area.compID == COMPONENT_Y)
-    {
-      ctxId = 1;
-    }
-    else if (area.compID == COMPONENT_Cb)
-    {
-      ctxId = 1;
-    }
-    else
-    {
-      ctxId = 2;
-    }
-    m_binEncoder.encodeBin(cbf, ctxSet(ctxId));
-  }
-  else
-  {
-    m_binEncoder.encodeBin(cbf, ctxSet(ctxId));
+    ctxId = area.compID == COMPONENT_Cr ? 2 : 1;
   }
-  DTRACE( g_trace_ctx, D_SYNTAX, "cbf_comp() etype=%d pos=(%d,%d) ctx=%d cbf=%d\n", area.compID, area.x, area.y, ctxId, cbf );
+
+  m_binEncoder.encodeBin(cbf ? 1 : 0, ctxSet(ctxId));
+
+  DTRACE(g_trace_ctx, D_SYNTAX, "cbf_comp() etype=%d pos=(%d,%d) ctx=%d cbf=%d\n", area.compID, area.x, area.y, ctxId,
+         cbf ? 1 : 0);
 }
 
 //================================================================================
@@ -2426,7 +2413,6 @@ void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv )
 //================================================================================
 void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partitioner& partitioner, const int subTuCounter)
 {
-  const CodingStructure&  cs = *tu.cs;
   const CodingUnit&       cu = *tu.cu;
   const UnitArea&         area = partitioner.currArea();
   const unsigned          trDepth = partitioner.currTrDepth;
@@ -2443,13 +2429,14 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partiti
       chromaCbfs.Cb     = TU::getCbfAtDepth(tu, COMPONENT_Cb, trDepth);
       if (!(cu.sbtInfo && tu.noResidual))
       {
-        cbf_comp(cs, chromaCbfs.Cb, area.blocks[COMPONENT_Cb], cbfDepth);
+        cbf_comp(chromaCbfs.Cb, area.blocks[COMPONENT_Cb], cbfDepth, false, false, cu.getBdpcmMode(COMPONENT_Cb));
       }
 
       chromaCbfs.Cr = TU::getCbfAtDepth(tu, COMPONENT_Cr, trDepth);
       if (!(cu.sbtInfo && tu.noResidual))
       {
-        cbf_comp(cs, chromaCbfs.Cr, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb);
+        cbf_comp(chromaCbfs.Cr, area.blocks[COMPONENT_Cr], cbfDepth, chromaCbfs.Cb, false,
+                 cu.getBdpcmMode(COMPONENT_Cr));
       }
     }
     else if (cu.isSepTree())
@@ -2508,7 +2495,8 @@ void CABACWriter::transform_unit( const TransformUnit& tu, CUCtx& cuCtx, Partiti
       }
       if (!lastCbfIsInferred)
       {
-        cbf_comp(cs, TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), tu.Y(), trDepth, previousCbf, cu.ispMode);
+        cbf_comp(TU::getCbfAtDepth(tu, COMPONENT_Y, trDepth), tu.Y(), trDepth, previousCbf, cu.ispMode,
+                 cu.getBdpcmMode(COMPONENT_Y));
       }
     }
   }
@@ -2659,7 +2647,7 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID,
   bool signHiding = cu.cs->slice->getSignDataHidingEnabledFlag();
 
   // init coeff coding context
-  CoeffCodingContext  cctx    ( tu, compID, signHiding );
+  CoeffCodingContext  cctx(tu, compID, signHiding, BdpcmMode::NONE);
   const TCoeff*       coeff   = tu.getCoeffs( compID ).buf;
 
   // determine and set last coeff position and sig group flags
@@ -2779,7 +2767,9 @@ void CABACWriter::mts_idx( const CodingUnit& cu, CUCtx* cuCtx )
 
 void CABACWriter::isp_mode( const CodingUnit& cu )
 {
-  if( !CU::isIntra( cu ) || !isLuma( cu.chType ) || cu.firstPU->multiRefIdx || !cu.cs->sps->getUseISP() || cu.bdpcmMode || !CU::canUseISP( cu, getFirstComponentOfChannel( cu.chType ) ) || cu.colorTransform )
+  if (!CU::isIntra(cu) || !isLuma(cu.chType) || cu.firstPU->multiRefIdx || !cu.cs->sps->getUseISP()
+      || cu.bdpcmMode != BdpcmMode::NONE || !CU::canUseISP(cu, getFirstComponentOfChannel(cu.chType))
+      || cu.colorTransform)
   {
     CHECK( cu.ispMode != NOT_INTRA_SUBPARTITIONS, "cu.ispMode != 0" );
     return;
@@ -3201,7 +3191,7 @@ void CABACWriter::residual_coding_subblockTS(CoeffCodingContext &cctx, const TCo
       cctx.decimateNumCtxBins(1);
       numNonZero++;
       cctx.neighTS(rightPixel, belowPixel, nextSigPos, coeff);
-      modAbsCoeff = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeffVal), cctx.bdpcm());
+      modAbsCoeff = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeffVal), cctx.bdpcm() != BdpcmMode::NONE);
       remAbsLevel = modAbsCoeff - 1;
 
       unsigned gt1 = !!remAbsLevel;
@@ -3227,7 +3217,8 @@ void CABACWriter::residual_coding_subblockTS(CoeffCodingContext &cctx, const TCo
   {
     unsigned absLevel;
     cctx.neighTS(rightPixel, belowPixel, scanPos, coeff);
-    absLevel = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm());
+    absLevel =
+      cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm() != BdpcmMode::NONE);
     cutoffVal = 2;
     for (int i = 0; i < numGtBins; i++)
     {
@@ -3250,7 +3241,8 @@ void CABACWriter::residual_coding_subblockTS(CoeffCodingContext &cctx, const TCo
     unsigned absLevel;
     cctx.neighTS(rightPixel, belowPixel, scanPos, coeff);
     cutoffVal = (scanPos <= lastScanPosPass2 ? 10 : (scanPos <= lastScanPosPass1 ? 2 : 0));
-    absLevel = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]), cctx.bdpcm()||!cutoffVal);
+    absLevel  = cctx.deriveModCoeff(rightPixel, belowPixel, abs(coeff[cctx.blockPos(scanPos)]),
+                                    cctx.bdpcm() != BdpcmMode::NONE || cutoffVal == 0);
 
     if( absLevel >= cutoffVal )
     {
diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h
index 9b6fd147ab..f8157847d9 100644
--- a/source/Lib/EncoderLib/CABACWriter.h
+++ b/source/Lib/EncoderLib/CABACWriter.h
@@ -140,7 +140,7 @@ public:
 
   // transform tree (clause 7.3.8.8)
   void        transform_tree            ( const CodingStructure&        cs,       Partitioner&      pm,     CUCtx& cuCtx,                         const PartSplit ispType = TU_NO_ISP, const int subTuIdx = -1 );
-  void        cbf_comp                  ( const CodingStructure&        cs,       bool              cbf,    const CompArea& area, unsigned depth, const bool prevCbf = false, const bool useISP = false );
+  void cbf_comp(bool cbf, const CompArea &area, unsigned depth, bool prevCbf, bool useISP, BdpcmMode bdpcmMode);
 
   // mvd coding (clause 7.3.8.9)
   void        mvd_coding                ( const Mv &rMvd, int8_t imv );
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index ac0c7fbd7d..aa0af68f5d 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -1934,7 +1934,7 @@ void EncCu::xCheckPLT(CodingStructure *&tempCS, CodingStructure *&bestCS, Partit
 
   cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1;
   cu.qp = encTestMode.qp;
-  cu.bdpcmMode = 0;
+  cu.bdpcmMode   = BdpcmMode::NONE;
 
   tempCS->addPU(CS::getArea(*tempCS, tempCS->area, partitioner.chType), partitioner.chType);
   tempCS->addTU(CS::getArea(*tempCS, tempCS->area, partitioner.chType), partitioner.chType);
@@ -2948,7 +2948,7 @@ void EncCu::xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure
   cu.mmvdSkip    = false;
   cu.skip        = false;
   cu.mipFlag     = false;
-  cu.bdpcmMode   = 0;
+  cu.bdpcmMode   = BdpcmMode::NONE;
 
   PredictionUnit &pu = tempCS->addPU(cu, pm.chType);
 #if GDR_ENABLED
@@ -3234,7 +3234,7 @@ void EncCu::xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure
       cu.mmvdSkip    = false;
       cu.skip        = false;
       cu.mipFlag     = false;
-      cu.bdpcmMode   = 0;
+      cu.bdpcmMode   = BdpcmMode::NONE;
 
       PredictionUnit &pu = tempCS->addPU(cu, pm.chType);
       pu.mergeFlag        = true;
diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp
index 2e1805f8bc..24a8615616 100644
--- a/source/Lib/EncoderLib/InterSearch.cpp
+++ b/source/Lib/EncoderLib/InterSearch.cpp
@@ -9321,13 +9321,18 @@ void InterSearch::xEncodeInterResidualQT(CodingStructure &cs, Partitioner &parti
       {
         const bool chroma_cbf = TU::getCbfAtDepth(currTU, COMPONENT_Cb, currDepth);
         if (!(cu.sbtInfo && (currDepth == 0 || (currDepth == 1 && currTU.noResidual))))
-          m_CABACEstimator->cbf_comp(cs, chroma_cbf, currArea.blocks[COMPONENT_Cb], currDepth);
+        {
+          m_CABACEstimator->cbf_comp(chroma_cbf, currArea.blocks[COMPONENT_Cb], currDepth, false, false,
+                                     BdpcmMode::NONE);
+        }
       }
       {
         const bool chroma_cbf = TU::getCbfAtDepth(currTU, COMPONENT_Cr, currDepth);
         if (!(cu.sbtInfo && (currDepth == 0 || (currDepth == 1 && currTU.noResidual))))
-          m_CABACEstimator->cbf_comp(cs, chroma_cbf, currArea.blocks[COMPONENT_Cr], currDepth,
-                                     TU::getCbfAtDepth(currTU, COMPONENT_Cb, currDepth));
+        {
+          m_CABACEstimator->cbf_comp(chroma_cbf, currArea.blocks[COMPONENT_Cr], currDepth,
+                                     TU::getCbfAtDepth(currTU, COMPONENT_Cb, currDepth), false, BdpcmMode::NONE);
+        }
       }
     }
 
@@ -9335,7 +9340,8 @@ void InterSearch::xEncodeInterResidualQT(CodingStructure &cs, Partitioner &parti
       && !isChroma(partitioner.chType)
       )
     {
-      m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, COMPONENT_Y, currDepth ), currArea.Y(), currDepth );
+      m_CABACEstimator->cbf_comp(TU::getCbfAtDepth(currTU, COMPONENT_Y, currDepth), currArea.Y(), currDepth, false,
+                                 false, BdpcmMode::NONE);
     }
   }
 
@@ -9882,7 +9888,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
           if (!tu.noResidual)
           {
             const bool prevCbf = ( compID == COMPONENT_Cr ? tu.cbf[COMPONENT_Cb] : false );
-            m_CABACEstimator->cbf_comp( *csFull, false, compArea, currDepth, prevCbf );
+            m_CABACEstimator->cbf_comp(false, compArea, currDepth, prevCbf, false, BdpcmMode::NONE);
           }
 
           nonCoeffFracBits = m_CABACEstimator->getEstFracBits();
@@ -9922,7 +9928,7 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
           }
 
           const bool prevCbf = (compID == COMPONENT_Cr ? tu.cbf[COMPONENT_Cb] : false);
-          m_CABACEstimator->cbf_comp(*csFull, true, compArea, currDepth, prevCbf);
+          m_CABACEstimator->cbf_comp(true, compArea, currDepth, prevCbf, false, BdpcmMode::NONE);
           if (compID == COMPONENT_Cr)
           {
             const int cbfMask = (tu.cbf[COMPONENT_Cb] ? CBF_MASK_CB : 0) + CBF_MASK_CR;
@@ -10207,8 +10213,8 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
             const bool cbfCb = (codedCbfMask & CBF_MASK_CB) != 0;
             const bool cbfCr = (codedCbfMask & CBF_MASK_CR) != 0;
 
-            m_CABACEstimator->cbf_comp(cs, cbfCb, cbArea, currDepth, false);
-            m_CABACEstimator->cbf_comp(cs, cbfCr, crArea, currDepth, cbfCb);
+            m_CABACEstimator->cbf_comp(cbfCb, cbArea, currDepth, false, false, BdpcmMode::NONE);
+            m_CABACEstimator->cbf_comp(cbfCr, crArea, currDepth, cbfCb, false, BdpcmMode::NONE);
             m_CABACEstimator->joint_cb_cr(tu, codedCbfMask);
             if (cbfCb)
             {
@@ -10318,8 +10324,8 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par
         if (tu.blocks[compID].valid())
         {
           const bool prevCbf = (compID == COMPONENT_Cr ? TU::getCbfAtDepth(tu, COMPONENT_Cb, currDepth) : false);
-          m_CABACEstimator->cbf_comp(*csFull, TU::getCbfAtDepth(tu, compID, currDepth), tu.blocks[compID], currDepth,
-                                     prevCbf);
+          m_CABACEstimator->cbf_comp(TU::getCbfAtDepth(tu, compID, currDepth), tu.blocks[compID], currDepth, prevCbf,
+                                     false, BdpcmMode::NONE);
         }
       }
     }
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index 86bf019542..fe608927fb 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -1184,7 +1184,7 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c
 
     //===== check modes (using r-d costs) =====
     ModeInfo       bestPuMode;
-    int            bestBDPCMMode = 0;
+    BdpcmMode      bestBDPCMMode    = BdpcmMode::NONE;
     double         bestCostNonBDPCM = MAX_DOUBLE;
 
     CodingStructure *csTemp = m_pTempCS[gp_sizeIdxInfo->idxFrom( cu.lwidth() )][gp_sizeIdxInfo->idxFrom( cu.lheight() )];
@@ -1216,17 +1216,19 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c
         continue;
       }
 
-      if (mode < 0 || (isSecondColorSpace && m_savedBDPCMModeFirstColorSpace[m_savedRdModeIdx][mode]))
+      if (mode < 0
+          || (isSecondColorSpace && m_savedBDPCMModeFirstColorSpace[m_savedRdModeIdx][mode] != BdpcmMode::NONE))
       {
-        cu.bdpcmMode = mode < 0 ? -mode : m_savedBDPCMModeFirstColorSpace[m_savedRdModeIdx][mode];
-        orgMode      = ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, cu.bdpcmMode == 2 ? VER_IDX : HOR_IDX);
+        cu.bdpcmMode = mode < 0 ? BdpcmMode(-mode) : m_savedBDPCMModeFirstColorSpace[m_savedRdModeIdx][mode];
+        orgMode =
+          ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, cu.bdpcmMode == BdpcmMode::VER ? VER_IDX : HOR_IDX);
       }
       else
       {
-        cu.bdpcmMode = 0;
+        cu.bdpcmMode = BdpcmMode::NONE;
         orgMode      = rdModeList[mode];
       }
-      if (!cu.bdpcmMode && rdModeList[mode].ispMod == INTRA_SUBPARTITIONS_RESERVED)
+      if (cu.bdpcmMode == BdpcmMode::NONE && rdModeList[mode].ispMod == INTRA_SUBPARTITIONS_RESERVED)
       {
         if (mode == numNonISPModes)   // the list needs to be sorted only once
         {
@@ -1299,7 +1301,8 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c
         }
       }
 
-      if (!cu.ispMode && !cu.mtsFlag && !cu.lfnstIdx && !cu.bdpcmMode && !pu.multiRefIdx && !cu.mipFlag && testISP)
+      if (!cu.ispMode && !cu.mtsFlag && !cu.lfnstIdx && cu.bdpcmMode == BdpcmMode::NONE && !pu.multiRefIdx
+          && !cu.mipFlag && testISP)
       {
         m_regIntraRDListWithCosts.push_back(
           ModeInfoWithCost(cu.mipFlag, pu.mipTransposedFlag, pu.multiRefIdx, cu.ispMode, orgMode.modeId, csTemp->cost));
@@ -1360,7 +1363,7 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c
             m_modeCtrl->setMtsFirstPassNoIspCost(csBest->cost);
           }
         }
-        if( !cu.ispMode && !cu.bdpcmMode && csBest->cost < bestCostNonBDPCM )
+        if (!cu.ispMode && cu.bdpcmMode == BdpcmMode::NONE && csBest->cost < bestCostNonBDPCM)
         {
           bestCostNonBDPCM = csBest->cost;
         }
@@ -1453,7 +1456,7 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
     uint32_t   bestMode      = 0;
     Distortion bestDist      = 0;
     double     bestCost      = MAX_DOUBLE;
-    int32_t    bestBDPCMMode = 0;
+    BdpcmMode  bestBDPCMMode = BdpcmMode::NONE;
 
     //----- init mode list ----
     {
@@ -1637,14 +1640,14 @@ void IntraSearch::estIntraPredChromaQT( CodingUnit &cu, Partitioner &partitioner
 
         if (mode < 0)
         {
-          cu.bdpcmModeChroma = -mode;
-          chromaIntraMode    = cu.bdpcmModeChroma == 2 ? chromaCandModes[1] : chromaCandModes[2];
+          cu.bdpcmModeChroma = BdpcmMode(-mode);
+          chromaIntraMode    = cu.bdpcmModeChroma == BdpcmMode::VER ? chromaCandModes[1] : chromaCandModes[2];
         }
         else
         {
           chromaIntraMode = chromaCandModes[mode];
 
-          cu.bdpcmModeChroma = 0;
+          cu.bdpcmModeChroma = BdpcmMode::NONE;
           if( PU::isLMCMode( chromaIntraMode ) && ( !PU::isLMCModeEnabled( pu, chromaIntraMode ) || cu.slice->getDisableLmChromaCheck() ) )
           {
             continue;
@@ -2995,8 +2998,8 @@ void IntraSearch::xEncSubdivCbfQT(CodingStructure &cs, Partitioner &partitioner,
         if (currDepth == 0 || TU::getCbfAtDepth(currTU, compID, currDepth - 1) || chromaCbfISP)
         {
           const bool prevCbf = (compID == COMPONENT_Cr ? TU::getCbfAtDepth(currTU, COMPONENT_Cb, currDepth) : false);
-          m_CABACEstimator->cbf_comp(cs, TU::getCbfAtDepth(currTU, compID, currDepth), currArea.blocks[compID],
-                                     cbfDepth, prevCbf);
+          m_CABACEstimator->cbf_comp(TU::getCbfAtDepth(currTU, compID, currDepth), currArea.blocks[compID], cbfDepth,
+                                     prevCbf, false, currCU.getBdpcmMode(compID));
         }
       }
     }
@@ -3056,7 +3059,8 @@ void IntraSearch::xEncSubdivCbfQT(CodingStructure &cs, Partitioner &partitioner,
       }
       if( !lastCbfIsInferred )
       {
-        m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, COMPONENT_Y, currDepth ), currTU.Y(), currTU.depth, previousCbf, currCU.ispMode );
+        m_CABACEstimator->cbf_comp(TU::getCbfAtDepth(currTU, COMPONENT_Y, currDepth), currTU.Y(), currTU.depth,
+                                   previousCbf, currCU.ispMode, currCU.getBdpcmMode(COMPONENT_Y));
       }
     }
   }
@@ -3169,7 +3173,8 @@ uint64_t IntraSearch::xGetIntraFracBitsQTSingleChromaComponent( CodingStructure
 
   //cbf coding
   const bool prevCbf = ( compID == COMPONENT_Cr ? TU::getCbfAtDepth( currTU, COMPONENT_Cb, partitioner.currTrDepth ) : false );
-  m_CABACEstimator->cbf_comp( cs, TU::getCbfAtDepth( currTU, compID, partitioner.currTrDepth ), currArea.blocks[compID], partitioner.currTrDepth - 1, prevCbf );
+  m_CABACEstimator->cbf_comp(TU::getCbfAtDepth(currTU, compID, partitioner.currTrDepth), currArea.blocks[compID],
+                             partitioner.currTrDepth - 1, prevCbf, false, currTU.cu->getBdpcmMode(compID));
   //coeffs coding and cross comp coding
   if( TU::getCbf( currTU, compID ) )
   {
@@ -3184,7 +3189,6 @@ uint64_t IntraSearch::xGetIntraFracBitsQTChroma(TransformUnit& currTU, const Com
 {
   m_CABACEstimator->resetBits();
   // Include Cbf and jointCbCr flags here as we make decisions across components
-  CodingStructure &cs = *currTU.cs;
 
   if ( currTU.jointCbCr )
   {
@@ -3192,8 +3196,10 @@ uint64_t IntraSearch::xGetIntraFracBitsQTChroma(TransformUnit& currTU, const Com
     const bool cbfMaskCr = TU::getCbf(currTU, COMPONENT_Cr);
     const int  cbfMask   = (cbfMaskCb ? CBF_MASK_CB : 0) + (cbfMaskCr ? CBF_MASK_CR : 0);
 
-    m_CABACEstimator->cbf_comp(cs, cbfMaskCb, currTU.blocks[COMPONENT_Cb], currTU.depth, false);
-    m_CABACEstimator->cbf_comp(cs, cbfMaskCr, currTU.blocks[COMPONENT_Cr], currTU.depth, cbfMaskCb);
+    m_CABACEstimator->cbf_comp(cbfMaskCb, currTU.blocks[COMPONENT_Cb], currTU.depth, false, false,
+                               currTU.cu->getBdpcmMode(COMPONENT_Cb));
+    m_CABACEstimator->cbf_comp(cbfMaskCr, currTU.blocks[COMPONENT_Cr], currTU.depth, cbfMaskCb, false,
+                               currTU.cu->getBdpcmMode(COMPONENT_Cr));
 
     if (cbfMask != 0)
     {
@@ -3212,14 +3218,16 @@ uint64_t IntraSearch::xGetIntraFracBitsQTChroma(TransformUnit& currTU, const Com
   {
     if ( compID == COMPONENT_Cb )
     {
-      m_CABACEstimator->cbf_comp( cs, TU::getCbf( currTU, compID ), currTU.blocks[ compID ], currTU.depth, false );
+      m_CABACEstimator->cbf_comp(TU::getCbf(currTU, compID), currTU.blocks[compID], currTU.depth, false, false,
+                                 currTU.cu->getBdpcmMode(compID));
     }
     else
     {
       const bool cbCbf    = TU::getCbf( currTU, COMPONENT_Cb );
       const bool crCbf    = TU::getCbf( currTU, compID );
       const int  cbfMask  = (cbCbf ? CBF_MASK_CB : 0) + (crCbf ? CBF_MASK_CR : 0);
-      m_CABACEstimator->cbf_comp( cs, crCbf, currTU.blocks[ compID ], currTU.depth, cbCbf );
+      m_CABACEstimator->cbf_comp(crCbf, currTU.blocks[compID], currTU.depth, cbCbf, false,
+                                 currTU.cu->getBdpcmMode(compID));
       m_CABACEstimator->joint_cb_cr( currTU, cbfMask );
     }
   }
@@ -3292,7 +3300,7 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
       }
 
       //===== get prediction signal =====
-      if (compID != COMPONENT_Y && !tu.cu->bdpcmModeChroma && PU::isLMCMode(chFinalMode))
+      if (compID != COMPONENT_Y && tu.cu->bdpcmModeChroma == BdpcmMode::NONE && PU::isLMCMode(chFinalMode))
       {
         xGetLumaRecPixels( pu, area );
         predIntraChromaLM(compID, piPred, pu, area, chFinalMode);
@@ -3410,7 +3418,8 @@ 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 (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmMode != 0)
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0)
+        || tu.cu->bdpcmMode != BdpcmMode::NONE)
     {
       m_pcTrQuant->transformNxN(tu, compID, cQP, absSum, m_CABACEstimator->getCtx(), loadTr);
     }
@@ -3424,8 +3433,8 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
       dist = MAX_INT;
       return;
     }
-    if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0)
-        && 0 == tu.cu->bdpcmMode)
+    if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0
+        && BdpcmMode::NONE == tu.cu->bdpcmMode)
     {
       absSum = 0;
       tu.getCoeffs(compID).fill(0);
@@ -3468,11 +3477,13 @@ void IntraSearch::xIntraCodingTUBlock(TransformUnit &tu, const ComponentID &comp
       }
     }
     // encoder bugfix: Set loadTr to aovid redundant transform process
-    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmModeChroma != 0)
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0)
+        || tu.cu->bdpcmModeChroma != BdpcmMode::NONE)
     {
       m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, absSum, m_CABACEstimator->getCtx(), loadTr);
     }
-    if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) && 0 == tu.cu->bdpcmModeChroma)
+    if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0)
+        && BdpcmMode::NONE == tu.cu->bdpcmModeChroma)
     {
       absSum = 0;
       tu.getCoeffs(compID).fill(0);
@@ -3639,11 +3650,13 @@ 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 (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmMode != 0)
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0)
+        || tu.cu->bdpcmMode != BdpcmMode::NONE)
     {
       m_pcTrQuant->transformNxN(tu, compID, cQP, absSum, m_CABACEstimator->getCtx(), loadTr);
     }
-    if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) && tu.cu->bdpcmMode == 0)
+    if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0)
+        && tu.cu->bdpcmMode == BdpcmMode::NONE)
     {
       absSum = 0;
       tu.getCoeffs(compID).fill(0);
@@ -3683,7 +3696,8 @@ void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &c
         tu.mtsIdx[(codeCompId == COMPONENT_Cr) ? COMPONENT_Cb : COMPONENT_Cr] = MTS_DCT2_DCT2;
       }
     }
-    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[codeCompId] == 0) || tu.cu->bdpcmModeChroma != 0)
+    if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[codeCompId] == 0)
+        || tu.cu->bdpcmModeChroma != BdpcmMode::NONE)
     {
       m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, absSum, m_CABACEstimator->getCtx(), loadTr);
     }
@@ -3913,8 +3927,8 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par
       if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
       {
         nNumTransformCands = 1;
-        CHECK(!tsAllowed && !cu.bdpcmMode, "transform skip should be enabled for LS");
-        if (cu.bdpcmMode)
+        CHECK(!tsAllowed && cu.bdpcmMode == BdpcmMode::NONE, "transform skip should be enabled for LS");
+        if (cu.bdpcmMode != BdpcmMode::NONE)
         {
           trModes.push_back(TrMode(0, true));
         }
@@ -4420,8 +4434,8 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
       if (lossless)
       {
         nNumTransformCands = 1;
-        CHECK(!tsAllowed && !cu.bdpcmMode, "transform skip should be enabled for LS");
-        if (cu.bdpcmMode)
+        CHECK(!tsAllowed && cu.bdpcmMode == BdpcmMode::NONE, "transform skip should be enabled for LS");
+        if (cu.bdpcmMode != BdpcmMode::NONE)
         {
           trModes.push_back(TrMode(0, true));
         }
@@ -4718,8 +4732,8 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti
       if (lossless)
       {
         numTransformCands = 1;
-        CHECK(!tsAllowed && !cu.bdpcmModeChroma, "transform skip should be enabled for LS");
-        if (cu.bdpcmModeChroma)
+        CHECK(!tsAllowed && cu.bdpcmModeChroma == BdpcmMode::NONE, "transform skip should be enabled for LS");
+        if (cu.bdpcmModeChroma != BdpcmMode::NONE)
         {
           trModes.push_back(TrMode(0, true));
         }
@@ -5160,7 +5174,8 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
     currTU.jointCbCr = 0;
 
     // Do predictions here to avoid repeating the "default0Save1Load2" stuff
-    int  predMode   = pu.cu->bdpcmModeChroma ? BDPCM_IDX : PU::getFinalIntraMode(pu, CHANNEL_TYPE_CHROMA);
+    int predMode =
+      pu.cu->bdpcmModeChroma != BdpcmMode::NONE ? BDPCM_IDX : PU::getFinalIntraMode(pu, CHANNEL_TYPE_CHROMA);
 
     PelBuf piPredCb = cs.getPredBuf(cbArea);
     PelBuf piPredCr = cs.getPredBuf(crArea);
@@ -5238,8 +5253,8 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
       if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
       {
         nNumTransformCands = 1;
-        CHECK(!tsAllowed && !currTU.cu->bdpcmModeChroma, "transform skip should be enabled for LS");
-        if (currTU.cu->bdpcmModeChroma)
+        CHECK(!tsAllowed && currTU.cu->bdpcmModeChroma == BdpcmMode::NONE, "transform skip should be enabled for LS");
+        if (currTU.cu->bdpcmModeChroma != BdpcmMode::NONE)
         {
           trModes.push_back(TrMode(0, true));
         }
@@ -5276,7 +5291,7 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
       {
         resiCb.copyFrom(orgResiCb[0]);
         resiCr.copyFrom(orgResiCr[0]);
-        currTU.mtsIdx[compID] = currTU.cu->bdpcmModeChroma ? MTS_SKIP : trModes[modeId].first;
+        currTU.mtsIdx[compID] = currTU.cu->bdpcmModeChroma != BdpcmMode::NONE ? MTS_SKIP : trModes[modeId].first;
 
         currModeId++;
 
@@ -5312,7 +5327,7 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
           xIntraCodingTUBlock(currTU, compID, singleDistCTmp, default0Save1Load2);
         }
 
-        if (((currTU.mtsIdx[compID] == MTS_SKIP && !currTU.cu->bdpcmModeChroma)
+        if (((currTU.mtsIdx[compID] == MTS_SKIP && currTU.cu->bdpcmModeChroma == BdpcmMode::NONE)
              && !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.
         {
@@ -5420,7 +5435,7 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
                          (TU::getCbf(tmpTU, COMPONENT_Cr) && tmpTU.mtsIdx[COMPONENT_Cr] == MTS_SKIP && !TU::getCbf(tmpTU, COMPONENT_Cb)) ||
                          (TU::getCbf(tmpTU, COMPONENT_Cb) && tmpTU.mtsIdx[COMPONENT_Cb] == MTS_SKIP && TU::getCbf(tmpTU, COMPONENT_Cr) && tmpTU.mtsIdx[COMPONENT_Cr] == MTS_SKIP);
 
-      if (jointCbfMasksToTest.size() && currTU.cu->bdpcmModeChroma)
+      if (jointCbfMasksToTest.size() && currTU.cu->bdpcmModeChroma != BdpcmMode::NONE)
       {
         CHECK(!checkTSOnly || checkDCTOnly, "bdpcm only allows transform skip");
       }
@@ -5441,7 +5456,7 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
           numTransformCands = 1;
         }
 
-        if (!checkTSOnly || currTU.cu->bdpcmModeChroma)
+        if (!checkTSOnly || currTU.cu->bdpcmModeChroma != BdpcmMode::NONE)
         {
           trModes.push_back(TrMode(0, true)); // DCT2
         }
@@ -5460,7 +5475,7 @@ ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitio
             continue;
           }
           Distortion distTmp = 0;
-          currTU.mtsIdx[codeCompId] = currTU.cu->bdpcmModeChroma ? MTS_SKIP : trModes[modeId].first;
+          currTU.mtsIdx[codeCompId]  = currTU.cu->bdpcmModeChroma != BdpcmMode::NONE ? MTS_SKIP : trModes[modeId].first;
           currTU.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
           m_CABACEstimator->getCtx() = ctxStartTU;
 
@@ -5643,7 +5658,9 @@ uint64_t IntraSearch::xFracModeBitsIntra(PredictionUnit &pu, const uint32_t &mod
   return m_CABACEstimator->getEstFracBits();
 }
 
-void IntraSearch::sortRdModeListFirstColorSpace(ModeInfo mode, double cost, char bdpcmMode, ModeInfo* rdModeList, double* rdCostList, char* bdpcmModeList, int& candNum)
+void IntraSearch::sortRdModeListFirstColorSpace(ModeInfo mode, double cost, const BdpcmMode bdpcmMode,
+                                                ModeInfo *rdModeList, double *rdCostList, BdpcmMode *bdpcmModeList,
+                                                int &candNum)
 {
   if (candNum == 0)
   {
@@ -5700,7 +5717,7 @@ void IntraSearch::invalidateBestRdModeFirstColorSpace()
     for (int j = 0; j < savedRdModeListSize; j++)
     {
       m_savedRdModeFirstColorSpace[i][j] = ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, 0);
-      m_savedBDPCMModeFirstColorSpace[i][j] = 0;
+      m_savedBDPCMModeFirstColorSpace[i][j] = BdpcmMode::NONE;
       m_savedRdCostFirstColorSpace[i][j] = MAX_DOUBLE;
     }
   }
diff --git a/source/Lib/EncoderLib/IntraSearch.h b/source/Lib/EncoderLib/IntraSearch.h
index 69e30c4c90..22d44c07c8 100644
--- a/source/Lib/EncoderLib/IntraSearch.h
+++ b/source/Lib/EncoderLib/IntraSearch.h
@@ -357,11 +357,11 @@ private:
   ModeInfo   m_savedRdModeList[ NUM_LFNST_NUM_PER_SET ][ NUM_LUMA_MODE ];
   int32_t    m_savedNumRdModes[ NUM_LFNST_NUM_PER_SET ];
 
-  ModeInfo m_savedRdModeFirstColorSpace[4 * NUM_LFNST_NUM_PER_SET * 2][FAST_UDI_MAX_RDMODE_NUM];
-  char     m_savedBDPCMModeFirstColorSpace[4 * NUM_LFNST_NUM_PER_SET * 2][FAST_UDI_MAX_RDMODE_NUM];
-  double   m_savedRdCostFirstColorSpace[4 * NUM_LFNST_NUM_PER_SET * 2][FAST_UDI_MAX_RDMODE_NUM];
-  int      m_numSavedRdModeFirstColorSpace[4 * NUM_LFNST_NUM_PER_SET * 2];
-  int      m_savedRdModeIdx;
+  ModeInfo  m_savedRdModeFirstColorSpace[4 * NUM_LFNST_NUM_PER_SET * 2][FAST_UDI_MAX_RDMODE_NUM];
+  BdpcmMode m_savedBDPCMModeFirstColorSpace[4 * NUM_LFNST_NUM_PER_SET * 2][FAST_UDI_MAX_RDMODE_NUM];
+  double    m_savedRdCostFirstColorSpace[4 * NUM_LFNST_NUM_PER_SET * 2][FAST_UDI_MAX_RDMODE_NUM];
+  int       m_numSavedRdModeFirstColorSpace[4 * NUM_LFNST_NUM_PER_SET * 2];
+  int       m_savedRdModeIdx;
 
   static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> m_savedRdModeListLFNST;
   static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> m_savedHadModeListLFNST;
@@ -430,7 +430,8 @@ public:
   uint64_t xFracModeBitsIntra(PredictionUnit &pu, const uint32_t &mode, const ChannelType &compID);
   void invalidateBestModeCost     () { for( int i = 0; i < NUM_LFNST_NUM_PER_SET; i++ ) m_bestModeCostValid[ i ] = false; };
 
-  void sortRdModeListFirstColorSpace(ModeInfo mode, double cost, char bdpcmMode, ModeInfo* rdModeList, double* rdCostList, char* bdpcmModeList, int& candNum);
+  void sortRdModeListFirstColorSpace(ModeInfo mode, double cost, BdpcmMode bdpcmMode, ModeInfo *rdModeList,
+                                     double *rdCostList, BdpcmMode *bdpcmModeList, int &candNum);
   void invalidateBestRdModeFirstColorSpace();
   void setSavedRdModeIdx(int idx) { m_savedRdModeIdx = idx; }
 
-- 
GitLab