diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 314e6107e2fde7363acdc8788ff643d4a9ef2d85..e1483ee3c17f745febaadf9411caad51b27f5461 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -818,10 +818,16 @@ void EncApp::xInitLibCfg() m_cEncLib.setLFNST ( m_LFNST ); #endif m_cEncLib.setUseFastLFNST ( m_useFastLFNST ); +#if JVET_AI0050_INTER_MTSS + m_cEncLib.setUseInterMTSS ( m_useInterMTSS ); +#endif +#if JVET_AI0050_SBT_LFNST + m_cEncLib.setUseSBTLFNST ( m_useSbtLFNST ); +#endif #if JVET_AH0103_LOW_DELAY_LFNST_NSPT m_cEncLib.setUseFastInterLFNST ( m_useFastInterLFNST ); #endif - m_cEncLib.setSbTmvpEnabledFlag(m_sbTmvpEnableFlag); + m_cEncLib.setSbTmvpEnabledFlag ( m_sbTmvpEnableFlag ); m_cEncLib.setAffine ( m_Affine ); m_cEncLib.setAffineType ( m_AffineType ); #if JVET_AH0185_ADAPTIVE_COST_IN_MERGE_MODE diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 7b160512a50e84825abefd5e981a5c91ea378719..59b69bb2a865ca96df744c0d0b521fb1235568f7 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1040,6 +1040,12 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ( "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 +#if JVET_AI0050_INTER_MTSS + ("InterMTSS", m_useInterMTSS, true, "Inter MTSS (0:off, 1:on) [default: on]") +#endif +#if JVET_AI0050_SBT_LFNST + ("SbtLFNST", m_useSbtLFNST, true, "SBT-LFNST (0:off, 1:on) [default: on]") #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]") @@ -5611,6 +5617,12 @@ void EncAppCfg::xPrintParameter() msg( VERBOSE, "InterLFNST:%d ", m_interLFNST ); #else msg( VERBOSE, "LFNST:%d ", m_LFNST ); +#endif +#if JVET_AI0050_INTER_MTSS + msg( VERBOSE, "InterMTSS:%d ", m_useInterMTSS ); +#endif +#if JVET_AI0050_SBT_LFNST + msg( VERBOSE, "SbtLFNST:%d ", m_useSbtLFNST ); #endif msg( VERBOSE, "MMVD:%d ", m_MMVD); msg( VERBOSE, "Affine:%d ", m_Affine ); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 575cc28da064fa486c80f1566e3741d5ddb37302..6c50a6d66d2d29a018e6ec1d484cc3a3150aef2f 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -405,6 +405,12 @@ protected: bool m_useFastLFNST; #if JVET_AH0103_LOW_DELAY_LFNST_NSPT bool m_useFastInterLFNST; +#endif +#if JVET_AI0050_INTER_MTSS + bool m_useInterMTSS; +#endif +#if JVET_AI0050_SBT_LFNST + bool m_useSbtLFNST; #endif bool m_sbTmvpEnableFlag; bool m_Affine; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index a087ad31f93504d23bde207d6d1d1efcd01abef0..51cb7e3cc107222060f8f21d133b45da4366f97e 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -1554,6 +1554,9 @@ static const int SBT_MAX_SIZE = 64; ///< maxi #endif static const int SBT_NUM_SL = 10; ///< maximum number of historical PU decision saved for a CU static const int SBT_NUM_RDO = 2; ///< maximum number of SBT mode tried for a PU +#if JVET_AI0050_SBT_LFNST +static const int NUM_SBT_LFNST_RDO = 2; +#endif #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS static const int NUM_INTER_CU_INFO_SAVE = 8; ///< maximum number of inter cu information saved for fast algorithm static const int LDT_MODE_TYPE_INHERIT = 0; ///< No need to signal mode_constraint_flag, and the modeType of the region is inherited from its parent node diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h index ef4ba72feb6d0f88daa0fd5b2972e0c8e8b37a6f..e96d70a087aa0b8cae56237f39a8fc68979a7bb2 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -712,6 +712,9 @@ public: static const CtxSet LFNSTIdx; #if JVET_AG0061_INTER_LFNST_NSPT static const CtxSet InterLFNSTIdx; +#endif +#if JVET_AI0050_INTER_MTSS + static const CtxSet InterLFNSTIntraIdx; #endif static const CtxSet PLTFlag; static const CtxSet RotationFlag; diff --git a/source/Lib/CommonLib/Contexts_ecm14.0.inl b/source/Lib/CommonLib/Contexts_ecm14.0.inl index f6f8b4082085735922d9ee3ade079cd083093ae9..5e3bc38da798f973b4cfb8ccca13cee02c58e371 100644 --- a/source/Lib/CommonLib/Contexts_ecm14.0.inl +++ b/source/Lib/CommonLib/Contexts_ecm14.0.inl @@ -6445,6 +6445,31 @@ const CtxSet ContextSetCfg::obicFlag = ContextSetCfg::addCtxSet { 133 }, }); #endif +#if JVET_AI0050_INTER_MTSS +const CtxSet ContextSetCfg::InterLFNSTIntraIdx = ContextSetCfg::addCtxSet({ +// ctx 1599 1599 + { CNU }, + { CNU }, + { CNU }, + { CNU }, + { DWS }, + { DWS }, + { DWS }, + { DWS }, + { DWE }, + { DWE }, + { DWE }, + { DWE }, + { DWO }, + { DWO }, + { DWO }, + { DWO }, + { DWO }, + { DWO }, + { DWO }, + { DWO }, + }); +#endif #if JVET_AI0136_ADAPTIVE_DUAL_TREE const CtxSet ContextSetCfg::SeparateTree = ContextSetCfg::addCtxSet ({ diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 8987e8af9989c277975d139c0c648db3cf44284b..7d9ba857eec8cae15eee5afacbd03ddfaac0356c 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -11541,7 +11541,11 @@ void IntraPrediction::predChromaTM(const CompArea &areaCb, const CompArea &areaC #endif #if ENABLE_DIMD && (JVET_AB0067_MIP_DIMD_LFNST || JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST || JVET_AG0058_EIP || JVET_AG0061_INTER_LFNST_NSPT) -int IntraPrediction::deriveIpmForTransform(CPelBuf predBuf, CodingUnit& cu) +int IntraPrediction::deriveIpmForTransform(CPelBuf predBuf, CodingUnit& cu +#if JVET_AI0050_INTER_MTSS + , int &secondMode +#endif +) { if (!cu.slice->getSPS()->getUseDimd()) { @@ -11559,15 +11563,29 @@ int IntraPrediction::deriveIpmForTransform(CPelBuf predBuf, CodingUnit& cu) int firstAmp = 0, curAmp = 0; int firstMode = 0, curMode = 0; +#if JVET_AI0050_INTER_MTSS + int secondAmp = 0; +#endif for (int i = 0; i < NUM_LUMA_MODE; i++) { curAmp = histogram[i]; curMode = i; if (curAmp > firstAmp) { +#if JVET_AI0050_INTER_MTSS + secondAmp = firstAmp; + secondMode = firstMode; +#endif firstAmp = curAmp; firstMode = curMode; } +#if JVET_AI0050_INTER_MTSS + else if (curAmp > secondAmp) + { + secondAmp = curAmp; + secondMode = curMode; + } +#endif } return firstMode; } @@ -13602,7 +13620,17 @@ void IntraPrediction::predIntraMip( const ComponentID compId, PelBuf &piPred, co } pReducePred += reducedPredTemp.stride; } - int iMode = deriveIpmForTransform(reducedPredTemp, *pu.cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + int iMode = deriveIpmForTransform(reducedPredTemp, *pu.cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + pu.cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif pu.cu->mipDimdMode = iMode; } else @@ -16714,7 +16742,17 @@ void IntraPrediction::xTMPFusionApplyModel(PelBuf &piPred, unsigned int uiBlkWid if (bDeriveDimdMode) { CPelBuf predBuf = piPred; - cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif } #endif return; @@ -16766,7 +16804,17 @@ void IntraPrediction::xGenerateTmpFlmPred(PelBuf &piPred, unsigned int uiBlkWidt if (bDeriveDimdMode) { CPelBuf predBuf = piPred; - cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif } #endif return; @@ -16968,7 +17016,17 @@ bool IntraPrediction::generateTMPrediction( Pel* piPred, unsigned int uiStride, #if JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST CPelBuf predBuf(pPred, uiStride, uiWidth, uiHeight); - cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif #endif return bSucceedFlag; } @@ -17330,7 +17388,17 @@ bool IntraPrediction::generateTMPrediction(Pel *piPred, unsigned int uiStride, i { #endif CPelBuf predBuf(pPred, uiStride, uiWidth, uiHeight); - pu.cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *pu.cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + pu.cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *pu.cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + pu.cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif #if JVET_AD0086_ENHANCED_INTRA_TMP } #endif @@ -17745,7 +17813,17 @@ bool IntraPrediction::generateTmDcPrediction( Pel* piPred, unsigned int uiStride } #if JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST CPelBuf predBuf(pPred, uiStride, uiBlkWidth, uiBlkHeight); - cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + cu->intraTmpDimdMode = deriveIpmForTransform(predBuf, *cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif #endif return bSucceedFlag; } diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h index faa92c10712db077ca31014e55cde2223211bf93..782590472d841805d9e0402a5de087b54af4efb9 100644 --- a/source/Lib/CommonLib/IntraPrediction.h +++ b/source/Lib/CommonLib/IntraPrediction.h @@ -801,7 +801,11 @@ public: #endif #endif #if ENABLE_DIMD && (JVET_AB0067_MIP_DIMD_LFNST || JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST || JVET_AG0058_EIP || JVET_AG0061_INTER_LFNST_NSPT) - static int deriveIpmForTransform(CPelBuf predBuf, CodingUnit& cu); + static int deriveIpmForTransform(CPelBuf predBuf, CodingUnit& cu +#if JVET_AI0050_INTER_MTSS + , int &secondMode +#endif + ); #endif #if !JVET_AG0061_INTER_LFNST_NSPT static int buildHistogram ( const Pel *pReco, int iStride, uint32_t uiHeight, uint32_t uiWidth, int* piHistogram, int direction, int bw, int bh ); diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index f6086c6aa73e55bc1bb209deb9dc564a8f7d6479..ae3e064254d97f445d6e5fcb9c32b4b27c7ae576 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1624,6 +1624,12 @@ private: bool m_enableMaxMttIncrease; #endif bool m_SBT; +#if JVET_AI0050_INTER_MTSS + bool m_interMTSS; +#endif +#if JVET_AI0050_SBT_LFNST + bool m_sbtLFNST; +#endif bool m_ISP; ChromaFormat m_chromaFormatIdc; #if !JVET_S0052_RM_SEPARATE_COLOUR_PLANE @@ -2463,6 +2469,14 @@ void setCCALFEnabledFlag( bool b ) unsigned getPLTMode() const { return m_PLTMode; } void setUseSBT( bool b ) { m_SBT = b; } bool getUseSBT() const { return m_SBT; } +#if JVET_AI0050_INTER_MTSS + void setUseInterMTSS(bool b) { m_interMTSS = b; } + bool getUseInterMTSS() const { return m_interMTSS; } +#endif +#if JVET_AI0050_SBT_LFNST + void setUseSbtLFNST(bool b) { m_sbtLFNST = b; } + bool getUseSbtLFNST() const { return m_sbtLFNST; } +#endif void setUseISP( bool b ) { m_ISP = b; } bool getUseISP() const { return m_ISP; } diff --git a/source/Lib/CommonLib/TrQuant.cpp b/source/Lib/CommonLib/TrQuant.cpp index ed8e0e8073a967a10b7d93d396da5619897d3615..079c9c4e20992d18f63889cc8b0c801bc02845c5 100644 --- a/source/Lib/CommonLib/TrQuant.cpp +++ b/source/Lib/CommonLib/TrQuant.cpp @@ -528,7 +528,17 @@ void TrQuant::xInvLfnst( const TransformUnit &tu, const ComponentID compID ) } if (tu.cu->geoFlag) { +#if JVET_AI0050_INTER_MTSS + intraMode = tu.cu->dimdDerivedIntraDir; +#else intraMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->firstPU->geoSplitDir][0]]; +#endif + } +#endif +#if JVET_AI0050_INTER_MTSS + if (tu.cu->lfnstIntra) + { + intraMode = tu.cu->dimdDerivedIntraDir2nd; } #endif #if JVET_AB0155_SGPM @@ -773,6 +783,9 @@ void TrQuant::xFwdLfnst( const TransformUnit &tu, const ComponentID compID, cons const uint32_t width = area.width; const uint32_t height = area.height; const uint32_t lfnstIdx = tu.cu->lfnstIdx; +#if JVET_AI0050_INTER_MTSS + const uint32_t lfnstIntra = tu.cu->lfnstIntra; +#endif #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS if( lfnstIdx && tu.mtsIdx[compID] != MTS_SKIP && (tu.cu->isSepTree() ? true : isLuma(compID)) ) #else @@ -841,7 +854,17 @@ void TrQuant::xFwdLfnst( const TransformUnit &tu, const ComponentID compID, cons } if (tu.cu->geoFlag) { +#if JVET_AI0050_INTER_MTSS + intraMode = tu.cu->dimdDerivedIntraDir; +#else intraMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->firstPU->geoSplitDir][0]]; +#endif + } +#endif +#if JVET_AI0050_INTER_MTSS + if (tu.cu->lfnstIntra) + { + intraMode = tu.cu->dimdDerivedIntraDir2nd; } #endif #if JVET_AB0155_SGPM @@ -915,7 +938,11 @@ void TrQuant::xFwdLfnst( const TransformUnit &tu, const ComponentID compID, cons TCoeff* lfnstTemp; TCoeff* coeffTemp; #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_INTER_MTSS + TCoeff * tempCoeff = loadTr ? m_mtsCoeffs[lfnstIdx ? lfnstIdx + NUM_TRAFO_MODES_MTS + 3 * lfnstIntra - 1 : tu.mtsIdx[compID]] : m_tempCoeff; +#else TCoeff * tempCoeff = loadTr ? m_mtsCoeffs[lfnstIdx ? lfnstIdx + NUM_TRAFO_MODES_MTS - 1 : tu.mtsIdx[compID]] : m_tempCoeff; +#endif #else TCoeff * tempCoeff = loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_tempCoeff; #endif @@ -1186,6 +1213,12 @@ void TrQuant::getTrTypes(const TransformUnit tu, const ComponentID compID, int & trTypeHor = DCT2; trTypeVer = DCT2; +#if JVET_AI0050_SBT_LFNST + if (isSBT && tu.cu->lfnstIdx) + { + return; + } +#endif if (isISP && tu.cu->lfnstIdx) { @@ -2013,10 +2046,23 @@ void TrQuant::transformNxN( TransformUnit& tu, const ComponentID& compID, const { #if JVET_AG0061_INTER_LFNST_NSPT tu.mtsIdx[compID] = it->first < NUM_TRAFO_MODES_MTS ? it->first : 0; +#if JVET_AI0050_INTER_MTSS + int factor = (it->first - NUM_TRAFO_MODES_MTS) / 3; + tu.lfnstIdx[compID] = it->first < NUM_TRAFO_MODES_MTS ? 0 : it->first - NUM_TRAFO_MODES_MTS - 3 * factor + 1; + tu.lfnstIntra[compID] = it->first < (NUM_TRAFO_MODES_MTS + 3) ? 0 : (it->first < (NUM_TRAFO_MODES_MTS + 6) ? 1 : 2); +#else tu.lfnstIdx[compID] = it->first < NUM_TRAFO_MODES_MTS ? 0 : it->first - NUM_TRAFO_MODES_MTS + 1; +#endif +#if JVET_AI0050_SBT_LFNST + if ((compID == COMPONENT_Y && !tu.cu->sbtInfo) || (!tu.noResidual && compID == COMPONENT_Y && tu.cu->sbtInfo)) +#else if (compID == COMPONENT_Y) +#endif { tu.cu->lfnstIdx = tu.lfnstIdx[compID]; +#if JVET_AI0050_INTER_MTSS + tu.cu->lfnstIntra = tu.lfnstIntra[compID]; +#endif } CoeffBuf tempCoeff(m_mtsCoeffs[it->first], rect); #else @@ -2167,7 +2213,11 @@ void TrQuant::transformNxN( TransformUnit& tu, const ComponentID& compID, const CHECK(cs.sps->getMaxTbSize() < uiWidth, "Unsupported transformation size"); #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_INTER_MTSS + CoeffBuf tempCoeff(loadTr ? m_mtsCoeffs[tu.lfnstIdx[compID] ? (tu.lfnstIdx[compID] + NUM_TRAFO_MODES_MTS + 3 * tu.lfnstIntra[compID] - 1) : tu.mtsIdx[compID]] : m_tempCoeff, rect); +#else CoeffBuf tempCoeff(loadTr ? m_mtsCoeffs[tu.lfnstIdx[compID] ? tu.lfnstIdx[compID] + NUM_TRAFO_MODES_MTS - 1 : tu.mtsIdx[compID]] : m_tempCoeff, rect); +#endif #else CoeffBuf tempCoeff(loadTr ? m_mtsCoeffs[tu.mtsIdx[compID]] : m_tempCoeff, rect); #endif @@ -2823,7 +2873,17 @@ int TrQuant::getLfnstIdx(const TransformUnit &tu, ComponentID compID) } if (tu.cu->geoFlag) { +#if JVET_AI0050_INTER_MTSS + intraMode = tu.cu->dimdDerivedIntraDir; +#else intraMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->firstPU->geoSplitDir][0]]; +#endif + } +#endif +#if JVET_AI0050_INTER_MTSS + if (tu.cu->lfnstIntra) + { + intraMode = tu.cu->dimdDerivedIntraDir2nd; } #endif #if JVET_AB0155_SGPM diff --git a/source/Lib/CommonLib/TrQuant.h b/source/Lib/CommonLib/TrQuant.h index 8d08972dbe53f097bcd04f36da01bcb32d569094..fd64488af58203dc77c937cedb2aa8952ec427be 100644 --- a/source/Lib/CommonLib/TrQuant.h +++ b/source/Lib/CommonLib/TrQuant.h @@ -174,7 +174,11 @@ protected: private: DepQuant *m_quant; //!< Quantizer #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_INTER_MTSS + TCoeff m_mtsCoeffs[NUM_TRAFO_MODES_MTS + 6][MAX_TB_SIZEY * MAX_TB_SIZEY]; +#else TCoeff m_mtsCoeffs[NUM_TRAFO_MODES_MTS + 3][MAX_TB_SIZEY * MAX_TB_SIZEY]; +#endif #else TCoeff m_mtsCoeffs[NUM_TRAFO_MODES_MTS][MAX_TB_SIZEY * MAX_TB_SIZEY]; #endif diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 11cd0a4f9468a4a18135c5b023d86bf39549c74d..431bac7969951e9eb829a2115ddf367f0dabfd7c 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -419,6 +419,8 @@ #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 +#define JVET_AI0050_INTER_MTSS 1 // JVET_AI0050: Multiple LFNST/NSPT kernel set selection for GPM coded block +#define JVET_AI0050_SBT_LFNST 1 // JVET_AI0050: Enable LFNST/NSPT for SBT coded block // Entropy Coding #define EC_HIGH_PRECISION 1 // CABAC high precision diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index e3f0d49736f1384a75eaaca2da38dc87f510f1bb..0718864168aa9b8d5e4b41c2d6be38d43391f097 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -286,6 +286,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) mtsFlag = other.mtsFlag; #if JVET_AG0061_INTER_LFNST_NSPT lfnstFlag = other.lfnstFlag; +#if JVET_AI0050_INTER_MTSS + lfnstIntra = other.lfnstIntra; +#endif #endif lfnstIdx = other.lfnstIdx; tileIdx = other.tileIdx; @@ -457,6 +460,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) #endif #if JVET_AG0061_INTER_LFNST_NSPT dimdDerivedIntraDir = other.dimdDerivedIntraDir; +#if JVET_AI0050_INTER_MTSS + dimdDerivedIntraDir2nd = other.dimdDerivedIntraDir2nd; +#endif #endif #endif #if JVET_AG0276_NLIC @@ -577,6 +583,9 @@ void CodingUnit::initData() mtsFlag = 0; #if JVET_AG0061_INTER_LFNST_NSPT lfnstFlag = 0; +#if JVET_AI0050_INTER_MTSS + lfnstIntra = 0; +#endif #endif lfnstIdx = 0; tileIdx = 0; @@ -738,6 +747,9 @@ void CodingUnit::initData() #endif #if JVET_AG0061_INTER_LFNST_NSPT dimdDerivedIntraDir = 0; +#if JVET_AI0050_INTER_MTSS + dimdDerivedIntraDir2nd = 0; +#endif #endif #endif #if JVET_AG0276_NLIC @@ -960,7 +972,7 @@ const uint8_t CodingUnit::checkAllowedSbt() const { return 0; } -#if JVET_Y0065_GPM_INTRA +#if JVET_Y0065_GPM_INTRA && !JVET_AI0050_SBT_LFNST if (firstPU->gpmIntraFlag) { return 0; @@ -2018,6 +2030,9 @@ void TransformUnit::initData() mtsIdx[i] = MTS_DCT2_DCT2; #if JVET_AG0061_INTER_LFNST_NSPT lfnstIdx[i] = 0; +#if JVET_AI0050_INTER_MTSS + lfnstIntra[i] = 0; +#endif #endif } depth = 0; @@ -2114,6 +2129,9 @@ TransformUnit& TransformUnit::operator=(const TransformUnit& other) mtsIdx[i] = other.mtsIdx[i]; #if JVET_AG0061_INTER_LFNST_NSPT lfnstIdx[i] = other.lfnstIdx[i]; +#if JVET_AI0050_INTER_MTSS + lfnstIntra[i] = other.lfnstIntra[i]; +#endif #endif } depth = other.depth; @@ -2161,6 +2179,9 @@ void TransformUnit::copyComponentFrom(const TransformUnit& other, const Componen mtsIdx[i] = other.mtsIdx[i]; #if JVET_AG0061_INTER_LFNST_NSPT lfnstIdx[i] = other.lfnstIdx[i]; +#if JVET_AI0050_INTER_MTSS + lfnstIntra[i] = other.lfnstIntra[i]; +#endif #endif noResidual = other.noResidual; jointCbCr = isChroma( i ) ? other.jointCbCr : jointCbCr; diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 1dce80296e5e80436f5e985ff1408d40dbfbaa42..fb1d0386ec5083ef2eae5005dd01e769a326050a 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -434,9 +434,15 @@ struct CodingUnit : public UnitArea uint8_t mtsFlag; #if JVET_AG0061_INTER_LFNST_NSPT uint8_t lfnstFlag; +#if JVET_AI0050_INTER_MTSS + uint8_t lfnstIntra; +#endif #endif #if JVET_AG0061_INTER_LFNST_NSPT int dimdDerivedIntraDir; +#if JVET_AI0050_INTER_MTSS + int dimdDerivedIntraDir2nd; +#endif #endif uint8_t lfnstIdx; uint8_t bcwIdx; @@ -923,6 +929,9 @@ struct TransformUnit : public UnitArea uint8_t mtsIdx [ MAX_NUM_TBLOCKS ]; #if JVET_AG0061_INTER_LFNST_NSPT uint8_t lfnstIdx [ MAX_NUM_TBLOCKS ]; +#if JVET_AI0050_INTER_MTSS + uint8_t lfnstIntra [ MAX_NUM_TBLOCKS ]; +#endif #endif bool noResidual; uint8_t jointCbCr; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index c5263fb5a69860f71eaef148060a7fc740ef419c..1e5d5f177b149b037e428b808901ef32b3fa39cc 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -29775,7 +29775,23 @@ bool CU::isSbtMode( const uint8_t sbtInfo ) uint8_t sbtIdx = getSbtIdx( sbtInfo ); return sbtIdx >= SBT_VER_HALF && sbtIdx <= SBT_HOR_QUAD; } - +#if JVET_AI0050_SBT_LFNST +void CU::getSBTPosAndSize(const CodingUnit &cu, Position& pos, Size& size, uint8_t sbtMode) +{ + switch (sbtMode) + { + case SBT_VER_H0: pos = Position(0, 0); size = Size(cu.lwidth() >> 1, cu.lheight()); break; + case SBT_VER_H1: pos = Position(cu.lwidth() >> 1, 0); size = Size(cu.lwidth() >> 1, cu.lheight()); break; + case SBT_HOR_H0: pos = Position(0, 0); size = Size(cu.lwidth(), cu.lheight() >> 1); break; + case SBT_HOR_H1: pos = Position(0, cu.lheight() >> 1); size = Size(cu.lwidth(), cu.lheight() >> 1); break; + case SBT_VER_Q0: pos = Position(0, 0); size = Size(cu.lwidth() >> 2, cu.lheight()); break; + case SBT_VER_Q1: pos = Position((3 * cu.lwidth()) >> 2, 0); size = Size(cu.lwidth() >> 2, cu.lheight()); break; + case SBT_HOR_Q0: pos = Position(0, 0); size = Size(cu.lwidth(), cu.lheight() >> 2); break; + case SBT_HOR_Q1: pos = Position(0, (3 * cu.lheight()) >> 2); size = Size(cu.lwidth(), cu.lheight() >> 2); break; + default: assert(0); + } +} +#endif bool CU::isSameSbtSize( const uint8_t sbtInfo1, const uint8_t sbtInfo2 ) { uint8_t sbtIdx1 = getSbtIdxFromSbtMode( sbtInfo1 ); @@ -31290,7 +31306,17 @@ uint32_t PU::getFinalIntraModeForTransform( const TransformUnit &tu, const Compo } if (tu.cu->geoFlag) { +#if JVET_AI0050_INTER_MTSS + intraMode = tu.cu->dimdDerivedIntraDir; +#else intraMode = g_geoAngle2IntraAng[g_geoParams[tu.cu->firstPU->geoSplitDir][0]]; +#endif + } +#endif +#if JVET_AI0050_INTER_MTSS + if (tu.cu->lfnstIntra) + { + intraMode = tu.cu->dimdDerivedIntraDir2nd; } #endif #if JVET_AB0155_SGPM diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 3e677b6145b0b31528dcd71232149bf1012347a2..fd02a6b691ea5a65ae7dc909baafc53f01733d56 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -172,6 +172,9 @@ namespace CU uint8_t numSbtModeRdo (uint8_t sbtAllowed); bool isSbtMode (const uint8_t sbtInfo); bool isSameSbtSize (const uint8_t sbtInfo1, const uint8_t sbtInfo2); +#if JVET_AI0050_SBT_LFNST + void getSBTPosAndSize (const CodingUnit &cu, Position& pos, Size& size, uint8_t sbtMode); +#endif bool getRprScaling ( const SPS* sps, const PPS* curPPS, Picture* refPic, int& xScale, int& yScale ); void checkConformanceILRP (Slice *slice); #if JVET_AB0157_TMRL diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index ad92a4d5f0c334cf4762b3a37e249dc04e36fad1..208045eb9529ce022bce2f05f09a0ea24b3a75f1 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -9218,7 +9218,9 @@ void CABACReader::residual_lfnst_mode( CodingUnit& cu, CUCtx& cuCtx ) #else || (cu.isSepTree() && cu.chType == CHANNEL_TYPE_CHROMA && std::min(cu.blocks[1].width, cu.blocks[1].height) < 4) #endif -#if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AG0061_INTER_LFNST_NSPT && JVET_AI0050_SBT_LFNST + || ( !cu.cs->sps->getUseSbtLFNST() && cu.sbtInfo && CU::isInter( cu ) ) +#elif JVET_AG0061_INTER_LFNST_NSPT || ( cu.sbtInfo && CU::isInter( cu ) ) //JVET-AG0208 (EE2-related: On LFNST/NSPT index signalling) #endif || (cu.blocks[chIdx].lumaSize().width > cu.cs->sps->getMaxTbSize() @@ -9294,6 +9296,12 @@ void CABACReader::residual_lfnst_mode( CodingUnit& cu, CUCtx& cuCtx ) } } cu.lfnstIdx = idxLFNST; +#if JVET_AI0050_INTER_MTSS + if (cu.cs->sps->getUseInterMTSS() && cu.lfnstIdx > 0 && cu.geoFlag) + { + cu.lfnstIntra = m_BinDecoder.decodeBin(Ctx::InterLFNSTIntraIdx()); + } +#endif } else { diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 9be322508766d5cc1be4125ef4c7db59e6f10164..58e3e321636965a7e559c1c67e08289bacd35609 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -1236,7 +1236,17 @@ void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) m_pcIntraPred->eipPred(pu, piPred); if (!isEncoder) { - pu.cu->eipModel.eipDimdMode = IntraPrediction::deriveIpmForTransform(piPred, *pu.cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + pu.cu->eipModel.eipDimdMode = IntraPrediction::deriveIpmForTransform(piPred, *pu.cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + pu.cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif } } #endif @@ -2699,7 +2709,37 @@ void DecCu::xDecodeInterTexture(CodingUnit &cu) #if JVET_AG0061_INTER_LFNST_NSPT if (cu.lfnstIdx) { - cu.dimdDerivedIntraDir = m_pcIntraPred->deriveIpmForTransform(cu.cs->getPredBuf(*cu.firstPU).Y(), cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif +#if JVET_AI0050_SBT_LFNST + if (cu.cs->sps->getUseSbtLFNST() && cu.sbtInfo) + { + Position pos(0, 0); + Size size(0, 0); + int sbtIdx = cu.getSbtIdx(); + int sbtPos = cu.getSbtPos(); + CU::getSBTPosAndSize(cu, pos, size, CU::getSbtMode(sbtIdx, sbtPos)); + cu.dimdDerivedIntraDir = m_pcIntraPred->deriveIpmForTransform(cu.cs->getPredBuf(*cu.firstPU).Y().subBuf(pos, size), cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); + } + else + { +#endif + cu.dimdDerivedIntraDir = m_pcIntraPred->deriveIpmForTransform(cu.cs->getPredBuf(*cu.firstPU).Y(), cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_SBT_LFNST + } +#endif +#if JVET_AI0050_INTER_MTSS + cu.dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif } #endif diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index bf2732572d60d58b357046f5fbad96d1a585e529..ffc93c24df6de8db0687cce6bb8bf10ee51206f3 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2100,6 +2100,12 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) 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 ); +#if JVET_AI0050_INTER_MTSS + if (pcSPS->getUseInterLFNST()) + { + READ_FLAG( uiCode, "sps_inter_mtss_enabled_flag" ); pcSPS->setUseInterMTSS( uiCode != 0 ); + } +#endif #else READ_FLAG(uiCode, "sps_lfnst_enabled_flag"); pcSPS->setUseLFNST(uiCode != 0); #endif @@ -2447,6 +2453,12 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) } #endif READ_FLAG(uiCode, "sps_sbt_enabled_flag"); pcSPS->setUseSBT ( uiCode != 0 ); +#if JVET_AI0050_SBT_LFNST + if (pcSPS->getUseSBT()) + { + READ_FLAG(uiCode, "sps_sbt_lfnst_enabled_flag"); pcSPS->setUseSbtLFNST(uiCode != 0); + } +#endif #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR READ_FLAG( uiCode, "sps_dmvd_enabled_flag" ); pcSPS->setUseDMVDMode( uiCode != 0 ); #endif diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 68de12b38ec15efe9def52541ad1456d1c11bb29..58d66b58559eb80230f85f66bfe8d28c62cfd3a4 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -9040,7 +9040,9 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) ( cu.isSepTree() && cu.chType == CHANNEL_TYPE_CHROMA && std::min( cu.blocks[ 1 ].width, cu.blocks[ 1 ].height ) < 4 ) #endif || ( cu.blocks[ chIdx ].lumaSize().width > cu.cs->sps->getMaxTbSize() || cu.blocks[ chIdx ].lumaSize().height > cu.cs->sps->getMaxTbSize() ) -#if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AG0061_INTER_LFNST_NSPT && JVET_AI0050_SBT_LFNST + || ( !cu.cs->sps->getUseSbtLFNST() && cu.sbtInfo && CU::isInter( cu )) +#elif JVET_AG0061_INTER_LFNST_NSPT || ( cu.sbtInfo && CU::isInter( cu ) ) //JVET-AG0208 (EE2-related: On LFNST/NSPT index signalling) #endif ) @@ -9112,6 +9114,12 @@ void CABACWriter::residual_lfnst_mode( const CodingUnit& cu, CUCtx& cuCtx ) m_BinEncoder.encodeBin(idxLFNST > 2, Ctx::InterLFNSTIdx(2)); } } +#if JVET_AI0050_INTER_MTSS + if (cu.cs->sps->getUseInterMTSS() && idxLFNST > 0 && cu.geoFlag) + { + m_BinEncoder.encodeBin(cu.lfnstIntra, Ctx::InterLFNSTIntraIdx()); + } +#endif } else { diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index b753a0a8e938421ab95f43dec24da81f36933148..2bd1cf6a5c461515aed3cfce320c6f61e2206ff7 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -413,6 +413,12 @@ protected: bool m_interLFNST; #else bool m_LFNST; +#endif +#if JVET_AI0050_INTER_MTSS + bool m_useInterMTSS; +#endif +#if JVET_AI0050_SBT_LFNST + bool m_useSbtLFNST; #endif bool m_useFastLFNST; #if JVET_AH0103_LOW_DELAY_LFNST_NSPT @@ -1579,7 +1585,14 @@ public: void setUseFastInterLFNST ( bool b ) { m_useFastInterLFNST = b; } bool getUseFastInterLFNST() const { return m_useFastInterLFNST; } #endif - +#if JVET_AI0050_INTER_MTSS + void setUseInterMTSS ( bool b ) { m_useInterMTSS = b; } + bool getUseInterMTSS() const { return m_useInterMTSS; } +#endif +#if JVET_AI0050_SBT_LFNST + void setUseSBTLFNST ( bool b ) { m_useSbtLFNST = b; } + bool getUseSBTLFNST() const { return m_useSbtLFNST; } +#endif void setUseLMChroma ( int n ) { m_LMChroma = n; } int getUseLMChroma() const { return m_LMChroma; } void setHorCollocatedChromaFlag( bool b ) { m_horCollocatedChromaFlag = b; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 0c959a7f138a8c072fc78fcfb82678b36cce9bdc..94a0ac381e017cd2140d09da6299ccf1802c06c9 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -9618,6 +9618,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_AG0061_INTER_LFNST_NSPT cu.lfnstFlag = false; cu.lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu.lfnstIntra = 0; +#endif #endif #if INTER_LIC cu.licFlag = false; @@ -11488,6 +11491,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_AG0061_INTER_LFNST_NSPT cu.lfnstFlag = false; cu.lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu.lfnstIntra = 0; +#endif #endif cu.imv = 0; cu.mmvdSkip = false; @@ -11829,6 +11835,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_AG0061_INTER_LFNST_NSPT cu.lfnstFlag = false; cu.lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu.lfnstIntra = 0; +#endif #endif cu.imv = 0; cu.mmvdSkip = false; @@ -13862,6 +13871,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_AG0061_INTER_LFNST_NSPT cu.lfnstFlag = false; cu.lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu.lfnstIntra = 0; +#endif #endif cu.imv = 0; cu.mmvdSkip = false; @@ -22844,6 +22856,9 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS #if JVET_AG0061_INTER_LFNST_NSPT cu->lfnstFlag = false; cu->lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu->lfnstIntra = 0; +#endif #if JVET_AH0103_LOW_DELAY_LFNST_NSPT const bool lfnstAllowed = tempCS->sps->getUseInterLFNST() && CU::isInter( *cu ) #else @@ -22942,6 +22957,9 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS #if JVET_AG0061_INTER_LFNST_NSPT cu->lfnstFlag = false; cu->lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu->lfnstIntra = 0; +#endif #endif const bool skipResidual = residualPass == 1; if( skipResidual || histBestSbt == MAX_UCHAR || !CU::isSbtMode( histBestSbt ) ) @@ -23034,107 +23052,194 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS numSbtRdo = 1; m_pcInterSearch->initSbtRdoOrder( CU::getSbtMode( CU::getSbtIdx( histBestSbt ), CU::getSbtPos( histBestSbt ) ) ); } +#if JVET_AI0050_SBT_LFNST + std::vector<TrCost> trCosts; + double costSBT[NUMBER_SBT_MODE]; + bool skipCurSBT[NUMBER_SBT_MODE]; + std::fill_n(costSBT, NUMBER_SBT_MODE, MAX_DOUBLE); + std::fill_n(skipCurSBT, NUMBER_SBT_MODE, true); - for( int sbtModeIdx = 0; sbtModeIdx < numSbtRdo; sbtModeIdx++ ) - { - uint8_t sbtMode = m_pcInterSearch->getSbtRdoOrder( sbtModeIdx ); - uint8_t sbtIdx = CU::getSbtIdxFromSbtMode( sbtMode ); - uint8_t sbtPos = CU::getSbtPosFromSbtMode( sbtMode ); - - //fast algorithm (early skip, save & load) - if( histBestSbt == MAX_UCHAR ) + const int32_t iPicSize = pu.cu->slice->getPic()->lumaSize().area(); + bool iPicSizeCondition = iPicSize < 4096000; + for (int lfnstIdx = 0; lfnstIdx < (tempCS->sps->getUseSbtLFNST() ? 2 : 1); lfnstIdx++) + { + if (lfnstIdx && prevBestSbt == 0 && trCosts[0].second != MAX_DOUBLE && trCosts[0].second != std::numeric_limits<int>::max() && iPicSizeCondition) // 4096000 = 2560 * 1600 { - uint8_t skipCode = m_pcInterSearch->skipSbtByRDCost( cu->lwidth(), cu->lheight(), cu->mtDepth, sbtIdx, sbtPos, bestCS->cost, sbtOffDist, sbtOffCost, sbtOffRootCbf ); - if( skipCode != MAX_UCHAR ) + double th = pu.cu->slice->getCheckLDB() ? (iPicSize < 2073600 ? 1.04 : 1.07) : 1.04; // 2073600 = 1920 * 1080 + if (trCosts[0].second > bestCS->cost * th) { continue; } + } +#endif + for (int sbtModeIdx = 0; sbtModeIdx < numSbtRdo; sbtModeIdx++) + { +#if JVET_AI0050_SBT_LFNST + if (lfnstIdx && skipCurSBT[sbtModeIdx] && iPicSizeCondition) + { + continue; + } +#endif + uint8_t sbtMode = m_pcInterSearch->getSbtRdoOrder(sbtModeIdx); + uint8_t sbtIdx = CU::getSbtIdxFromSbtMode(sbtMode); + uint8_t sbtPos = CU::getSbtPosFromSbtMode(sbtMode); - if( sbtModeIdx > 0 ) + //fast algorithm (early skip, save & load) + if (histBestSbt == MAX_UCHAR) { - uint8_t prevSbtMode = m_pcInterSearch->getSbtRdoOrder( sbtModeIdx - 1 ); - //make sure the prevSbtMode is the same size as the current SBT mode (otherwise the estimated dist may not be comparable) - if( CU::isSameSbtSize( prevSbtMode, sbtMode ) ) + uint8_t skipCode = m_pcInterSearch->skipSbtByRDCost(cu->lwidth(), cu->lheight(), cu->mtDepth, sbtIdx, sbtPos, bestCS->cost, sbtOffDist, sbtOffCost, sbtOffRootCbf); + if (skipCode != MAX_UCHAR) + { + continue; + } + + if (sbtModeIdx > 0) { - Distortion currEstDist = m_pcInterSearch->getEstDistSbt( sbtMode ); - Distortion prevEstDist = m_pcInterSearch->getEstDistSbt( prevSbtMode ); - if( currEstDist > prevEstDist * 1.15 ) + uint8_t prevSbtMode = m_pcInterSearch->getSbtRdoOrder(sbtModeIdx - 1); + //make sure the prevSbtMode is the same size as the current SBT mode (otherwise the estimated dist may not be comparable) + if (CU::isSameSbtSize(prevSbtMode, sbtMode)) { - continue; + Distortion currEstDist = m_pcInterSearch->getEstDistSbt(sbtMode); + Distortion prevEstDist = m_pcInterSearch->getEstDistSbt(prevSbtMode); + if (currEstDist > prevEstDist * 1.15) + { + continue; + } } } } - } - //init tempCS and TU - if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated - { - tempCS->clearTUs(); - } - else if( false == swapped ) - { - tempCS->initStructData( encTestMode.qp ); - tempCS->copyStructure( *bestCS, partitioner.chType ); - tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() ); - bestCost = bestCS->cost; - cu = tempCS->getCU( partitioner.chType ); - swapped = true; - } - else - { - tempCS->clearTUs(); - bestCost = bestCS->cost; - cu = tempCS->getCU( partitioner.chType ); - } + //init tempCS and TU + if (bestCost == bestCS->cost) //The first EMT pass didn't become the bestCS, so we clear the TUs generated + { + tempCS->clearTUs(); + } + else if (false == swapped) + { + tempCS->initStructData(encTestMode.qp); + tempCS->copyStructure(*bestCS, partitioner.chType); + tempCS->getPredBuf().copyFrom(bestCS->getPredBuf()); + bestCost = bestCS->cost; + cu = tempCS->getCU(partitioner.chType); + swapped = true; + } + else + { + tempCS->clearTUs(); + bestCost = bestCS->cost; + cu = tempCS->getCU(partitioner.chType); + } - //we need to restart the distortion for the new tempCS, the bit count and the cost - tempCS->dist = 0; - tempCS->fracBits = 0; - tempCS->cost = MAX_DOUBLE; - cu->skip = false; + //we need to restart the distortion for the new tempCS, the bit count and the cost + tempCS->dist = 0; + tempCS->fracBits = 0; + tempCS->cost = MAX_DOUBLE; + cu->skip = false; #if JVET_AG0061_INTER_LFNST_NSPT - cu->lfnstFlag = false; - cu->lfnstIdx = 0; +#if JVET_AI0050_SBT_LFNST + cu->lfnstFlag = lfnstIdx; + if (cu->lfnstFlag) + { +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; #endif - //set SBT info - cu->setSbtIdx( sbtIdx ); - cu->setSbtPos( sbtPos ); - - //try residual coding - m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual ); - if (tempCS->slice->getSPS()->getUseColorTrans()) - { - bestCS->tmpColorSpaceCost = tempCS->tmpColorSpaceCost; - bestCS->firstColorSpaceSelected = tempCS->firstColorSpaceSelected; - } - numRDOTried++; + Position pos(0, 0); + Size size(0, 0); + CU::getSBTPosAndSize(*cu, pos, size, sbtMode); + cu->dimdDerivedIntraDir = m_pcIntraSearch->deriveIpmForTransform(cu->cs->getPredBuf(*cu->firstPU).Y().subBuf(pos, size), *cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif + } +#else + cu->lfnstFlag = false; +#endif + cu->lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu->lfnstIntra = 0; +#endif +#endif + //set SBT info + cu->setSbtIdx(sbtIdx); + cu->setSbtPos(sbtPos); - xEncodeDontSplit( *tempCS, partitioner ); + //try residual coding +#if JVET_AI0050_SBT_LFNST + bool isValid = m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, skipResidual); +#else + m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, skipResidual); +#endif +#if JVET_AI0050_SBT_LFNST + if (isValid || !cu->lfnstFlag) + { +#endif + if (tempCS->slice->getSPS()->getUseColorTrans()) + { + bestCS->tmpColorSpaceCost = tempCS->tmpColorSpaceCost; + bestCS->firstColorSpaceSelected = tempCS->firstColorSpaceSelected; + } + numRDOTried++; - xCheckDQP( *tempCS, partitioner ); - xCheckChromaQPOffset( *tempCS, partitioner ); + xEncodeDontSplit(*tempCS, partitioner); - if( NULL != bestHasNonResi && ( bestCostInternal > tempCS->cost ) ) - { - bestCostInternal = tempCS->cost; - if( !( tempCS->getPU( partitioner.chType )->ciipFlag ) ) - *bestHasNonResi = !cu->rootCbf; - } + xCheckDQP(*tempCS, partitioner); + xCheckChromaQPOffset(*tempCS, partitioner); - if( tempCS->cost < currBestCost ) - { - currBestSbt = cu->sbtInfo; - currBestTrs = tempCS->tus[cu->sbtInfo ? cu->getSbtPos() : 0]->mtsIdx[COMPONENT_Y]; - assert( currBestTrs == 0 || currBestTrs == 1 ); - currBestCost = tempCS->cost; - } + if (NULL != bestHasNonResi && (bestCostInternal > tempCS->cost)) + { + bestCostInternal = tempCS->cost; + if (!(tempCS->getPU(partitioner.chType)->ciipFlag)) + { + *bestHasNonResi = !cu->rootCbf; + } + } + if (tempCS->cost < currBestCost) + { + currBestSbt = cu->sbtInfo; + currBestTrs = tempCS->tus[cu->sbtInfo ? cu->getSbtPos() : 0]->mtsIdx[COMPONENT_Y]; + assert(currBestTrs == 0 || currBestTrs == 1); + currBestCost = tempCS->cost; + } +#if JVET_AI0050_SBT_LFNST + if (lfnstIdx == 0) + { + costSBT[sbtModeIdx] = tempCS->cost; + } +#endif #if WCG_EXT - DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) ); + DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda(true)); #else - DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda() ); + DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda()); +#endif + xCheckBestMode(tempCS, bestCS, partitioner, encTestMode); +#if JVET_AI0050_SBT_LFNST + } + } + if (lfnstIdx == 0) + { + for (int i = 0; i < NUMBER_SBT_MODE; i++) + { + trCosts.push_back(TrCost(i, int(std::min<double>(costSBT[i], std::numeric_limits<int>::max())))); + } + std::stable_sort(trCosts.begin(), trCosts.end(), [](const TrCost l, const TrCost r) {return l.second < r.second; }); + for (int i = 0; i < NUM_SBT_LFNST_RDO; i++) + { + if (trCosts[i].second != MAX_DOUBLE && trCosts[i].second != std::numeric_limits<int>::max()) + { + double th = 1.1; + if (i == 0 || (i > 0 && (trCosts[i].second < th * trCosts[0].second))) + { + skipCurSBT[trCosts[i].first] = false; + } + } + } + } #endif - xCheckBestMode( tempCS, bestCS, partitioner, encTestMode ); } #if JVET_AA0133_INTER_MTS_OPT if (!skipResidual && mtsAllowed) @@ -23171,6 +23276,9 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS #if JVET_AG0061_INTER_LFNST_NSPT cu->lfnstFlag = false; cu->lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu->lfnstIntra = 0; +#endif #endif #endif m_pcInterSearch->setBestCost(bestCS->cost); @@ -23222,6 +23330,9 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS cu->mtsFlag = true; cu->lfnstFlag = false; cu->lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu->lfnstIntra = 0; +#endif #endif //try residual coding bool isValid = m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, skipResidual); @@ -23329,7 +23440,17 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS bestCost = bestCS->cost; cu = tempCS->getCU(partitioner.chType); } - cu->dimdDerivedIntraDir = m_pcIntraSearch->deriveIpmForTransform(cu->cs->getPredBuf(*cu->firstPU).Y(), *cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + cu->dimdDerivedIntraDir = m_pcIntraSearch->deriveIpmForTransform(cu->cs->getPredBuf(*cu->firstPU).Y(), *cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + cu->dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif // we need to restart the distortion for the new tempCS, the bit count and the cost tempCS->dist = 0; tempCS->fracBits = 0; @@ -23340,6 +23461,9 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS cu->mtsFlag = false; cu->lfnstFlag = true; cu->lfnstIdx = 0; +#if JVET_AI0050_INTER_MTSS + cu->lfnstIntra = 0; +#endif m_pcInterSearch->setBestCost(bestCS->cost); { // try residual coding diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 52deaa69eae7a93654d3747cbff63fe68ebcc24c..1f35e46e9f6536d59a6648a765755ab926147c1d 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1971,6 +1971,12 @@ void EncLib::xInitSPS( SPS& sps ) sps.setUseIntraMTS ( m_IntraMTS ); sps.setUseInterMTS ( m_InterMTS ); sps.setUseSBT ( m_SBT ); +#if JVET_AI0050_INTER_MTSS + sps.setUseInterMTSS ( m_useInterMTSS ); +#endif +#if JVET_AI0050_SBT_LFNST + sps.setUseSbtLFNST ( m_useSbtLFNST ); +#endif sps.setUseSMVD ( m_SMVD ); sps.setUseBcw ( m_bcw ); #if INTER_LIC diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 5777a304521117d9a1cc67ac72d9cfce1a29ed7c..da4eedd5e920bfb3fdeca7d275b679841c929031 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -13197,8 +13197,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par const bool mtsAllowed = CU::isMTSAllowed( *tu.cu, compID ); #endif #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_SBT_LFNST + const bool lfnstAllowed = CU::isLfnstAllowed(*tu.cu, compID) && cu.lfnstFlag && !tu.noResidual; +#else const bool lfnstAllowed = CU::isLfnstAllowed(*tu.cu, compID) && cu.lfnstFlag; #endif +#endif #if JVET_AG0061_INTER_LFNST_NSPT uint8_t nNumTransformCands = 0; @@ -13213,7 +13217,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par #endif std::vector<TrMode> trModes; #if TU_256 - if(tu.idx != cu.firstTU->idx) +#if JVET_AI0050_SBT_LFNST + if (tu.idx != cu.firstTU->idx && ((cu.sbtInfo && tu.noResidual) || !cu.sbtInfo)) +#else + if (tu.idx != cu.firstTU->idx) +#endif { trModes.push_back( TrMode( cu.firstTU->mtsIdx[compID], true ) ); nNumTransformCands = 1; @@ -13226,7 +13234,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par nNumTransformCands = 0; } #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_SBT_LFNST + else if (!((cu.mtsFlag || (cu.lfnstFlag && !tu.noResidual)) && compID == COMPONENT_Y)) +#else else if (!((cu.mtsFlag || cu.lfnstFlag) && compID == COMPONENT_Y)) +#endif #elif JVET_AA0133_INTER_MTS_OPT else if (!(cu.mtsFlag && compID == COMPONENT_Y)) #else @@ -13273,7 +13285,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par #if JVET_AG0061_INTER_LFNST_NSPT if (lfnstAllowed) { +#if JVET_AI0050_INTER_MTSS + int numMode = cu.cs->sps->getUseInterMTSS() && tu.cu->geoFlag ? 6 : 3; + for (int i = NUM_TRAFO_MODES_MTS; i < NUM_TRAFO_MODES_MTS + numMode; i++) // 3 or 6 lfnst +#else for (int i = NUM_TRAFO_MODES_MTS; i < NUM_TRAFO_MODES_MTS + 3; i++) // 3 lfnst +#endif { { trModes.push_back(TrMode(i, true)); @@ -13487,12 +13504,25 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par } #if JVET_AG0061_INTER_LFNST_NSPT tu.mtsIdx[compID] = trModes[transformMode].first < NUM_TRAFO_MODES_MTS ? trModes[transformMode].first : 0; +#if JVET_AI0050_INTER_MTSS + int factor = (trModes[transformMode].first - NUM_TRAFO_MODES_MTS) / 3; + tu.lfnstIdx[compID] = trModes[transformMode].first < NUM_TRAFO_MODES_MTS ? 0 : trModes[transformMode].first - NUM_TRAFO_MODES_MTS - 3 * factor + 1; + tu.lfnstIntra[compID] = trModes[transformMode].first < (NUM_TRAFO_MODES_MTS + 3) ? 0 : (trModes[transformMode].first < (NUM_TRAFO_MODES_MTS + 6) ? 1 : 2); +#else tu.lfnstIdx[compID] = trModes[transformMode].first < NUM_TRAFO_MODES_MTS ? 0 : trModes[transformMode].first - NUM_TRAFO_MODES_MTS + 1; +#endif +#if JVET_AI0050_SBT_LFNST + if ((compID == COMPONENT_Y && !cu.sbtInfo) || (!tu.noResidual && compID == COMPONENT_Y && cu.sbtInfo)) +#else if (compID == COMPONENT_Y) +#endif { tu.cu->lfnstIdx = tu.lfnstIdx[compID]; +#if JVET_AI0050_INTER_MTSS + tu.cu->lfnstIntra = tu.lfnstIntra[compID]; +#endif } #else tu.mtsIdx[compID] = trModes[transformMode].first; @@ -13546,13 +13576,30 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par if( transformMode == 0 ) { #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_INTER_MTSS + m_pcTrQuant->transformNxN(tu, compID, cQP, &trModes, m_pcEncCfg->getMTSInterMaxCand() + 6); +#else m_pcTrQuant->transformNxN(tu, compID, cQP, &trModes, m_pcEncCfg->getMTSInterMaxCand() + 3); +#endif tu.mtsIdx[compID] = trModes[0].first < NUM_TRAFO_MODES_MTS ? trModes[0].first : 0; +#if JVET_AI0050_INTER_MTSS + int factor = (trModes[0].first - NUM_TRAFO_MODES_MTS) / 3; + tu.lfnstIdx[compID] = trModes[0].first < NUM_TRAFO_MODES_MTS ? 0 : trModes[0].first - NUM_TRAFO_MODES_MTS - 3 * factor + 1; + tu.lfnstIntra[compID] = trModes[0].first < (NUM_TRAFO_MODES_MTS + 3) ? 0 : (trModes[0].first < (NUM_TRAFO_MODES_MTS + 6) ? 1 : 2); +#else tu.lfnstIdx[compID] = trModes[0].first < NUM_TRAFO_MODES_MTS ? 0 : trModes[0].first - NUM_TRAFO_MODES_MTS + 1; +#endif +#if JVET_AI0050_SBT_LFNST + if ((compID == COMPONENT_Y && !tu.cu->sbtInfo) || (!tu.noResidual && compID == COMPONENT_Y && tu.cu->sbtInfo)) +#else if (compID == COMPONENT_Y) +#endif { tu.cu->lfnstIdx = tu.lfnstIdx[compID]; +#if JVET_AI0050_INTER_MTSS + tu.cu->lfnstIntra = tu.lfnstIntra[compID]; +#endif } #else m_pcTrQuant->transformNxN(tu, compID, cQP, &trModes, m_pcEncCfg->getMTSInterMaxCand()); @@ -13924,7 +13971,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par #endif } #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_SBT_LFNST + else if ((cu.mtsFlag && compID == COMPONENT_Y) || (transformMode > 0) || (cu.lfnstFlag && !tu.noResidual && compID == COMPONENT_Y)) +#else else if ((cu.mtsFlag && compID == COMPONENT_Y) || (transformMode > 0) || (cu.lfnstFlag && compID == COMPONENT_Y)) +#endif #elif JVET_AA0133_INTER_MTS_OPT else if ((cu.mtsFlag && compID == COMPONENT_Y) || (transformMode > 0)) #else @@ -14007,7 +14058,11 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par if (compID == 0) { #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_SBT_LFNST + if (cu.mtsFlag || (cu.lfnstFlag && !bestTU.noResidual)) +#else if (cu.mtsFlag || cu.lfnstFlag) +#endif #else if (cu.mtsFlag) #endif @@ -14033,9 +14088,16 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par // copy component tu.copyComponentFrom(bestTU, compID); #if JVET_AG0061_INTER_LFNST_NSPT +#if JVET_AI0050_SBT_LFNST + if ((compID == COMPONENT_Y && !tu.cu->sbtInfo) || (!tu.noResidual && compID == COMPONENT_Y && tu.cu->sbtInfo)) +#else if (compID == COMPONENT_Y) +#endif { tu.cu->lfnstIdx = tu.lfnstIdx[compID]; +#if JVET_AI0050_INTER_MTSS + tu.cu->lfnstIntra = tu.lfnstIntra[compID]; +#endif } #endif csFull->getResiBuf( compArea ).copyFrom( saveCS.getResiBuf( compArea ) ); @@ -14691,12 +14753,34 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par else THROW( "Implicit TU split not available!" ); +#if JVET_AI0050_SBT_LFNST + bool isValid = false; +#endif do { +#if JVET_AI0050_SBT_LFNST + if (cu.sbtInfo) + { + bool isSubValid = false; + isSubValid = xEstimateInterResidualQT(*csSplit, partitioner, bCheckFull ? nullptr : puiZeroDist, luma, chroma, orgResi); + if (!csSplit->tus.back()->noResidual) + { + isValid = isSubValid; + } + } + else + { + xEstimateInterResidualQT(*csSplit, partitioner, bCheckFull ? nullptr : puiZeroDist + , luma, chroma + , orgResi + ); + } +#else xEstimateInterResidualQT(*csSplit, partitioner, bCheckFull ? nullptr : puiZeroDist , luma, chroma , orgResi ); +#endif csSplit->cost = m_pcRdCost->calcRdCost( csSplit->fracBits, csSplit->dist ); } while( partitioner.nextPart( *csSplit ) ); @@ -14773,6 +14857,12 @@ void InterSearch::xEstimateInterResidualQT(CodingStructure &cs, Partitioner &par csSplit->releaseIntermediateData(); csFull ->releaseIntermediateData(); } +#if JVET_AI0050_SBT_LFNST + if (cu.sbtInfo) + { + return isValid; + } +#endif } #if JVET_AA0133_INTER_MTS_OPT return true; diff --git a/source/Lib/EncoderLib/IntraSearch.cpp b/source/Lib/EncoderLib/IntraSearch.cpp index 73c9ad5c6318859cb09fbf0b4fd250c39cabb95b..346021d07f138760c3aae185592172f4a0c94d17 100644 --- a/source/Lib/EncoderLib/IntraSearch.cpp +++ b/source/Lib/EncoderLib/IntraSearch.cpp @@ -2774,13 +2774,33 @@ bool IntraSearch::estIntraPredLumaQT(CodingUnit &cu, Partitioner &partitioner, c if(modeInfo.mipTrFlg) { PelBuf eipSaveBuf(m_eipMergePredBuf[modeIdx], pu.Y()); - m_eipMergeModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + m_eipMergeModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + cu.dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif CHECK(modeIdx >= NUM_EIP_MERGE_SIGNAL, "modeIdx >= NUM_EIP_MERGE_SIGNAL"); } else { PelBuf eipSaveBuf(m_eipPredBuf[modeIdx], pu.Y()); - m_eipModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu); +#if JVET_AI0050_INTER_MTSS + int secondDimdIntraDir = 0; +#endif + m_eipModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu +#if JVET_AI0050_INTER_MTSS + , secondDimdIntraDir +#endif + ); +#if JVET_AI0050_INTER_MTSS + cu.dimdDerivedIntraDir2nd = secondDimdIntraDir; +#endif CHECK(modeIdx >= NUM_DERIVED_EIP, "modeIdx >= NUM_DERIVED_EIP"); } } diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index e2be260307c3dd4f3b82cbdc7c9acbe2d9736e74..d6f48b26a83df345186042afdd139ef1df64bd7f 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1287,6 +1287,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) 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" ); +#if JVET_AI0050_INTER_MTSS + if (pcSPS->getUseInterLFNST()) + { + WRITE_FLAG(pcSPS->getUseInterMTSS() ? 1 : 0, "sps_inter_mtss_enabled_flag"); + } +#endif #else WRITE_FLAG(pcSPS->getUseLFNST() ? 1 : 0, "sps_lfnst_enabled_flag"); #endif @@ -1534,6 +1540,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) } #endif WRITE_FLAG( pcSPS->getUseSBT() ? 1 : 0, "sps_sbt_enabled_flag"); +#if JVET_AI0050_SBT_LFNST + if (pcSPS->getUseSBT()) + { + WRITE_FLAG( pcSPS->getUseSbtLFNST() ? 1 : 0, "sps_sbt_lfnst_enabled_flag"); + } +#endif #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR WRITE_FLAG( pcSPS->getUseDMVDMode() ? 1 : 0, "sps_dmvd_enabled_flag" ); #endif