From 537aa0c698f02fb1238c04ff9b87f8edf37d7f5e Mon Sep 17 00:00:00 2001 From: Yang Wang <wangyang.cs@bytedance.com> Date: Fri, 26 Jul 2024 05:51:17 +0000 Subject: [PATCH] JVET-AI0082: GPM with inter prediction and IBC and temporal BV (Test 3.3b) --- source/App/EncoderApp/EncApp.cpp | 3 + source/App/EncoderApp/EncAppCfg.cpp | 6 + source/App/EncoderApp/EncAppCfg.h | 3 + source/Lib/CommonLib/CommonDef.h | 12 + source/Lib/CommonLib/Contexts.h | 4 + source/Lib/CommonLib/Contexts_ecm13.inl | 50 ++ source/Lib/CommonLib/Contexts_ecm14.0.inl | 50 ++ source/Lib/CommonLib/InterPrediction.cpp | 159 +++++++ source/Lib/CommonLib/InterPrediction.h | 67 +++ source/Lib/CommonLib/IntraPrediction.cpp | 4 + source/Lib/CommonLib/Slice.h | 7 + source/Lib/CommonLib/TypeDef.h | 2 + source/Lib/CommonLib/Unit.cpp | 9 + source/Lib/CommonLib/Unit.h | 3 + source/Lib/CommonLib/UnitTools.cpp | 533 ++++++++++++++++++++++ source/Lib/CommonLib/UnitTools.h | 14 +- source/Lib/DecoderLib/CABACReader.cpp | 95 ++++ source/Lib/DecoderLib/CABACReader.h | 4 + source/Lib/DecoderLib/DecCu.cpp | 6 + source/Lib/DecoderLib/DecCu.h | 3 + source/Lib/DecoderLib/VLCReader.cpp | 4 + source/Lib/EncoderLib/CABACWriter.cpp | 102 +++++ source/Lib/EncoderLib/CABACWriter.h | 4 + source/Lib/EncoderLib/EncCfg.h | 7 + source/Lib/EncoderLib/EncCu.cpp | 414 ++++++++++++++++- source/Lib/EncoderLib/EncCu.h | 18 + source/Lib/EncoderLib/EncLib.cpp | 3 + source/Lib/EncoderLib/EncSlice.cpp | 12 + source/Lib/EncoderLib/InterSearch.cpp | 44 ++ source/Lib/EncoderLib/InterSearch.h | 57 +++ source/Lib/EncoderLib/VLCWriter.cpp | 3 + 31 files changed, 1700 insertions(+), 2 deletions(-) diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index db5c26b3b..878ed3a23 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -970,6 +970,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setUseCiipTimd (m_ciipTimd); #endif m_cEncLib.setUseGeo ( m_Geo ); +#if JVET_AI0082_GPM_WITH_INTER_IBC + m_cEncLib.setUseGeoInterIbc ( m_Geo ? m_geoInterIbc : false ); +#endif m_cEncLib.setUseHashME ( m_HashME ); m_cEncLib.setAllowDisFracMMVD ( m_allowDisFracMMVD ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 05f6b088a..60c27c6eb 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1186,6 +1186,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("CIIPTIMD", m_ciipTimd, true, "Enable CIIP-TIMD mode") #endif ("Geo", m_Geo, false, "Enable geometric partitioning mode (0:off, 1:on)") +#if JVET_AI0082_GPM_WITH_INTER_IBC + ("GeoInterIbc", m_geoInterIbc, true, "GPM with inter and IBC (0:off, 1:on) [default: off]" ) +#endif ("HashME", m_HashME, false, "Enable hash motion estimation (0:off, 1:on)") ("AllowDisFracMMVD", m_allowDisFracMMVD, false, "Disable fractional MVD in MMVD mode adaptively") @@ -5645,6 +5648,9 @@ void EncAppCfg::xPrintParameter() msg(VERBOSE, "CIIPAffine:%d ", m_useCiipAffine); #endif msg( VERBOSE, "Geo:%d ", m_Geo ); +#if JVET_AI0082_GPM_WITH_INTER_IBC + msg( VERBOSE, "GeoInterIbc:%d ", m_geoInterIbc ); +#endif m_allowDisFracMMVD = m_MMVD ? m_allowDisFracMMVD : false; if ( m_MMVD ) msg(VERBOSE, "AllowDisFracMMVD:%d ", m_allowDisFracMMVD); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index fb0a2f886..61eac5f61 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -534,6 +534,9 @@ protected: bool m_ciipTimd; #endif bool m_Geo; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool m_geoInterIbc; +#endif bool m_HashME; bool m_allowDisFracMMVD; bool m_AffineAmvr; diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 03f70d2f1..1cfe4b347 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -1415,7 +1415,12 @@ static const int GEO_MAX_NUM_UNI_AFF_CANDS_ARMC = 22; #if JVET_Y0065_GPM_INTRA static const int GEO_MAX_NUM_INTRA_CANDS = 3; +#if JVET_AI0082_GPM_WITH_INTER_IBC +static const int GEO_MAX_NUM_IBC_CANDS = 4; +static const int GEO_NUM_INTRA_RDO_BUFFER = 23 + GEO_MAX_NUM_IBC_CANDS; +#else static const int GEO_NUM_INTRA_RDO_BUFFER = 23; +#endif #if JVET_AG0112_REGRESSION_BASED_GPM_BLENDING static const int GEO_BLEND_MAX_NUM_CANDS = ((GEO_MAX_NUM_UNI_CANDS + 1) >> 1) * ((GEO_MAX_NUM_UNI_CANDS + 1) >> 1) / 2; static const int GEO_NUM_RDO_BUFFER = GEO_MAX_NUM_UNI_CANDS + 67 + 1 + 1; @@ -1426,7 +1431,11 @@ static const int GEO_NUM_RDO_BUFFER = GEO_MAX_NUM_ static const int GEO_NUM_RDO_BUFFER = GEO_MAX_NUM_UNI_CANDS + GEO_NUM_INTRA_RDO_BUFFER; #endif #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC +static const int GEO_MAX_NUM_CANDS = (GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS) * ((GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS) - 1); +#else static const int GEO_MAX_NUM_CANDS = (GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS) * ((GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS) - 1); +#endif #else static const int GEO_MAX_NUM_CANDS = GEO_MAX_NUM_UNI_CANDS * (GEO_MAX_NUM_UNI_CANDS - 1); #endif @@ -1469,6 +1478,9 @@ static const int GEO_ENC_MMVD_MAX_REFINE_NUM_ADJ = 1 // regular merge(1) #if JVET_Y0065_GPM_INTRA + 1 // intra(1) #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + + 1 // IBC(1) +#endif ; #else static const int GEO_MV_MASK_SIZE = GEO_WEIGHT_MASK_SIZE >> 2; diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h index ae31d29cc..51201653b 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -494,6 +494,10 @@ public: #endif #if JVET_Y0065_GPM_INTRA static const CtxSet GPMIntraFlag; +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + static const CtxSet GpmInterIbcFlag; + static const CtxSet GpmInterIbcIdx; #endif static const CtxSet PredMode; static const CtxSet MultiRefLineIdx; diff --git a/source/Lib/CommonLib/Contexts_ecm13.inl b/source/Lib/CommonLib/Contexts_ecm13.inl index 92548a12a..a214a33a4 100644 --- a/source/Lib/CommonLib/Contexts_ecm13.inl +++ b/source/Lib/CommonLib/Contexts_ecm13.inl @@ -450,6 +450,56 @@ const CtxSet ContextSetCfg::GPMIntraFlag = ContextSetCfg::addCtxSet({ { 133 }, }); +#if JVET_AI0082_GPM_WITH_INTER_IBC +const CtxSet ContextSetCfg::GpmInterIbcFlag = ContextSetCfg::addCtxSet +({ + { CNU, }, + { CNU, }, + { CNU, }, + { CNU, }, + { DWS, }, + { DWS, }, + { DWS, }, + { DWS, }, + { DWE, }, + { DWE, }, + { DWE, }, + { DWE, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + }); + +const CtxSet ContextSetCfg::GpmInterIbcIdx = ContextSetCfg::addCtxSet +({ + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { DWS, DWS, DWS, }, + { DWS, DWS, DWS, }, + { DWS, DWS, DWS, }, + { DWS, DWS, DWS, }, + { DWE, DWE, DWE, }, + { DWE, DWE, DWE, }, + { DWE, DWE, DWE, }, + { DWE, DWE, DWE, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + }); +#endif + const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet({ // ctx 81 84 { 25, 34, 35, 35 }, diff --git a/source/Lib/CommonLib/Contexts_ecm14.0.inl b/source/Lib/CommonLib/Contexts_ecm14.0.inl index c3dbadb5a..2632028e8 100644 --- a/source/Lib/CommonLib/Contexts_ecm14.0.inl +++ b/source/Lib/CommonLib/Contexts_ecm14.0.inl @@ -450,6 +450,56 @@ const CtxSet ContextSetCfg::GPMIntraFlag = ContextSetCfg::addCtxSet({ { 133 }, }); +#if JVET_AI0082_GPM_WITH_INTER_IBC +const CtxSet ContextSetCfg::GpmInterIbcFlag = ContextSetCfg::addCtxSet +({ + { CNU, }, + { CNU, }, + { CNU, }, + { CNU, }, + { DWS, }, + { DWS, }, + { DWS, }, + { DWS, }, + { DWE, }, + { DWE, }, + { DWE, }, + { DWE, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + { DWO, }, + }); + +const CtxSet ContextSetCfg::GpmInterIbcIdx = ContextSetCfg::addCtxSet +({ + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { CNU, CNU, CNU, }, + { DWS, DWS, DWS, }, + { DWS, DWS, DWS, }, + { DWS, DWS, DWS, }, + { DWS, DWS, DWS, }, + { DWE, DWE, DWE, }, + { DWE, DWE, DWE, }, + { DWE, DWE, DWE, }, + { DWE, DWE, DWE, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + { DWO, DWO, DWO, }, + }); +#endif + const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet({ // ctx 81 84 { 25, 34, 35, 35 }, diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index f476f3732..693bcfb2d 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -9055,6 +9055,9 @@ void InterPrediction::deriveGpmSplitMode(PredictionUnit& pu, MergeCtx &geoMrgCtx #if JVET_Y0065_GPM_INTRA , IntraPrediction* pcIntraPred #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , Mv* geoBvList +#endif ) { if ( pu.cu->cs->pcv->isEncoder || !pu.cs->slice->getSPS()->getUseAltGPMSplitModeCode()) @@ -9109,6 +9112,15 @@ void InterPrediction::deriveGpmSplitMode(PredictionUnit& pu, MergeCtx &geoMrgCtx fillPartGPMRefTemplate<0>(pu, geoMrgCtx, pu.geoMergeIdx0, geoMmvdIdx0); fillPartGPMRefTemplate<1>(pu, geoMrgCtx, pu.geoMergeIdx1, geoMmvdIdx1); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (pu.gpmInterIbcFlag) + { + std::vector<Pel>* lut = m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() ? &m_pcReshape->getInvLUT() : nullptr; + fillPartGpmInterIbcRefTemplate<0>(pu, lut, geoBvList, pu.geoMergeIdx0, geoMmvdIdx0); + fillPartGpmInterIbcRefTemplate<1>(pu, lut, geoBvList, pu.geoMergeIdx1, geoMmvdIdx1); + } + else +#endif #if JVET_Y0065_GPM_INTRA if (pu.gpmIntraFlag) { @@ -9134,11 +9146,21 @@ void InterPrediction::deriveGpmSplitMode(PredictionUnit& pu, MergeCtx &geoMrgCtx { #if JVET_AG0164_AFFINE_GPM +#if JVET_AI0082_GPM_WITH_INTER_IBC + isIintra[0] = pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS && pu.geoMergeIdx0 < GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; + isIintra[1] = pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS && pu.geoMergeIdx1 < GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#else isIintra[0] = pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS; isIintra[1] = pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS; +#endif +#else +#if JVET_AI0082_GPM_WITH_INTER_IBC + isIintra[0] = pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS && pu.geoMergeIdx0 < GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; + isIintra[1] = pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS && pu.geoMergeIdx1 < GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; #else isIintra[0] = pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS; isIintra[1] = pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS; +#endif #endif for (uint8_t partIdx = 0; partIdx < 2; ++partIdx) { @@ -9538,10 +9560,17 @@ void InterPrediction::motionCompensationGeoBlend( CodingUnit& cu, MergeCtx& geoM #if JVET_AG0164_AFFINE_GPM AffineMergeCtx dummyAffineMergeCtx; +#if JVET_AI0082_GPM_WITH_INTER_IBC + PU::spanGeoMMVDMotionInfo( pu, geoMrgCtx + , dummyAffineMergeCtx + , geoMrgCtx, geoMrgCtx, 0, geoMergeIdx0, geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, 0, intraMPM, nullptr + , pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, subBdofBuf[geoMergeIdx0], subBdofBuf[geoMergeIdx1] ); +#else PU::spanGeoMMVDMotionInfo( pu, geoMrgCtx , dummyAffineMergeCtx , geoMrgCtx, geoMrgCtx, 0, geoMergeIdx0, geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, 0, intraMPM , pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, subBdofBuf[geoMergeIdx0], subBdofBuf[geoMergeIdx1] ); +#endif #else PU::spanGeoMMVDMotionInfo( pu, geoMrgCtx, geoMrgCtx, geoMrgCtx, 0, geoMergeIdx0, geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, 0, intraMPM , pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, subBdofBuf[geoMergeIdx0], subBdofBuf[geoMergeIdx1] ); @@ -9578,6 +9607,9 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx #if JVET_Y0065_GPM_INTRA , IntraPrediction* pcIntraPred, std::vector<Pel>* reshapeLUT #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , Mv* geoBvList +#endif ) #else #if JVET_W0097_GPM_MMVD_TM && TM_MRG @@ -9602,6 +9634,33 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx #endif #endif { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (cu.firstPU->gpmInterIbcFlag) + { + MergeCtx geoBvMrgCtx; + PU::getIBCMergeCandidates(*cu.firstPU, geoBvMrgCtx); + memset(geoBvMrgCtx.ibcLicFlags, false, sizeof(bool) * geoBvMrgCtx.numValidMergeCand); + memset(geoBvMrgCtx.ibcFilterFlags, false, sizeof(bool) * geoBvMrgCtx.numValidMergeCand); + memset(geoBvMrgCtx.rribcFlipTypes, 0, sizeof(int) * geoBvMrgCtx.numValidMergeCand); +#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL + if (cu.cs->sps->getUseAML() && cu.cs->sps->getTMnoninterToolsEnableFlag()) +#else + if (cu.cs->sps->getUseAML()) +#endif + { + PredictionUnit puSaved = *cu.firstPU; + puSaved.cu->predMode = MODE_IBC; + adjustIBCMergeCandidates(puSaved, geoBvMrgCtx, 0, geoBvMrgCtx.numValidMergeCand); + puSaved.cu->predMode = MODE_INTER; + } + for (uint32_t ibcIdx = 0; ibcIdx < GEO_MAX_NUM_IBC_CANDS; ibcIdx++) + { + geoBvList[ibcIdx] = geoBvMrgCtx.mvFieldNeighbours[ibcIdx << 1].mv; + } + setFillCurTplAboveARMC(false); + setFillCurTplLeftARMC(false); + } +#endif #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING deriveGpmSplitMode(*cu.firstPU, geoMrgCtx #if JVET_W0097_GPM_MMVD_TM && TM_MRG @@ -9612,6 +9671,9 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx #endif #if JVET_Y0065_GPM_INTRA , pcIntraPred +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , geoBvList #endif ); #if JVET_W0097_GPM_MMVD_TM && TM_MRG @@ -9659,6 +9721,48 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx #else bool isIntra0 = candIdx0 >= GEO_MAX_NUM_UNI_CANDS; bool isIntra1 = candIdx1 >= GEO_MAX_NUM_UNI_CANDS; +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC +#if JVET_AG0164_AFFINE_GPM + bool isIbc0 = candIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; + bool isIbc1 = candIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#else + bool isIbc0 = candIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; + bool isIbc1 = candIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif + if (isIbc0) + { + Mv mv = pu.mv[0]; + int dir = pu.interDir; +#if JVET_AG0164_AFFINE_GPM + int ibcIdx = candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int ibcIdx = candIdx0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + const bool luma = cu.Y().valid(); + const bool chroma = isChromaEnabled(cu.chromaFormat) && cu.Cb().valid(); + pu.cu->predMode = MODE_IBC; + pu.mv[0] = geoBvList[ibcIdx]; + pu.interDir = 1; + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution + if (luma && (chroma || !isChromaEnabled(cu.chromaFormat))) + { + motionCompensation(*cu.firstPU, tmpGeoBuf0, REF_PIC_LIST_0, true, true); + } + else + { +#if JVET_AE0169_BIPREDICTIVE_IBC + motionCompensation(*cu.firstPU, tmpGeoBuf0, REF_PIC_LIST_0, luma, chroma); +#else + m_pcInterPred->motionCompensation(*cu.firstPU, tmpGeoBuf0, REF_PIC_LIST_0, luma, chroma); +#endif + } + pu.cu->predMode = MODE_INTER; + pu.mv[0] = mv; + pu.interDir = dir; + } + else #endif if (isIntra0) { @@ -9796,6 +9900,41 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx } } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { + Mv mv = pu.mv[0]; + int dir = pu.interDir; +#if JVET_AG0164_AFFINE_GPM + int ibcIdx = candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int ibcIdx = candIdx1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + const bool luma = cu.Y().valid(); + const bool chroma = isChromaEnabled(cu.chromaFormat) && cu.Cb().valid(); + pu.cu->predMode = MODE_IBC; + pu.mv[0] = geoBvList[ibcIdx]; + pu.interDir = 1; + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution + if (luma && (chroma || !isChromaEnabled(cu.chromaFormat))) + { + motionCompensation(*cu.firstPU, tmpGeoBuf1, REF_PIC_LIST_0, true, true); + } + else + { +#if JVET_AE0169_BIPREDICTIVE_IBC + motionCompensation(*cu.firstPU, tmpGeoBuf1, REF_PIC_LIST_0, luma, chroma); +#else + m_pcInterPred->motionCompensation(*cu.firstPU, tmpGeoBuf1, REF_PIC_LIST_0, luma, chroma); +#endif + } + pu.cu->predMode = MODE_INTER; + pu.mv[0] = mv; + pu.interDir = dir; + } + else +#endif if (isIntra1) { PU::getGeoIntraMPMs(pu, pcIntraPred->m_intraMPM+GEO_MAX_NUM_INTRA_CANDS, splitDir, g_geoTmShape[1][g_geoParams[pu.geoSplitDir][0]]); @@ -11537,7 +11676,11 @@ bool InterPrediction::xAMLIBCGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWi #if JVET_AC0112_IBC_LIC #if JVET_AE0169_IBC_MBVD_LIST_DERIVATION +#if JVET_AI0082_GPM_WITH_INTER_IBC +void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, int nCurBlkHeight, bool doIbcLic, bool checkTmlBvValidaion, Pel* pcBufPredRefTop, Pel* pcBufPredRefLeft) +#else void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, int nCurBlkHeight, bool doIbcLic, bool checkTmlBvValidaion) +#endif #else void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, int nCurBlkHeight, bool doIbcLic) #endif @@ -11778,7 +11921,11 @@ void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, bool isFracMv = pu.cs->sps->getIBCFracFlag() && mvTop.isFracMv(); if (isFracMv) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + PelUnitBuf pcYBuf(pu.chromaFormat, PelBuf(pcBufPredRefTop == nullptr ? m_acYuvRefAMLTemplate[0][0] : pcBufPredRefTop, nCurBlkWidth, AML_MERGE_TEMPLATE_SIZE)); +#else PelUnitBuf pcYBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nCurBlkWidth, AML_MERGE_TEMPLATE_SIZE)); +#endif getPredIBCBlk(pu, COMPONENT_Y, &currPic, mvTop, pcYBuf, filterIdx == 1, true); #if JVET_AA0070_RRIBC pcYBuf.Y().flip(pu.cu->rribcFlipType); @@ -11796,7 +11943,11 @@ void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, #else const Pel* rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(mvTop.hor, mvTop.ver)); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + PelBuf pcYBuf = PelBuf(pcBufPredRefTop == nullptr ? m_acYuvRefAMLTemplate[0][0] : pcBufPredRefTop, nCurBlkWidth, AML_MERGE_TEMPLATE_SIZE); +#else PelBuf pcYBuf = PelBuf(m_acYuvRefAMLTemplate[0][0], nCurBlkWidth, AML_MERGE_TEMPLATE_SIZE); +#endif Pel* pcY = pcYBuf.bufAt(0, 0); if (numTemplate[0] + numTemplate[1] > 0) { @@ -11862,7 +12013,11 @@ void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, bool isFracMv = pu.cs->sps->getIBCFracFlag() && mvLeft.isFracMv(); if (isFracMv) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + PelUnitBuf pcYBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft == nullptr ? m_acYuvRefAMLTemplate[1][0] : pcBufPredRefLeft, AML_MERGE_TEMPLATE_SIZE, nCurBlkHeight)); +#else PelUnitBuf pcYBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nCurBlkHeight)); +#endif getPredIBCBlk(pu, COMPONENT_Y, &currPic, mvLeft, pcYBuf, filterIdx == 1, true); #if JVET_AA0070_RRIBC pcYBuf.Y().flip(pu.cu->rribcFlipType); @@ -11876,7 +12031,11 @@ void InterPrediction::getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, else { #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + PelBuf pcYBuf = PelBuf(pcBufPredRefLeft == nullptr ? m_acYuvRefAMLTemplate[1][0] : pcBufPredRefLeft, AML_MERGE_TEMPLATE_SIZE, nCurBlkHeight); +#else PelBuf pcYBuf = PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nCurBlkHeight); +#endif Pel* pcY = pcYBuf.bufAt(0, 0); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS const Pel* rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset( mvLeft.hor >> MV_FRACTIONAL_BITS_INTERNAL, mvLeft.ver >> MV_FRACTIONAL_BITS_INTERNAL)); diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index 7229835ea..e3cea919d 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -794,6 +794,9 @@ public: #endif #if JVET_Y0065_GPM_INTRA , IntraPrediction* pcIntraPred +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , Mv* geoBvList #endif ); #endif @@ -824,6 +827,9 @@ public: #endif #if JVET_Y0065_GPM_INTRA , IntraPrediction* pcIntraPred, std::vector<Pel>* reshapeLUT +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , Mv* geoBvList #endif ); #else @@ -901,7 +907,11 @@ public: bool xAMLIBCGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWidth, int nCurBlkHeight); #if JVET_AC0112_IBC_LIC #if JVET_AE0169_IBC_MBVD_LIST_DERIVATION +#if JVET_AI0082_GPM_WITH_INTER_IBC + void getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, int nCurBlkHeight, bool doIbcLic = false, bool checkTmlBvValidaion = true, Pel* pcBufPredRefTop = nullptr, Pel* pcBufPredRefLeft = nullptr); +#else void getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, int nCurBlkHeight, bool doIbcLic = false, bool checkTmlBvValidaion = true); +#endif #else void getIBCAMLRefTemplate(PredictionUnit &pu, int nCurBlkWidth, int nCurBlkHeight, bool doIbcLic = false); #endif @@ -1294,6 +1304,63 @@ public: pu.cu->affine = false; #endif } +#if JVET_AI0082_GPM_WITH_INTER_IBC + template <uint8_t partIdx, bool useDefaultPelBuffer = true> + void fillPartGpmInterIbcRefTemplate(PredictionUnit &pu, std::vector<Pel>* lut, Pel* bufTop = nullptr, Pel* bufLeft = nullptr) + { + if (useDefaultPelBuffer) + { + bufTop = partIdx == 0 ? m_acYuvRefAMLTemplatePart0[0] : m_acYuvRefAMLTemplatePart1[0]; + bufLeft = partIdx == 0 ? m_acYuvRefAMLTemplatePart0[1] : m_acYuvRefAMLTemplatePart1[1]; + } + getIBCAMLRefTemplate(pu, pu.lumaSize().width, pu.lumaSize().height, false, true, bufTop, bufLeft); + if (lut != nullptr) + { + if (m_bAMLTemplateAvailabe[0]) + { + for (int w = 0; w < pu.lwidth(); ++w) + { + bufTop[w] = (*lut)[bufTop[w]]; + } + } + + if (m_bAMLTemplateAvailabe[1]) + { + for (int h = 0; h < pu.lheight(); ++h) + { + bufLeft[h] = (*lut)[bufLeft[h]]; + } + } + } + } + + template <uint8_t partIdx, bool useDefaultPelBuffer = true> + void fillPartGpmInterIbcRefTemplate(PredictionUnit &pu, std::vector<Pel>* lut, Mv* geoBvList, int candIdx, int geoMmvdIdx = -1, Pel* bufTop = nullptr, Pel* bufLeft = nullptr) + { +#if JVET_Y0065_GPM_INTRA +#if JVET_AG0164_AFFINE_GPM + if (candIdx < GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) +#else + if (candIdx < GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) +#endif +#else + if (candIdx < GEO_MAX_NUM_UNI_CANDS) +#endif + { + return; + } + pu.cu->predMode = MODE_IBC; +#if JVET_AG0164_AFFINE_GPM + pu.mv[REF_PIC_LIST_0] = geoBvList[candIdx - (GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS)]; +#else + pu.mv[REF_PIC_LIST_0] = geoBvList[candIdx - (GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS)]; +#endif + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + fillPartGpmInterIbcRefTemplate<partIdx, useDefaultPelBuffer>(pu, lut, bufTop, bufLeft); + pu.cu->predMode = MODE_INTER; + } +#endif #endif #if INTER_LIC || JVET_AC0112_IBC_LIC #if JVET_AE0078_IBC_LIC_EXTENSION diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 5edefec98..dcbb11a38 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -26897,7 +26897,11 @@ void IntraPrediction::getNeiEipCands(const PredictionUnit& pu, static_vector<Eip for (int i = 0; i < 2 && foundNeighMV == false; i++) { int refIdx = miNeigh.refIdx[i]; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (miNeigh.isInter && refIdx != -1) +#else if (refIdx != -1) +#endif { const int currRefPOC = slice.getRefPic(RefPicList(i), refIdx)->getPOC(); if (currRefPOC == colPOC) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 38adb6e21..65adf26ba 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1855,6 +1855,9 @@ private: bool m_ciipAffine; #endif bool m_Geo; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool m_geoInterIbc; +#endif #if INTER_LIC bool m_licEnabledFlag; #if JVET_AG0276_LIC_SLOPE_ADJUST @@ -2595,6 +2598,10 @@ void setCCALFEnabledFlag( bool b ) #endif void setUseGeo ( bool b ) { m_Geo = b; } bool getUseGeo () const { return m_Geo; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + void setUseGeoInterIbc ( bool b ) { m_geoInterIbc = b; } + bool getUseGeoInterIbc () const { return m_geoInterIbc; } +#endif #if INTER_LIC void setLicEnabledFlag ( bool b ) { m_licEnabledFlag = b; } bool getLicEnabledFlag () const { return m_licEnabledFlag; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 5b27cc0ae..d09dc1d1e 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -249,6 +249,7 @@ #define JVET_AE0174_NONINTER_TM_TOOLS_CONTROL 1 // JVET-AE0174: Add non-inter TM sps flag to control whether template matching is used for non-inter (Intra and IBC) tools #define JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES 1 // JVET-AE0094: IBC with non-adjacent spatial candidates #define JVET_AG0091_ARBVP 1 // JVET-AG0091: Auto-relocated block vector prediction +#define JVET_AI0082_TEMPORAL_BV 1 // JVET-AI0081: Temporal BV for IBC merge list construction #if JVET_AC0071_DBV && JVET_V0130_INTRA_TMP #define JVET_AF0066_ENABLE_DBV_4_SINGLE_TREE 1 // JVET-AF0066: Enable DBV mode in single tree configuration @@ -305,6 +306,7 @@ #define JVET_Z0139_HIST_AFF 1 // JVET-Z0139: Affine HMVP #define JVET_Z0139_NA_AFF 1 // JVET-Z0139: Constructed non-adjacent spatial neighbors for affine mode #define JVET_AA0058_GPM_ADAPTIVE_BLENDING 1 // JVET-AA0058: GPM adaptive blending +#define JVET_AI0082_GPM_WITH_INTER_IBC 1 // JVET-AI0082: GPM with inter prediction and IBC #define JVET_AA0146_WRAP_AROUND_FIX 1 // JVET-AA0146: bugfix&cleanup for wrap around motion compensation #define JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION 1 // JVET-AA0107 Regression based affine merge candidate derivation #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 75cb57008..7ceacd620 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -1090,6 +1090,9 @@ void PredictionUnit::initData() #if JVET_Y0065_GPM_INTRA gpmIntraFlag = false; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + gpmInterIbcFlag = false; +#endif #if JVET_W0097_GPM_MMVD_TM geoMMVDFlag0 = false; geoMMVDIdx0 = MAX_UCHAR; @@ -1313,6 +1316,9 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData) #if JVET_Y0065_GPM_INTRA gpmIntraFlag = predData.gpmIntraFlag; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + gpmInterIbcFlag = predData.gpmInterIbcFlag; +#endif #if JVET_W0097_GPM_MMVD_TM geoMMVDFlag0 = predData.geoMMVDFlag0; geoMMVDIdx0 = predData.geoMMVDIdx0; @@ -1544,6 +1550,9 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other ) #if JVET_Y0065_GPM_INTRA gpmIntraFlag = other.gpmIntraFlag; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + gpmInterIbcFlag = other.gpmInterIbcFlag; +#endif #if JVET_W0097_GPM_MMVD_TM geoMMVDFlag0 = other.geoMMVDFlag0; geoMMVDIdx0 = other.geoMMVDIdx0; diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 4400c04be..9cc8b9b20 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -643,6 +643,9 @@ struct InterPredictionData #if JVET_Y0065_GPM_INTRA bool gpmIntraFlag; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool gpmInterIbcFlag; +#endif #if JVET_W0097_GPM_MMVD_TM bool geoMMVDFlag0; uint8_t geoMMVDIdx0; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index ccff4189e..e6b8cdcc2 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -1324,7 +1324,11 @@ void getNeighBv(const PredictionUnit& puOrg, const PredictionUnit* pu, std::vect #endif ) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (!pu || ((pu->cu->predMode != MODE_IBC) && (!pu->cu->tmpFlag) && (!pu->cu->geoFlag))) +#else if (!pu || ((pu->cu->predMode != MODE_IBC) && (!pu->cu->tmpFlag))) +#endif { return; } @@ -1452,6 +1456,46 @@ void getNeighBv(const PredictionUnit& puOrg, const PredictionUnit* pu, std::vect } return; } + +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (pu && CU::isInter(*pu->cu) && pu->cu->geoFlag && pu->gpmInterIbcFlag) + { + bool isValid = pu->getMotionInfo(pu->lumaPos().offset(pu->lwidth() >> 1, pu->lheight() >> 1)).isIBCmot; + if (isValid) + { + MotionInfo mi = pu->getMotionInfo(pu->lumaPos().offset(pu->lwidth() >> 1, pu->lheight() >> 1)); + Mv bv = mi.mv[0]; + bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + if (PU::validItmpBv(puOrg, bv.hor, bv.ver)) + { +#if JVET_AH0055_INTRA_TMP_ARBVP + if (!PU::CheckBvAvailable(pBv, bv)) +#else + if (!CheckBvAvailable(pBv, bv)) +#endif + { + pBv.push_back(bv); + } + } + +#if JVET_AH0200_INTRA_TMP_BV_REORDER + bv.changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL); + if (PU::validIBCItmpMv(puOrg, bv, SGPM_TEMPLATE_SIZE)) + { +#if JVET_AH0055_INTRA_TMP_ARBVP + if (!PU::CheckBvAvailable(pSgpmMvs, bv)) +#else + if (!CheckBvAvailable(pSgpmMvs, bv)) +#endif + { + pSgpmMvs.push_back(bv); + } + } +#endif + } + return; + } +#endif } int PU::getItmpMergeCandidate(const PredictionUnit& pu, std::vector<Mv>& pBvs @@ -6497,7 +6541,16 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #else const bool isAvailableA1 = puLeft && pu.cu != puLeft->cu && CU::isIBC(*puLeft->cu); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isAvailableGpmIbcA1 = puLeft && pu.cu != puLeft->cu && CU::isInter(*puLeft->cu) && puLeft->cu->geoFlag; + if (isAvailableGpmIbcA1) + { + isAvailableGpmIbcA1 &= puLeft->getMotionInfo(posLB.offset(-1, 0)).isIBCmot; + } + if (isGt4x4 && (isAvailableA1 || isAvailableGpmIbcA1)) +#else if (isGt4x4 && isAvailableA1) +#endif { miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0)); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS @@ -6650,7 +6703,16 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #else bool isAvailableB1 = puAbove && pu.cu != puAbove->cu && CU::isIBC(*puAbove->cu); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isAvailableGpmIbcB1 = puAbove && pu.cu != puAbove->cu && CU::isInter(*puAbove->cu) && puAbove->cu->geoFlag; + if (isAvailableGpmIbcB1) + { + isAvailableGpmIbcB1 &= puAbove->getMotionInfo(posRT.offset(0, -1)).isIBCmot; + } + if (isGt4x4 && (isAvailableB1 || isAvailableGpmIbcB1)) +#else if (isGt4x4 && isAvailableB1) +#endif { miAbove = puAbove->getMotionInfo(posRT.offset(0, -1)); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS @@ -6819,7 +6881,16 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #else bool isAvailableB0 = puAboveRight && pu.cu != puAboveRight->cu && CU::isIBC(*puAboveRight->cu); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isAvailableGpmIbcB0 = puAboveRight && pu.cu != puAboveRight->cu && CU::isInter(*puAboveRight->cu) && puAboveRight->cu->geoFlag; + if (isAvailableGpmIbcB0) + { + isAvailableGpmIbcB0 &= puAboveRight->getMotionInfo(posRT.offset(1, -1)).isIBCmot; + } + if (isGt4x4 && (isAvailableB0 || isAvailableGpmIbcB0)) +#else if (isGt4x4 && isAvailableB0) +#endif { miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1)); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS @@ -6979,7 +7050,16 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #else bool isAvailableA0 = puLeftBottom && pu.cu != puLeftBottom->cu && CU::isIBC(*puLeftBottom->cu); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isAvailableGpmIbcA0 = puLeftBottom && pu.cu != puLeftBottom->cu && CU::isInter(*puLeftBottom->cu) && puLeftBottom->cu->geoFlag; + if (isAvailableGpmIbcA0) + { + isAvailableGpmIbcA0 &= puLeftBottom->getMotionInfo(posLB.offset(-1, 1)).isIBCmot; + } + if (isGt4x4 && (isAvailableA0 || isAvailableGpmIbcA0)) +#else if (isGt4x4 && isAvailableA0) +#endif { miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1)); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS @@ -7149,7 +7229,16 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #else bool isAvailableB2 = puAboveLeft && pu.cu != puAboveLeft->cu && CU::isIBC(*puAboveLeft->cu); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isAvailableGpmIbcB2 = puAboveLeft && pu.cu != puAboveLeft->cu && CU::isInter(*puAboveLeft->cu) && puAboveLeft->cu->geoFlag; + if (isAvailableGpmIbcB2) + { + isAvailableGpmIbcB2 &= puAboveLeft->getMotionInfo(posLT.offset(-1, -1)).isIBCmot; + } + if (isGt4x4 && (isAvailableB2 || isAvailableGpmIbcB2)) +#else if (isGt4x4 && isAvailableB2) +#endif { miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1)); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS @@ -7381,7 +7470,16 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); bool isAvailableNonAdjacent = puNonAdjacent && pu.cu != puNonAdjacent->cu && (CU::isIBC(*puNonAdjacent->cu) || puNonAdjacent->cu->tmpFlag); +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isAvailableNonAdjacentGpmIbc = puNonAdjacent && pu.cu != puNonAdjacent->cu && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->cu->geoFlag; + if (isAvailableNonAdjacentGpmIbc) + { + isAvailableNonAdjacentGpmIbc &= puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isIBCmot; + } + if (isGt4x4 && (isAvailableNonAdjacent || isAvailableNonAdjacentGpmIbc)) +#else if (isGt4x4 && isAvailableNonAdjacent) +#endif { miNonAdjacent = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS @@ -7591,7 +7689,16 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); bool isAvailableNonAdjacent = puNonAdjacent && pu.cu != puNonAdjacent->cu && (CU::isIBC(*puNonAdjacent->cu) || puNonAdjacent->cu->tmpFlag); +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isAvailableNonAdjacentGpmIbc = puNonAdjacent && pu.cu != puNonAdjacent->cu && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->cu->geoFlag; + if (isAvailableNonAdjacentGpmIbc) + { + isAvailableNonAdjacentGpmIbc &= puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isIBCmot; + } + if (isGt4x4 && (isAvailableNonAdjacent || isAvailableNonAdjacentGpmIbc)) +#else if (isGt4x4 && isAvailableNonAdjacent) +#endif { miNonAdjacent = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS @@ -7751,6 +7858,57 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const } } } +#endif +#if JVET_AI0082_TEMPORAL_BV + std::vector<MotionInfo> temporalMi; + getTemporalBv(pu, temporalMi); + int numValidTemporalBv = 0; + for(MotionInfo mi: temporalMi) + { + if(checkIsIBCCandidateValid(pu, mi) && cnt < maxNumMergeCand && numValidTemporalBv < 8) + { + mrgCtx.initMrgCand(cnt); + mrgCtx.interDirNeighbours[cnt] = 1; + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(mi.mv[0], MAX_NUM_REF); + mrgCtx.useAltHpelIf[cnt] = pu.mergeFlag ? mi.useAltHpelIf : (pu.cu->imv == IMV_HPEL); + mrgCtx.rribcFlipTypes[cnt] = (mi.isIBCmot && !pu.tmMergeFlag && !pu.ibcMbvdMergeFlag) ? mi.rribcFlipType : 0; + if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + numValidTemporalBv++; + // early termination + if (cnt == maxNumMergeCand) + { + mrgCtx.numAMVPMergeCand = cnt; + return; + } + } + } + if(mi.interDir == 3) + { + MotionInfo mi1 = mi; + mi1.mv[0] = mi1.mv[1]; + if(checkIsIBCCandidateValid(pu, mi1) && cnt < maxNumMergeCand && numValidTemporalBv < 8) + { + mrgCtx.initMrgCand(cnt); + mrgCtx.interDirNeighbours[cnt] = 1; + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(mi1.mv[0], MAX_NUM_REF); + mrgCtx.useAltHpelIf[cnt] = pu.mergeFlag ? mi1.useAltHpelIf : (pu.cu->imv == IMV_HPEL); + mrgCtx.rribcFlipTypes[cnt] = (mi1.isIBCmot && !pu.tmMergeFlag && !pu.ibcMbvdMergeFlag) ? mi1.rribcFlipType : 0; + if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + numValidTemporalBv++; + // early termination + if (cnt == maxNumMergeCand) + { + mrgCtx.numAMVPMergeCand = cnt; + return; + } + } + } + } + } #endif if (cnt != maxNumMergeCand) { @@ -7830,7 +7988,16 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const const PredictionUnit* puCascaded = cs.getPURestricted(posCand[n].offset(offsetX, offsetY), pu, pu.chType); bool isAvailableCascaded = puCascaded && pu.cu != puCascaded->cu && (CU::isIBC(*puCascaded->cu) || puCascaded->cu->tmpFlag); +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isAvailableCascadedGpm = puCascaded && pu.cu != puCascaded->cu && CU::isInter(*puCascaded->cu) && puCascaded->cu->geoFlag; + if (isAvailableCascadedGpm) + { + isAvailableCascadedGpm &= puCascaded->getMotionInfo(posCand[n].offset(offsetX, offsetY)).isIBCmot; + } + if (isGt4x4 && (isAvailableCascaded || isAvailableCascadedGpm)) +#else if (isGt4x4 && isAvailableCascaded) +#endif { miCascaded = puCascaded->getMotionInfo(posCand[n].offset(offsetX, offsetY)); #if JVET_AA0070_RRIBC @@ -25689,6 +25856,13 @@ void PU::spanSCCInfo(PredictionUnit &pu) motionInfo[x].isRefRefSCC = false; motionInfo[x].isSCC = CU::isIBC(*pu.cu) || CU::isPLT(*pu.cu) || (pu.cu->bdpcmMode > 0); +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (CU::isInter(*pu.cu) && pu.cu->geoFlag && motionInfo[x].isIBCmot) + { + motionInfo[x].isSCC = true; + continue; + } +#endif if (CU::isInter(*pu.cu) && motionInfo[x].isInter && (motionInfo[x].interDir == 1 || motionInfo[x].interDir == 2)) { cMv = motionInfo[x].mv[motionInfo[x].interDir - 1]; @@ -26634,9 +26808,17 @@ void PU::spanGeoMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const uint8 #if JVET_AG0164_AFFINE_GPM bool isIntra0 = candIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS; bool isIntra1 = candIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isIbc0 = candIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; + bool isIbc1 = candIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif #else bool isIntra0 = candIdx0 >= GEO_MAX_NUM_UNI_CANDS; bool isIntra1 = candIdx1 >= GEO_MAX_NUM_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isIbc0 = candIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; + bool isIbc1 = candIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif #endif uint32_t sliceIdx = pu.cs->slice->getIndependentSliceIdx(); #else @@ -26836,9 +27018,17 @@ void PU::spanGeoMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const uint8 #if JVET_AG0164_AFFINE_GPM geoIpm[0] = isIntra0 ? intraMPM[candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS] : -1; geoIpm[1] = isIntra1 ? intraMPM[candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS] : -1; +#if JVET_AI0082_GPM_WITH_INTER_IBC + geoIpm[0] = isIntra0 ? (isIbc0 ? PLANAR_IDX : intraMPM[candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS]) : -1; + geoIpm[1] = isIntra1 ? (isIbc1 ? PLANAR_IDX : intraMPM[candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS]) : -1; +#endif #else geoIpm[0] = isIntra0 ? intraMPM[candIdx0 - GEO_MAX_NUM_UNI_CANDS] : -1; geoIpm[1] = isIntra1 ? intraMPM[candIdx1 - GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS] : -1; +#if JVET_AI0082_GPM_WITH_INTER_IBC + geoIpm[0] = isIntra0 ? (isIbc0 ? PLANAR_IDX : intraMPM[candIdx0 - GEO_MAX_NUM_UNI_CANDS]) : -1; + geoIpm[1] = isIntra1 ? (isIbc1 ? PLANAR_IDX : intraMPM[candIdx1 - GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS]) : -1; +#endif #endif geoIpm[2] = (isIntra0 && isIntra1) ? ((candIdx1 < candIdx0) ? geoIpm[1] : geoIpm[0]) : isIntra0 ? geoIpm[0] : geoIpm[1]; @@ -27138,6 +27328,9 @@ void PU::spanGeoMMVDMotionInfo(PredictionUnit& pu, MergeCtx& geoMrgCtx , AffineMergeCtx& geoAffMrgCtx #endif , MergeCtx& geoTmMrgCtx0, MergeCtx& geoTmMrgCtx1, const uint8_t splitDir, const uint8_t mergeIdx0, const uint8_t mergeIdx1, const bool tmFlag0, const bool mmvdFlag0, const uint8_t mmvdIdx0, const bool tmFlag1, const bool mmvdFlag1, const uint8_t mmvdIdx1, const uint8_t bldIdx, const uint8_t *intraMPM, +#if JVET_AI0082_GPM_WITH_INTER_IBC + const Mv* geoBvList, +#endif const bool dmvrPart0, const bool dmvrPart1, Mv* bdofSubPuMvOffsetPart0, Mv* bdofSubPuMvOffsetPart1) #else void PU::spanGeoMMVDMotionInfo(PredictionUnit &pu, MergeCtx &geoMrgCtx, MergeCtx &geoTmMrgCtx0, MergeCtx &geoTmMrgCtx1, const uint8_t splitDir, const uint8_t mergeIdx0, const uint8_t mergeIdx1, const bool tmFlag0, const bool mmvdFlag0, const uint8_t mmvdIdx0, const bool tmFlag1, const bool mmvdFlag1, const uint8_t mmvdIdx1, const uint8_t bldIdx, const uint8_t *intraMPM) @@ -27575,9 +27768,36 @@ void PU::spanGeoMMVDMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const u #if JVET_AG0164_AFFINE_GPM bool isIntra0 = mergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS; bool isIntra1 = mergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isIbc0 = mergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; + bool isIbc1 = mergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif #else bool isIntra0 = mergeIdx0 >= GEO_MAX_NUM_UNI_CANDS; bool isIntra1 = mergeIdx1 >= GEO_MAX_NUM_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isIbc0 = mergeIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; + bool isIbc1 = mergeIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + Mv bv = Mv(0, 0); + if (isIbc0) + { +#if JVET_AG0164_AFFINE_GPM + bv = geoBvList[mergeIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS]; +#else + bv = geoBvList[mergeIdx0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS]; +#endif + } + else if (isIbc1) + { +#if JVET_AG0164_AFFINE_GPM + bv = geoBvList[mergeIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS]; +#else + bv = geoBvList[mergeIdx1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS]; +#endif + } #endif uint32_t sliceIdx = pu.cs->slice->getIndependentSliceIdx(); #else @@ -27672,6 +27892,26 @@ void PU::spanGeoMMVDMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const u tpmMask = motionIdx <= 0 ? (1 - isFlip) : isFlip; if (tpmMask == 0 && isIntra0) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc0) + { + mb.at(x, y).isInter = false; + mb.at(x, y).isIBCmot = true; + mb.at(x, y).useIbcLic = false; + mb.at(x, y).useIbcFilter = false; + mb.at(x, y).rribcFlipType = 0; + mb.at(x, y).interDir = 1; + mb.at(x, y).refIdx[0] = MAX_NUM_REF; + mb.at(x, y).refIdx[1] = -1; + mb.at(x, y).mv[0] = bv; + mb.at(x, y).mv[1] = Mv(); + mb.at(x, y).bv = mb.at(x, y).mv[0]; + mb.at(x, y).bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + mb.at(x, y).sliceIdx = sliceIdx; + } + else + { +#endif mb.at(x, y).isInter = false; mb.at(x, y).interDir = MAX_UCHAR; mb.at(x, y).refIdx[0] = -1; @@ -27679,6 +27919,9 @@ void PU::spanGeoMMVDMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const u mb.at(x, y).mv[0] = Mv(); mb.at(x, y).mv[1] = Mv(); mb.at(x, y).sliceIdx = sliceIdx; +#if JVET_AI0082_GPM_WITH_INTER_IBC + } +#endif } #else #if !JVET_AE0046_BI_GPM @@ -27743,6 +27986,26 @@ void PU::spanGeoMMVDMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const u #if JVET_Y0065_GPM_INTRA else if (tpmMask == 1 && isIntra1) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { + mb.at(x, y).isInter = false; + mb.at(x, y).isIBCmot = true; + mb.at(x, y).useIbcLic = false; + mb.at(x, y).useIbcFilter = false; + mb.at(x, y).rribcFlipType = 0; + mb.at(x, y).interDir = 1; + mb.at(x, y).refIdx[0] = MAX_NUM_REF; + mb.at(x, y).refIdx[1] = -1; + mb.at(x, y).mv[0] = bv; + mb.at(x, y).mv[1] = Mv(); + mb.at(x, y).bv = mb.at(x, y).mv[0]; + mb.at(x, y).bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + mb.at(x, y).sliceIdx = sliceIdx; + } + else + { +#endif mb.at(x, y).isInter = false; mb.at(x, y).interDir = MAX_UCHAR; mb.at(x, y).refIdx[0] = -1; @@ -27750,6 +28013,9 @@ void PU::spanGeoMMVDMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const u mb.at(x, y).mv[0] = Mv(); mb.at(x, y).mv[1] = Mv(); mb.at(x, y).sliceIdx = sliceIdx; +#if JVET_AI0082_GPM_WITH_INTER_IBC + } +#endif } #endif else @@ -27822,9 +28088,17 @@ void PU::spanGeoMMVDMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const u #if JVET_AG0164_AFFINE_GPM geoIpm[0] = isIntra0 ? intraMPM[mergeIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS] : -1; geoIpm[1] = isIntra1 ? intraMPM[mergeIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS] : -1; +#if JVET_AI0082_GPM_WITH_INTER_IBC + geoIpm[0] = isIntra0 ? (isIbc0 ? PLANAR_IDX : intraMPM[mergeIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS]) : -1; + geoIpm[1] = isIntra1 ? (isIbc1 ? PLANAR_IDX : intraMPM[mergeIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS]) : -1; +#endif #else geoIpm[0] = isIntra0 ? intraMPM[mergeIdx0 - GEO_MAX_NUM_UNI_CANDS] : -1; geoIpm[1] = isIntra1 ? intraMPM[mergeIdx1 - GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS] : -1; +#if JVET_AI0082_GPM_WITH_INTER_IBC + geoIpm[0] = isIntra0 ? (isIbc0 ? PLANAR_IDX : intraMPM[mergeIdx0 - GEO_MAX_NUM_UNI_CANDS]) : -1; + geoIpm[1] = isIntra1 ? (isIbc1 ? PLANAR_IDX : intraMPM[mergeIdx1 - GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS]) : -1; +#endif #endif geoIpm[2] = (isIntra0 && isIntra1) ? ((mergeIdx1 < mergeIdx0) ? geoIpm[1] : geoIpm[0]) : isIntra0 ? geoIpm[0] : geoIpm[1]; @@ -31093,4 +31367,263 @@ void CU::saveModelsInHEIP(const CodingUnit &cu) } #endif +#if JVET_AI0082_TEMPORAL_BV +bool getColocatedBVP(const PredictionUnit &pu, const Position &posIn, MotionInfo& rcMv, const int col) +{ + // don't perform MV compression when generally disabled or subPuMvp is used + const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4); + const unsigned mask = ~( scale - 1 ); + const Position pos = Position{ PosType( posIn.x & mask ), PosType( posIn.y & mask ) }; + const Slice &slice = *pu.cs->slice; + const Picture* const pColPic = slice.getRefPic(RefPicList(col == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), col == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); + const MotionInfo& mi = pColPic->cs->getMotionInfo( pos ); + if( !pColPic ) + { + return false; + } + if (mi.isIBCmot) + { + rcMv = mi; + return true; + } + else + { + return false; + } +} + +struct ShiftCand +{ + Mv shiftMv; + int colIdx; + ShiftCand(): shiftMv(Mv(0, 0)), colIdx(0) {} + ShiftCand(Mv mv, int colid): shiftMv(mv), colIdx(colid){} + bool operator==(const ShiftCand &other) const + { + if (shiftMv == other.shiftMv && colIdx == other.colIdx) + { + return true; + } + return false; + } +}; + +void addOneTypeTempCandidates(const PredictionUnit &pu, std::vector<MotionInfo> &temporalMiCandList, + std::vector<ShiftCand> &shiftCands) +{ + std::vector<std::pair<MotionInfo, Position>> tempCandList; + const CodingStructure &cs = *pu.cs; + const PreCalcValues &pcv = *cs.pcv; + const SubPic &curSubPic = cs.slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + Position posCand[5] = {pu.Y().center(), pu.Y().topLeft(), pu.Y().topRight(), pu.Y().bottomLeft(), pu.Y().bottomRight()}; + for (auto shiftCand: shiftCands) + { + for (int refPosIdx = 0; refPosIdx < 5; refPosIdx++) + { + int colIdx = shiftCand.colIdx; + Mv shiftMv = shiftCand.shiftMv; + shiftMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + Position shiftedRefPos = Position(posCand[refPosIdx].x + shiftMv.hor, posCand[refPosIdx].y + shiftMv.ver); + bool boundaryCond = false; + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = (shiftedRefPos.x <= curSubPic.getSubPicRight()) && (shiftedRefPos.y <= curSubPic.getSubPicBottom()); + } + else + { + boundaryCond = (shiftedRefPos.x < pcv.lumaWidth) && (shiftedRefPos.y < pcv.lumaHeight); + } + MotionInfo cColMi; + bool bExistMv = boundaryCond && getColocatedBVP(pu, shiftedRefPos, cColMi, colIdx); + if (bExistMv) + { + // temporalMiCandList.push_back(cColMi); + tempCandList.push_back({cColMi, Position(abs(shiftedRefPos.x - posCand[0].x), abs(shiftedRefPos.y - posCand[0].y))}); + } + } + } + std::stable_sort(tempCandList.begin(), tempCandList.end(), [](const std::pair<MotionInfo, Position> &a, const std::pair<MotionInfo, Position> &b) { return (a.second.x + a.second.y) < (b.second.x + b.second.y); }); + for(auto cand: tempCandList) + { + temporalMiCandList.push_back(cand.first); + } +} + +void getTemporalBv(const PredictionUnit &pu, std::vector<MotionInfo>& temporalMiCandList) +{ + const CodingStructure &cs = *pu.cs; + const Slice &slice = *cs.slice; + // co-located positions in colocated picture + std::vector<ShiftCand> colPos; + for (int colIdx = 0; colIdx < (slice.isInterB() ? 2 : 1) && !slice.isIntra(); colIdx++) + { + const Picture* const pColPic = slice.getRefPic(RefPicList(colIdx == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), colIdx == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); + if( !pColPic || pColPic->isRefScaled( slice.getPPS() )) + { + continue; + } + colPos.push_back(ShiftCand(Mv(0, 0), colIdx)); + } + + // shifted positions in colocated pictures + std::vector<ShiftCand> shiftedColPos; + const Position topLeft = pu.Y().topLeft(); + const Position posCand[5] = { topLeft.offset(-1, pu.Y().height - 1), topLeft.offset(pu.Y().width - 1, -1), + topLeft.offset(-1, -1), topLeft.offset(pu.Y().width, -1), + topLeft.offset(-1, pu.Y().height) }; + const unsigned plevel = cs.sps->getLog2ParallelMergeLevelMinus2() + 2; + for (int colIdx = 0; colIdx < (slice.isInterB() ? 2 : 1) && !slice.isIntra(); colIdx++) + { + const Picture* const pColPic = slice.getRefPic(RefPicList(colIdx == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), colIdx == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); + if( !pColPic || pColPic->isRefScaled( slice.getPPS() )) + { + continue; + } + MotionInfo miNeigh; + const int colPOC = pColPic->getPOC(); + for (int posIdx = 0; posIdx < 5; posIdx++) + { + const PredictionUnit *puRef = cs.getPURestricted(posCand[posIdx], pu, pu.chType); + bool isAvailableNeigh = puRef && + PU::isDiffMER(pu.lumaPos(), posCand[posIdx], plevel) && + puRef->getMotionInfo( posCand[posIdx] ).isInter && + pu.cu != puRef->cu && CU::isInter(*puRef->cu); + if (isAvailableNeigh) + { + miNeigh = puRef->getMotionInfo(posCand[posIdx]); + for (int i = 0; i < 2; i++) + { + int refIdx = miNeigh.refIdx[i]; + if (refIdx != -1) + { + const int currRefPOC = slice.getRefPic(RefPicList(i), refIdx)->getPOC(); + if (currRefPOC == colPOC) + { + shiftedColPos.push_back(ShiftCand(miNeigh.mv[i], colIdx)); + } + else + { + int distPOC0 = colPOC - cs.picture->getPOC(); + int distPOC1 = currRefPOC - cs.picture->getPOC(); + if(SIGN(distPOC0) == SIGN(distPOC1)) + { + Mv scaledMv(miNeigh.mv[i].getHor() * distPOC0 / distPOC1, miNeigh.mv[i].getVer() * distPOC0 / distPOC1); + shiftedColPos.push_back(ShiftCand(scaledMv, colIdx)); + } + } + } + } + } + } + } + + std::vector<ShiftCand> oppositeShiftedColPos; + int colPic0Poc = -1; + int colPic1Poc = -1; + for (int colIdx = 0; colIdx < (slice.isInterB() ? 2 : 1) && !slice.isIntra(); colIdx++) + { + const Picture* const pColPic = slice.getRefPic(RefPicList(colIdx == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), colIdx == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); + if( !pColPic || pColPic->isRefScaled( slice.getPPS() ) ) + { + continue; + } + if(colIdx) + { + colPic1Poc = pColPic->getPOC(); + } + else + { + colPic0Poc = pColPic->getPOC(); + } + } + if(colPic0Poc != -1 && colPic1Poc != -1) + { + int curPoc = cs.picture->getPOC(); + int distPoc0 = colPic0Poc - curPoc; + int distPoc1 = colPic1Poc - curPoc; + // CHECK(abs(distPoc0) != abs(distPoc1), "abs(distPoc0) != abs(distPoc1)"); + for(auto shiftCand: shiftedColPos) + { + Mv shiftMv = shiftCand.shiftMv; + int colIdx = shiftCand.colIdx; + int mvHor = (colIdx == 0) ? (shiftMv.hor * distPoc1 / distPoc0) : (shiftMv.hor * distPoc0 / distPoc1); + int mvVer = (colIdx == 0) ? (shiftMv.ver * distPoc1 / distPoc0) : (shiftMv.ver * distPoc0 / distPoc1); + oppositeShiftedColPos.push_back({Mv(mvHor, mvVer), colIdx == 0 ? 1 : 0}); + } + } + + // scaled positions in colocated pictures + std::vector<ShiftCand> scaledColPos; + for (int colIdx = 0; colIdx < (slice.isInterB() ? 2 : 1) && !slice.isIntra(); colIdx++) + { + const Picture* const pColPic = slice.getRefPic(RefPicList(colIdx == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), colIdx == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); + if( !pColPic || pColPic->isRefScaled( slice.getPPS() )) + { + continue; + } + MotionInfo miNeigh; + const int colPOC = pColPic->getPOC(); + for (int posIdx = 0; posIdx < 5; posIdx++) + { + const PredictionUnit *puRef = cs.getPURestricted(posCand[posIdx], pu, pu.chType); + bool isAvailableNeigh = puRef && + PU::isDiffMER(pu.lumaPos(), posCand[posIdx], plevel) && + puRef->getMotionInfo( posCand[posIdx] ).isInter && + pu.cu != puRef->cu && CU::isInter(*puRef->cu); + if (isAvailableNeigh) + { + miNeigh = puRef->getMotionInfo(posCand[posIdx]); + for (int i = 0; i < 2; i++) + { + int refIdx = miNeigh.refIdx[i]; + if (refIdx != -1) + { + const int currRefPOC = slice.getRefPic(RefPicList(i), refIdx)->getPOC(); + if (currRefPOC != colPOC) + { + int distPOC0 = colPOC - cs.picture->getPOC(); + int distPOC1 = currRefPOC - cs.picture->getPOC(); + if(SIGN(distPOC0) == SIGN(distPOC1)) + { + Mv scaledMv(miNeigh.mv[i].getHor() * distPOC0 / distPOC1, miNeigh.mv[i].getVer() * distPOC0 / distPOC1); + scaledColPos.push_back(ShiftCand(scaledMv, colIdx)); + } + } + } + } + } + } + } + std::vector<ShiftCand> temporalPos; + auto addPos = [&](const ShiftCand pos)->void + { + bool isIncluded = false; + for(auto posInList: temporalPos) + { + isIncluded |= (pos == posInList); + } + if (!isIncluded) + { + temporalPos.push_back(pos); + } + }; + for(auto pos: colPos) + { + addPos(pos); + } + for(auto pos: shiftedColPos) + { + addPos(pos); + } + for(auto pos: oppositeShiftedColPos) + { + addPos(pos); + } + for(auto pos: scaledColPos) + { + addPos(pos); + } + addOneTypeTempCandidates(pu, temporalMiCandList, temporalPos); +} +#endif diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 1ec488897..98e26459c 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -446,7 +446,7 @@ namespace PU inline void getRribcBvpCand(PredictionUnit &pu, AMVPInfo *amvpInfo); inline void clusterBvpCand(const int cbWidth, const int cbHeight, AMVPInfo *pInfo); #endif - void fillMvpCand ( PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo + void fillMvpCand ( PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo #if TM_AMVP || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV , InterPrediction* interPred = nullptr #endif @@ -809,6 +809,9 @@ namespace PU , AffineMergeCtx& geoAffMrgCtx #endif , MergeCtx& geoTmMrgCtx0, MergeCtx& geoTmMrgCtx1, const uint8_t splitDir, const uint8_t mergeIdx0, const uint8_t mergeIdx1, const bool tmFlag0, const bool mmvdFlag0, const uint8_t mmvdIdx0, const bool tmFlag1, const bool mmvdFlag1, const uint8_t mmvdIdx1, const uint8_t bldIdx,const uint8_t *intraMPM, +#if JVET_AI0082_GPM_WITH_INTER_IBC + const Mv* geoBvList, +#endif const bool dmvrPart0 = false, const bool dmvrPart1 = false, Mv* bdofSubPuMvOffsetPart0 = nullptr, Mv* bdofSubPuMvOffsetPart1 = nullptr); #else void spanGeoMMVDMotionInfo(PredictionUnit &pu, MergeCtx &geoMrgCtx, MergeCtx &geoTmMrgCtx0, MergeCtx &geoTmMrgCtx1, const uint8_t splitDir, const uint8_t mergeIdx0, const uint8_t mergeIdx1, const bool tmFlag0, const bool mmvdFlag0, const uint8_t mmvdIdx0, const bool tmFlag1, const bool mmvdFlag1, const uint8_t mmvdIdx1, const uint8_t bldIdx, const uint8_t *intraMPM); @@ -1367,7 +1370,11 @@ void sortIntraCandList(double uiCost, int mergeCand, static_vector<double, N>& c { size_t shift = 0; size_t currSize = candCostList.size(); +#if JVET_AI0082_GPM_WITH_INTER_IBC + CHECK(currSize >= GEO_MAX_NUM_INTRA_CANDS + GEO_MAX_NUM_IBC_CANDS, "list overflow!"); +#else CHECK(currSize >= GEO_MAX_NUM_INTRA_CANDS, "list overflow!"); +#endif while (shift < currSize && uiCost < candCostList[currSize - 1 - shift]) { @@ -1407,6 +1414,11 @@ bool getAllowedEipMerge(const CodingUnit &cu, const ComponentID compId); bool getAllowedEip(const CodingUnit &cu, const ComponentID compId); int getAllowedCurEip(const CodingUnit& cu, const ComponentID compId, static_vector<EIPInfo, NUM_DERIVED_EIP>& eipInfoList); #endif + +#if JVET_AI0082_TEMPORAL_BV +bool getColocatedBVP(const PredictionUnit &pu, const Position &posIn, MotionInfo &rcMv, const int col); +void getTemporalBv(const PredictionUnit &pu, std::vector<MotionInfo>& temporalMiCandList); +#endif #endif #if JVET_AG0061_INTER_LFNST_NSPT 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/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 82dc26815..4c146425d 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -5561,6 +5561,9 @@ void CABACReader::merge_idx( PredictionUnit& pu ) pu.geoMergeIdx0 = (uint8_t)pu.mergeIdx; pu.geoMergeIdx1 = (uint8_t)pu.mergeIdx; pu.gpmIntraFlag = false; +#if JVET_AI0082_GPM_WITH_INTER_IBC + pu.gpmInterIbcFlag = false; +#endif return; } #endif @@ -5578,6 +5581,11 @@ void CABACReader::merge_idx( PredictionUnit& pu ) bool isIntra0 = false; bool isIntra1 = false; bool bUseOnlyOneVector = pu.cs->slice->isInterP() || pu.cs->sps->getMaxNumGeoCand() == 1; +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isIbc0 = false; + bool isIbc1 = false; + bool isGpmInterIbcEnabled = pu.cs->sps->getUseGeoInterIbc(); #endif pu.geoMMVDFlag0 = m_BinDecoder.decodeBin(Ctx::GeoMmvdFlag()); if (pu.geoMMVDFlag0) @@ -5599,6 +5607,12 @@ void CABACReader::merge_idx( PredictionUnit& pu ) else { isIntra0 = m_BinDecoder.decodeBin( Ctx::GPMIntraFlag() ) ? true : false; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIntra0 && isGpmInterIbcEnabled) + { + isIbc0 = m_BinDecoder.decodeBin( Ctx::GpmInterIbcFlag() ) ? true : false; + } +#endif } if (!bUseOnlyOneVector || isIntra0) @@ -5624,6 +5638,12 @@ void CABACReader::merge_idx( PredictionUnit& pu ) else if (!isIntra0) { isIntra1 = m_BinDecoder.decodeBin( Ctx::GPMIntraFlag() ) ? true : false; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIntra1 && isGpmInterIbcEnabled) + { + isIbc1 = m_BinDecoder.decodeBin( Ctx::GpmInterIbcFlag() ) ? true : false; + } +#endif } } else @@ -5631,6 +5651,9 @@ void CABACReader::merge_idx( PredictionUnit& pu ) isIntra1 = true; } pu.gpmIntraFlag = (isIntra0 || isIntra1); +#if JVET_AI0082_GPM_WITH_INTER_IBC + pu.gpmInterIbcFlag = (isIbc0 || isIbc1); +#endif #endif #if TM_MRG @@ -5664,7 +5687,11 @@ void CABACReader::merge_idx( PredictionUnit& pu ) #if JVET_Y0065_GPM_INTRA if (isIntra0 || isIntra1) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + geo_merge_idx1(pu, isIntra0, isIntra1, isIbc0, isIbc1); +#else geo_merge_idx1(pu, isIntra0, isIntra1); +#endif } else #endif @@ -5693,7 +5720,11 @@ void CABACReader::merge_idx( PredictionUnit& pu ) else { #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + geo_merge_idx1(pu, isIntra0, isIntra1, isIbc0, isIbc1); +#else geo_merge_idx1(pu, isIntra0, isIntra1); +#endif #else geo_merge_idx1(pu); #endif @@ -5702,7 +5733,11 @@ void CABACReader::merge_idx( PredictionUnit& pu ) else { #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + geo_merge_idx1(pu, isIntra0, isIntra1, isIbc0, isIbc1); +#else geo_merge_idx1(pu, isIntra0, isIntra1); +#endif #else geo_merge_idx1(pu); #endif @@ -6041,7 +6076,11 @@ void CABACReader::geo_merge_idx(PredictionUnit& pu) } #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC +void CABACReader::geo_merge_idx1(PredictionUnit& pu, bool isIntra0, bool isIntra1, bool isIbc0, bool isIbc1) +#else void CABACReader::geo_merge_idx1(PredictionUnit& pu, bool isIntra0, bool isIntra1) +#endif #else void CABACReader::geo_merge_idx1(PredictionUnit& pu) #endif @@ -6072,10 +6111,38 @@ void CABACReader::geo_merge_idx1(PredictionUnit& pu) #if JVET_Y0065_GPM_INTRA if (isIntra0) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc0) + { + unsigned int uiUnaryIdx = 0; + int numCandminus1 = GEO_MAX_NUM_IBC_CANDS - 1; + for (; uiUnaryIdx < numCandminus1; ++uiUnaryIdx) + { + if (!m_BinDecoder.decodeBin(Ctx::GpmInterIbcIdx((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)))) + { + break; + } + } +#if JVET_AG0164_AFFINE_GPM + mergeCand0 = GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS + uiUnaryIdx; +#else + mergeCand0 = GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS + uiUnaryIdx; +#endif + } + else + { +#if JVET_AG0164_AFFINE_GPM + mergeCand0 = GEO_MAX_ALL_INTER_UNI_CANDS + unary_max_eqprob(GEO_MAX_NUM_INTRA_CANDS-1); +#else + mergeCand0 = GEO_MAX_NUM_UNI_CANDS + unary_max_eqprob(GEO_MAX_NUM_INTRA_CANDS - 1); +#endif + } +#else #if JVET_AG0164_AFFINE_GPM mergeCand0 = GEO_MAX_ALL_INTER_UNI_CANDS + unary_max_eqprob(GEO_MAX_NUM_INTRA_CANDS-1); #else mergeCand0 = GEO_MAX_NUM_UNI_CANDS + unary_max_eqprob(GEO_MAX_NUM_INTRA_CANDS-1); +#endif #endif } else if (numCandminus2 >= 0) @@ -6107,10 +6174,38 @@ void CABACReader::geo_merge_idx1(PredictionUnit& pu) if (isIntra1) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { + unsigned int uiUnaryIdx = 0; + int numCandminus1 = GEO_MAX_NUM_IBC_CANDS - 1; + for (; uiUnaryIdx < numCandminus1; ++uiUnaryIdx) + { + if (!m_BinDecoder.decodeBin(Ctx::GpmInterIbcIdx((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx)))) + { + break; + } + } +#if JVET_AG0164_AFFINE_GPM + mergeCand1 = GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS + uiUnaryIdx; +#else + mergeCand1 = GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS + uiUnaryIdx; +#endif + } + else + { +#if JVET_AG0164_AFFINE_GPM + mergeCand1 = GEO_MAX_ALL_INTER_UNI_CANDS + unary_max_eqprob(GEO_MAX_NUM_INTRA_CANDS - 1); +#else + mergeCand1 = GEO_MAX_NUM_UNI_CANDS + unary_max_eqprob(GEO_MAX_NUM_INTRA_CANDS - 1); +#endif + } +#else #if JVET_AG0164_AFFINE_GPM mergeCand1 = GEO_MAX_ALL_INTER_UNI_CANDS + unary_max_eqprob(GEO_MAX_NUM_INTRA_CANDS - 1); #else mergeCand1 = GEO_MAX_NUM_UNI_CANDS + unary_max_eqprob(GEO_MAX_NUM_INTRA_CANDS-1); +#endif #endif } else if (numCandminus2 >= 0) diff --git a/source/Lib/DecoderLib/CABACReader.h b/source/Lib/DecoderLib/CABACReader.h index 1465c72a7..bb0de1181 100644 --- a/source/Lib/DecoderLib/CABACReader.h +++ b/source/Lib/DecoderLib/CABACReader.h @@ -212,7 +212,11 @@ public: void geo_mmvd_idx(PredictionUnit& pu, RefPicList eRefPicList); void geo_merge_idx(PredictionUnit& pu); #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + void geo_merge_idx1 ( PredictionUnit& pu, bool isIntra0, bool isIntra1, bool isIbc0, bool isIbc1); +#else void geo_merge_idx1 ( PredictionUnit& pu, bool isIntra0, bool isIntra1); +#endif #else void geo_merge_idx1 ( PredictionUnit& pu); #endif diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 90fb33183..ad4d824cd 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -1889,6 +1889,9 @@ void DecCu::xReconInter(CodingUnit &cu) #endif #if JVET_Y0065_GPM_INTRA , m_pcIntraPred, (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) ? &m_pcReshape->getFwdLUT() : nullptr +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , m_geoBvList #endif ); #if JVET_W0097_GPM_MMVD_TM && TM_MRG @@ -1922,6 +1925,9 @@ void DecCu::xReconInter(CodingUnit &cu) , cu.firstPU->geoBldIdx #endif , m_pcIntraPred->m_intraMPM +#if JVET_AI0082_GPM_WITH_INTER_IBC + , m_geoBvList +#endif #if JVET_AE0046_BI_GPM , cu.firstPU->gpmDmvrRefinePart0 , cu.firstPU->gpmDmvrRefinePart1 diff --git a/source/Lib/DecoderLib/DecCu.h b/source/Lib/DecoderLib/DecCu.h index 4e1793d13..c74e55597 100644 --- a/source/Lib/DecoderLib/DecCu.h +++ b/source/Lib/DecoderLib/DecCu.h @@ -131,6 +131,9 @@ private: #if JVET_AG0164_AFFINE_GPM AffineMergeCtx m_geoAffMrgCtx; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + Mv m_geoBvList[GEO_MAX_NUM_IBC_CANDS]; +#endif #if JVET_W0097_GPM_MMVD_TM && TM_MRG #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING MergeCtx m_geoTmMrgCtx[GEO_NUM_TM_MV_CAND]; diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index d644b269c..a1cd16a6b 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2638,6 +2638,10 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) { READ_FLAG( uiCode, "sps_gpm_tm_enabled_flag" ); pcSPS->setUseGPMTMMode( uiCode != 0 ); } +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + READ_FLAG(uiCode, "sps_gpm_inter_ibc_enabled_flag"); + pcSPS->setUseGeoInterIbc(uiCode != 0); #endif } #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 084b4c091..0b38f85a3 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -5200,6 +5200,16 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) bool isIntra1 = (pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS); #endif bool bUseOnlyOneVector = pu.cs->slice->isInterP() || pu.cs->sps->getMaxNumGeoCand() == 1; +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC +#if JVET_AG0164_AFFINE_GPM + bool isIbc0 = (pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); + bool isIbc1 = (pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); +#else + bool isIbc0 = (pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); + bool isIbc1 = (pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); +#endif + bool isGpmInterIbcEnabled = pu.cs->sps->getUseGeoInterIbc(); #endif m_BinEncoder.encodeBin(pu.geoMMVDFlag0, Ctx::GeoMmvdFlag()); if (pu.geoMMVDFlag0) @@ -5222,6 +5232,12 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) else { m_BinEncoder.encodeBin( isIntra0 ? 1 : 0, Ctx::GPMIntraFlag() ); +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIntra0 && isGpmInterIbcEnabled) + { + m_BinEncoder.encodeBin( isIbc0 ? 1 : 0, Ctx::GpmInterIbcFlag() ); + } +#endif } if (!bUseOnlyOneVector || isIntra0) @@ -5248,6 +5264,12 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) else if (!isIntra0) { m_BinEncoder.encodeBin( isIntra1 ? 1 : 0, Ctx::GPMIntraFlag() ); +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIntra1 && isGpmInterIbcEnabled) + { + m_BinEncoder.encodeBin( isIbc1 ? 1 : 0, Ctx::GpmInterIbcFlag() ); + } +#endif } } else @@ -5256,6 +5278,9 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) } CHECK( pu.gpmIntraFlag != (isIntra0 || isIntra1), "gpmIntraFlag shall be equal to (isIntra0 || isIntra1)" ); +#if JVET_AI0082_GPM_WITH_INTER_IBC + CHECK( pu.gpmInterIbcFlag != (isIbc0 || isIbc1), "gpmInterIbcFlag shall be equal to (isIbc0 || isIbc1)" ); +#endif #endif #if TM_MRG @@ -5846,6 +5871,15 @@ void CABACWriter::geo_merge_idx1(const PredictionUnit& pu) bool isIntra1 = (candIdx1 >= GEO_MAX_NUM_UNI_CANDS); #endif #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC +#if JVET_AG0164_AFFINE_GPM + bool isIbc0 = (candIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); + bool isIbc1 = (candIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); +#else + bool isIbc0 = (candIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); + bool isIbc1 = (candIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); +#endif +#endif #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING geoModeIdx(pu); @@ -5862,10 +5896,40 @@ void CABACWriter::geo_merge_idx1(const PredictionUnit& pu) #if JVET_Y0065_GPM_INTRA if (isIntra0) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc0) + { +#if JVET_AG0164_AFFINE_GPM + int mergeIdx = candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int mergeIdx = candIdx0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + int numCandminus1 = GEO_MAX_NUM_IBC_CANDS - 1; + unsigned int uiUnaryIdx = 0; + for (; uiUnaryIdx < numCandminus1; ++uiUnaryIdx) + { + unsigned int uiSymbol = mergeIdx == uiUnaryIdx ? 0 : 1; + m_BinEncoder.encodeBin(uiSymbol, Ctx::GpmInterIbcIdx((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx))); + if (uiSymbol == 0) + { + break; + } + } + } + else + { +#if JVET_AG0164_AFFINE_GPM + unary_max_eqprob(candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS-1); +#else + unary_max_eqprob(candIdx0 - GEO_MAX_NUM_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS - 1); +#endif + } +#else #if JVET_AG0164_AFFINE_GPM unary_max_eqprob(candIdx0 - GEO_MAX_ALL_INTER_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS-1); #else unary_max_eqprob(candIdx0 - GEO_MAX_NUM_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS-1); +#endif #endif } else if (numCandminus2 >= 0) @@ -5903,10 +5967,40 @@ void CABACWriter::geo_merge_idx1(const PredictionUnit& pu) if (isIntra1) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { +#if JVET_AG0164_AFFINE_GPM + int mergeIdx = candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int mergeIdx = candIdx1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + int numCandminus1 = GEO_MAX_NUM_IBC_CANDS - 1; + unsigned int uiUnaryIdx = 0; + for (; uiUnaryIdx < numCandminus1; ++uiUnaryIdx) + { + unsigned int uiSymbol = mergeIdx == uiUnaryIdx ? 0 : 1; + m_BinEncoder.encodeBin(uiSymbol, Ctx::GpmInterIbcIdx((uiUnaryIdx > LAST_MERGE_IDX_CABAC - 1 ? LAST_MERGE_IDX_CABAC - 1 : uiUnaryIdx))); + if (uiSymbol == 0) + { + break; + } + } + } + else + { +#if JVET_AG0164_AFFINE_GPM + unary_max_eqprob(candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS - 1); +#else + unary_max_eqprob(candIdx1 - GEO_MAX_NUM_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS - 1); +#endif + } +#else #if JVET_AG0164_AFFINE_GPM unary_max_eqprob(candIdx1 - GEO_MAX_ALL_INTER_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS - 1); #else unary_max_eqprob(candIdx1 - GEO_MAX_NUM_UNI_CANDS, GEO_MAX_NUM_INTRA_CANDS-1); +#endif #endif } else if (numCandminus2 >= 0) @@ -6022,11 +6116,19 @@ uint64_t CABACWriter::geo_intraFlag_est( const TempCtx& ctxStart, const int flag return getEstFracBits(); } +#if JVET_AI0082_GPM_WITH_INTER_IBC +uint64_t CABACWriter::geo_intraIdx_est( const int intraIdx, const bool isGeoIbc) +#else uint64_t CABACWriter::geo_intraIdx_est( const int intraIdx) +#endif { resetBits(); +#if JVET_AI0082_GPM_WITH_INTER_IBC + unary_max_eqprob(intraIdx, GEO_MAX_NUM_INTRA_CANDS + (isGeoIbc ? GEO_MAX_NUM_IBC_CANDS : 0) - 1); +#else unary_max_eqprob(intraIdx, GEO_MAX_NUM_INTRA_CANDS-1); +#endif return getEstFracBits(); } diff --git a/source/Lib/EncoderLib/CABACWriter.h b/source/Lib/EncoderLib/CABACWriter.h index 598949f2a..edaa3ae66 100644 --- a/source/Lib/EncoderLib/CABACWriter.h +++ b/source/Lib/EncoderLib/CABACWriter.h @@ -243,7 +243,11 @@ public: ); #if JVET_Y0065_GPM_INTRA uint64_t geo_intraFlag_est ( const TempCtx& ctxStart, const int flag); +#if JVET_AI0082_GPM_WITH_INTER_IBC + uint64_t geo_intraIdx_est ( const int intraIdx, const bool isGeoIbc); +#else uint64_t geo_intraIdx_est ( const int intraIdx); +#endif #endif uint64_t geo_mmvdFlag_est(const TempCtx& ctxStart, const int flag); uint64_t geo_mmvdIdx_est(const TempCtx& ctxStart, const int mmvdIdx, const bool extMMVD); diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 1a3010a99..21dccb06d 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -541,6 +541,9 @@ protected: bool m_ciipTimd; #endif bool m_Geo; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool m_geoInterIbc; +#endif bool m_allowDisFracMMVD; bool m_AffineAmvr; bool m_HashME; @@ -1817,6 +1820,10 @@ public: #endif void setUseGeo ( bool b ) { m_Geo = b; } bool getUseGeo () const { return m_Geo; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + void setUseGeoInterIbc ( bool b ) { m_geoInterIbc = b; } + bool getUseGeoInterIbc () const { return m_geoInterIbc; } +#endif void setAllowDisFracMMVD ( bool b ) { m_allowDisFracMMVD = b; } bool getAllowDisFracMMVD () const { return m_allowDisFracMMVD; } void setUseHashME ( bool b ) { m_HashME = b; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index bca42b840..274ebaa26 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -75,7 +75,11 @@ EncCu::EncCu() : m_GeoModeTest #if NON_ADJACENT_MRG_CAND int numGeoModeTest = 0; #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + for (int i = 1; i < GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS; i++) +#else for (int i = 1; i < GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS; i++) +#endif #else for (int i = 1; i < GEO_MAX_NUM_UNI_CANDS; i++) #endif @@ -8858,6 +8862,10 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct refinePossible.fill(false); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool testGeoInterIbc = sps.getUseGeoInterIbc(); +#endif + // 1. bit estimation const double sqrtLambdaFracBits = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE; uint8_t maxNumMergeCandidates = tempCS->sps->getMaxNumGeoCand(); @@ -8942,7 +8950,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif #if JVET_Y0065_GPM_INTRA bool bUseOnlyOneVector = (tempCS->slice->isInterP() || tempCS->sps->getMaxNumGeoCand() == 1); +#if JVET_AI0082_GPM_WITH_INTER_IBC + double geoIntraFlag0Cost[2], geoIntraFlag1Cost[2][2], geoIntraIdxCost[GEO_MAX_NUM_INTRA_CANDS + GEO_MAX_NUM_IBC_CANDS]; +#else double geoIntraFlag0Cost[2], geoIntraFlag1Cost[2][2], geoIntraIdxCost[GEO_MAX_NUM_INTRA_CANDS]; +#endif for (int idx = 0; idx < 2; idx++) { uint64_t fracBits = m_CABACEstimator->geo_intraFlag_est(ctxStart, idx); @@ -8950,9 +8962,17 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct geoIntraFlag1Cost[0][idx] = !bUseOnlyOneVector ? geoIntraFlag0Cost[idx] : 0; geoIntraFlag1Cost[1][idx] = 0; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + for (int idx = 0; idx < GEO_MAX_NUM_INTRA_CANDS + (testGeoInterIbc ? GEO_MAX_NUM_IBC_CANDS : 0); idx++) +#else for (int idx = 0; idx < GEO_MAX_NUM_INTRA_CANDS; idx++) +#endif { +#if JVET_AI0082_GPM_WITH_INTER_IBC + uint64_t fracBits = m_CABACEstimator->geo_intraIdx_est(idx, testGeoInterIbc); +#else uint64_t fracBits = m_CABACEstimator->geo_intraIdx_est(idx); +#endif geoIntraIdxCost[idx] = (double)fracBits * sqrtLambdaFracBits; } #endif @@ -9134,6 +9154,15 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct double bestNormalMrgCost = MAX_DOUBLE; #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + Distortion sadIntraWholeBlk[GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_IBC_CANDS]; + uint8_t isGeoChromaAvail[GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_IBC_CANDS]; + uint8_t isGeoMMVDChromaAvail[GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_IBC_CANDS][GPM_EXT_MMVD_MAX_REFINE_NUM]; + uint8_t isGeoIntraChromaAvail[GEO_NUM_INTRA_RDO_BUFFER]; + memset(isGeoChromaAvail, 0, sizeof(uint8_t) * (GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_IBC_CANDS)); + memset(isGeoMMVDChromaAvail, 0, sizeof(uint8_t) * (GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_IBC_CANDS)* GPM_EXT_MMVD_MAX_REFINE_NUM); + memset(isGeoIntraChromaAvail, 0, sizeof(uint8_t) * GEO_NUM_INTRA_RDO_BUFFER); +#else Distortion sadIntraWholeBlk[GEO_MAX_ALL_INTER_UNI_CANDS]; uint8_t isGeoChromaAvail[GEO_MAX_ALL_INTER_UNI_CANDS]; uint8_t isGeoMMVDChromaAvail[GEO_MAX_ALL_INTER_UNI_CANDS][GPM_EXT_MMVD_MAX_REFINE_NUM]; @@ -9141,6 +9170,7 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct memset(isGeoChromaAvail, 0, sizeof(uint8_t) * GEO_MAX_ALL_INTER_UNI_CANDS); memset(isGeoMMVDChromaAvail, 0, sizeof(uint8_t) * GEO_MAX_ALL_INTER_UNI_CANDS* GPM_EXT_MMVD_MAX_REFINE_NUM); memset(isGeoIntraChromaAvail, 0, sizeof(uint8_t) * GEO_NUM_INTRA_RDO_BUFFER); +#endif #else bool isGeoChromaAvail[GEO_MAX_ALL_INTER_UNI_CANDS]; bool isGeoMMVDChromaAvail[GEO_MAX_ALL_INTER_UNI_CANDS][GPM_EXT_MMVD_MAX_REFINE_NUM]; @@ -9431,10 +9461,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct for (int intraIdx = 0; intraIdx < GEO_MAX_NUM_INTRA_CANDS; intraIdx++) { uint8_t intraPred = geoIntraMPMList[splitDir][partIdx][intraIdx]; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (intraRDOBufIdx[intraPred] >= GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) +#else if (intraRDOBufIdx[intraPred] >= GEO_NUM_INTRA_RDO_BUFFER) +#endif { uint8_t intraCand = intraRDOBufCnt++; +#if JVET_AI0082_GPM_WITH_INTER_IBC + CHECK(intraCand >= GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS, "Geo Intra buffer overflow"); +#else CHECK(intraCand >= GEO_NUM_INTRA_RDO_BUFFER, "Geo Intra buffer overflow"); +#endif intraRDOBufIdx[intraPred] = intraCand; pu.intraDir[0] = intraPred; @@ -9528,6 +9566,97 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct pu.geoBldIdx = 0; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + auto isFracBv = [&tempCS](Mv mv) + { + return tempCS->sps->getIBCFracFlag() + && ((mv.hor & ((1 << MV_FRACTIONAL_BITS_INTERNAL) - 1)) != 0 || (mv.ver & ((1 << MV_FRACTIONAL_BITS_INTERNAL) - 1)) != 0); + }; + Mv geoBvList[GEO_MAX_NUM_IBC_CANDS]; + bool skipIbcCand[GEO_MAX_NUM_IBC_CANDS] = {false}; + if (testGeoInterIbc) + { + MergeCtx geoBvMrgCtx; + PU::getIBCMergeCandidates(pu, geoBvMrgCtx); + memset(geoBvMrgCtx.ibcLicFlags, false, sizeof(bool) * geoBvMrgCtx.numValidMergeCand); + memset(geoBvMrgCtx.ibcFilterFlags, false, sizeof(bool) * geoBvMrgCtx.numValidMergeCand); + memset(geoBvMrgCtx.rribcFlipTypes, 0, sizeof(int) * geoBvMrgCtx.numValidMergeCand); +#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL + if (pu.cs->sps->getUseAML() && pu.cs->sps->getTMnoninterToolsEnableFlag()) +#else + if (pu.cs->sps->getUseAML()) +#endif + { + PredictionUnit puSaved = pu; + puSaved.cu->predMode = MODE_IBC; + m_pcInterSearch->adjustIBCMergeCandidates(puSaved, geoBvMrgCtx, 0, geoBvMrgCtx.numValidMergeCand); + m_pcInterSearch->setFillCurTplAboveARMC(false); + m_pcInterSearch->setFillCurTplLeftARMC(false); + puSaved.cu->predMode = MODE_INTER; + } + for (int ibcIdx = 0; ibcIdx < GEO_MAX_NUM_IBC_CANDS; ibcIdx++) + { + geoBvList[ibcIdx] = geoBvMrgCtx.mvFieldNeighbours[ibcIdx << 1].mv; + Mv bv = geoBvList[ibcIdx]; + if (bv == Mv(0, 0)) + { + skipIbcCand[ibcIdx] = true; + continue; + } +#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS + bool foundFracBV = isFracBv(bv); + int ibcRdoBuf = GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS + ibcIdx; +#if JVET_AG0164_AFFINE_GPM + geoIntraBuffer[ibcRdoBuf] = m_acMergeBuffer[GEO_MAX_ALL_INTER_UNI_CANDS + ibcRdoBuf].getBuf(localUnitArea); +#else + geoIntraBuffer[ibcRdoBuf] = m_acMergeBuffer[GEO_MAX_NUM_UNI_CANDS + ibcRdoBuf].getBuf(localUnitArea); +#endif + if (foundFracBV) + { + pu.cu->predMode = MODE_IBC; + pu.mv[0] = bv; + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + m_pcInterSearch->getPredIBCBlk(pu, COMPONENT_Y, pu.cu->slice->getPic(), pu.mv[0], geoIntraBuffer[ibcRdoBuf], false, false); + pu.cu->predMode = MODE_INTER; + } + else +#endif + { + pu.bv = bv; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + int xPred = pu.bv.getHor(); + int yPred = pu.bv.getVer(); + Picture* refPic = pu.cu->slice->getPic(); + const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]); + const Pel* piRefSrch = refBuf.buf; + int refStride = refBuf.stride; + Pel* piPred = geoIntraBuffer[ibcRdoBuf].Y().buf; + int predStride = geoIntraBuffer[ibcRdoBuf].Y().stride; + int height = geoIntraBuffer[ibcRdoBuf].Y().height; + int width = geoIntraBuffer[ibcRdoBuf].Y().width; + for (int h = 0; h < height; h++) + { + memcpy(piPred, piRefSrch + h * refStride + refStride * yPred + xPred, width * sizeof(Pel)); + piPred += predStride; + } + } + if (pu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) + { + geoIntraTempBuf[ibcRdoBuf] = m_acGeoMMVDTmpBuffer[0][ibcRdoBuf].getBuf(localUnitArea); + geoIntraTempBuf[ibcRdoBuf].Y().rspSignal(geoIntraBuffer[ibcRdoBuf].Y(), m_pcReshape->getInvLUT()); + } + else + { + geoIntraTempBuf[ibcRdoBuf] = geoIntraBuffer[ibcRdoBuf]; + } + distParamWholeBlk.cur.buf = geoIntraTempBuf[ibcRdoBuf].Y().buf; + distParamWholeBlk.cur.stride = geoIntraTempBuf[ibcRdoBuf].Y().stride; + sadIntraWholeBlk[ibcRdoBuf] = distParamWholeBlk.distFunc(distParamWholeBlk); + } + } +#endif + int wIdx = floorLog2(cu.lwidth()) - GEO_MIN_CU_LOG2; int hIdx = floorLog2(cu.lheight()) - GEO_MIN_CU_LOG2; Distortion sadSmall = 0, sadLarge = 0; @@ -9542,10 +9671,17 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct static_vector<double, 5> sadCostList0[GEO_NUM_PARTITION_MODE]; static_vector<double, 5> sadCostList1[GEO_NUM_PARTITION_MODE]; #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + static_vector<int, GEO_MAX_NUM_INTRA_CANDS + GEO_MAX_NUM_IBC_CANDS> intraCandList0[GEO_NUM_PARTITION_MODE]; + static_vector<int, GEO_MAX_NUM_INTRA_CANDS + GEO_MAX_NUM_IBC_CANDS> intraCandList1[GEO_NUM_PARTITION_MODE]; + static_vector<double, GEO_MAX_NUM_INTRA_CANDS + GEO_MAX_NUM_IBC_CANDS> intraSadCostList0[GEO_NUM_PARTITION_MODE]; + static_vector<double, GEO_MAX_NUM_INTRA_CANDS + GEO_MAX_NUM_IBC_CANDS> intraSadCostList1[GEO_NUM_PARTITION_MODE]; +#else static_vector<int, GEO_MAX_NUM_INTRA_CANDS> intraCandList0[GEO_NUM_PARTITION_MODE]; static_vector<int, GEO_MAX_NUM_INTRA_CANDS> intraCandList1[GEO_NUM_PARTITION_MODE]; static_vector<double, GEO_MAX_NUM_INTRA_CANDS> intraSadCostList0[GEO_NUM_PARTITION_MODE]; static_vector<double, GEO_MAX_NUM_INTRA_CANDS> intraSadCostList1[GEO_NUM_PARTITION_MODE]; +#endif #endif for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) @@ -9574,12 +9710,26 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct } #if JVET_AG0164_AFFINE_GPM +#if JVET_AI0082_GPM_WITH_INTER_IBC + for (uint8_t mergeCand = 0; mergeCand < GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS + GEO_MAX_NUM_IBC_CANDS; mergeCand++) +#else for (uint8_t mergeCand = 0; mergeCand < GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; mergeCand++) +#endif { if ((mergeCand < maxNumMergeCandidates && mrgDuplicated[mergeCand]) || (mergeCand >= maxNumMergeCandidates && mergeCand < GEO_MAX_ALL_INTER_UNI_CANDS)) { continue; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (!testGeoInterIbc && mergeCand >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) + { + continue; + } + if (mergeCand >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS && skipIbcCand[mergeCand - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS]) + { + continue; + } +#endif double tempCost; int isAffine = (mergeCand < numRegularGpmMergeCand || mergeCand >= GEO_MAX_ALL_INTER_UNI_CANDS) ? 0 : 1; @@ -9588,7 +9738,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct { #else #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + for (uint8_t mergeCand = 0; mergeCand < GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS + GEO_MAX_NUM_IBC_CANDS; mergeCand++) +#else for (uint8_t mergeCand = 0; mergeCand < GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; mergeCand++) +#endif #else for (uint8_t mergeCand = 0; mergeCand < maxNumMergeCandidates; mergeCand++) #endif @@ -9601,6 +9755,16 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct { continue; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (!testGeoIbc && mergeCand >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) + { + continue; + } + if (mergeCand >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS && skipIbcCand[mergeCand - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS]) + { + continue; + } +#endif #if JVET_Y0065_GPM_INTRA double tempCost; if (mergeCand < GEO_MAX_NUM_UNI_CANDS) @@ -9655,7 +9819,17 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #else int intraIdx = mergeCand - GEO_MAX_NUM_UNI_CANDS; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC +#if JVET_AG0164_AFFINE_GPM + bool isIbc = (mergeCand >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); + int rdobuffer = isIbc ? (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS : intraRDOBufIdx[geoIntraMPMList[splitDir][0][intraIdx]]; +#else + bool isIbc = (mergeCand >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); + int rdobuffer = isIbc ? (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS : intraRDOBufIdx[geoIntraMPMList[splitDir][0][intraIdx]]; +#endif +#else int rdobuffer = intraRDOBufIdx[geoIntraMPMList[splitDir][0][intraIdx]]; +#endif m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), geoIntraTempBuf[rdobuffer].Y().buf, geoIntraTempBuf[rdobuffer].Y().stride, sadMask, maskStride, stepX, maskStride2, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y); sadLarge = distParam.distFunc(distParam); tempCost = (double)sadLarge + geoIntraIdxCost[intraIdx] + geoIntraFlag0Cost[1] + geoMMVDFlagCost[0]; @@ -9665,7 +9839,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct m_geoMMVDCostList.insert(splitDir, 0, mergeCand, 0, tempCost); sortIntraCandList(tempCost, mergeCand, intraSadCostList0[splitDir], intraCandList0[splitDir]); +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (!isIbc && geoIntraMPMList[splitDir][0][intraIdx] != geoIntraMPMList[splitDir][1][intraIdx]) +#else if (geoIntraMPMList[splitDir][0][intraIdx] != geoIntraMPMList[splitDir][1][intraIdx]) +#endif { rdobuffer = intraRDOBufIdx[geoIntraMPMList[splitDir][1][intraIdx]]; m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), geoIntraTempBuf[rdobuffer].Y().buf, geoIntraTempBuf[rdobuffer].Y().stride, sadMask, maskStride, stepX, maskStride2, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y); @@ -9753,6 +9931,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif #if JVET_Y0065_GPM_INTRA , m_pcIntraSearch +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , geoBvList #endif ); geoSyntaxMode = m_pcInterSearch->convertGeoSplitModeToSyntax(splitDir, mergeCand0, mergeCand1); @@ -9848,14 +10029,34 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct { CHECK(!affGPMValid, "AffGPMFlag should be false"); } +#if JVET_AI0082_GPM_WITH_INTER_IBC + int isIbc0 = (mergeCand0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; + int isIbc1 = (mergeCand1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; +#endif #else int isIntra0 = (mergeCand0 >= GEO_MAX_NUM_UNI_CANDS) ? 1 : 0; int isIntra1 = (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS) ? 1 : 0; +#if JVET_AI0082_GPM_WITH_INTER_IBC + int isIbc0 = (mergeCand0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; + int isIbc1 = (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; +#endif #endif int candidateSAD = candidateIdx * GEO_BLENDING_NUM + bldIdx; if (isIntra0 || isIntra1) { PelUnitBuf predSrc0, predSrc1; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc0) + { +#if JVET_AG0164_AFFINE_GPM + int rdobuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int rdobuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + predSrc0 = geoIntraBuffer[rdobuffer]; + } + else +#endif if (isIntra0) { #if JVET_AG0164_AFFINE_GPM @@ -9870,6 +10071,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct { predSrc0 = geoTempBuf[mergeCand0]; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { +#if JVET_AG0164_AFFINE_GPM + int rdobuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int rdobuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + predSrc1 = geoIntraBuffer[rdobuffer]; + } + else +#endif if (isIntra1) { #if JVET_AG0164_AFFINE_GPM @@ -9933,7 +10146,7 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct int intraIdx1 = mergeCand1 - GEO_MAX_ALL_INTER_UNI_CANDS; if (!isAffine0) { - updateCost+= geoIntraFlag0Cost[isIntra0]; + updateCost+= geoIntraFlag0Cost[isIntra0]; } int mergeIdx0 = mergeCand0 - isAffine0 * numRegularGpmMergeCand; int mergeIdx1 = mergeCand1 - isAffine1 * numRegularGpmMergeCand; @@ -10168,10 +10381,43 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct int isIntra1 = (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS) ? 1 : 0; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC +#if JVET_AG0164_AFFINE_GPM + int isIbc0 = (mergeCand0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; + int isIbc1 = (mergeCand1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; +#else + int isIbc0 = (mergeCand0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; + int isIbc1 = (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; +#endif +#endif if (!isChromaEnabled(pu.chromaFormat) && !isIntra0 && !isIntra1) { continue; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc0) + { +#if JVET_AG0164_AFFINE_GPM + int ibcIdx = mergeCand0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int ibcIdx = mergeCand0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + ibcIdx; + Mv bv = geoBvList[ibcIdx]; + if (isChromaEnabled(pu.chromaFormat) && !isGeoIntraChromaAvail[rdoBuffer]) + { + pu.cu->predMode = MODE_IBC; + pu.mv[0] = bv; + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution + m_pcInterSearch->motionCompensation(pu, geoIntraBuffer[rdoBuffer], REF_PIC_LIST_0, false, true); + pu.cu->predMode = MODE_INTER; + isGeoIntraChromaAvail[rdoBuffer] = 2; + } + predSrc0 = geoIntraBuffer[rdoBuffer]; + } + else +#endif if (isIntra0) { #if JVET_AG0164_AFFINE_GPM @@ -10253,6 +10499,30 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct predSrc0 = geoTempBuf[mergeCand0]; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { +#if JVET_AG0164_AFFINE_GPM + int ibcIdx = mergeCand1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int ibcIdx = mergeCand1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + ibcIdx; + Mv bv = geoBvList[ibcIdx]; + if (isChromaEnabled(pu.chromaFormat) && !isGeoIntraChromaAvail[rdoBuffer]) + { + pu.cu->predMode = MODE_IBC; + pu.mv[0] = bv; + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution + m_pcInterSearch->motionCompensation(pu, geoIntraBuffer[rdoBuffer], REF_PIC_LIST_0, false, true); + pu.cu->predMode = MODE_INTER; + isGeoIntraChromaAvail[rdoBuffer] = 2; + } + predSrc1 = geoIntraBuffer[rdoBuffer]; + } + else +#endif if (isIntra1) { #if JVET_AG0164_AFFINE_GPM @@ -10621,6 +10891,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_Y0065_GPM_INTRA #if JVET_AG0164_AFFINE_GPM pu.gpmIntraFlag = pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS || pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + pu.gpmInterIbcFlag = pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS || pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif if (pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS) { memcpy(m_pcIntraSearch->m_intraMPM, geoIntraMPMList[pu.geoSplitDir][0], sizeof(uint8_t)*GEO_MAX_NUM_INTRA_CANDS); @@ -10631,6 +10904,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct } #else pu.gpmIntraFlag = pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS || pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + pu.gpmInterIbcFlag = pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS || pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif if (pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS) { memcpy(m_pcIntraSearch->m_intraMPM, geoIntraMPMList[pu.geoSplitDir][0], sizeof(uint8_t)*GEO_MAX_NUM_INTRA_CANDS); @@ -10731,6 +11007,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct , affMergeCtx #endif , *mergeTmCtx0, *mergeTmCtx1, pu.geoSplitDir, pu.geoMergeIdx0, pu.geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, pu.geoBldIdx, m_pcIntraSearch->m_intraMPM, +#if JVET_AI0082_GPM_WITH_INTER_IBC + geoBvList, +#endif pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, pu.gpmDmvrRefinePart0 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][pu.geoMergeIdx0] : nullptr, pu.gpmDmvrRefinePart1 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][pu.geoMergeIdx1] : nullptr); #else PU::spanGeoMMVDMotionInfo(pu, mergeCtx[GEO_TM_OFF], *mergeTmCtx0, *mergeTmCtx1, pu.geoSplitDir, pu.geoMergeIdx0, pu.geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, pu.geoBldIdx, m_pcIntraSearch->m_intraMPM); @@ -11165,6 +11444,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif #if JVET_Y0065_GPM_INTRA , m_pcIntraSearch +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , geoBvList #endif , mmvdCand0 - 1, mmvdCand1 - 1); geoSyntaxMode = m_pcInterSearch->convertGeoSplitModeToSyntax(splitDir, mergeCand0, mergeCand1, mmvdCand0 - 1, mmvdCand1 - 1); @@ -11526,9 +11808,17 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_AG0164_AFFINE_GPM int isIntra0 = (mergeCand0 >= GEO_MAX_ALL_INTER_UNI_CANDS) ? 1 : 0; int isIntra1 = (mergeCand1 >= GEO_MAX_ALL_INTER_UNI_CANDS) ? 1 : 0; +#if JVET_AI0082_GPM_WITH_INTER_IBC + int isIbc0 = (mergeCand0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; + int isIbc1 = (mergeCand1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; +#endif #else int isIntra0 = (mergeCand0 >= GEO_MAX_NUM_UNI_CANDS) ? 1 : 0; int isIntra1 = (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS) ? 1 : 0; +#if JVET_AI0082_GPM_WITH_INTER_IBC + int isIbc0 = (mergeCand0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; + int isIbc1 = (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; +#endif #endif int candidateSAD = candidateIdx * GEO_BLENDING_NUM + bldIdx; #endif @@ -11544,6 +11834,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif if (isIntra0 || isIntra1) { +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc0) + { +#if JVET_AG0164_AFFINE_GPM + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + predSrc0 = geoIntraBuffer[rdoBuffer]; + } + else +#endif if (isIntra0) { int rdoBuffer = intraRDOBufIdx[geoIntraMPMList[splitDir][0][intraIdx0]]; @@ -11561,6 +11863,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct predSrc0 = geoMMVDTempBuf[mergeCand0][mmvdCand0]; } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { +#if JVET_AG0164_AFFINE_GPM + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + predSrc1 = geoIntraBuffer[rdoBuffer]; + } + else +#endif if (isIntra1) { int rdoBuffer = intraRDOBufIdx[geoIntraMPMList[splitDir][1][intraIdx1]]; @@ -11996,11 +12310,43 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct int isIntra1 = (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS) ? 1 : 0; #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC +#if JVET_AG0164_AFFINE_GPM + int isIbc0 = (mergeCand0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; + int isIbc1 = (mergeCand1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; +#else + int isIbc0 = (mergeCand0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; + int isIbc1 = (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) ? 1 : 0; +#endif +#endif if (!isChromaEnabled(pu.chromaFormat) && !isIntra0 && !isIntra1) { continue; } int mrgIntraCand0 = MAX_INT, mrgIntraCand1 = MAX_INT; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc0) + { +#if JVET_AG0164_AFFINE_GPM + int ibcIdx = mergeCand0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int ibcIdx = mergeCand0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + ibcIdx; + Mv bv = geoBvList[ibcIdx]; + if (isChromaEnabled(pu.chromaFormat) && !isGeoIntraChromaAvail[rdoBuffer]) + { + pu.cu->predMode = MODE_IBC; + pu.mv[0] = bv; + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution + m_pcInterSearch->motionCompensation(pu, geoIntraBuffer[rdoBuffer], REF_PIC_LIST_0, false, true); + pu.cu->predMode = MODE_INTER; + isGeoIntraChromaAvail[rdoBuffer] = 2; + } + } + else +#endif if (isIntra0) { #if JVET_AG0164_AFFINE_GPM @@ -12133,6 +12479,29 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct } } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { +#if JVET_AG0164_AFFINE_GPM + int ibcIdx = mergeCand1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int ibcIdx = mergeCand1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + ibcIdx; + Mv bv = geoBvList[ibcIdx]; + if (isChromaEnabled(pu.chromaFormat) && !isGeoIntraChromaAvail[rdoBuffer]) + { + pu.cu->predMode = MODE_IBC; + pu.mv[0] = bv; + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution + m_pcInterSearch->motionCompensation(pu, geoIntraBuffer[rdoBuffer], REF_PIC_LIST_0, false, true); + pu.cu->predMode = MODE_INTER; + isGeoIntraChromaAvail[rdoBuffer] = 2; + } + } + else +#endif if (isIntra1) { #if JVET_AG0164_AFFINE_GPM @@ -12276,6 +12645,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct PelUnitBuf predSrcTemp0, predSrcTemp1; uint8_t* chromaAvailPtr0 = nullptr; uint8_t* chromaAvailPtr1 = nullptr; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc0) + { +#if JVET_AG0164_AFFINE_GPM + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand0 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand0 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + predSrcTemp0 = geoIntraBuffer[rdoBuffer]; + } + else +#endif if (isIntra0) { predSrcTemp0 = geoIntraBuffer[mrgIntraCand0]; @@ -12352,6 +12733,18 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif } +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIbc1) + { +#if JVET_AG0164_AFFINE_GPM + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand1 - GEO_MAX_ALL_INTER_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#else + int rdoBuffer = (GEO_NUM_INTRA_RDO_BUFFER - GEO_MAX_NUM_IBC_CANDS) + mergeCand1 - GEO_MAX_NUM_UNI_CANDS - GEO_MAX_NUM_INTRA_CANDS; +#endif + predSrcTemp1 = geoIntraBuffer[rdoBuffer]; + } + else +#endif if (isIntra1) { predSrcTemp1 = geoIntraBuffer[mrgIntraCand1]; @@ -12858,6 +13251,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_Y0065_GPM_INTRA #if JVET_AG0164_AFFINE_GPM pu.gpmIntraFlag = pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS || pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + pu.gpmInterIbcFlag = pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS || pu.geoMergeIdx1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif if (pu.geoMergeIdx0 >= GEO_MAX_ALL_INTER_UNI_CANDS) { memcpy(m_pcIntraSearch->m_intraMPM, geoIntraMPMList[pu.geoSplitDir][0], sizeof(uint8_t) * GEO_MAX_NUM_INTRA_CANDS); @@ -12868,6 +13264,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct } #else pu.gpmIntraFlag = pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS || pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + pu.gpmInterIbcFlag = pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS || pu.geoMergeIdx1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS; +#endif if (pu.geoMergeIdx0 >= GEO_MAX_NUM_UNI_CANDS) { memcpy(m_pcIntraSearch->m_intraMPM, geoIntraMPMList[pu.geoSplitDir][0], sizeof(uint8_t)*GEO_MAX_NUM_INTRA_CANDS); @@ -13090,6 +13489,9 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct , affMergeCtx #endif , *mrgTmCtx0, *mrgTmCtx1, pu.geoSplitDir, pu.geoMergeIdx0, pu.geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, pu.geoBldIdx, m_pcIntraSearch->m_intraMPM, +#if JVET_AI0082_GPM_WITH_INTER_IBC + geoBvList, +#endif pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, bdofSubPuMvOffsetPart0, bdofSubPuMvOffsetPart1); #else PU::spanGeoMMVDMotionInfo(pu, mergeCtx[GEO_TM_OFF], *mrgTmCtx0, *mrgTmCtx1, pu.geoSplitDir, pu.geoMergeIdx0, pu.geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, pu.geoBldIdx, m_pcIntraSearch->m_intraMPM); @@ -13306,11 +13708,21 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct uint8_t intraMPM[2] = { PLANAR_IDX, PLANAR_IDX }; #if JVET_AG0164_AFFINE_GPM +#if JVET_AI0082_GPM_WITH_INTER_IBC + PU::spanGeoMMVDMotionInfo(pu, mergeCtx[GEO_TM_OFF], affMergeCtx, mergeCtx[GEO_TM_OFF], mergeCtx[GEO_TM_OFF], 0, geoMergeIdx0, geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, 0, intraMPM, geoBvList, + pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, pu.gpmDmvrRefinePart0 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][geoMergeIdx0] : nullptr, pu.gpmDmvrRefinePart1 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][geoMergeIdx1] : nullptr); +#else PU::spanGeoMMVDMotionInfo(pu, mergeCtx[GEO_TM_OFF], affMergeCtx, mergeCtx[GEO_TM_OFF], mergeCtx[GEO_TM_OFF], 0, geoMergeIdx0, geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, 0, intraMPM, pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, pu.gpmDmvrRefinePart0 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][geoMergeIdx0] : nullptr, pu.gpmDmvrRefinePart1 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][geoMergeIdx1] : nullptr); +#endif +#else +#if JVET_AI0082_GPM_WITH_INTER_IBC + PU::spanGeoMMVDMotionInfo(pu, mergeCtx[GEO_TM_OFF], mergeCtx[GEO_TM_OFF], mergeCtx[GEO_TM_OFF], 0, geoMergeIdx0, geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, 0, intraMPM, geoBvList, + pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, pu.gpmDmvrRefinePart0 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][geoMergeIdx0] : nullptr, pu.gpmDmvrRefinePart1 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][geoMergeIdx1] : nullptr); #else PU::spanGeoMMVDMotionInfo(pu, mergeCtx[GEO_TM_OFF], mergeCtx[GEO_TM_OFF], mergeCtx[GEO_TM_OFF], 0, geoMergeIdx0, geoMergeIdx1, pu.geoTmFlag0, pu.geoMMVDFlag0, pu.geoMMVDIdx0, pu.geoTmFlag1, pu.geoMMVDFlag1, pu.geoMMVDIdx1, 0, intraMPM, pu.gpmDmvrRefinePart0, pu.gpmDmvrRefinePart1, pu.gpmDmvrRefinePart0 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][geoMergeIdx0] : nullptr, pu.gpmDmvrRefinePart1 ? m_mvBufEncBDOF4GPM[GEO_TM_OFF][geoMergeIdx1] : nullptr); +#endif #endif tempCS->getPredBuf().copyFrom(blendBuffer); diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index 2d69e526c..f2d3f81d5 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -190,15 +190,25 @@ public: for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) { #if JVET_AG0164_AFFINE_GPM +#if JVET_AI0082_GPM_WITH_INTER_IBC + singleDistList[partIdx][splitDir] = new SingleGeoMMVDMergeEntry*[GEO_MAX_ALL_INTER_UNI_CANDS +GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS]; + for (int candIdx = 0; candIdx < GEO_MAX_ALL_INTER_UNI_CANDS +GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS; candIdx++) +#else singleDistList[partIdx][splitDir] = new SingleGeoMMVDMergeEntry*[GEO_MAX_ALL_INTER_UNI_CANDS +GEO_MAX_NUM_INTRA_CANDS]; for (int candIdx = 0; candIdx < GEO_MAX_ALL_INTER_UNI_CANDS +GEO_MAX_NUM_INTRA_CANDS; candIdx++) +#endif { singleDistList[partIdx][splitDir][candIdx] = new SingleGeoMMVDMergeEntry[GPM_EXT_MMVD_MAX_REFINE_NUM + 2]; } #else #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + singleDistList[partIdx][splitDir] = new SingleGeoMMVDMergeEntry*[GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS]; + for (int candIdx = 0; candIdx < GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS; candIdx++) +#else singleDistList[partIdx][splitDir] = new SingleGeoMMVDMergeEntry*[GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS]; for (int candIdx = 0; candIdx < GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS; candIdx++) +#endif #else singleDistList[partIdx][splitDir] = new SingleGeoMMVDMergeEntry*[MRG_MAX_NUM_CANDS]; for (int candIdx = 0; candIdx < MRG_MAX_NUM_CANDS; candIdx++) @@ -221,13 +231,21 @@ public: for (int splitDir = 0; splitDir < GEO_NUM_PARTITION_MODE; splitDir++) { #if JVET_AG0164_AFFINE_GPM +#if JVET_AI0082_GPM_WITH_INTER_IBC + for (int candIdx = 0; candIdx < GEO_MAX_ALL_INTER_UNI_CANDS +GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS; candIdx++) +#else for (int candIdx = 0; candIdx < GEO_MAX_ALL_INTER_UNI_CANDS +GEO_MAX_NUM_INTRA_CANDS; candIdx++) +#endif { delete[] singleDistList[partIdx][splitDir][candIdx]; } #else #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + for (int candIdx = 0; candIdx < GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS+GEO_MAX_NUM_IBC_CANDS; candIdx++) +#else for (int candIdx = 0; candIdx < GEO_MAX_NUM_UNI_CANDS+GEO_MAX_NUM_INTRA_CANDS; candIdx++) +#endif #else for (int candIdx = 0; candIdx < MRG_MAX_NUM_CANDS; candIdx++) #endif diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index bd04d79e6..edc1fa640 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -2038,6 +2038,9 @@ void EncLib::xInitSPS( SPS& sps ) sps.setUseGeo ( m_Geo ); #if JVET_AG0112_REGRESSION_BASED_GPM_BLENDING sps.setUseGeoBlend ( true ); +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + sps.setUseGeoInterIbc ( m_Geo ? m_geoInterIbc : false ); #endif sps.setUseMMVD ( m_MMVD ); sps.setFpelMmvdEnabledFlag (( m_MMVD ) ? m_allowDisFracMMVD : false); diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index dd89a2531..04372afdb 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -2111,6 +2111,18 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons } } #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (m_pcCuEncoder->getEncCfg()->getUseGeoInterIbc()) + { + SPS* spsTmp = const_cast<SPS*>(cs.sps); + hashBlkHitPerc = (hashBlkHitPerc == -1) ? m_pcCuEncoder->getIbcHashMap().calHashBlkMatchPerc(cs.area.Y()) : hashBlkHitPerc; + bool isSCC = hashBlkHitPerc >= 20; + if (cs.slice->getPOC() == 0 || cs.slice->getSliceType() == I_SLICE) + { + spsTmp->setUseGeoInterIbc(isSCC); + } + } +#endif #if JVET_AD0188_CCP_MERGE if ((pCfg->getSwitchPOC() != pcPic->poc || -1 == pCfg->getDebugCTU())) { diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 904938f7a..715df8738 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -8279,12 +8279,20 @@ void InterSearch::setGeoSplitModeToSyntaxTable(PredictionUnit& pu, MergeCtx& mer #endif #if JVET_Y0065_GPM_INTRA , IntraPrediction* pcIntraPred +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , Mv* geoBvList #endif , int mmvdCand0, int mmvdCand1) { #if JVET_Y0065_GPM_INTRA bool isIntra[2]; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isIbc[2]; + xRemapMrgIndexAndMmvdIdx(mergeCand0, mergeCand1, mmvdCand0, mmvdCand1, isIntra[0], isIntra[1], isIbc[0], isIbc[1]); +#else xRemapMrgIndexAndMmvdIdx(mergeCand0, mergeCand1, mmvdCand0, mmvdCand1, isIntra[0], isIntra[1]); +#endif #endif const int idx0 = mmvdCand0 + 1; const int idx1 = mmvdCand1 + 1; @@ -8299,6 +8307,9 @@ void InterSearch::setGeoSplitModeToSyntaxTable(PredictionUnit& pu, MergeCtx& mer #endif #if JVET_Y0065_GPM_INTRA , pcIntraPred +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , geoBvList #endif , m_gpmPartTplCost[idx0][mergeCand0] , m_gpmPartTplCost[idx1][mergeCand1] @@ -8310,6 +8321,9 @@ void InterSearch::setGeoSplitModeToSyntaxTable(PredictionUnit& pu, MergeCtx& mer #else + (isIntra[0] ? GEO_MAX_NUM_UNI_CANDS : 0) #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + + (isIbc[0] ? GEO_MAX_NUM_INTRA_CANDS : 0) +#endif #endif , mergeCtx1 , mergeCand1 @@ -8319,6 +8333,9 @@ void InterSearch::setGeoSplitModeToSyntaxTable(PredictionUnit& pu, MergeCtx& mer #else + (isIntra[1] ? GEO_MAX_NUM_UNI_CANDS : 0) #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + + (isIbc[1] ? GEO_MAX_NUM_INTRA_CANDS : 0) +#endif #endif , numValidInList , modeList @@ -8363,7 +8380,12 @@ int InterSearch::convertGeoSplitModeToSyntax(int splitDir, int mergeCand0, int m { #if JVET_Y0065_GPM_INTRA bool isIntra[2]; +#if JVET_AI0082_GPM_WITH_INTER_IBC + bool isIbc[2]; + xRemapMrgIndexAndMmvdIdx(mergeCand0, mergeCand1, mmvdCand0, mmvdCand1, isIntra[0], isIntra[1], isIbc[0], isIbc[1]); +#else xRemapMrgIndexAndMmvdIdx(mergeCand0, mergeCand1, mmvdCand0, mmvdCand1, isIntra[0], isIntra[1]); +#endif #endif return m_gpmacsSplitModeTmSel[mmvdCand0 + 1][mmvdCand1 + 1][mergeCand0][mergeCand1][splitDir]; } @@ -8374,6 +8396,9 @@ bool InterSearch::selectGeoSplitModes(PredictionUnit &pu, #endif #if JVET_Y0065_GPM_INTRA IntraPrediction* pcIntraPred, +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + Mv* geoBvList, #endif uint32_t (&gpmTplCostPart0)[2][GEO_NUM_PARTITION_MODE], uint32_t (&gpmTplCostPart1)[2][GEO_NUM_PARTITION_MODE], @@ -8405,6 +8430,9 @@ bool InterSearch::selectGeoSplitModes(PredictionUnit &pu, Pel* pRefLeftPart0 = m_acYuvRefAMLTemplatePart0[1]; Pel* pRefTopPart1 = m_acYuvRefAMLTemplatePart1[0]; Pel* pRefLeftPart1 = m_acYuvRefAMLTemplatePart1[1]; +#if JVET_AI0082_GPM_WITH_INTER_IBC + std::vector<Pel>* lut = m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() ? &m_pcReshape->getInvLUT() : nullptr; +#endif // First partition if (fillRefTplPart0) @@ -8414,6 +8442,9 @@ bool InterSearch::selectGeoSplitModes(PredictionUnit &pu, #else fillPartGPMRefTemplate<0, false>(pu, mergeCtx0, mergeCand0, mmvdCand0, pRefTopPart0, pRefLeftPart0); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + fillPartGpmInterIbcRefTemplate<0, false>(pu, lut, geoBvList, mergeCand0, mmvdCand0, pRefTopPart0, pRefLeftPart0); +#endif #if JVET_Y0065_GPM_INTRA xCollectIntraGeoPartCost<0>(pu, pcIntraPred, mergeCand0, gpmTplCostPart0[0]); #endif @@ -8427,6 +8458,9 @@ bool InterSearch::selectGeoSplitModes(PredictionUnit &pu, #else fillPartGPMRefTemplate<1, false>(pu, mergeCtx1, mergeCand1, mmvdCand1, pRefTopPart1, pRefLeftPart1); #endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + fillPartGpmInterIbcRefTemplate<1, false>(pu, lut, geoBvList, mergeCand1, mmvdCand1, pRefTopPart1, pRefLeftPart1); +#endif #if JVET_Y0065_GPM_INTRA xCollectIntraGeoPartCost<1>(pu, pcIntraPred, mergeCand1, gpmTplCostPart1[1]); #endif @@ -8773,6 +8807,16 @@ void InterSearch::xCollectIntraGeoPartCost(PredictionUnit &pu, IntraPrediction* { return; } +#if JVET_AI0082_GPM_WITH_INTER_IBC +#if JVET_AG0164_AFFINE_GPM + if (mergeCand >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) +#else + if (mergeCand >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) +#endif + { + return; + } +#endif std::vector<Pel>* LUT = m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag() ? &m_pcReshape->getInvLUT() : nullptr; pcIntraPred->fillIntraGPMRefTemplateAll(pu, m_bAMLTemplateAvailabe[0], m_bAMLTemplateAvailabe[1], true, false, false, LUT, (partIdx == 0 ? mergeCand : 0), (partIdx == 1 ? mergeCand : 0)); diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h index eb3e73afa..dcda0aac2 100644 --- a/source/Lib/EncoderLib/InterSearch.h +++ b/source/Lib/EncoderLib/InterSearch.h @@ -1359,6 +1359,9 @@ public: #endif #if JVET_Y0065_GPM_INTRA , IntraPrediction* pcIntraPred +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + , Mv* geoBvList #endif , int mmvdCand0 = -1, int mmvdCand1 = -1); // mmvdCandX = -1: regular, 0~GPM_EXT_MMVD_MAX_REFINE_NUM-1: MMVD, >=GPM_EXT_MMVD_MAX_REFINE_NUM: TM #if JVET_W0097_GPM_MMVD_TM && TM_MRG @@ -1375,21 +1378,51 @@ public: protected: #if JVET_Y0065_GPM_INTRA +#if JVET_AI0082_GPM_WITH_INTER_IBC + inline void xRemapMrgIndexAndMmvdIdx(int& mergeCand0, int& mergeCand1, int& mmvdCand0, int& mmvdCand1, bool &isIntra0, bool &isIntra1, bool &isIbc0, bool &isIbc1) +#else inline void xRemapMrgIndexAndMmvdIdx(int& mergeCand0, int& mergeCand1, int& mmvdCand0, int& mmvdCand1, bool &isIntra0, bool &isIntra1) +#endif { +#if JVET_AI0082_GPM_WITH_INTER_IBC +#if JVET_AG0164_AFFINE_GPM + bool isIbc = (mergeCand0 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) || (mergeCand1 >= GEO_MAX_ALL_INTER_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); +#else + bool isIbc = (mergeCand0 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS) || (mergeCand1 >= GEO_MAX_NUM_UNI_CANDS + GEO_MAX_NUM_INTRA_CANDS); +#endif +#endif #if JVET_W0097_GPM_MMVD_TM +#if JVET_AI0082_GPM_WITH_INTER_IBC + const int intraMmvdBufIdx = (GPM_EXT_MMVD_MAX_REFINE_NUM + 1) + 1 + (isIbc ? 1 : 0); +#else static const int intraMmvdBufIdx = (GPM_EXT_MMVD_MAX_REFINE_NUM + 1) + 1; +#endif +#else +#if JVET_AI0082_GPM_WITH_INTER_IBC + const int intraMmvdBufIdx = 1 + (isIbc ? 1 : 0); #else static const int intraMmvdBufIdx = 1; +#endif #endif isIntra0 = false; isIntra1 = false; +#if JVET_AI0082_GPM_WITH_INTER_IBC + isIbc0 = false; + isIbc1 = false; +#endif #if JVET_AG0164_AFFINE_GPM if (mergeCand0 >= GEO_MAX_ALL_INTER_UNI_CANDS) { isIntra0 = true; mergeCand0 -= GEO_MAX_ALL_INTER_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIntra0 && mergeCand0 >= GEO_MAX_NUM_INTRA_CANDS) + { + isIbc0 = true; + mergeCand0 -= GEO_MAX_NUM_INTRA_CANDS; + } +#endif mmvdCand0 = intraMmvdBufIdx - 1; } @@ -1397,6 +1430,13 @@ protected: { isIntra1 = true; mergeCand1 -= GEO_MAX_ALL_INTER_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIntra1 && mergeCand1 >= GEO_MAX_NUM_INTRA_CANDS) + { + isIbc1 = true; + mergeCand1 -= GEO_MAX_NUM_INTRA_CANDS; + } +#endif mmvdCand1 = intraMmvdBufIdx - 1; } #else @@ -1404,6 +1444,13 @@ protected: { isIntra0 = true; mergeCand0 -= GEO_MAX_NUM_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIntra0 && mergeCand0 >= GEO_MAX_NUM_INTRA_CANDS) + { + isIbc0 = true; + mergeCand0 -= GEO_MAX_NUM_INTRA_CANDS; + } +#endif mmvdCand0 = intraMmvdBufIdx - 1; } @@ -1411,6 +1458,13 @@ protected: { isIntra1 = true; mergeCand1 -= GEO_MAX_NUM_UNI_CANDS; +#if JVET_AI0082_GPM_WITH_INTER_IBC + if (isIntra1 && mergeCand1 >= GEO_MAX_NUM_INTRA_CANDS) + { + isIbc1 = true; + mergeCand1 -= GEO_MAX_NUM_INTRA_CANDS; + } +#endif mmvdCand1 = intraMmvdBufIdx - 1; } #endif @@ -1437,6 +1491,9 @@ protected: #endif #if JVET_Y0065_GPM_INTRA IntraPrediction* pcIntraPred, +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + Mv* geoBvList, #endif uint32_t (&gpmTplCostPart0)[2][GEO_NUM_PARTITION_MODE], uint32_t (&gpmTplCostPart1)[2][GEO_NUM_PARTITION_MODE], diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index ded408a49..17f6d8dc9 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1674,6 +1674,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) { WRITE_FLAG(pcSPS->getUseGPMTMMode() ? 1 : 0, "sps_gpm_tm_enabled_flag"); } +#endif +#if JVET_AI0082_GPM_WITH_INTER_IBC + WRITE_FLAG(pcSPS->getUseGeoInterIbc() ? 1 : 0, "sps_gpm_inter_ibc_enabled_flag"); #endif } #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG -- GitLab