diff --git a/cfg/encoder_intra_ecm.cfg b/cfg/encoder_intra_ecm.cfg index 6bdc61a035b576575b6359537d964183a232782b..d22aba251746decf56eee6d9dba1f349de45a132 100644 --- a/cfg/encoder_intra_ecm.cfg +++ b/cfg/encoder_intra_ecm.cfg @@ -114,6 +114,7 @@ FastMrg : 1 AMaxBT : 1 FastMIP : 1 FastLFNST : 1 +MTTSkipping : 1 # MTTSkipping: 0: disable, 1:enable # Encoder optimization tools AffineAmvrEncOpt : 0 diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index b149ac464cb2e05f3ac342cd13db708cde4e417c..1ba5adb972080804319dee2719f214ab644c5ac5 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -1189,7 +1189,7 @@ void EncApp::xInitLibCfg() #if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT m_cEncLib.setTempCabacInitMode ( m_tempCabacInitMode ); #endif - #if JVET_AE0057_MTT_ET + #if JVET_AJ0226_MTT_SKIP m_cEncLib.setUseMttSkip (m_useMttSkip); #endif // set internal bit-depth and constants diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index e9efe75120028a9f72c7ecbd3bf430cf88e4c953..05e6f31461c235b5409f8b74cad48336f8db3347 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1390,7 +1390,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("PBIntraFast", m_usePbIntraFast, false, "Fast assertion if the intra mode is probable") ("AMaxBT", m_useAMaxBT, false, "Adaptive maximal BT-size") ("E0023FastEnc", m_e0023FastEnc, true, "Fast encoding setting for QTBT (proposal E0023)") -#if JVET_AE0057_MTT_ET +#if JVET_AJ0226_MTT_SKIP ("MTTSkipping", m_useMttSkip, false, "MTT split modes early termination") #endif ("ContentBasedFastQtbt", m_contentBasedFastQtbt, false, "Signal based QTBT speed-up") diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index e999b0988c8ed2dac680a9253c967c39b3d77195..a9b97a805b4aae4f5ca8d9d756c6c4a7a4d7e207 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -707,7 +707,7 @@ protected: unsigned m_uiMaxCUWidth; ///< max. CU width in pixel unsigned m_uiMaxCUHeight; ///< max. CU height in pixel unsigned m_log2MinCuSize; ///< min. CU size log2 -#if JVET_AE0057_MTT_ET +#if JVET_AJ0226_MTT_SKIP bool m_useMttSkip; #endif diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index cecac60bf30e775ec762867667720aa7206f2a7f..db50f722cc9257a577de395ae1b9886f08ea4266 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -63,7 +63,6 @@ #define ALF_SAO_TRUE_ORG 1 // using true original samples for SAO and ALF optimization #define REMOVE_PCM 1 // Remove PCM related code for memory reduction and speedup #define JVET_Y0152_TT_ENC_SPEEDUP 1 // TT encoding speedup -#define JVET_AE0057_MTT_ET 1 // JVET-AE0057: MTT early termination of 64x64 luma CU based on no-split RD cost #define JVET_AF0177_ALF_COV_FLOAT 1 // JVET-AF0177: Use float for ALF and CCALF covariance matrix @@ -93,6 +92,7 @@ #define LMCS_CHROMA_CALC_CU 1 // Derive chroma LMCS parameter based on neighbor CUs. Needed by VPDU removal and 128x128 transform. #endif #define JVET_AI0087_BTCUS_RESTRICTION 1 // JVET-AI0087: Restriction on BT CUs from applying QT like partitioning structure +#define JVET_AJ0226_MTT_SKIP 1 // JVET-AJ0226: MTT early termination applied to 64x64 & 32x32 luma CUs //-- intra #define INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS 1 // Enable 2xN and Nx2 block by removing SCIPU constraints diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 9a2cd70cc0510aaa95464412e48905c13fd6d219..5572978251f9aa29cfa26385f89f613785e49fa1 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -682,7 +682,7 @@ protected: int m_fastLocalDualTreeMode; #endif uint32_t m_log2MaxTbSize; -#if JVET_AE0057_MTT_ET +#if JVET_AJ0226_MTT_SKIP bool m_useMttSkip; #endif @@ -2088,7 +2088,7 @@ public: int getFastLocalDualTreeMode () const { return m_fastLocalDualTreeMode; } #endif void setLog2MaxTbSize ( uint32_t u ) { m_log2MaxTbSize = u; } -#if JVET_AE0057_MTT_ET +#if JVET_AJ0226_MTT_SKIP void setUseMttSkip (bool i) { m_useMttSkip = i; } bool getUseMttSkip () const { return m_useMttSkip; } #endif diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 9382e7c45e731ecd5bae8b3ba605fe2b43ef11b6..a4bdb314820cf9ea329ae8762275bef650ca1399 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -1005,6 +1005,143 @@ bool EncCu::xStoreRDcostandPredMode(CodingStructure *&tempCS, CodingStructure *& return true; } #endif +#if JVET_AJ0226_MTT_SKIP +void EncCu::xStoreMttSplitFlagCabacBits(CodingStructure*& tempCS, Partitioner& partitioner, int mttSplitFlagCabacBits) +{ + m_CABACEstimator->getCtx() = SubCtx(Ctx::Split, m_CurrCtx->start); + // TTH Split flag CABAC bits + m_CABACEstimator->resetBits(); + m_CABACEstimator->split_cu_mode(PartSplit::CU_TRIH_SPLIT, *tempCS, partitioner +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + , nullptr +#endif + , 0); + + if (partitioner.currArea().lheight() == 256) + { + m_modeCtrl->setTthCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 0); + } + else if (partitioner.currArea().lheight() == 128) + { + m_modeCtrl->setTthCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 1); + } + else if (partitioner.currArea().lheight() == 64) + { + m_modeCtrl->setTthCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 2); + } + else if (partitioner.currArea().lheight() == 32) + { + m_modeCtrl->setTthCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 3); + } + + m_CABACEstimator->getCtx() = SubCtx(Ctx::Split, m_CurrCtx->start); + + // TTV Split flag CABAC bits + m_CABACEstimator->resetBits(); + m_CABACEstimator->split_cu_mode(PartSplit::CU_TRIV_SPLIT, *tempCS, partitioner +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + , nullptr +#endif + , 0); + if (partitioner.currArea().lheight() == 256) + { + m_modeCtrl->setTtvCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 0); + } + else if (partitioner.currArea().lheight() == 128) + { + m_modeCtrl->setTtvCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 1); + } + else if (partitioner.currArea().lheight() == 64) + { + m_modeCtrl->setTtvCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 2); + } + else if (partitioner.currArea().lheight() == 32) + { + m_modeCtrl->setTtvCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 3); + } + + m_CABACEstimator->getCtx() = SubCtx(Ctx::Split, m_CurrCtx->start); + + // BTH Split flag CABAC bits + m_CABACEstimator->resetBits(); + m_CABACEstimator->split_cu_mode(PartSplit::CU_HORZ_SPLIT, *tempCS, partitioner +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + , nullptr +#endif + , 0); + if (partitioner.currArea().lheight() == 256) + { + m_modeCtrl->setBthCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 0); + } + else if (partitioner.currArea().lheight() == 128) + { + m_modeCtrl->setBthCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 1); + } + else if (partitioner.currArea().lheight() == 64) + { + m_modeCtrl->setBthCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 2); + } + else if (partitioner.currArea().lheight() == 32) + { + m_modeCtrl->setBthCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 3); + } + + m_CABACEstimator->getCtx() = SubCtx(Ctx::Split, m_CurrCtx->start); + + // BTV Split flag CABAC bits + m_CABACEstimator->resetBits(); + m_CABACEstimator->split_cu_mode(PartSplit::CU_VERT_SPLIT, *tempCS, partitioner +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + , nullptr +#endif + , 0); + if (partitioner.currArea().lheight() == 256) + { + m_modeCtrl->setBtvCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 0); + } + else if (partitioner.currArea().lheight() == 128) + { + m_modeCtrl->setBtvCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 1); + } + else if (partitioner.currArea().lheight() == 64) + { + m_modeCtrl->setBtvCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 2); + } + else if (partitioner.currArea().lheight() == 32) + { + m_modeCtrl->setBtvCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 3); + } + + m_CABACEstimator->getCtx() = SubCtx(Ctx::Split, m_CurrCtx->start); + + // QT Split flag CABAC bits + m_CABACEstimator->resetBits(); + m_CABACEstimator->split_cu_mode(PartSplit::CU_QUAD_SPLIT, *tempCS, partitioner +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + , nullptr +#endif + , 0); + + if (partitioner.currArea().lheight() == 256) + { + m_modeCtrl->setQtCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 0); + } + else if (partitioner.currArea().lheight() == 128) + { + m_modeCtrl->setQtCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 1); + } + else if (partitioner.currArea().lheight() == 64) + { + m_modeCtrl->setQtCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 2); + } + else if (partitioner.currArea().lheight() == 32) + { + m_modeCtrl->setQtCabacBits(mttSplitFlagCabacBits + (int)m_CABACEstimator->getEstFracBits(), 3); + } + + m_CABACEstimator->getCtx() = SubCtx(Ctx::Split, m_CurrCtx->start); +} +#endif bool EncCu::xCheckBestMode( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ) { @@ -1050,7 +1187,11 @@ bool EncCu::xCheckBestMode( CodingStructure *&tempCS, CodingStructure *&bestCS, } -void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner, double maxCostAllowed ) +void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& partitioner, double maxCostAllowed +#if JVET_AJ0226_MTT_SKIP + , int mttSplitFlagCabacBits +#endif +) { CHECK(maxCostAllowed < 0, "Wrong value of maxCostAllowed!"); #if JVET_AA0133_INTER_MTS_OPT @@ -1321,6 +1462,16 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par #endif m_CurrCtx->start = m_CABACEstimator->getCtx(); +#if JVET_AJ0226_MTT_SKIP + if (partitioner.currBtDepth == 0 && (partitioner.currArea().lwidth() == partitioner.currArea().lheight()) && ( partitioner.currArea().lwidth() == 32 || partitioner.currArea().lwidth() == 64 || partitioner.currArea().lwidth() == 128 || partitioner.currArea().lwidth() == 256) +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + && (!(bestCS->slice->getProcessingIntraRegion() && bestCS->slice->getProcessingSeparateTrees()) || bestCS->slice->isIntra()) +#endif + ) + { + EncCu::xStoreMttSplitFlagCabacBits(tempCS, partitioner,mttSplitFlagCabacBits); + } +#endif m_cuChromaQpOffsetIdxPlus1 = 0; if( slice.getUseChromaQpAdj() ) @@ -1712,16 +1863,25 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par { xCheckRDCostIntra(tempCS, bestCS, partitioner, currTestMode, false); } -#if JVET_AE0057_MTT_ET - if (partitioner.currQtDepth == (tempCS->sps->getCTUSize() == 256 ? 2 : 1) && partitioner.currBtDepth == 0 - && partitioner.currArea().lwidth() == 64 && partitioner.currArea().lheight() == 64) - { - if ((partitioner.chType == CHANNEL_TYPE_LUMA) - && ((partitioner.currArea().Y().x + 63 < bestCS->picture->lwidth()) - && (partitioner.currArea().Y().y + 63 < bestCS->picture->lheight()))) - +#if JVET_AJ0226_MTT_SKIP + if ((partitioner.chType == CHANNEL_TYPE_LUMA) && partitioner.currBtDepth == 0 + && (partitioner.currArea().lwidth() == partitioner.currArea().lheight()) +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + && (!(bestCS->slice->getProcessingIntraRegion() && bestCS->slice->getProcessingSeparateTrees()) || bestCS->slice->isIntra()) +#endif + ) + { + if (( partitioner.currArea().Y().x + partitioner.currArea().lheight() - 1 < bestCS->picture->lwidth()) + && (partitioner.currArea().Y().y + partitioner.currArea().lheight() - 1 < bestCS->picture->lheight())) { - m_modeCtrl->setNoSplitIntraCost(bestCS->cost); + if (partitioner.currArea().lheight() == 64) + { + m_modeCtrl->setNoSplitIntraCost64CU(bestCS->cost); + } + if (partitioner.currArea().lheight() == 32) + { + m_modeCtrl->setNoSplitIntraCost32CU(bestCS->cost); + } } } #endif @@ -1885,11 +2045,30 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par xCheckModeSplit( tempCS, bestCS, partitioner, currTestMode, modeTypeParent, skipInterPass ); #endif #else +#if JVET_AJ0226_MTT_SKIP + if (partitioner.currBtDepth == 0 && (currTestMode.type == ETM_SPLIT_QT) && (partitioner.currArea().lwidth() == partitioner.currArea().lheight()) && partitioner.chType == CHANNEL_TYPE_LUMA +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + && (!(bestCS->slice->getProcessingIntraRegion() && bestCS->slice->getProcessingSeparateTrees()) || bestCS->slice->isIntra()) +#endif + ) + { + mttSplitFlagCabacBits = (partitioner.currArea().lwidth() == 128 ? m_modeCtrl->getQtCabacBits(0) : partitioner.currArea().lwidth() == 64 ? m_modeCtrl->getQtCabacBits(1) : partitioner.currArea().lwidth() == 32 ? m_modeCtrl->getQtCabacBits(2) : 0); + } +#endif #if JVET_Y0152_TT_ENC_SPEEDUP - xCheckModeSplit(tempCS, bestCS, partitioner, currTestMode, splitRdCostBest); + + xCheckModeSplit(tempCS, bestCS, partitioner, currTestMode, splitRdCostBest +#if JVET_AJ0226_MTT_SKIP + , mttSplitFlagCabacBits +#endif + ); tempCS->splitRdCostBest = splitRdCostBest; #else - xCheckModeSplit(tempCS, bestCS, partitioner, currTestMode); + xCheckModeSplit(tempCS, bestCS, partitioner, currTestMode +#if JVET_AJ0226_MTT_SKIP + , mttSplitFlagCabacBits +#endif + ); #endif #endif #if JVET_AI0087_BTCUS_RESTRICTION @@ -2478,9 +2657,17 @@ void EncCu::copyState( EncCu* other, Partitioner& partitioner, const UnitArea& c #endif #if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS #if JVET_Y0152_TT_ENC_SPEEDUP -void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, double *splitRdCostBest) +void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, double *splitRdCostBest +#if JVET_AJ0226_MTT_SKIP + , int mttSplitFlagCabacBits +#endif +) #else -void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ) +void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode +#if JVET_AJ0226_MTT_SKIP + , int mttSplitFlagCabacBits +#endif +) #endif #else #if JVET_Y0152_TT_ENC_SPEEDUP @@ -2610,15 +2797,25 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, CodingStructure *tempSubCS = m_pTempCS[wIdx][hIdx]; CodingStructure *bestSubCS = m_pBestCS[wIdx][hIdx]; -#if JVET_AE0057_MTT_ET - if (partitioner.currQtDepth == (tempCS->sps->getCTUSize() == 256 ? 2 : 1) && partitioner.currBtDepth == 0 - && partitioner.currArea().lwidth() == 64 && partitioner.currArea().lheight() == 64) +#if JVET_AJ0226_MTT_SKIP + if ((partitioner.chType == CHANNEL_TYPE_LUMA) && partitioner.currBtDepth == 0 + && (partitioner.currArea().lwidth() == partitioner.currArea().lheight()) +#if JVET_AI0136_ADAPTIVE_DUAL_TREE + && (!(bestCS->slice->getProcessingIntraRegion() && bestCS->slice->getProcessingSeparateTrees()) || bestCS->slice->isIntra()) +#endif + ) { - if ((partitioner.chType == CHANNEL_TYPE_LUMA) - && ((partitioner.currArea().Y().x + 63 < bestCS->picture->lwidth()) - && (partitioner.currArea().Y().y + 63 < bestCS->picture->lheight()))) + if ((( partitioner.currArea().Y().x + partitioner.currArea().lheight() - 1) < bestCS->picture->lwidth()) + && ((partitioner.currArea().Y().y + partitioner.currArea().lheight() - 1) < bestCS->picture->lheight())) { - m_modeCtrl->setNoSplitIntraCost(0.0); + if (partitioner.currArea().lheight() == 64) + { + m_modeCtrl->setNoSplitIntraCost64CU(0.0); + } + if (partitioner.currArea().lheight() == 32) + { + m_modeCtrl->setNoSplitIntraCost32CU(0.0); + } } } #endif @@ -2690,7 +2887,11 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, tempSubCS->bestParent = bestSubCS->bestParent = bestCS; double newMaxCostAllowed = isLuma(partitioner.chType) ? std::min(encTestMode.maxCostAllowed, bestCS->cost - m_pcRdCost->calcRdCost(tempCS->fracBits, tempCS->dist)) : MAX_DOUBLE; newMaxCostAllowed = std::max(0.0, newMaxCostAllowed); - xCompressCU(tempSubCS, bestSubCS, partitioner, newMaxCostAllowed); + xCompressCU(tempSubCS, bestSubCS, partitioner, newMaxCostAllowed +#if JVET_AJ0226_MTT_SKIP + , mttSplitFlagCabacBits +#endif + ); tempSubCS->bestParent = bestSubCS->bestParent = nullptr; if( bestSubCS->cost == MAX_DOUBLE ) diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index ae0e5cff63e62f7adcde06d4cf039a105afea21c..982211a7dfce095678da7c51b107b81fc2cd830e 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -528,8 +528,14 @@ protected: void xCalDebCost ( CodingStructure &cs, Partitioner &partitioner, bool calDist = false ); Distortion getDistortionDb ( CodingStructure &cs, CPelBuf org, CPelBuf reco, ComponentID compID, const CompArea& compArea, bool afterDb ); - - void xCompressCU ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, double maxCostAllowed = MAX_DOUBLE ); +#if JVET_AJ0226_MTT_SKIP + void xStoreMttSplitFlagCabacBits(CodingStructure*& tempCS, Partitioner& partitioner, int mttSplitFlagCabacBits); +#endif + void xCompressCU ( CodingStructure*& tempCS, CodingStructure*& bestCS, Partitioner& pm, double maxCostAllowed = MAX_DOUBLE +#if JVET_AJ0226_MTT_SKIP + , int mttSplitFlagCabacBits = 0 +#endif + ); #if ENABLE_SPLIT_PARALLELISM void xCompressCUParallel ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm ); void copyState ( EncCu* other, Partitioner& pm, const UnitArea& currArea, const bool isDist ); @@ -538,15 +544,31 @@ protected: xCheckBestMode ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestmode ); #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS #if JVET_Y0152_TT_ENC_SPEEDUP - void xCheckModeSplit ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool &skipInterPass, double *splitRdCostBest ); + void xCheckModeSplit ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool &skipInterPass, double *splitRdCostBest +#if JVET_AJ0226_MTT_SKIP + , int mttSplitFlagCabacBits +#endif + ); #else - void xCheckModeSplit ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool &skipInterPass ); + void xCheckModeSplit ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, const ModeType modeTypeParent, bool &skipInterPass +#if JVET_AJ0226_MTT_SKIP + , int mttSplitFlagCabacBits +#endif + ); #endif #else #if JVET_Y0152_TT_ENC_SPEEDUP - void xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, double *splitRdCostBest); + void xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, double *splitRdCostBest +#if JVET_AJ0226_MTT_SKIP + , int mttSplitFlagCabacBits +#endif + ); #else - void xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); + void xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode +#if JVET_AJ0226_MTT_SKIP + , int mttSplitFlagCabacBits +#endif + ); #endif #endif bool xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, bool adaptiveColorTrans); diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 0328a69b8e0fc213129b5ead2fc425216e19a169..b2472bf5e2f7fab82157c65b71893823a78898df 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1727,12 +1727,11 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru #if JVET_AI0087_BTCUS_RESTRICTION bool disableBTV = false; bool disableBTH = false; - + if (EncModeCtrl::isLumaNonBoundaryCu(partitioner, cs.picture->lwidth(), cs.picture->lheight()) #if JVET_AI0136_ADAPTIVE_DUAL_TREE - if (EncModeCtrl::isLumaNonBoundaryCu(partitioner, cs.picture->lwidth(), cs.picture->lheight()) && (!(cs.slice->getProcessingIntraRegion() && cs.slice->getProcessingSeparateTrees()) || cs.slice->isIntra()) ) -#else - if (EncModeCtrl::isLumaNonBoundaryCu(partitioner, cs.picture->lwidth(), cs.picture->lheight()) ) + && (!(cs.slice->getProcessingIntraRegion() && cs.slice->getProcessingSeparateTrees()) || cs.slice->isIntra()) #endif + ) { if ((partitioner.currBtDepth == 1) && (partitioner.currPartIdx() == 1)) { @@ -2541,28 +2540,48 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt ComprCUCtx& cuECtx = m_ComprCUCtxList[EncModeCtrl::m_treeIdx].back(); #else ComprCUCtx& cuECtx = m_ComprCUCtxList.back(); -#endif - // MTT modes early termination for 64x64 luma CU based on nosplit intra cost -#if JVET_AE0057_MTT_ET - if (m_pcEncCfg->getUseMttSkip() && partitioner.currQtDepth == (cs.sps->getCTUSize() == 256 ? 2 : 1) - && partitioner.currBtDepth == 0 - && partitioner.currArea().lwidth() == 64 && partitioner.currArea().lheight() == 64 +#endif + +#if JVET_AJ0226_MTT_SKIP + if (m_pcEncCfg->getUseMttSkip() && partitioner.currBtDepth == 0 && (partitioner.currArea().lwidth() == partitioner.currArea().lheight()) && + (partitioner.currArea().lwidth() == 64 || partitioner.currArea().lwidth() == 32 )) + { + if (((partitioner.currArea().Y().x + partitioner.currArea().lwidth()-1 < cs.picture->lwidth()) + && (partitioner.currArea().Y().y + partitioner.currArea().lwidth()-1 < cs.picture->lheight())) + && (encTestmode.type == ETM_SPLIT_BT_H || encTestmode.type == ETM_SPLIT_BT_V + || encTestmode.type == ETM_SPLIT_TT_H || encTestmode.type == ETM_SPLIT_TT_V) + && partitioner.chType == CHANNEL_TYPE_LUMA #if JVET_AI0136_ADAPTIVE_DUAL_TREE - && !(cs.slice->getSeparateTreeEnabled() && cs.sps->getInterSliceSeparateTreeEnabled()) + && (!(cs.slice->getProcessingIntraRegion() && cs.slice->getProcessingSeparateTrees()) || cs.slice->isIntra()) #endif - ) - { - if (((partitioner.currArea().Y().x + 63 < cs.picture->lwidth()) - && (partitioner.currArea().Y().y + 63 < cs.picture->lheight())) - && (encTestmode.type == ETM_SPLIT_BT_H || encTestmode.type == ETM_SPLIT_BT_V - || encTestmode.type == ETM_SPLIT_TT_H || encTestmode.type == ETM_SPLIT_TT_V) - && partitioner.chType == CHANNEL_TYPE_LUMA) + ) { - int thresholdMTT = Clip3(0, MAX_INT, (120 - ((m_pcEncCfg->getBaseQP() - 22) * 3)) * 1000000); - if (m_noSplitIntraRdCost > thresholdMTT) + double splitSignalCostScaling = Clip3(0.0, 4.0, (4.0 * pow(0.5, (m_pcEncCfg->getBaseQP() - 22.0) / 5))); + int modeCabacCost = 0; + + if (encTestmode.type == ETM_SPLIT_TT_H) { - const PartSplit split = getPartSplit(encTestmode); + modeCabacCost = partitioner.currArea().lwidth() == 64 ? m_cabacBitsforTTH[2] : partitioner.currArea().lwidth() == 32 ? m_cabacBitsforTTH[3] : 0; + } + else if (encTestmode.type == ETM_SPLIT_TT_V) + { + modeCabacCost = partitioner.currArea().lwidth() == 64 ? m_cabacBitsforTTV[2] : partitioner.currArea().lwidth() == 32 ? m_cabacBitsforTTV[3] : 0; + } + else if (encTestmode.type == ETM_SPLIT_BT_H) + { + modeCabacCost = partitioner.currArea().lwidth() == 64 ? m_cabacBitsforBTH[2] : partitioner.currArea().lwidth() == 32 ? m_cabacBitsforBTH[3] : 0; + } + else if (encTestmode.type == ETM_SPLIT_BT_V) + { + modeCabacCost = partitioner.currArea().lwidth() == 64 ? m_cabacBitsforBTV[2] : partitioner.currArea().lwidth() == 32 ? m_cabacBitsforBTV[3] : 0; + } + + int thresholdMTT = Clip3(0, MAX_INT, (140 - ((cs.slice->getSliceQp() - 22) * 3)) * (1000000 - (int)(modeCabacCost * splitSignalCostScaling) )); + double noSplitCost = partitioner.currArea().lwidth() == 64 ? m_noSplitIntraRdCost64CU : partitioner.currArea().lwidth() == 32 ? m_noSplitIntraRdCost32CU : 0; + if (noSplitCost > thresholdMTT) + { + const PartSplit split = getPartSplit(encTestmode); if (split == CU_HORZ_SPLIT) { cuECtx.set(DID_HORZ_SPLIT, false); @@ -2571,6 +2590,14 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt { cuECtx.set(DID_VERT_SPLIT, false); } + if (split == CU_TRIH_SPLIT) + { + cuECtx.set(DO_TRIH_SPLIT, false); + } + if (split == CU_TRIV_SPLIT) + { + cuECtx.set(DO_TRIV_SPLIT, false); + } return false; } } diff --git a/source/Lib/EncoderLib/EncModeCtrl.h b/source/Lib/EncoderLib/EncModeCtrl.h index f86fbb8b29ab9edeacbb5a8de36ee63fc43d2101..b58a6ee74372a53f33f9424c42a8106ecea597b8 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.h +++ b/source/Lib/EncoderLib/EncModeCtrl.h @@ -356,8 +356,14 @@ protected: InterSearch* m_pcInterSearch; bool m_doPlt; -#if JVET_AE0057_MTT_ET - double m_noSplitIntraRdCost; +#if JVET_AJ0226_MTT_SKIP + double m_noSplitIntraRdCost64CU; + double m_noSplitIntraRdCost32CU; + int m_cabacBitsforBTH[4]; + int m_cabacBitsforBTV[4]; + int m_cabacBitsforTTH[4]; + int m_cabacBitsforTTV[4]; + int m_cabacBitsforQT[4]; #endif #if JVET_AI0136_ADAPTIVE_DUAL_TREE @@ -410,8 +416,23 @@ public: #if JVET_AI0087_BTCUS_RESTRICTION bool isLumaNonBoundaryCu(const Partitioner& partitioner, SizeType picWidth, SizeType picHeight); #endif -#if JVET_AE0057_MTT_ET - void setNoSplitIntraCost (double cost) { m_noSplitIntraRdCost = cost; } +#if JVET_AJ0226_MTT_SKIP + void setNoSplitIntraCost64CU(double cost) { m_noSplitIntraRdCost64CU = cost; } + void setNoSplitIntraCost32CU (double cost) { m_noSplitIntraRdCost32CU = cost;} + + void setBthCabacBits(int bitsCabac, int pos) { m_cabacBitsforBTH[pos] = bitsCabac; } + void setBtvCabacBits(int bitsCabac, int pos) { m_cabacBitsforBTV[pos] = bitsCabac; } + void setTthCabacBits(int bitsCabac, int pos) { m_cabacBitsforTTH[pos] = bitsCabac; } + void setTtvCabacBits(int bitsCabac, int pos) { m_cabacBitsforTTV[pos] = bitsCabac; } + void setQtCabacBits (int bitsCabac, int pos) { m_cabacBitsforQT[pos] = bitsCabac; } + + + int getBthCabacBits(int pos) { return m_cabacBitsforBTH[pos] ; } + int getBtvCabacBits(int pos) { return m_cabacBitsforBTV[pos] ; } + int getTthCabacBits(int pos) { return m_cabacBitsforTTH[pos] ; } + int getTtvCabacBits(int pos) { return m_cabacBitsforTTV[pos] ; } + int getQtCabacBits (int pos) { return m_cabacBitsforQT[pos] ; } + #endif #if JVET_AI0136_ADAPTIVE_DUAL_TREE ComprCUCtx& getComprCUCtx () { CHECK( m_ComprCUCtxList[m_treeIdx].empty(), "Accessing empty list!"); return m_ComprCUCtxList[m_treeIdx].back(); } @@ -517,6 +538,18 @@ public: void setStopNonDCT2Transforms ( bool val ) { m_ComprCUCtxList.back().stopNonDCT2Transforms = val; } #endif + +#if JVET_AJ0226_MTT_SKIP + void resetSplitSignalCostParams() + { + std::memset(m_cabacBitsforTTH, 0, sizeof(m_cabacBitsforTTH)); + std::memset(m_cabacBitsforTTV, 0, sizeof(m_cabacBitsforTTV)); + std::memset(m_cabacBitsforBTH, 0, sizeof(m_cabacBitsforBTH)); + std::memset(m_cabacBitsforBTV, 0, sizeof(m_cabacBitsforBTV)); + std::memset(m_cabacBitsforQT, 0, sizeof(m_cabacBitsforQT)); + } +#endif + void setInterSearch (InterSearch* pcInterSearch) { m_pcInterSearch = pcInterSearch; } void setPltEnc ( bool b ) { m_doPlt = b; } bool getPltEnc() const { return m_doPlt; } diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index b61088704df6c3edfa2c90cd38390d6d0b9791fc..af77dcfd4c4481b513fa72cbd28dd0186c1f4b74 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -2080,6 +2080,9 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons { const int32_t ctuRsAddr = pcSlice->getCtuAddrInSlice( ctuIdx ); +#if JVET_AJ0226_MTT_SKIP + m_pcCuEncoder->getModeCtrl()->resetSplitSignalCostParams(); +#endif // update CABAC state const uint32_t ctuXPosInCtus = ctuRsAddr % widthInCtus; const uint32_t ctuYPosInCtus = ctuRsAddr / widthInCtus;