diff --git a/cfg/encoder_intra_ecm.cfg b/cfg/encoder_intra_ecm.cfg index 02726537c8685d5bc7600656614dd59655439f26..6366f730c6c827f5d4b7c0e89a8be548a4c508dd 100644 --- a/cfg/encoder_intra_ecm.cfg +++ b/cfg/encoder_intra_ecm.cfg @@ -79,7 +79,9 @@ MTS : 1 MTSIntraMaxCand : 4 MTSInterMaxCand : 4 SBT : 1 -LFNST : 1 +IntraLFNSTISlice : 1 +IntraLFNSTPBSlice : 1 +InterLFNST : 1 ISP : 1 Affine : 1 SbTMVP : 1 diff --git a/cfg/encoder_lowdelay_P_ecm.cfg b/cfg/encoder_lowdelay_P_ecm.cfg index 86840958ab3ef2a8c1162d546468ff441c556851..81632b2112a0f8e784db7d6b939cb0928baf007a 100644 --- a/cfg/encoder_lowdelay_P_ecm.cfg +++ b/cfg/encoder_lowdelay_P_ecm.cfg @@ -104,6 +104,9 @@ MTS : 3 MTSIntraMaxCand : 3 MTSInterMaxCand : 4 SBT : 1 +IntraLFNSTISlice : 1 +IntraLFNSTPBSlice : 0 +InterLFNST : 1 ISP : 1 Affine : 1 SbTMVP : 1 @@ -140,6 +143,8 @@ ISPFast : 0 FastMrg : 1 AMaxBT : 1 FastMIP : 0 +FastLFNST : 0 +FastInterLFNST : 1 MTTSkipping : 1 # MTTSkipping: 0: disable, 1:enable # Encoder optimization tools diff --git a/cfg/encoder_lowdelay_ecm.cfg b/cfg/encoder_lowdelay_ecm.cfg index 7ad59713347a937654a228ec2d95e9b75f996470..f1def45954326bbf91fe3ffedeed7e096138c1d3 100644 --- a/cfg/encoder_lowdelay_ecm.cfg +++ b/cfg/encoder_lowdelay_ecm.cfg @@ -104,6 +104,9 @@ MTS : 3 MTSIntraMaxCand : 3 MTSInterMaxCand : 4 SBT : 1 +IntraLFNSTISlice : 1 +IntraLFNSTPBSlice : 0 +InterLFNST : 1 ISP : 1 MMVD : 1 Affine : 1 @@ -144,6 +147,8 @@ ISPFast : 0 FastMrg : 1 AMaxBT : 1 FastMIP : 0 +FastLFNST : 0 +FastInterLFNST : 1 MTTSkipping : 1 # MTTSkipping: 0: disable, 1:enable # Encoder optimization tools diff --git a/cfg/encoder_randomaccess_ecm.cfg b/cfg/encoder_randomaccess_ecm.cfg index 203e92d3941810e27a3eb1283ce392f357524eb3..9df53758e22bc5283cc384b41fbcb96da08c4533 100644 --- a/cfg/encoder_randomaccess_ecm.cfg +++ b/cfg/encoder_randomaccess_ecm.cfg @@ -131,7 +131,9 @@ MTS : 3 MTSIntraMaxCand : 4 MTSInterMaxCand : 4 SBT : 1 -LFNST : 1 +IntraLFNSTISlice : 1 +IntraLFNSTPBSlice : 1 +InterLFNST : 1 ISP : 1 MMVD : 1 Affine : 1 @@ -174,6 +176,7 @@ FastMrg : 1 AMaxBT : 1 FastMIP : 0 FastLFNST : 0 +FastInterLFNST : 0 ChromaTS : 1 MTTSkipping : 1 # MTTSkipping: 0: disable, 1:enable diff --git a/cfg/encoder_randomaccess_gop16_ecm.cfg b/cfg/encoder_randomaccess_gop16_ecm.cfg index 18b7c9a00e635ddb0d18b1301eb9f0d260b40274..d7d98040d7d5d873db49128120fb7f83a8183b61 100644 --- a/cfg/encoder_randomaccess_gop16_ecm.cfg +++ b/cfg/encoder_randomaccess_gop16_ecm.cfg @@ -115,7 +115,9 @@ MTS : 1 MTSIntraMaxCand : 4 MTSInterMaxCand : 4 SBT : 1 -LFNST : 1 +IntraLFNSTISlice : 1 +IntraLFNSTPBSlice : 1 +InterLFNST : 1 ISP : 1 MMVD : 1 Affine : 1 @@ -158,6 +160,7 @@ FastMrg : 1 AMaxBT : 1 FastMIP : 0 FastLFNST : 0 +FastInterLFNST : 0 ChromaTS : 1 MTTSkipping : 1 # MTTSkipping: 0: disable, 1:enable diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 1e24e4cdb824a6ce6bc2b49fc0f6993ee8ca6001..4d5d237f3493d8612b9f8d10eee6acc775cb534c 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -493,7 +493,13 @@ void EncApp::xInitLibCfg() CHECK(m_noMipConstraintFlag && m_MIP, "MIP shall be deactivated when m_noMipConstraintFlag is equal to 1"); m_cEncLib.setNoLfnstConstraintFlag(m_noLfnstConstraintFlag); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsLfnstEnabled = ( m_intraLFNSTISlice || m_intraLFNSTPBSlice ); + spsLfnstEnabled |= m_interLFNST; + CHECK( m_noLfnstConstraintFlag && spsLfnstEnabled, "LFNST shall be deactivated when m_noLfnstConstraintFlag is equal to 1" ); +#else CHECK(m_noLfnstConstraintFlag && m_LFNST, "LFNST shall be deactivated when m_noLfnstConstraintFlag is equal to 1"); +#endif m_cEncLib.setNoMmvdConstraintFlag(m_noMmvdConstraintFlag); CHECK(m_noMmvdConstraintFlag && m_MMVD, "MMVD shall be deactivated when m_noMmvdConstraintFlag is equal to 1"); @@ -804,8 +810,17 @@ void EncApp::xInitLibCfg() m_cEncLib.setLog2SignPredArea (m_log2SignPredArea); #endif #endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + m_cEncLib.setIntraLFNSTISlice ( m_intraLFNSTISlice ); + m_cEncLib.setIntraLFNSTPBSlice ( m_intraLFNSTPBSlice ); + m_cEncLib.setInterLFNST ( m_interLFNST ); +#else m_cEncLib.setLFNST ( m_LFNST ); +#endif m_cEncLib.setUseFastLFNST ( m_useFastLFNST ); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + m_cEncLib.setUseFastInterLFNST ( m_useFastInterLFNST ); +#endif m_cEncLib.setSbTmvpEnabledFlag(m_sbTmvpEnableFlag); m_cEncLib.setAffine ( m_Affine ); m_cEncLib.setAffineType ( m_AffineType ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index d8032107fd686efe39aca62eefc471f6a3772748..f3f85bb99469dc1737a21c6a6f58f593ab5feb89 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1028,8 +1028,17 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("TTFastSkipThr", m_ttFastSkipThr, 1.075, "Threshold value of fast skip method for TT split partition") #endif ("DualITree", m_dualTree, false, "Use separate QTBT trees for intra slice luma and chroma channel types") +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + ( "IntraLFNSTISlice", m_intraLFNSTISlice, false, "Enable intra-LFNST for I-Slice (0:off, 1:on) [default: off]" ) + ( "IntraLFNSTPBSlice", m_intraLFNSTPBSlice, false, "Enable intra-LFNST for P/B-Slice (0:off, 1:on) [default: off]" ) + ( "InterLFNST", m_interLFNST, false, "Enable inter-LFNST/NSPT (0:off, 1:on) [default: off]" ) +#else ( "LFNST", m_LFNST, false, "Enable LFNST (0:off, 1:on) [default: off]" ) +#endif ( "FastLFNST", m_useFastLFNST, false, "Fast methods for LFNST" ) +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + ( "FastInterLFNST", m_useFastInterLFNST, false, "Fast methods for inter-LFNST/NSPT" ) +#endif ("SbTMVP", m_sbTmvpEnableFlag, false, "Enable Subblock Temporal Motion Vector Prediction (0: off, 1: on) [default: off]") ("MMVD", m_MMVD, true, "Enable Merge mode with Motion Vector Difference (0:off, 1:on) [default: 1]") ("Affine", m_Affine, false, "Enable affine prediction (0:off, 1:on) [default: off]") @@ -5572,7 +5581,13 @@ void EncAppCfg::xPrintParameter() { msg( VERBOSE, "\nTOOL CFG: " ); msg( VERBOSE, "GOP:%d ", m_iGOPSize ); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + msg( VERBOSE, "IntraLFNSTISlice:%d ", m_intraLFNSTISlice ); + msg( VERBOSE, "IntraLFNSTPBSlice:%d ", m_intraLFNSTPBSlice ); + msg( VERBOSE, "InterLFNST:%d ", m_interLFNST ); +#else msg( VERBOSE, "LFNST:%d ", m_LFNST ); +#endif msg( VERBOSE, "MMVD:%d ", m_MMVD); msg( VERBOSE, "Affine:%d ", m_Affine ); if ( m_Affine ) @@ -5730,7 +5745,16 @@ void EncAppCfg::xPrintParameter() if( m_ImvMode ) msg( VERBOSE, "IMV4PelFast:%d ", m_Imv4PelFast ); if( m_MTS ) msg( VERBOSE, "MTSMaxCand: %1d(intra) %1d(inter) ", m_MTSIntraMaxCand, m_MTSInterMaxCand ); if( m_ISP ) msg( VERBOSE, "ISPFast:%d ", m_useFastISP ); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( m_intraLFNSTISlice || m_intraLFNSTPBSlice ) msg( VERBOSE, "FastLFNST:%d ", m_useFastLFNST ); +#else if( m_LFNST ) msg( VERBOSE, "FastLFNST:%d ", m_useFastLFNST ); +#endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool lfnstEnabled = ( m_intraLFNSTISlice || m_intraLFNSTPBSlice ); + lfnstEnabled |= m_interLFNST; + if( lfnstEnabled ) msg( VERBOSE, "FastInterLFNST:%d ", m_useFastInterLFNST ); +#endif msg( VERBOSE, "AMaxBT:%d ", m_useAMaxBT ); msg( VERBOSE, "E0023FastEnc:%d ", m_e0023FastEnc ); msg( VERBOSE, "ContentBasedFastQtbt:%d ", m_contentBasedFastQtbt ); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index dc8a06a036134f157de7739e160dc8c15c53d0e1..e7bd2baad728c284dfa8cf8012c6270372ce11e2 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -392,8 +392,17 @@ protected: double m_ttFastSkipThr; #endif bool m_dualTree; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool m_intraLFNSTISlice; + bool m_intraLFNSTPBSlice; + bool m_interLFNST; +#else bool m_LFNST; +#endif bool m_useFastLFNST; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool m_useFastInterLFNST; +#endif bool m_sbTmvpEnableFlag; bool m_Affine; bool m_AffineType; diff --git a/source/Lib/CommonLib/DepQuant.cpp b/source/Lib/CommonLib/DepQuant.cpp index c5024cb6054218fec20830176e01e8f5be49636c..7ae5a97687b3c6d172b0bacb7184064d3312b0fe 100644 --- a/source/Lib/CommonLib/DepQuant.cpp +++ b/source/Lib/CommonLib/DepQuant.cpp @@ -2684,7 +2684,13 @@ const CtxSet &ctxSetGt4 = isLfnst ? Ctx::GtxFlagL[6 + chType] : Ctx::GtxFlag[6 + { #if JVET_W0119_LFNST_EXTENSION #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed(tu, compID, width, height, CU::isIntra(*(tu.cu))); +#endif if (allowNSPT) { @@ -2699,7 +2705,13 @@ const CtxSet &ctxSetGt4 = isLfnst ? Ctx::GtxFlagL[6 + chType] : Ctx::GtxFlag[6 + #endif #else #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed(tu, compID, width, height, CU::isIntra(*(tu.cu))); +#endif if (allowNSPT) { diff --git a/source/Lib/CommonLib/Quant.cpp b/source/Lib/CommonLib/Quant.cpp index a6dd4a7a7eb83c4e5d175707978a992cd90476fc..b9fdcf51446d905d871639dc4456b393d209e846 100644 --- a/source/Lib/CommonLib/Quant.cpp +++ b/source/Lib/CommonLib/Quant.cpp @@ -1010,7 +1010,13 @@ void Quant::quant(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf const uint32_t lfnstIdx = tu.cu->lfnstIdx; #if JVET_W0119_LFNST_EXTENSION #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, uiWidth, uiHeight, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed( tu, compID, uiWidth, uiHeight, CU::isIntra( *( tu.cu ) ) ); +#endif const int maxNumberOfCoeffs = lfnstIdx > 0 ? ( allowNSPT ? PU::getNSPTMatrixDim( uiWidth, uiHeight ) : PU::getLFNSTMatrixDim( uiWidth, uiHeight ) ) : piQCoef.area(); #else @@ -1018,7 +1024,13 @@ void Quant::quant(TransformUnit &tu, const ComponentID &compID, const CCoeffBuf #endif #else #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, uiWidth, uiHeight, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed( tu, compID, uiWidth, uiHeight, CU::isIntra( *( tu.cu ) ) ); +#endif const int maxNumberOfCoeffs = lfnstIdx > 0 ? ( allowNSPT ? PU::getNSPTMatrixDim( uiWidth, uiHeight ) : ( ( ( uiWidth == 4 && uiHeight == 4 ) || ( uiWidth == 8 && uiHeight == 8 ) ) ? 8 : 16 ) ) : piQCoef.area(); #else diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 9b02bafe3dc73e111149c58e17994d7861f29a2e..2f11cb39fa5ba669ef55772c455a6839efd56e6c 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -3897,7 +3897,13 @@ SPS::SPS() , m_verCollocatedChromaFlag ( false ) , m_IntraMTS ( false ) , m_InterMTS ( false ) +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT +, m_intraLFNSTISlice ( false ) +, m_intraLFNSTPBSlice ( false ) +, m_interLFNST ( false ) +#else , m_LFNST ( false ) +#endif , m_Affine ( false ) , m_AffineType ( false ) #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index b36f05e40bce68b13088e924546a26bff8dfb92a..39633a31ff1bb34e4d8459be9bdf4bc81d725306 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1774,7 +1774,13 @@ private: bool m_MTS; bool m_IntraMTS; // 18 bool m_InterMTS; // 19 +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool m_intraLFNSTISlice; + bool m_intraLFNSTPBSlice; + bool m_interLFNST; +#else bool m_LFNST; +#endif bool m_SMVD; bool m_Affine; bool m_AffineType; @@ -2459,8 +2465,17 @@ void setCCALFEnabledFlag( bool b ) bool getUseIntraMTS () const { return m_IntraMTS; } void setUseInterMTS ( bool b ) { m_InterMTS = b; } bool getUseInterMTS () const { return m_InterMTS; } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + void setUseIntraLFNSTISlice ( bool b ) { m_intraLFNSTISlice = b; } + bool getUseIntraLFNSTISlice () const { return m_intraLFNSTISlice; } + void setUseIntraLFNSTPBSlice ( bool b ) { m_intraLFNSTPBSlice = b; } + bool getUseIntraLFNSTPBSlice () const { return m_intraLFNSTPBSlice; } + void setUseInterLFNST ( bool b ) { m_interLFNST = b; } + bool getUseInterLFNST () const { return m_interLFNST; } +#else void setUseLFNST ( bool b ) { m_LFNST = b; } bool getUseLFNST () const { return m_LFNST; } +#endif void setUseSMVD(bool b) { m_SMVD = b; } bool getUseSMVD() const { return m_SMVD; } void setUseBcw ( bool b ) { m_bcw = b; } diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp index 4c0b9d24ab785eb8122608a378560cb99e8288ce..1e48b2621a9eca7654c56db0917726195daeb3e2 100644 --- a/source/Lib/CommonLib/TrQuant.cpp +++ b/source/Lib/CommonLib/TrQuant.cpp @@ -477,7 +477,13 @@ void TrQuant::xInvLfnst( const TransformUnit &tu, const ComponentID compID ) #endif { #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, CU::isIntra( *( tu.cu ) ) ); +#endif if( allowNSPT ) { return; @@ -770,7 +776,13 @@ void TrQuant::xFwdLfnst( const TransformUnit &tu, const ComponentID compID, cons #endif { #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, CU::isIntra( *( tu.cu ) ) ); +#endif if( allowNSPT ) { return; @@ -1057,7 +1069,13 @@ void TrQuant::invTransformNxN( TransformUnit &tu, const ComponentID &compID, Pel DTRACE_COEFF_BUF(D_TCOEFF, tempCoeff, tu, tu.cu->predMode, compID); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + if( ( spsIntraLfnstEnabled && CU::isIntra( *tu.cu ) ) || ( tu.cs->sps->getUseInterLFNST() && CU::isInter( *tu.cu ) ) ) +#else if (tu.cs->sps->getUseLFNST()) +#endif { xInvLfnst(tu, compID); } @@ -1393,8 +1411,14 @@ void TrQuant::xT( const TransformUnit &tu, const ComponentID &compID, const CPel #endif #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else const bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, CU::isIntra( *(tu.cu) ) ); #endif +#endif #if EXTENDED_LFNST if( tu.cs->sps->getUseLFNST() && tu.cu->lfnstIdx && width >= 4 && height >= 4) @@ -1405,10 +1429,18 @@ void TrQuant::xT( const TransformUnit &tu, const ComponentID &compID, const CPel skipHeight = height - lfnst_threshold; } #else +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT +#if JVET_AC0130_NSPT + if( ( ( spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ) || ( tu.cs->sps->getUseInterLFNST() && CU::isInter( *( tu.cu ) ) ) ) && tu.cu->lfnstIdx && !allowNSPT ) +#else + if( ( ( spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ) || ( tu.cs->sps->getUseInterLFNST() && CU::isInter( *( tu.cu ) ) ) ) && tu.cu->lfnstIdx ) +#endif +#else #if JVET_AC0130_NSPT if( tu.cs->sps->getUseLFNST() && tu.cu->lfnstIdx && !allowNSPT ) #else if( tu.cs->sps->getUseLFNST() && tu.cu->lfnstIdx ) +#endif #endif { if( ( width == 4 && height > 16 ) || ( width > 16 && height == 4 ) ) @@ -1516,8 +1548,14 @@ void TrQuant::xIT( const TransformUnit &tu, const ComponentID &compID, const CCo #endif #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else const bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, CU::isIntra( *(tu.cu) ) ); #endif +#endif #if EXTENDED_LFNST if (tu.cs->sps->getUseLFNST() && tu.cu->lfnstIdx && width >= 4 && height >= 4) @@ -1528,10 +1566,18 @@ void TrQuant::xIT( const TransformUnit &tu, const ComponentID &compID, const CCo skipHeight = height - lfnst_threshold; } #else +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT +#if JVET_AC0130_NSPT + if( ( ( spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ) || ( tu.cs->sps->getUseInterLFNST() && CU::isInter( *( tu.cu ) ) ) ) && tu.cu->lfnstIdx && !allowNSPT ) +#else + if( ( ( spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ) || ( tu.cs->sps->getUseInterLFNST() && CU::isInter( *( tu.cu ) ) ) ) && tu.cu->lfnstIdx ) +#endif +#else #if JVET_AC0130_NSPT if( tu.cs->sps->getUseLFNST() && tu.cu->lfnstIdx && !allowNSPT ) #else if( tu.cs->sps->getUseLFNST() && tu.cu->lfnstIdx ) +#endif #endif { if( ( width == 4 && height > 16 ) || ( width > 16 && height == 4 ) ) @@ -2130,14 +2176,26 @@ void TrQuant::transformNxN( TransformUnit& tu, const ComponentID& compID, const xT(tu, compID, resiBuf, tempCoeff, uiWidth, uiHeight); } #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + if( ( spsIntraLfnstEnabled && CU::isIntra( *tu.cu ) ) || ( sps.getUseInterLFNST() && CU::isInter( *tu.cu ) ) ) +#else if (sps.getUseLFNST()) +#endif { xFwdLfnst(tu, compID); } #endif } #if !JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + if( ( spsIntraLfnstEnabled && CU::isIntra( *tu.cu ) ) || ( sps.getUseInterLFNST() && CU::isInter( *tu.cu ) ) ) +#else if (sps.getUseLFNST()) +#endif { xFwdLfnst(tu, compID, loadTr); } @@ -2388,7 +2446,13 @@ void TrQuant::predCoeffSigns(TransformUnit &tu, const ComponentID compID, const int log2Width = floorLog2(uiWidth); int log2Height = floorLog2(uiHeight); int actualTrIdx = 0, actualLfnstIdx = 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool lfnstEnabled = ( ( ( spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ) || ( tu.cu->cs->sps->getUseInterLFNST() && CU::isInter( *( tu.cu ) ) ) ) && tu.checkLFNSTApplied( residCompID ) ); +#else bool lfnstEnabled = tu.checkLFNSTApplied(residCompID); +#endif if (lfnstEnabled) { actualLfnstIdx = getLfnstIdx(tu, residCompID); @@ -2785,7 +2849,13 @@ int TrQuant::getLfnstIdx(const TransformUnit &tu, ComponentID compID) CHECK((lfnstIdx != 1) && (lfnstIdx != 2), "invalid lfnst idx"); #endif #if JVET_AC0130_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, area.width, area.height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed( tu, compID, area.width, area.height, CU::isIntra( *( tu.cu ) ) ); +#endif intraMode = allowNSPT ? PU::getNSPTIntraMode( PU::getWideAngle( tu, intraMode, compID ) ) : getLFNSTIntraMode( PU::getWideAngle( tu, intraMode, compID ) ); #else intraMode = getLFNSTIntraMode(PU::getWideAngle(tu, intraMode, compID)); diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 1b0ab966ea3dfdc2e236b4c9dde77996da41bd0f..4e39367b5b4fca2d8ea6128817c64278379ebaea 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -402,6 +402,7 @@ #define JVET_AG0061_INTER_LFNST_NSPT 1 // JVET-AG0061: 3.3 Utilizing LFNST/NSPT for inter coding #define JVET_AG0100_TRANSFORM_COEFFICIENT_CODING 1 // JVET_AG0100: 3.2b Transform coefficient coding #define JVET_AG0143_INTER_INTRA 1 // JVET_AG0143: 3.1c CABAC inter/intra model switch +#define JVET_AH0103_LOW_DELAY_LFNST_NSPT 1 // JVET_AH0103: Low-delay configurations for LFNST/NSPT // Entropy Coding #define EC_HIGH_PRECISION 1 // CABAC high precision diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 2b943a60ab2bb972a63e93b53ba470597dd95489..8823129e63632b98158936ceb5e4234690e8d8a5 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -29700,7 +29700,11 @@ bool CU::isNSPTAllowed( const TransformUnit &tu, const ComponentID compID, int w { bool allowNSPT = isIntra; #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( tu.cs->sps->getUseInterLFNST() && CU::isInter( *tu.cu ) ) +#else if (CU::isInter(*tu.cu)) +#endif { allowNSPT = true; } diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 72ab4d649d397e1b1baa0e749e6ab4c14088554c..0eb3543011dbe31271930946705a4eae4bc3e485 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -8519,7 +8519,13 @@ void CABACReader::residual_coding( TransformUnit& tu, ComponentID compID, CUCtx& #if JVET_AC0130_NSPT uint32_t width = tu.blocks[ compID ].width; uint32_t height = tu.blocks[ compID ].height; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, CU::isIntra( *( tu.cu ) ) ); +#endif #if JVET_W0119_LFNST_EXTENSION const int maxLfnstPos = ( allowNSPT ? PU::getNSPTMatrixDim( width, height ) : PU::getLFNSTMatrixDim( width, height ) ) - 1; @@ -8782,13 +8788,25 @@ void CABACReader::residual_lfnst_mode( CodingUnit& cu, CUCtx& cuCtx ) int chIdx = CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_CHROMA ? 1 : 0; #else int chIdx = cu.isSepTree() && cu.chType == CHANNEL_TYPE_CHROMA ? 1 : 0; +#endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( cu.slice->getSliceType() == I_SLICE && cu.cs->sps->getUseIntraLFNSTISlice() ) || + ( cu.slice->getSliceType() != I_SLICE && cu.cs->sps->getUseIntraLFNSTPBSlice() ) ); #endif if ((cu.ispMode && !CU::canUseLfnstWithISP(cu, cu.chType)) +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT +#if JVET_V0130_INTRA_TMP + || ( spsIntraLfnstEnabled && CU::isIntra( cu ) && ( ( cu.mipFlag && !allowLfnstWithMip( cu.firstPU->lumaSize() ) ) || ( cu.tmpFlag && !allowLfnstWithTmp() ) ) ) +#else + || ( spsIntraLfnstEnabled && CU::isIntra( cu ) && cu.mipFlag && !allowLfnstWithMip( cu.firstPU->lumaSize() ) ) +#endif +#else #if JVET_V0130_INTRA_TMP || (cu.cs->sps->getUseLFNST() && CU::isIntra(cu) && ((cu.mipFlag && !allowLfnstWithMip(cu.firstPU->lumaSize())) || (cu.tmpFlag && !allowLfnstWithTmp()))) #else || (cu.cs->sps->getUseLFNST() && CU::isIntra(cu) && cu.mipFlag && !allowLfnstWithMip(cu.firstPU->lumaSize())) #endif +#endif #if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS || (CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_CHROMA && std::min(cu.blocks[1].width, cu.blocks[1].height) < 4) #else @@ -8811,9 +8829,17 @@ void CABACReader::residual_lfnst_mode( CodingUnit& cu, CUCtx& cuCtx ) #endif #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( ( spsIntraLfnstEnabled && CU::isIntra( cu ) ) || ( cu.cs->sps->getUseInterLFNST() && CU::isInter( cu ) ) ) +#else if (cu.cs->sps->getUseLFNST() && (CU::isIntra(cu) || CU::isInter(cu))) +#endif +#else +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && CU::isIntra( cu ) ) #else if (cu.cs->sps->getUseLFNST() && CU::isIntra(cu)) +#endif #endif { #if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 882575d6aae92ac71ad3b1a7269d9d8bbaee71aa..d099894c61ace4fa7c2052019d02d21887300f3a 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2085,8 +2085,14 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) } #endif } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + READ_FLAG( uiCode, "sps_intra_lfnst_intra_slice_enabled_flag" ); pcSPS->setUseIntraLFNSTISlice( uiCode != 0 ); + READ_FLAG( uiCode, "sps_intra_lfnst_inter_slice_enabled_flag" ); pcSPS->setUseIntraLFNSTPBSlice( uiCode != 0 ); + READ_FLAG( uiCode, "sps_inter_lfnst_enabled_flag" ); pcSPS->setUseInterLFNST( uiCode != 0 ); +#else READ_FLAG(uiCode, "sps_lfnst_enabled_flag"); pcSPS->setUseLFNST(uiCode != 0); #endif +#endif #if JVET_S0052_RM_SEPARATE_COLOUR_PLANE if (pcSPS->getChromaFormatIdc() != CHROMA_400) @@ -2916,7 +2922,13 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) } #endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsLfnstEnabled = ( pcSPS->getUseIntraLFNSTISlice() || pcSPS->getUseIntraLFNSTPBSlice() ); + spsLfnstEnabled |= pcSPS->getUseInterLFNST(); + if( spsLfnstEnabled && pcSPS->getScalingListFlag() ) +#else if (pcSPS->getUseLFNST() && pcSPS->getScalingListFlag()) +#endif { READ_FLAG(uiCode, "scaling_matrix_for_lfnst_disabled_flag"); pcSPS->setDisableScalingMatrixForLfnstBlks(uiCode ? true : false); } diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 7836398289583cd5b10b10f12f5d953b3916f87c..bbbef76b7823bd0f89c1fec41d0e8d6cde6bf6bb 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -8302,7 +8302,13 @@ void CABACWriter::residual_coding( const TransformUnit& tu, ComponentID compID, #if JVET_AC0130_NSPT uint32_t width = tu.blocks[compID].width; uint32_t height = tu.blocks[compID].height; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tu.cu->slice->getSliceType() == I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTISlice() ) || + ( tu.cu->slice->getSliceType() != I_SLICE && tu.cu->cs->sps->getUseIntraLFNSTPBSlice() ) ); + bool allowNSPT = CU::isNSPTAllowed( tu, compID, width, height, spsIntraLfnstEnabled && CU::isIntra( *( tu.cu ) ) ); +#else bool allowNSPT = CU::isNSPTAllowed(tu, compID, width, height, CU::isIntra(*(tu.cu))); +#endif #if JVET_W0119_LFNST_EXTENSION const int maxLfnstPos = (allowNSPT ? PU::getNSPTMatrixDim(width, height) : PU::getLFNSTMatrixDim(width, height)) - 1; @@ -8578,13 +8584,25 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) int chIdx = CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_CHROMA ? 1 : 0; #else int chIdx = cu.isSepTree() && cu.chType == CHANNEL_TYPE_CHROMA ? 1 : 0; +#endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( cu.slice->getSliceType() == I_SLICE && cu.cs->sps->getUseIntraLFNSTISlice() ) || + ( cu.slice->getSliceType() != I_SLICE && cu.cs->sps->getUseIntraLFNSTPBSlice() ) ); #endif if( ( cu.ispMode && !CU::canUseLfnstWithISP( cu, cu.chType ) ) || +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT +#if JVET_V0130_INTRA_TMP + ( spsIntraLfnstEnabled && CU::isIntra( cu ) && ( ( cu.mipFlag && !allowLfnstWithMip( cu.firstPU->lumaSize() ) ) || ( cu.tmpFlag && !allowLfnstWithTmp() ) ) ) || +#else + ( spsIntraLfnstEnabled && CU::isIntra( cu ) && cu.mipFlag && !allowLfnstWithMip( cu.firstPU->lumaSize() ) ) || +#endif +#else #if JVET_V0130_INTRA_TMP (cu.cs->sps->getUseLFNST() && CU::isIntra(cu) && ((cu.mipFlag && !allowLfnstWithMip(cu.firstPU->lumaSize())) || (cu.tmpFlag && !allowLfnstWithTmp()))) || #else (cu.cs->sps->getUseLFNST() && CU::isIntra(cu) && cu.mipFlag && !allowLfnstWithMip(cu.firstPU->lumaSize())) || #endif +#endif #if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS (CS::isDualITree(*cu.cs) && cu.chType == CHANNEL_TYPE_CHROMA && std::min(cu.blocks[1].width, cu.blocks[1].height) < 4) #else @@ -8606,9 +8624,17 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) #endif #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( ( spsIntraLfnstEnabled && CU::isIntra( cu ) ) || ( cu.cs->sps->getUseInterLFNST() && CU::isInter( cu ) ) ) +#else if (cu.cs->sps->getUseLFNST() && (CU::isIntra(cu) || CU::isInter(cu))) +#endif +#else +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && CU::isIntra( cu ) ) #else if (cu.cs->sps->getUseLFNST() && CU::isIntra(cu)) +#endif #endif { #if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index cb7aed7c7604e767f013ccdf5b027c16d354f573..eff9b562b6818c873dc4fc89c1aeedae6d6dc22a 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -407,8 +407,17 @@ protected: bool m_SBT; ///< Sub-Block Transform for inter blocks int m_SBTFast64WidthTh; ///< Enable size-64 SBT in encoder RDO check for HD and above sequences +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool m_intraLFNSTISlice; + bool m_intraLFNSTPBSlice; + bool m_interLFNST; +#else bool m_LFNST; +#endif bool m_useFastLFNST; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool m_useFastInterLFNST; +#endif bool m_sbTmvpEnableFlag; bool m_Affine; bool m_AffineType; @@ -1532,10 +1541,23 @@ public: bool getSubPicIdMappingInSpsFlag () { return m_subPicIdMappingInSpsFlag; } uint32_t getSubPicIdLen () { return m_subPicIdLen; } uint32_t getSubPicId (int i) { return m_subPicId[i]; } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + void setIntraLFNSTISlice ( bool b ) { m_intraLFNSTISlice = b; } + bool getIntraLFNSTISlice() const { return m_intraLFNSTISlice; } + void setIntraLFNSTPBSlice ( bool b ) { m_intraLFNSTPBSlice = b; } + bool getIntraLFNSTPBSlice() const { return m_intraLFNSTPBSlice; } + void setInterLFNST ( bool b ) { m_interLFNST = b; } + bool getInterLFNST() const { return m_interLFNST; } +#else void setLFNST ( bool b ) { m_LFNST = b; } bool getLFNST() const { return m_LFNST; } +#endif void setUseFastLFNST ( bool b ) { m_useFastLFNST = b; } bool getUseFastLFNST() const { return m_useFastLFNST; } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + void setUseFastInterLFNST ( bool b ) { m_useFastInterLFNST = b; } + bool getUseFastInterLFNST() const { return m_useFastInterLFNST; } +#endif void setUseLMChroma ( int n ) { m_LMChroma = n; } int getUseLMChroma() const { return m_LMChroma; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 3398fb01e2e3b4a4fc66e4270b2db771f94c748b..336a73354b6a25c87e9d1c1bae42b17fe7f63a96 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -2530,9 +2530,17 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS #endif #endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( tempCS->slice->getSliceType() == I_SLICE && sps.getUseIntraLFNSTISlice() ) || + ( tempCS->slice->getSliceType() != I_SLICE && sps.getUseIntraLFNSTPBSlice() ) ); +#endif bool skipOtherLfnst = false; int startLfnstIdx = 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + int endLfnstIdx = spsIntraLfnstEnabled ? maxLfnstIdx : 0; +#else int endLfnstIdx = sps.getUseLFNST() ? maxLfnstIdx : 0; +#endif #if INTRA_TRANS_ENC_OPT if (m_pcEncCfg->getIntraPeriod() == 1) { @@ -2545,8 +2553,12 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS #endif #if JVET_W0103_INTRA_MTS int grpNumMax = 1; +#else +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + int grpNumMax = spsIntraLfnstEnabled ? m_pcEncCfg->getMTSIntraMaxCand() : 1; #else int grpNumMax = sps.getUseLFNST() ? m_pcEncCfg->getMTSIntraMaxCand() : 1; +#endif #endif m_modeCtrl->setISPWasTested(false); m_pcIntraSearch->invalidateBestModeCost(); @@ -2794,7 +2806,11 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS for( int trGrpIdx = 0; trGrpIdx < grpNumMax; trGrpIdx++ ) { const uint8_t startMtsFlag = trGrpIdx > 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + const uint8_t endMtsFlag = spsIntraLfnstEnabled ? considerMtsSecondPass : 0; +#else const uint8_t endMtsFlag = sps.getUseLFNST() ? considerMtsSecondPass : 0; +#endif if( ( trGrpIdx == 0 || ( !skipSecondMtsPass && considerMtsSecondPass ) ) && trGrpCheck[ trGrpIdx ] ) { @@ -2811,7 +2827,11 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS continue; } //3) if interHad is 0, only try further modes if some intra mode was already better than inter +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && m_pcEncCfg->getUsePbIntraFast() && !tempCS->slice->isIntra() && bestCU && CU::isInter( *bestCS->getCU( partitioner.chType ) ) && interHad == 0 ) +#else if( sps.getUseLFNST() && m_pcEncCfg->getUsePbIntraFast() && !tempCS->slice->isIntra() && bestCU && CU::isInter( *bestCS->getCU( partitioner.chType ) ) && interHad == 0 ) +#endif { continue; } @@ -3362,7 +3382,11 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS if( !mtsFlag ) static_cast< double& >( costSize2Nx2NmtsFirstPass ) = tempCS->cost; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && !tempCS->cus.empty() ) +#else if( sps.getUseLFNST() && !tempCS->cus.empty() ) +#endif { skipOtherLfnst = m_modeCtrl->checkSkipOtherLfnst( encTestMode, tempCS, partitioner ); } @@ -3385,7 +3409,11 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS } } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( !spsIntraLfnstEnabled ) +#else if( !sps.getUseLFNST() ) +#endif { xCheckBestMode( tempCS, bestCS, partitioner, encTestMode ); } @@ -3465,7 +3493,11 @@ bool EncCu::xCheckRDCostIntra(CodingStructure *&tempCS, CodingStructure *&bestCS } //for lfnstIdx } //if (!skipSecondMtsPass && considerMtsSecondPass && trGrpCheck[iGrpIdx]) +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && trGrpIdx < 3 ) +#else if( sps.getUseLFNST() && trGrpIdx < 3 ) +#endif { trGrpCheck[ trGrpIdx + 1 ] = false; @@ -21571,7 +21603,11 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS #if JVET_AG0061_INTER_LFNST_NSPT cu->lfnstFlag = false; cu->lfnstIdx = 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + const bool lfnstAllowed = tempCS->sps->getUseInterLFNST() && CU::isInter( *cu ) +#else const bool lfnstAllowed = tempCS->sps->getUseLFNST() && CU::isInter(*cu) +#endif && partitioner.currArea().lwidth() <= tempCS->sps->getMaxTbSize() && partitioner.currArea().lheight() <= tempCS->sps->getMaxTbSize(); #endif @@ -22016,7 +22052,11 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS bool testLN = true; if (bestCost != MAX_DOUBLE && LNOffCost != MAX_DOUBLE) { +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + double th = m_pcEncCfg->getUseFastInterLFNST() ? 1.01 : std::max( ( 1.0 + 1.0 / sqrt( cu->lwidth() * cu->lheight() ) ), 1.07 ); +#else double th = std::max((1.0 + 1.0 / sqrt(cu->lwidth() * cu->lheight())), 1.07); +#endif if (!(prevBestLN == 0 || m_LNCostSave == MAX_DOUBLE)) { assert(m_sbtCostSave[1] <= m_LNCostSave); diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 39e3ee26b9b52b22b6e8fd2a5b8e8592134f3b12..817b49b30043ca29a3715219a89b390f6ef93e8c 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1809,7 +1809,13 @@ void EncLib::xInitSPS( SPS& sps ) sps.setLog2SignPredArea (m_log2SignPredArea); #endif #endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + sps.setUseIntraLFNSTISlice ( m_intraLFNSTISlice ); + sps.setUseIntraLFNSTPBSlice ( m_intraLFNSTPBSlice ); + sps.setUseInterLFNST ( m_interLFNST ); +#else sps.setUseLFNST ( m_LFNST ); +#endif sps.setSbTMVPEnabledFlag(m_sbTmvpEnableFlag); sps.setAMVREnabledFlag ( m_ImvMode != IMV_OFF ); sps.setBDOFEnabledFlag ( m_BIO ); diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index c5a1b6ba21ebf85699a522ca11640f9da5ebedea..6ac68ae8981d9447a93c24416d3181a720e16754 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -743,9 +743,18 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c }; CHECK( !cu.firstPU, "CU has no PUs" ); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( cu.slice->getSliceType() == I_SLICE && cu.cs->sps->getUseIntraLFNSTISlice() ) || + ( cu.slice->getSliceType() != I_SLICE && cu.cs->sps->getUseIntraLFNSTPBSlice() ) ); +#endif // variables for saving fast intra modes scan results across multiple LFNST passes +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool LFNSTLoadFlag = spsIntraLfnstEnabled && cu.lfnstIdx != 0; + bool LFNSTSaveFlag = spsIntraLfnstEnabled && cu.lfnstIdx == 0; +#else bool LFNSTLoadFlag = sps.getUseLFNST() && cu.lfnstIdx != 0; bool LFNSTSaveFlag = sps.getUseLFNST() && cu.lfnstIdx == 0; +#endif LFNSTSaveFlag &= sps.getUseIntraMTS() ? cu.mtsFlag == 0 : true; #if JVET_AB0155_SGPM @@ -772,7 +781,11 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c const int maxSizeEMT = MTS_INTRA_MAX_CU_SIZE; if( width <= maxSizeEMT && height <= maxSizeEMT && sps.getUseIntraMTS() ) { +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + mtsUsageFlag = ( spsIntraLfnstEnabled && cu.mtsFlag == 1 ) ? 2 : 1; +#else mtsUsageFlag = ( sps.getUseLFNST() && cu.mtsFlag == 1 ) ? 2 : 1; +#endif } if( width * height < 64 && !m_pcEncCfg->getUseFastLFNST() ) @@ -845,8 +858,13 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c int numTotalPartsVer = (int)height >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_HORZ_SPLIT)); m_ispTestedModes[0].init( numTotalPartsHor, numTotalPartsVer ); //the total number of subpartitions is modified to take into account the cases where LFNST cannot be combined with ISP due to size restrictions +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + numTotalPartsHor = spsIntraLfnstEnabled && CU::canUseLfnstWithISP( cu.Y(), HOR_INTRA_SUBPARTITIONS ) ? numTotalPartsHor : 0; + numTotalPartsVer = spsIntraLfnstEnabled && CU::canUseLfnstWithISP( cu.Y(), VER_INTRA_SUBPARTITIONS ) ? numTotalPartsVer : 0; +#else numTotalPartsHor = sps.getUseLFNST() && CU::canUseLfnstWithISP(cu.Y(), HOR_INTRA_SUBPARTITIONS) ? numTotalPartsHor : 0; numTotalPartsVer = sps.getUseLFNST() && CU::canUseLfnstWithISP(cu.Y(), VER_INTRA_SUBPARTITIONS) ? numTotalPartsVer : 0; +#endif for (int j = 1; j < NUM_LFNST_NUM_PER_SET; j++) { m_ispTestedModes[j].init(numTotalPartsHor, numTotalPartsVer); @@ -2750,7 +2768,11 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c { THROW("Full search not supported for MIP"); } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && mtsUsageFlag == 1 ) +#else if (sps.getUseLFNST() && mtsUsageFlag == 1) +#endif { // Store the modes to be checked with RD m_savedNumRdModes[lfnstIdx] = numModesForFullRD; @@ -2864,7 +2886,11 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c { uiRdModeList.resize(std::min<size_t>(uiRdModeList.size(), maxSize)); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && mtsUsageFlag == 1 ) +#else if (sps.getUseLFNST() && mtsUsageFlag == 1) +#endif { // Update also the number of stored modes to avoid partial fill of mode storage m_savedNumRdModes[lfnstIdx] = std::min<int32_t>(int32_t(uiRdModeList.size()), m_savedNumRdModes[lfnstIdx]); @@ -2895,7 +2921,11 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c } } #if JVET_Y0142_ADAPT_INTRA_MTS +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && m_modesForMTS.size() == 0 && cu.mtsFlag ) +#else if (sps.getUseLFNST() && m_modesForMTS.size() == 0 && cu.mtsFlag) +#endif { return false; } @@ -2964,7 +2994,11 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c if ( testISP ) { // we reserve positions for ISP in the common full RD list +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + const int maxNumRDModesISP = spsIntraLfnstEnabled ? 16 * NUM_LFNST_NUM_PER_SET : 16; +#else const int maxNumRDModesISP = sps.getUseLFNST() ? 16 * NUM_LFNST_NUM_PER_SET : 16; +#endif m_curIspLfnstIdx = 0; for (int i = 0; i < maxNumRDModesISP; i++) { @@ -3422,10 +3456,18 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c } validReturn |= tmpValidReturn; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT +#if JVET_W0123_TIMD_FUSION + if( spsIntraLfnstEnabled && mtsUsageFlag == 1 && !cu.ispMode && mode >= 0 && !cu.timd ) +#else + if( spsIntraLfnstEnabled && mtsUsageFlag == 1 && !cu.ispMode && mode >= 0 ) +#endif +#else #if JVET_W0123_TIMD_FUSION if( sps.getUseLFNST() && mtsUsageFlag == 1 && !cu.ispMode && mode >= 0 && !cu.timd ) #else if( sps.getUseLFNST() && mtsUsageFlag == 1 && !cu.ispMode && mode >= 0 ) +#endif #endif { m_modeCostStore[lfnstIdx][mode] = tmpValidReturn ? csTemp->cost : (MAX_DOUBLE / 2.0); //(MAX_DOUBLE / 2.0) ?? @@ -3534,13 +3576,21 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c } #endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && mtsUsageFlag == 1 && !cu.ispMode ) +#else if( sps.getUseLFNST() && mtsUsageFlag == 1 && !cu.ispMode ) +#endif { m_bestModeCostStore[ lfnstIdx ] = csBest->cost; //cs.cost; m_bestModeCostValid[ lfnstIdx ] = true; } #if JVET_W0103_INTRA_MTS +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && m_globalBestCostStore > csBest->cost ) +#else if (sps.getUseLFNST() && m_globalBestCostStore > csBest->cost) +#endif { m_globalBestCostStore = csBest->cost; m_globalBestCostValid = true; @@ -10483,6 +10533,10 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par } bool validReturnFull = false; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( slice.getSliceType() == I_SLICE && sps.getUseIntraLFNSTISlice() ) || + ( slice.getSliceType() != I_SLICE && sps.getUseIntraLFNSTPBSlice() ) ); +#endif if( bCheckFull ) { @@ -10495,7 +10549,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par const bool mtsAllowed = CU::isMTSAllowed( cu, COMPONENT_Y ); std::vector<TrMode> trModes; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if( sps.getUseLFNST() ) +#endif { checkTransformSkip &= tsAllowed; checkTransformSkip &= !cu.mtsFlag; @@ -10557,12 +10615,21 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par Distortion singleDistTmpLuma = 0; uint64_t singleTmpFracBits = 0; double singleCostTmp = 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + int firstCheckId = ( spsIntraLfnstEnabled && mtsCheckRangeFlag && cu.mtsFlag ) ? mtsFirstCheckId : 0; + + //we add the MTS candidates to the loop. TransformSkip will still be the last one to be checked (when modeId == lastCheckId) as long as checkTransformSkip is true + int lastCheckId = spsIntraLfnstEnabled ? ( ( mtsCheckRangeFlag && cu.mtsFlag ) ? ( mtsLastCheckId + ( int ) checkTransformSkip ) : ( numTransformIndexCands - ( firstCheckId + 1 ) + ( int ) checkTransformSkip ) ) : + trModes[ nNumTransformCands - 1 ].first; + bool isNotOnlyOneMode = spsIntraLfnstEnabled ? lastCheckId != firstCheckId : nNumTransformCands != 1; +#else int firstCheckId = ( sps.getUseLFNST() && mtsCheckRangeFlag && cu.mtsFlag ) ? mtsFirstCheckId : 0; //we add the MTS candidates to the loop. TransformSkip will still be the last one to be checked (when modeId == lastCheckId) as long as checkTransformSkip is true int lastCheckId = sps.getUseLFNST() ? ( ( mtsCheckRangeFlag && cu.mtsFlag ) ? ( mtsLastCheckId + ( int ) checkTransformSkip ) : ( numTransformIndexCands - ( firstCheckId + 1 ) + ( int ) checkTransformSkip ) ) : trModes[ nNumTransformCands - 1 ].first; bool isNotOnlyOneMode = sps.getUseLFNST() ? lastCheckId != firstCheckId : nNumTransformCands != 1; +#endif if( isNotOnlyOneMode ) { @@ -10580,7 +10647,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par bool cbfBestModeValid = false; bool cbfDCT2 = true; #if JVET_W0103_INTRA_MTS +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && cu.mtsFlag ) +#else if (sps.getUseLFNST() && cu.mtsFlag) +#endif { xSelectAMTForFullRD(tu #if JVET_AG0136_INTRA_TMP_LIC @@ -10591,11 +10662,19 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par #endif double bestDCT2cost = MAX_DOUBLE; double threshold = m_pcEncCfg->getUseFastISP() && !cu.ispMode && ispIsCurrentWinner && nNumTransformCands > 1 ? 1 + 1.4 / sqrt( cu.lwidth() * cu.lheight() ) : 1; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + for( int modeId = firstCheckId; modeId <= ( spsIntraLfnstEnabled ? lastCheckId : ( nNumTransformCands - 1 ) ); modeId++ ) +#else for( int modeId = firstCheckId; modeId <= ( sps.getUseLFNST() ? lastCheckId : ( nNumTransformCands - 1 ) ); modeId++ ) +#endif { uint8_t transformIndex = modeId; #if JVET_W0103_INTRA_MTS +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && cu.mtsFlag ) +#else if (sps.getUseLFNST() && cu.mtsFlag) +#endif { if (modeId >= m_numCandAMTForFullRD) { @@ -10607,7 +10686,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par m_validMTSReturn = true; #endif #endif +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if( sps.getUseLFNST() ) +#endif { if( ( transformIndex < lastCheckId ) || ( ( transformIndex == lastCheckId ) && !checkTransformSkip ) ) //we avoid this if the mode is transformSkip { @@ -10649,13 +10732,21 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par int default0Save1Load2 = 0; singleDistTmpLuma = 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( modeId == firstCheckId && ( spsIntraLfnstEnabled ? ( modeId != lastCheckId ) : ( nNumTransformCands > 1 ) ) ) +#else if( modeId == firstCheckId && ( sps.getUseLFNST() ? ( modeId != lastCheckId ) : ( nNumTransformCands > 1 ) ) ) +#endif { default0Save1Load2 = 1; } else if (modeId != firstCheckId) { +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && !cbfBestModeValid ) +#else if( sps.getUseLFNST() && !cbfBestModeValid ) +#endif { default0Save1Load2 = 1; } @@ -10668,7 +10759,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par { default0Save1Load2 = 0; } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if( sps.getUseLFNST() ) +#endif { if( cu.mtsFlag ) { @@ -10777,7 +10872,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par #endif //----- determine rate and r-d cost ----- +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( ( spsIntraLfnstEnabled ? ( modeId == lastCheckId && modeId != 0 && checkTransformSkip ) : ( trModes[ modeId ].first != 0 ) ) && !TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ) ) +#else if( ( sps.getUseLFNST() ? ( modeId == lastCheckId && modeId != 0 && checkTransformSkip ) : ( trModes[ modeId ].first != 0 ) ) && !TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ) ) +#endif { //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden. if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless()) @@ -10850,7 +10949,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par bestDCT2cost = singleCostTmp; } #if JVET_W0103_INTRA_MTS +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && cu.mtsFlag ) +#else if (sps.getUseLFNST() && cu.mtsFlag) +#endif { if (singleCostTmp != MAX_DOUBLE) { @@ -10879,7 +10982,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par uiSingleDistLuma = singleDistTmpLuma; singleFracBits = singleTmpFracBits; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if( sps.getUseLFNST() ) +#endif { bestModeId[ COMPONENT_Y ] = modeId; cbfBestMode = TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ); @@ -10916,7 +11023,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par } } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && !validReturnFull ) +#else if( sps.getUseLFNST() && !validReturnFull ) +#endif { csFull->cost = MAX_DOUBLE; @@ -10992,7 +11103,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par #endif #endif subTuCounter += subTuCounter != -1 ? 1 : 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled && !tmpValidReturnSplit ) +#else if( sps.getUseLFNST() && !tmpValidReturnSplit ) +#endif { splitIsSelected = false; break; @@ -11070,7 +11185,11 @@ bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &par bool retVal = false; if( csFull || csSplit ) { +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( !spsIntraLfnstEnabled || validReturnFull || validReturnSplit ) +#else if( !sps.getUseLFNST() || validReturnFull || validReturnSplit ) +#endif { // otherwise this would've happened in useSubStructure #if JVET_Z0118_GDR @@ -11119,6 +11238,10 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti } bool validReturnFull = false; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsIntraLfnstEnabled = ( ( slice.getSliceType() == I_SLICE && sps.getUseIntraLFNSTISlice() ) || + ( slice.getSliceType() != I_SLICE && sps.getUseIntraLFNSTPBSlice() ) ); +#endif if (bCheckFull) { @@ -11225,7 +11348,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti const bool mtsAllowed = CU::isMTSAllowed(cu, COMPONENT_Y); std::vector<TrMode> trModes; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if (sps.getUseLFNST()) +#endif { checkTransformSkip &= tsAllowed; checkTransformSkip &= !cu.mtsFlag; @@ -11276,9 +11403,15 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti Distortion singleDistTmpLuma = 0; uint64_t singleTmpFracBits = 0; double singleCostTmp = 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + int firstCheckId = ( spsIntraLfnstEnabled && mtsCheckRangeFlag && cu.mtsFlag ) ? mtsFirstCheckId : 0; + int lastCheckId = spsIntraLfnstEnabled ? ( ( mtsCheckRangeFlag && cu.mtsFlag ) ? ( mtsLastCheckId + ( int ) checkTransformSkip ) : ( numTransformIndexCands - ( firstCheckId + 1 ) + ( int ) checkTransformSkip ) ) : trModes[ nNumTransformCands - 1 ].first; + bool isNotOnlyOneMode = spsIntraLfnstEnabled ? lastCheckId != firstCheckId : nNumTransformCands != 1; +#else int firstCheckId = (sps.getUseLFNST() && mtsCheckRangeFlag && cu.mtsFlag) ? mtsFirstCheckId : 0; int lastCheckId = sps.getUseLFNST() ? ((mtsCheckRangeFlag && cu.mtsFlag) ? (mtsLastCheckId + (int)checkTransformSkip) : (numTransformIndexCands - (firstCheckId + 1) + (int)checkTransformSkip)) : trModes[nNumTransformCands - 1].first; bool isNotOnlyOneMode = sps.getUseLFNST() ? lastCheckId != firstCheckId : nNumTransformCands != 1; +#endif if (isNotOnlyOneMode) { @@ -11302,7 +11435,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti m_CABACEstimator->getCtx() = ctxStart; m_CABACEstimator->resetBits(); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if (sps.getUseLFNST()) +#endif { if ((transformIndex < lastCheckId) || ((transformIndex == lastCheckId) && !checkTransformSkip)) //we avoid this if the mode is transformSkip { @@ -11330,7 +11467,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti } singleDistTmpLuma = 0; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if (sps.getUseLFNST()) +#endif { if (cu.mtsFlag) { @@ -11406,7 +11547,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti cuCtx.isDQPCoded = true; cuCtx.isChromaQpAdjCoded = true; //----- determine rate and r-d cost ----- +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( ( spsIntraLfnstEnabled ? ( modeId == lastCheckId && modeId != 0 && checkTransformSkip ) : ( trModes[ modeId ].first != 0 ) ) && !TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ) ) +#else if ((sps.getUseLFNST() ? (modeId == lastCheckId && modeId != 0 && checkTransformSkip) : (trModes[modeId].first != 0)) && !TU::getCbfAtDepth(tu, COMPONENT_Y, currDepth)) +#endif { //In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden. if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless()) @@ -11449,7 +11594,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti dSingleCostLuma = singleCostTmp; validReturnFull = true; +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if (sps.getUseLFNST()) +#endif { bestLumaModeId = modeId; cbfBestMode = TU::getCbfAtDepth(tu, COMPONENT_Y, currDepth); @@ -11475,7 +11624,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless()) m_pcRdCost->lambdaAdjustColorTrans(false, COMPONENT_Y); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if (sps.getUseLFNST()) +#endif { if (!validReturnFull) { @@ -11885,7 +12038,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti do { bool tmpValidReturnSplit = xRecurIntraCodingACTQT(*csSplit, partitioner, mtsCheckRangeFlag, mtsFirstCheckId, mtsLastCheckId, moreProbMTSIdxFirst); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if (sps.getUseLFNST()) +#endif { if (!tmpValidReturnSplit) { @@ -11930,7 +12087,11 @@ bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &parti bool retVal = false; if (csFull || csSplit) { +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + if( spsIntraLfnstEnabled ) +#else if (sps.getUseLFNST()) +#endif { if (validReturnFull || validReturnSplit) { diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 56dcc142ef9dd781ceb6fc98f38f84acea4b8cf7..31d954c68cd4188f8686ee548fff4295ac6b980a 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1273,8 +1273,14 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) } #endif } +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + WRITE_FLAG( pcSPS->getUseIntraLFNSTISlice() ? 1 : 0, "sps_intra_lfnst_intra_slice_enabled_flag" ); + WRITE_FLAG( pcSPS->getUseIntraLFNSTPBSlice() ? 1 : 0, "sps_intra_lfnst_inter_slice_enabled_flag" ); + WRITE_FLAG( pcSPS->getUseInterLFNST() ? 1 : 0, "sps_inter_lfnst_enabled_flag" ); +#else WRITE_FLAG(pcSPS->getUseLFNST() ? 1 : 0, "sps_lfnst_enabled_flag"); #endif +#endif #if JVET_S0052_RM_SEPARATE_COLOUR_PLANE if (pcSPS->getChromaFormatIdc() != CHROMA_400) @@ -1884,8 +1890,14 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) } #if !JVET_S0074_SPS_REORDER WRITE_FLAG(pcSPS->getUseLmcs() ? 1 : 0, "sps_lmcs_enable_flag"); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + WRITE_FLAG( pcSPS->getUseIntraLFNSTISlice() ? 1 : 0, "sps_intra_lfnst_intra_slice_enabled_flag" ); + WRITE_FLAG( pcSPS->getUseIntraLFNSTPBSlice() ? 1 : 0, "sps_intra_lfnst_inter_slice_enabled_flag" ); + WRITE_FLAG( pcSPS->getUseInterLFNST() ? 1 : 0, "sps_inter_lfnst_enabled_flag" ); +#else WRITE_FLAG( pcSPS->getUseLFNST() ? 1 : 0, "sps_lfnst_enabled_flag" ); #endif +#endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET WRITE_FLAG( pcSPS->getLadfEnabled() ? 1 : 0, "sps_ladf_enabled_flag" ); if ( pcSPS->getLadfEnabled() ) @@ -1924,7 +1936,13 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) // KJS: remove scaling lists? WRITE_FLAG( pcSPS->getScalingListFlag() ? 1 : 0, "sps_explicit_scaling_list_enabled_flag" ); +#if JVET_AH0103_LOW_DELAY_LFNST_NSPT + bool spsLfnstEnabled = ( pcSPS->getUseIntraLFNSTISlice() || pcSPS->getUseIntraLFNSTPBSlice() ); + spsLfnstEnabled |= pcSPS->getUseInterLFNST(); + if( spsLfnstEnabled && pcSPS->getScalingListFlag() ) +#else if (pcSPS->getUseLFNST() && pcSPS->getScalingListFlag()) +#endif { WRITE_FLAG(pcSPS->getDisableScalingMatrixForLfnstBlks(), "scaling_matrix_for_lfnst_disabled_flag"); }