diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp
index a4eda30ba38cad7da373264a93c357443283e20c..f74325519568fac1dd6a86067d8a8fcda95ed705 100644
--- a/source/App/EncoderApp/EncApp.cpp
+++ b/source/App/EncoderApp/EncApp.cpp
@@ -300,6 +300,9 @@ void EncApp::xInitLibCfg()
   m_cEncLib.setQuadtreeTULog2MinSize                             ( m_quadtreeTULog2MinSize );
   m_cEncLib.setQuadtreeTUMaxDepthInter                           ( m_uiQuadtreeTUMaxDepthInter );
   m_cEncLib.setQuadtreeTUMaxDepthIntra                           ( m_uiQuadtreeTUMaxDepthIntra );
+#if JVET_M0428_ENC_DB_OPT
+  m_cEncLib.setUseEncDbOpt(m_encDbOpt);
+#endif
   m_cEncLib.setUseFastLCTU                                       ( m_useFastLCTU );
   m_cEncLib.setFastInterSearchMode                               ( m_fastInterSearchMode );
   m_cEncLib.setUseEarlyCU                                        ( m_bUseEarlyCU  );
diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp
index 5ca2c6bdfd3146186163a90f81799e5064041e6a..2fc1897c73e6fde982a536c40cf9c5b68346e92d 100644
--- a/source/App/EncoderApp/EncAppCfg.cpp
+++ b/source/App/EncoderApp/EncAppCfg.cpp
@@ -898,6 +898,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] )
   ("WrapAroundOffset",                                m_wrapAroundOffset,                                  0u, "Offset in luma samples used for computing the horizontal wrap-around position")
 
   // ADD_NEW_TOOL : (encoder app) add parsing parameters here
+#if JVET_M0428_ENC_DB_OPT
+  ("EncDbOpt",                                        m_encDbOpt,                                       false, "Encoder optimization with deblocking filter")
+#endif
 #if JVET_M0427_INLOOP_RESHAPER
   ("LumaReshapeEnable",                               m_lumaReshapeEnable,                              false, "Enable Reshaping for Luma Channel")
   ("ReshapeSignalType",                               m_reshapeSignalType,                                 0u, "Input signal type: 0: SDR, 1:PQ, 2:HLG")
@@ -3246,6 +3249,9 @@ void EncAppCfg::xPrintParameter()
       msg(VERBOSE, "(Sigal:%s ", m_reshapeSignalType==0? "SDR" : "HDR-PQ");
       msg(VERBOSE, ") ");
     }
+#endif
+#if JVET_M0428_ENC_DB_OPT
+    msg(VERBOSE, "EncDbOpt:%d ", m_encDbOpt);
 #endif
   msg( VERBOSE, "\nFAST TOOL CFG: " );
   if( m_LargeCTU )
diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h
index 5b080d5df6390c0df4fc92699d2ae4df8c22ce81..2a2d062a0b624f8065df632f88779fc22acad2ed 100644
--- a/source/App/EncoderApp/EncAppCfg.h
+++ b/source/App/EncoderApp/EncAppCfg.h
@@ -276,6 +276,9 @@ protected:
   uint32_t  m_reshapeSignalType;
   uint32_t  m_intraCMD;
   ReshapeCW m_reshapeCW;
+#endif
+#if JVET_M0428_ENC_DB_OPT
+  bool      m_encDbOpt;
 #endif
   unsigned  m_uiMaxCUWidth;                                   ///< max. CU width in pixel
   unsigned  m_uiMaxCUHeight;                                  ///< max. CU height in pixel
diff --git a/source/Lib/CommonLib/CodingStructure.cpp b/source/Lib/CommonLib/CodingStructure.cpp
index f52f4205834c8bfafe0841b22e45451cb4462b16..bf711f3ba8f175a93ca30d842a85771171ed226a 100644
--- a/source/Lib/CommonLib/CodingStructure.cpp
+++ b/source/Lib/CommonLib/CodingStructure.cpp
@@ -751,6 +751,11 @@ void CodingStructure::initSubStructure( CodingStructure& subStruct, const Channe
 {
   CHECK( this == &subStruct, "Trying to init self as sub-structure" );
 
+#if JVET_M0428_ENC_DB_OPT
+  subStruct.useDbCost = false;
+  subStruct.costDbOffset = 0;
+#endif
+
   for( uint32_t i = 0; i < subStruct.area.blocks.size(); i++ )
   {
     CHECKD( subStruct.area.blocks[i].size() != subArea.blocks[i].size(), "Trying to init sub-structure of incompatible size" );
@@ -852,7 +857,9 @@ void CodingStructure::useSubStructure( const CodingStructure& subStruct, const C
       fracBits += subStruct.fracBits;
       dist     += subStruct.dist;
       cost     += subStruct.cost;
-
+#if JVET_M0428_ENC_DB_OPT
+      costDbOffset += subStruct.costDbOffset;
+#endif
       if( parent )
       {
         // allow this to be false at the top level
@@ -916,7 +923,9 @@ void CodingStructure::useSubStructure( const CodingStructure& subStruct, const C
   fracBits += subStruct.fracBits;
   dist     += subStruct.dist;
   cost     += subStruct.cost;
-
+#if JVET_M0428_ENC_DB_OPT
+  costDbOffset += subStruct.costDbOffset;
+#endif
   if( parent )
   {
     // allow this to be false at the top level
@@ -978,7 +987,9 @@ void CodingStructure::copyStructure( const CodingStructure& other, const Channel
   fracBits = other.fracBits;
   dist     = other.dist;
   cost     = other.cost;
-
+#if JVET_M0428_ENC_DB_OPT
+  costDbOffset = other.costDbOffset;
+#endif
   CHECKD( area != other.area, "Incompatible sizes" );
 
   const UnitArea dualITreeArea = CS::getArea( *this, this->area, chType );
@@ -1110,6 +1121,10 @@ void CodingStructure::initStructData( const int &QP, const bool &_isLosses, cons
   cost     = MAX_DOUBLE;
 #if JVET_M0102_INTRA_SUBPARTITIONS
   lumaCost = MAX_DOUBLE;
+#endif
+#if JVET_M0428_ENC_DB_OPT
+  costDbOffset = 0;
+  useDbCost = false;
 #endif
   interHad = std::numeric_limits<Distortion>::max();
 }
diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h
index f28500a798c9a02ea29c2f58e19501540d80f94a..67ca6d94738a476430f8d78f28e61bfc22a143ce 100644
--- a/source/Lib/CommonLib/CodingStructure.h
+++ b/source/Lib/CommonLib/CodingStructure.h
@@ -179,6 +179,10 @@ public:
   static_vector<double, NUM_ENC_FEATURES> features;
 
   double      cost;
+#if JVET_M0428_ENC_DB_OPT
+  bool        useDbCost;
+  double      costDbOffset;
+#endif
 #if JVET_M0102_INTRA_SUBPARTITIONS
   double      lumaCost;
 #endif
diff --git a/source/Lib/CommonLib/LoopFilter.cpp b/source/Lib/CommonLib/LoopFilter.cpp
index 4a484f6c43082285884d61a766d2fb6934efafa2..30da1494256aebfb0381a135acc22c3eae71cda2 100644
--- a/source/Lib/CommonLib/LoopFilter.cpp
+++ b/source/Lib/CommonLib/LoopFilter.cpp
@@ -126,7 +126,19 @@ void LoopFilter::create( const unsigned uiMaxCUDepth )
     m_aapucBS       [edgeDir].resize( numPartitions );
     m_aapbEdgeFilter[edgeDir].resize( numPartitions );
   }
+#if JVET_M0428_ENC_DB_OPT
+  m_bEnc = false;
+#endif
+}
+
+#if JVET_M0428_ENC_DB_OPT
+void LoopFilter::initEncPicYuvBuffer(ChromaFormat chromaFormat, int lumaWidth, int lumaHeight)
+{
+  const UnitArea picArea(chromaFormat, Area(0, 0, lumaWidth, lumaHeight));
+  m_encPicYuvBuffer.destroy();
+  m_encPicYuvBuffer.create(picArea);
 }
+#endif
 
 void LoopFilter::destroy()
 {
@@ -135,6 +147,9 @@ void LoopFilter::destroy()
     m_aapucBS       [edgeDir].clear();
     m_aapbEdgeFilter[edgeDir].clear();
   }
+#if JVET_M0428_ENC_DB_OPT
+  m_encPicYuvBuffer.destroy();
+#endif
 }
 
 /**
@@ -731,7 +746,11 @@ void LoopFilter::xEdgeFilterLuma(const CodingUnit& cu, const DeblockEdgeDir edge
   const CompArea&  lumaArea = cu.block(COMPONENT_Y);
   const PreCalcValues& pcv = *cu.cs->pcv;
 
+#if JVET_M0428_ENC_DB_OPT
+  PelBuf        picYuvRec = m_bEnc ? m_encPicYuvBuffer.getBuf(lumaArea) : cu.cs->getRecoBuf(lumaArea);
+#else
   PelBuf        picYuvRec = cu.cs->getRecoBuf( lumaArea );
+#endif
   Pel           *piSrc    = picYuvRec.buf;
   const int     iStride   = picYuvRec.stride;
   Pel           *piTmpSrc = piSrc;
@@ -1003,9 +1022,13 @@ void LoopFilter::xEdgeFilterChroma(const CodingUnit& cu, const DeblockEdgeDir ed
 
   const PreCalcValues& pcv = *cu.cs->pcv;
   unsigned  rasterIdx      = getRasterIdx( lumaPos, pcv );
-
+#if JVET_M0428_ENC_DB_OPT
+  PelBuf     picYuvRecCb = m_bEnc ? m_encPicYuvBuffer.getBuf(cu.block(COMPONENT_Cb)) : cu.cs->getRecoBuf(cu.block(COMPONENT_Cb));
+  PelBuf     picYuvRecCr = m_bEnc ? m_encPicYuvBuffer.getBuf(cu.block(COMPONENT_Cr)) : cu.cs->getRecoBuf(cu.block(COMPONENT_Cr));
+#else
   PelBuf     picYuvRecCb   = cu.cs->getRecoBuf( cu.block(COMPONENT_Cb) );
   PelBuf     picYuvRecCr   = cu.cs->getRecoBuf( cu.block(COMPONENT_Cr) );
+#endif
   Pel       *piSrcCb       = picYuvRecCb.buf;
   Pel       *piSrcCr       = picYuvRecCr.buf;
   const int  iStride       = picYuvRecCb.stride;
diff --git a/source/Lib/CommonLib/LoopFilter.h b/source/Lib/CommonLib/LoopFilter.h
index 5f2b0bafb0a13b0e004bed96061e9e07790e7529..fae4ef19338d87ce0b0defdec9fc22d82ac63211 100644
--- a/source/Lib/CommonLib/LoopFilter.h
+++ b/source/Lib/CommonLib/LoopFilter.h
@@ -58,11 +58,16 @@ private:
   static_vector<char, MAX_NUM_PARTS_IN_CTU> m_aapucBS       [NUM_EDGE_DIR];         ///< Bs for [Ver/Hor][Y/U/V][Blk_Idx]
   static_vector<bool, MAX_NUM_PARTS_IN_CTU> m_aapbEdgeFilter[NUM_EDGE_DIR];
   LFCUParam m_stLFCUParam;                   ///< status structure
-
+#if JVET_M0428_ENC_DB_OPT
+  PelStorage                   m_encPicYuvBuffer;
+  bool                         m_bEnc;
+#endif
 private:
+#if !JVET_M0428_ENC_DB_OPT
   /// CU-level deblocking function
   void xDeblockCU                 (       CodingUnit& cu, const DeblockEdgeDir edgeDir );
-
+#endif
+  
   // set / get functions
   void xSetLoopfilterParam        ( const CodingUnit& cu );
 
@@ -111,6 +116,14 @@ public:
   LoopFilter();
   ~LoopFilter();
 
+#if JVET_M0428_ENC_DB_OPT
+  /// CU-level deblocking function
+  void xDeblockCU(CodingUnit& cu, const DeblockEdgeDir edgeDir);
+  void  initEncPicYuvBuffer(ChromaFormat chromaFormat, int lumaWidth, int lumaHeight);
+  PelStorage& getDbEncPicYuvBuffer() { return m_encPicYuvBuffer; }
+  void  setEnc(bool b) { m_bEnc = b; }
+#endif
+
   void  create                    ( const unsigned uiMaxCUDepth );
   void  destroy                   ();
 
diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h
index e4da03d020ab9c122d14b1436d5ad2ab9c07a561..e40eb2f3851fe5e0a391b1120ea9d0fb8100452d 100644
--- a/source/Lib/CommonLib/TypeDef.h
+++ b/source/Lib/CommonLib/TypeDef.h
@@ -50,6 +50,8 @@
 #include <assert.h>
 #include <cassert>
 
+#define JVET_M0428_ENC_DB_OPT                             1 // Encoder optimization with deblocking filter
+
 #define JVET_M0055_DEBUG_CTU                              1 // DebugCTU encoder debug option
 
 #define JVET_M0297_32PT_MTS_ZERO_OUT                      1 // 32 point MTS based on skipping high frequency coefficients
diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h
index 07e78283c1954f8eaa915671b770c5d956286904..ba4741c101186c89be969c260f7d4a2a720068eb 100644
--- a/source/Lib/EncoderLib/EncCfg.h
+++ b/source/Lib/EncoderLib/EncCfg.h
@@ -276,6 +276,9 @@ protected:
   unsigned  m_reshapeSignalType;
   unsigned  m_intraCMD;
   ReshapeCW m_reshapeCW;
+#endif
+#if JVET_M0428_ENC_DB_OPT
+  bool      m_encDbOpt;
 #endif
   bool      m_useFastLCTU;
   bool      m_useFastMrg;
@@ -847,6 +850,10 @@ public:
   void      setMaxCodingDepth               ( uint32_t  u )      { m_maxTotalCUDepth = u; }
   uint32_t      getMaxCodingDepth               () const         { return m_maxTotalCUDepth; }
   void      setLog2DiffMaxMinCodingBlockSize( uint32_t  u )      { m_log2DiffMaxMinCodingBlockSize = u; }
+#if JVET_M0428_ENC_DB_OPT
+  void      setUseEncDbOpt                  ( bool  n )          { m_encDbOpt = n; }
+  bool      getUseEncDbOpt                  () const             { return m_encDbOpt; }
+#endif
 
   void      setUseFastLCTU                  ( bool  n )      { m_useFastLCTU = n; }
   bool      getUseFastLCTU                  () const         { return m_useFastLCTU; }
diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp
index 93cb6a1d1fe13bf72154be0d5ca11b8bef309416..c20ae0983c0da14369f78f2edef0710e21158e43 100644
--- a/source/Lib/EncoderLib/EncCu.cpp
+++ b/source/Lib/EncoderLib/EncCu.cpp
@@ -320,6 +320,9 @@ void EncCu::init( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int tId ) )
   m_pcEncLib           = pcEncLib;
   m_dataId             = tId;
 #endif
+#if JVET_M0428_ENC_DB_OPT
+  m_pcLoopFilter       = pcEncLib->getLoopFilter();
+#endif
 #if JVET_M0170_MRG_SHARELIST
   m_shareState = NO_SHARE;
   m_pcInterSearch->setShareState(0);
@@ -655,6 +658,9 @@ bool EncCu::xCheckBestMode( CodingStructure *&tempCS, CodingStructure *&bestCS,
       std::swap( tempCS, bestCS );
       // store temp best CI for next CU coding
       m_CurrCtx->best = m_CABACEstimator->getCtx();
+#if JVET_M0428_ENC_DB_OPT
+      m_bestModeUpdated = true;
+#endif
       bestCSUpdated = true;
     }
   }
@@ -1227,7 +1233,14 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
 #endif
 
   const double factor = ( tempCS->currQP[partitioner.chType] > 30 ? 1.1 : 1.075 );
+#if JVET_M0428_ENC_DB_OPT
+  tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
+  if (!tempCS->useDbCost)
+    CHECK(bestCS->costDbOffset != 0, "error");
+  const double cost   = m_pcRdCost->calcRdCost( uint64_t( m_CABACEstimator->getEstFracBits() + ( ( bestCS->fracBits ) / factor ) ), Distortion( bestCS->dist / factor ) ) + bestCS->costDbOffset / factor;
+#else
   const double cost   = m_pcRdCost->calcRdCost( uint64_t( m_CABACEstimator->getEstFracBits() + ( ( bestCS->fracBits ) / factor ) ), Distortion( bestCS->dist / factor ) );
+#endif
 
   m_CABACEstimator->getCtx() = SubCtx( Ctx::SplitFlag,   ctxStartSP );
 #if JVET_M0421_SPLIT_SIG
@@ -1238,7 +1251,11 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
   m_CABACEstimator->getCtx() = SubCtx( Ctx::BTSplitFlag, ctxStartBT );
 #endif
 
+#if JVET_M0428_ENC_DB_OPT
+  if (cost > bestCS->cost + bestCS->costDbOffset)
+#else
   if( cost > bestCS->cost )
+#endif
   {
     xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
     return;
@@ -1346,6 +1363,10 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
       {
         CHECK( split == CU_QUAD_SPLIT, "Split decision reusing cannot skip quad split" );
         tempCS->cost = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+        tempCS->costDbOffset = 0;
+        tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
+#endif
         m_CurrCtx--;
         partitioner.exitCurrSplit();
         bool bestCSUpdated =
@@ -1474,9 +1495,18 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS,
 #endif
     {
       bestCS->cost = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+      bestCS->costDbOffset = 0;
+#endif
     }
   }
-
+#if JVET_M0428_ENC_DB_OPT
+  else
+  {
+    bestCS->costDbOffset = 0;
+  }
+  tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
+#endif
 
   // RD check for sub partitioned coding structure.
   bool bestCSUpdated =
@@ -1576,6 +1606,10 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
 
     tempCS->interHad    = interHad;
 
+#if JVET_M0428_ENC_DB_OPT
+    m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
+
     if( isLuma( partitioner.chType ) )
     {
 #if JVET_M0102_INTRA_SUBPARTITIONS
@@ -1696,6 +1730,12 @@ void EncCu::xCheckRDCostIntra( CodingStructure *&tempCS, CodingStructure *&bestC
       m_modeCtrl->setBestCostWithoutSplitFlags( tmpCostWithoutSplitFlags );
     }
 #endif
+
+#if JVET_M0428_ENC_DB_OPT
+    xCalDebCost(*tempCS, partitioner);
+    tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
+#endif
+
 #if !JVET_M0464_UNI_MTS
     // we save the cost of the modes for the first EMT pass
     if( !emtCuFlag ) static_cast< double& >( costSize2Nx2NemtFirstPass ) = tempCS->cost;
@@ -1795,6 +1835,11 @@ void EncCu::xCheckIntraPCM(CodingStructure *&tempCS, CodingStructure *&bestCS, P
 
   xCheckDQP( *tempCS, partitioner );
 
+#if JVET_M0428_ENC_DB_OPT
+  xCalDebCost(*tempCS, partitioner);
+  tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
+#endif
+
 #if WCG_EXT
   DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
 #else
@@ -1927,6 +1972,10 @@ void EncCu::xCheckRDCostHashInter( CodingStructure *&tempCS, CodingStructure *&b
     const unsigned wIdx = gp_sizeIdxInfo->idxFrom(tempCS->area.lwidth());
     double equGBiCost = MAX_DOUBLE;
 
+#if JVET_M0428_ENC_DB_OPT
+    m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
+
 #if JVET_M0464_UNI_MTS
     xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode, 0
       , m_pImvTempCS ? m_pImvTempCS[wIdx] : NULL
@@ -1940,6 +1989,11 @@ void EncCu::xCheckRDCostHashInter( CodingStructure *&tempCS, CodingStructure *&b
       , &equGBiCost
 #endif
     );
+
+#if JVET_M0428_ENC_DB_OPT
+    if (m_bestModeUpdated && bestCS->cost != MAX_DOUBLE)
+      xCalDebCost(*bestCS, partitioner);
+#endif
   }
   tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
 
@@ -2447,7 +2501,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       }
     }
   }
-
+#if JVET_M0428_ENC_DB_OPT
+  m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
 #if !JVET_M0253_HASH_ME
   const uint32_t iteration = encTestMode.lossless ? 1 : 2;
 
@@ -2658,6 +2714,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&
       }
     }
   }
+#if JVET_M0428_ENC_DB_OPT
+  if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
+    xCalDebCost( *bestCS, partitioner );
+#endif
 }
 
 void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
@@ -2857,7 +2917,9 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
 
     tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
   }
-
+#if JVET_M0428_ENC_DB_OPT
+  m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
   {
 #if !JVET_M0253_HASH_ME
     const uint8_t iteration = encTestMode.lossless ? 1 : 2;
@@ -2959,6 +3021,10 @@ void EncCu::xCheckRDCostMergeTriangle2Nx2N( CodingStructure *&tempCS, CodingStru
       }// end loop mrgHADIdx
     }
   }
+#if JVET_M0428_ENC_DB_OPT
+  if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
+    xCalDebCost( *bestCS, partitioner );
+#endif
 }
 
 void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
@@ -2972,7 +3038,9 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
   {
     return;
   }
-
+#if JVET_M0428_ENC_DB_OPT
+  m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
   const Slice &slice = *tempCS->slice;
 
   CHECK( slice.getSliceType() == I_SLICE, "Affine Merge modes not available for I-slices" );
@@ -3255,6 +3323,10 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct
       }
     }
   }
+#if JVET_M0428_ENC_DB_OPT
+  if (m_bestModeUpdated && bestCS->cost != MAX_DOUBLE)
+    xCalDebCost(*bestCS, partitioner);
+#endif
 }
 //////////////////////////////////////////////////////////////////////////////////////////////
 // ibc merge/skip mode check
@@ -3439,6 +3511,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
         tempCS->dist = 0;
         tempCS->fracBits = 0;
         tempCS->cost = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+        tempCS->costDbOffset = 0;
+#endif
         tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
         return;
       }
@@ -3449,7 +3524,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
 
 
   const unsigned int iteration = encTestMode.lossless ? 1 : 2;
-
+#if JVET_M0428_ENC_DB_OPT
+  m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
   // 2. Pass: check candidates using full RD test
   for (unsigned int numResidualPass = 0; numResidualPass < iteration; numResidualPass++)
   {
@@ -3566,7 +3643,10 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct
       }
     }
   }
-
+#if JVET_M0428_ENC_DB_OPT
+  if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
+    xCalDebCost( *bestCS, partitioner );
+#endif
 }
 
 void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode)
@@ -3578,6 +3658,10 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
 
     tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
 
+#if JVET_M0428_ENC_DB_OPT
+    m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
+
     CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType), partitioner.chType);
 
     partitioner.setCUData(cu);
@@ -3604,6 +3688,10 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
 
     CU::addPUs(cu);
 
+#if JVET_M0428_ENC_DB_OPT
+    m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
+
     PredictionUnit& pu = *cu.firstPU;
     cu.mmvdSkip = false;
     pu.mmvdMergeFlag = false;
@@ -3664,6 +3752,12 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
             xCheckDQP(*tempCS, partitioner);
           }
 
+#if JVET_M0428_ENC_DB_OPT
+          tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
+          if ( m_bestModeUpdated )
+            xCalDebCost( *tempCS, partitioner );
+#endif
+
           DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
           xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
 
@@ -3694,6 +3788,9 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
               tempCS->dist = 0;
               tempCS->fracBits = 0;
               tempCS->cost = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+              tempCS->costDbOffset = 0;
+#endif
             }
           }
 #endif
@@ -3705,6 +3802,9 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
         tempCS->dist = 0;
         tempCS->fracBits = 0;
         tempCS->cost = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+        tempCS->costDbOffset = 0;
+#endif
       }
     }
  // chroma CU ibc comp
@@ -3755,6 +3855,11 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
         xEncodeDontSplit(*tempCS, partitioner);
 
         xCheckDQP(*tempCS, partitioner);
+#if JVET_M0428_ENC_DB_OPT
+        tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
+        if (m_bestModeUpdated)
+          xCalDebCost(*tempCS, partitioner);
+#endif
 
         DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
 
@@ -3765,6 +3870,9 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best
         tempCS->dist = 0;
         tempCS->fracBits = 0;
         tempCS->cost = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+        tempCS->costDbOffset = 0;
+#endif
       }
     }
   }
@@ -3796,6 +3904,10 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
   double curBestCost = bestCS->cost;
   double equGBiCost = MAX_DOUBLE;
 
+#if JVET_M0428_ENC_DB_OPT
+  m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
+
   for( int gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
   {
     if( m_pcEncCfg->getUseGBiFast() )
@@ -3900,6 +4012,10 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC
     break;
   }
  }  // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
+#if JVET_M0428_ENC_DB_OPT
+ if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
+   xCalDebCost( *bestCS, partitioner );
+#endif
 }
 
 
@@ -3914,6 +4030,10 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
   CHECK( iIMV != 1 && iIMV != 2 && iIMV != 3, "Unsupported IMV Mode" );
   // Fast 4-Pel Mode
 
+#if JVET_M0428_ENC_DB_OPT
+  m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
+#endif
+
   EncTestMode encTestModeBase = encTestMode;                                        // copy for clearing non-IMV options
   encTestModeBase.opts        = EncTestModeOpts( encTestModeBase.opts & ETO_IMV );  // clear non-IMV options (is that intended?)
 
@@ -4157,6 +4277,11 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
 #endif
  } // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
 
+#if JVET_M0428_ENC_DB_OPT
+ if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
+   xCalDebCost( *bestCS, partitioner );
+#endif
+
 #if JVET_M0246_AFFINE_AMVR
   return tempCS->slice->getSPS()->getAffineAmvrEnabledFlag() ? validMode : true;
 #else
@@ -4164,6 +4289,230 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be
 #endif
 }
 
+#if JVET_M0428_ENC_DB_OPT
+void EncCu::xCalDebCost(CodingStructure &cs, Partitioner &partitioner, bool calDist)
+{
+  if (cs.cost == MAX_DOUBLE)
+    cs.costDbOffset = 0;
+
+  if (cs.slice->getDeblockingFilterDisable() || (!m_pcEncCfg->getUseEncDbOpt() && !calDist))
+    return;
+
+  m_pcLoopFilter->setEnc(true);
+  const ChromaFormat format = cs.area.chromaFormat;
+  CodingUnit*                cu = cs.getCU(partitioner.chType);
+  const Position lumaPos = cu->Y().valid() ? cu->Y().pos() : recalcPosition(format, cu->chType, CHANNEL_TYPE_LUMA, cu->blocks[cu->chType].pos());
+  bool topEdgeAvai  = lumaPos.y > 0 && ((lumaPos.y % 8) == 0);
+  bool leftEdgeAvai = lumaPos.x > 0 && ((lumaPos.x % 8) == 0);
+  bool anyEdgeAvai = topEdgeAvai || leftEdgeAvai;
+  cs.costDbOffset = 0;
+
+  if (calDist)
+  {
+    const UnitArea currCsArea = clipArea(CS::getArea(cs, cs.area, partitioner.chType), *cs.picture);
+    ComponentID compStr = (CS::isDualITree(cs) && !isLuma(partitioner.chType)) ? COMPONENT_Cb : COMPONENT_Y;
+    ComponentID compEnd = (CS::isDualITree(cs) && isLuma(partitioner.chType)) ? COMPONENT_Y : COMPONENT_Cr;
+    Distortion finalDistortion = 0;
+    for (int comp = compStr; comp <= compEnd; comp++)
+    {
+      const ComponentID compID = ComponentID(comp);
+      CPelBuf org = cs.getOrgBuf(compID);
+      CPelBuf reco = cs.getRecoBuf(compID);
+      finalDistortion += getDistortionDb(cs, org, reco, compID, currCsArea.block(compID), false);
+    }
+    //updated distortion
+    cs.dist = finalDistortion;
+  }
+
+  if (anyEdgeAvai && m_pcEncCfg->getUseEncDbOpt())
+  {
+    ComponentID compStr = (CS::isDualITree(cs) && !isLuma(partitioner.chType)) ? COMPONENT_Cb : COMPONENT_Y;
+    ComponentID compEnd = (CS::isDualITree(cs) && isLuma(partitioner.chType)) ? COMPONENT_Y : COMPONENT_Cr;
+
+    const UnitArea currCsArea = clipArea(CS::getArea(cs, cs.area, partitioner.chType), *cs.picture);
+
+    PelStorage&          picDbBuf = m_pcLoopFilter->getDbEncPicYuvBuffer();
+
+    //deblock neighbour pixels
+    const Size     lumaSize = cu->Y().valid() ? cu->Y().size() : recalcSize(format, cu->chType, CHANNEL_TYPE_LUMA, cu->blocks[cu->chType].size());
+
+#if  JVET_M0471_LONG_DEBLOCKING_FILTERS
+    const int verOffset = lumaPos.y > 7 ? 8 : 4;
+    const int horOffset = lumaPos.x > 7 ? 8 : 4;
+#else
+    const int verOffset = 4;
+    const int horOffset = 4;
+#endif
+    const UnitArea areaTop(format, Area(lumaPos.x, lumaPos.y - verOffset, lumaSize.width, verOffset));
+    const UnitArea areaLeft(format, Area(lumaPos.x - horOffset, lumaPos.y, horOffset, lumaSize.height));
+    for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
+    {
+      ComponentID compId = (ComponentID)compIdx;
+
+      //Copy current CU's reco to Deblock Pic Buffer
+      const CompArea&  curCompArea = currCsArea.block(compId);
+      picDbBuf.getBuf(curCompArea).copyFrom(cs.getRecoBuf(curCompArea));
+#if JVET_M0427_INLOOP_RESHAPER
+      if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId))
+      {
+        picDbBuf.getBuf(curCompArea).rspSignal(m_pcReshape->getInvLUT());
+      }
+#endif
+
+      //left neighbour
+      if (leftEdgeAvai)
+      {
+        const CompArea&  compArea = areaLeft.block(compId);
+        picDbBuf.getBuf(compArea).copyFrom(cs.picture->getRecoBuf(compArea));
+#if JVET_M0427_INLOOP_RESHAPER       
+        if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId))
+        {
+          picDbBuf.getBuf(compArea).rspSignal(m_pcReshape->getInvLUT());
+        }
+#endif
+      }
+      //top neighbour
+      if (topEdgeAvai)
+      {
+        const CompArea&  compArea = areaTop.block(compId);
+        picDbBuf.getBuf(compArea).copyFrom(cs.picture->getRecoBuf(compArea));
+#if JVET_M0427_INLOOP_RESHAPER
+        if (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && isLuma(compId))
+        {
+          picDbBuf.getBuf(compArea).rspSignal(m_pcReshape->getInvLUT());
+        }
+#endif
+      }
+    }
+
+    //deblock
+    if (leftEdgeAvai)
+    {
+      m_pcLoopFilter->xDeblockCU(*cu, EDGE_VER);
+    }
+
+    if (topEdgeAvai)
+    {
+      m_pcLoopFilter->xDeblockCU(*cu, EDGE_HOR);
+    }
+
+    //update current CU SSE
+    Distortion distCur = 0;
+    for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
+    {
+      ComponentID compId = (ComponentID)compIdx;
+      CPelBuf reco = picDbBuf.getBuf(currCsArea.block(compId));
+      CPelBuf org = cs.getOrgBuf(compId);
+      distCur += getDistortionDb(cs, org, reco, compId, currCsArea.block(compId), true);
+    }
+
+    //calculate difference between DB_before_SSE and DB_after_SSE for neighbouring CUs
+    Distortion distBeforeDb = 0, distAfterDb = 0;
+    for (int compIdx = compStr; compIdx <= compEnd; compIdx++)
+    {
+      ComponentID compId = (ComponentID)compIdx;
+      if (leftEdgeAvai)
+      {
+        const CompArea&  compArea = areaLeft.block(compId);
+        CPelBuf org = cs.picture->getOrigBuf(compArea);
+        CPelBuf reco = cs.picture->getRecoBuf(compArea);
+        CPelBuf recoDb = picDbBuf.getBuf(compArea);
+        distBeforeDb += getDistortionDb(cs, org, reco,   compId, compArea, false);
+        distAfterDb  += getDistortionDb(cs, org, recoDb, compId, compArea, true);
+      }
+      if (topEdgeAvai)
+      {
+        const CompArea&  compArea = areaTop.block(compId);
+        CPelBuf org = cs.picture->getOrigBuf(compArea);
+        CPelBuf reco = cs.picture->getRecoBuf(compArea);
+        CPelBuf recoDb = picDbBuf.getBuf(compArea);
+        distBeforeDb += getDistortionDb(cs, org, reco,   compId, compArea, false);
+        distAfterDb  += getDistortionDb(cs, org, recoDb, compId, compArea, true);
+      }
+    }
+
+    //updated cost
+    int64_t distTmp = distCur - cs.dist + distAfterDb - distBeforeDb;
+    int sign = distTmp < 0 ? -1 : 1;
+    distTmp = distTmp < 0 ? -distTmp : distTmp;
+    cs.costDbOffset = sign * m_pcRdCost->calcRdCost(0, distTmp);
+  }
+  /*
+  else if (calDist)
+  {
+    const UnitArea currCsArea = clipArea(CS::getArea(cs, cs.area, partitioner.chType), *cs.picture);
+    ComponentID compStr = (CS::isDualITree(cs) && !isLuma(partitioner.chType)) ? COMPONENT_Cb : COMPONENT_Y;
+    ComponentID compEnd = (CS::isDualITree(cs) && isLuma(partitioner.chType)) ? COMPONENT_Y : COMPONENT_Cr;
+    Distortion finalDistortion = 0;
+    for (int comp = compStr; comp <= compEnd; comp++)
+    {
+      const ComponentID compID = ComponentID(comp);
+      CPelBuf org = cs.getOrgBuf(compID);
+      CPelBuf reco = cs.getRecoBuf(compID);
+      finalDistortion += getDistortionDb(cs, org, reco, compID, currCsArea.block(compID), false);
+    }
+    //updated cost
+    cs.dist = finalDistortion;
+    cs.cost = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
+    cs.costDbOffset = 0;
+  }
+  */
+  m_pcLoopFilter->setEnc(false);
+}
+
+Distortion EncCu::getDistortionDb(CodingStructure &cs, CPelBuf org, CPelBuf reco, ComponentID compID, const CompArea& compArea, bool afterDb)
+{
+  Distortion dist = 0;
+#if WCG_EXT
+  CPelBuf orgLuma = cs.picture->getOrigBuf(compArea);
+#if JVET_M0427_INLOOP_RESHAPER
+  if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (
+    m_pcEncCfg->getReshaper() && (cs.slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())))
+#else
+  if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled())
+#endif
+  {
+#if JVET_M0427_INLOOP_RESHAPER
+    if (compID == COMPONENT_Y && !afterDb)
+    {
+      CompArea    tmpArea(COMPONENT_Y, cs.area.chromaFormat, Position(0, 0), compArea.size());
+      PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf(tmpArea);
+      tmpRecLuma.copyFrom(reco);
+      tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
+      dist += m_pcRdCost->getDistPart(org, tmpRecLuma, cs.sps->getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+    }
+    else
+#endif
+    {
+      dist += m_pcRdCost->getDistPart(org, reco, cs.sps->getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
+    }
+  }
+#if JVET_M0427_INLOOP_RESHAPER
+  else if (m_pcEncCfg->getReshaper() && cs.slice->getReshapeInfo().getUseSliceReshaper() && cs.slice->isIntra()) //intra slice
+  {
+    if (compID == COMPONENT_Y && afterDb)
+    {
+      CompArea    tmpArea(COMPONENT_Y, cs.area.chromaFormat, Position(0, 0), compArea.size());
+      PelBuf tmpRecLuma = m_tmpStorageLCU->getBuf(tmpArea);
+      tmpRecLuma.copyFrom(reco);
+      tmpRecLuma.rspSignal(m_pcReshape->getFwdLUT());
+      dist += m_pcRdCost->getDistPart(org, tmpRecLuma, cs.sps->getBitDepth(toChannelType(compID)), compID, DF_SSE);
+    }
+    else
+    {
+      dist += m_pcRdCost->getDistPart(org, reco, cs.sps->getBitDepth(toChannelType(compID)), compID, DF_SSE);
+    }
+  }
+#endif
+  else
+#endif
+  {
+    dist = m_pcRdCost->getDistPart(org, reco, cs.sps->getBitDepth(toChannelType(compID)), compID, DF_SSE);
+  }
+  return dist;
+}
+#endif
+
 #if JVET_M0464_UNI_MTS
 void EncCu::xEncodeInterResidual(   CodingStructure *&tempCS
                                   , CodingStructure *&bestCS
@@ -4316,6 +4665,9 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
       tempCS->dist     = 0;
       tempCS->fracBits = 0;
       tempCS->cost     = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+      tempCS->costDbOffset = 0;
+#endif
     }
 
     reloadCU    = true; // enable cu reloading
@@ -4395,6 +4747,9 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&be
       if (tempCS->getPU(partitioner.chType)->mhIntraFlag)
       {
         tempCS->cost = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+        tempCS->costDbOffset = 0;
+#endif
         return;
       }
     }
@@ -4656,8 +5011,6 @@ void EncCu::xEncodeDontSplit( CodingStructure &cs, Partitioner &partitioner )
 #if REUSE_CU_RESULTS
 void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner )
 {
-  const SPS &sps = *tempCS->sps;
-
   BestEncInfoCache* bestEncCache = dynamic_cast<BestEncInfoCache*>( m_modeCtrl );
   CHECK( !bestEncCache, "If this mode is chosen, mode controller has to implement the mode caching capabilities" );
   EncTestMode cachedMode;
@@ -4681,6 +5034,11 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best
       xReconInter( cu );
     }
 
+#if JVET_M0428_ENC_DB_OPT
+    tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
+    xCalDebCost( *tempCS, partitioner, true );
+#else
+    const SPS &sps = *tempCS->sps;
     Distortion finalDistortion = 0;
     const int  numValidComponents = getNumberValidComponents( tempCS->area.chromaFormat );
 
@@ -4723,6 +5081,7 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best
 #endif
       finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
     }
+#endif
 
     m_CABACEstimator->getCtx() = m_CurrCtx->start;
     m_CABACEstimator->resetBits();
@@ -4732,7 +5091,9 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best
     cuCtx.isChromaQpAdjCoded = true;
     m_CABACEstimator->coding_unit( cu, partitioner, cuCtx );
 
+#if JVET_M0428_ENC_DB_OPT == 0
     tempCS->dist     = finalDistortion;
+#endif
     tempCS->fracBits = m_CABACEstimator->getEstFracBits();
     tempCS->cost     = m_pcRdCost->calcRdCost( tempCS->fracBits, tempCS->dist );
 
@@ -4745,7 +5106,6 @@ void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&best
     THROW( "Should never happen!" );
   }
 }
-
 #endif
 
 
diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h
index 89760c8491b9caaee20b70da692b5d4fdea5b113..f0ae05c89dfd3314ced3d7249b1df4bd82d17b8d 100644
--- a/source/Lib/EncoderLib/EncCu.h
+++ b/source/Lib/EncoderLib/EncCu.h
@@ -46,6 +46,9 @@
 #include "CommonLib/Unit.h"
 #include "CommonLib/UnitPartitioner.h"
 #include "CommonLib/IbcHashMap.h"
+#if JVET_M0428_ENC_DB_OPT
+#include "CommonLib/LoopFilter.h"
+#endif
 
 #if REUSE_CU_RESULTS
 #include "DecoderLib/DecCu.h"
@@ -84,7 +87,9 @@ class EncCu
 #endif
 {
 private:
-
+#if JVET_M0428_ENC_DB_OPT
+  bool m_bestModeUpdated;
+#endif
   struct CtxPair
   {
     Ctx start;
@@ -116,6 +121,9 @@ private:
   TrQuant*              m_pcTrQuant;
   RdCost*               m_pcRdCost;
   EncSlice*             m_pcSliceEncoder;
+#if JVET_M0428_ENC_DB_OPT
+  LoopFilter*           m_pcLoopFilter;
+#endif
 
   CABACWriter*          m_CABACEstimator;
   RateCtrl*             m_pcRateCtrl;
@@ -191,6 +199,11 @@ public:
 
 protected:
 
+#if JVET_M0428_ENC_DB_OPT
+  void xCalDebCost            ( CodingStructure &cs, Partitioner &partitioner, bool calDist = false );
+  Distortion getDistortionDb  ( CodingStructure &cs, CPelBuf org, CPelBuf reco, ComponentID compID, const CompArea& compArea, bool afterDb );
+#endif
+
   void xCompressCU            ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm
     , LutMotionCand *&tempMotCandLUTs
     , LutMotionCand *&bestMotCandLUTs
diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp
index b1b3f24159ded1f3e1e2bd8a1e79db99acba2279..ba6be0143d37568c2f45ca44516c30278636cf9c 100644
--- a/source/Lib/EncoderLib/EncLib.cpp
+++ b/source/Lib/EncoderLib/EncLib.cpp
@@ -130,7 +130,12 @@ void EncLib::create ()
   }
 
   m_cLoopFilter.create( m_maxTotalCUDepth );
-
+#if JVET_M0428_ENC_DB_OPT
+  if (!m_bLoopFilterDisable)
+  {
+    m_cLoopFilter.initEncPicYuvBuffer(m_chromaFormatIDC, getSourceWidth(), getSourceHeight());
+  }
+#endif
   if( m_alf )
   {
     m_cEncALF.create( getSourceWidth(), getSourceHeight(), m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, m_bitDepth, m_inputBitDepth );
diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp
index 075bc81c15afb0eb3a149aa18becfc499db2a6ba..dd608c374a27083d3677e8709da0366a0e0b4f96 100644
--- a/source/Lib/EncoderLib/EncModeCtrl.cpp
+++ b/source/Lib/EncoderLib/EncModeCtrl.cpp
@@ -1983,7 +1983,11 @@ bool EncModeCtrlMTnoRQT::useModeResult( const EncTestMode& encTestmode, CodingSt
   }
 
   // for now just a simple decision based on RD-cost or choose tempCS if bestCS is not yet coded
+#if JVET_M0428_ENC_DB_OPT
+  if( !cuECtx.bestCS || ( ( tempCS->features[ENC_FT_RD_COST] + ( tempCS->useDbCost ? tempCS->costDbOffset : 0 ) ) < ( cuECtx.bestCS->features[ENC_FT_RD_COST] + ( tempCS->useDbCost ? cuECtx.bestCS->costDbOffset : 0 ) ) ) )
+#else
   if( !cuECtx.bestCS || tempCS->features[ENC_FT_RD_COST] < cuECtx.bestCS->features[ENC_FT_RD_COST] )
+#endif
   {
     cuECtx.bestCS = tempCS;
     cuECtx.bestCU = tempCS->cus[0];
diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp
index 64bdafea669deb9623196d329f40ccf8e528d5b3..a2d48e5c1aaf6620c3bb795e4e7ee171da1a023a 100644
--- a/source/Lib/EncoderLib/IntraSearch.cpp
+++ b/source/Lib/EncoderLib/IntraSearch.cpp
@@ -908,6 +908,9 @@ void IntraSearch::estIntraPredLumaQT( CodingUnit &cu, Partitioner &partitioner )
       if( cu.ispMode && !csTemp->cus[0]->firstTU->cbf[COMPONENT_Y] )
       {
         csTemp->cost = MAX_DOUBLE;
+#if JVET_M0428_ENC_DB_OPT
+        csTemp->costDbOffset = 0;
+#endif
       }
 #else
       xRecurIntraCodingLumaQT( *csTemp, partitioner );