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 );