From fcf374da2be945b5a4c2e5f034ba77f515ebfdb0 Mon Sep 17 00:00:00 2001 From: Yang Wang <wangyang.cs@bytedance.com> Date: Thu, 8 Feb 2024 17:08:26 +0000 Subject: [PATCH] JVET-AG0276: LIC improvements (Test 2.6j) --- source/App/EncoderApp/EncApp.cpp | 19 + source/App/EncoderApp/EncAppCfg.cpp | 48 + source/App/EncoderApp/EncAppCfg.h | 19 + source/Lib/CommonLib/Buffer.cpp | 13 + source/Lib/CommonLib/Common.h | 31 + source/Lib/CommonLib/CommonDef.h | 13 + source/Lib/CommonLib/ContextModelling.cpp | 503 ++- source/Lib/CommonLib/ContextModelling.h | 49 + source/Lib/CommonLib/Contexts.h | 8 + source/Lib/CommonLib/Contexts_ecm12.inl | 94 + source/Lib/CommonLib/InterPrediction.cpp | 4969 ++++++++++++++++----- source/Lib/CommonLib/InterPrediction.h | 163 + source/Lib/CommonLib/Rom.cpp | 3 + source/Lib/CommonLib/Rom.h | 3 + source/Lib/CommonLib/Slice.cpp | 24 + source/Lib/CommonLib/Slice.h | 64 +- source/Lib/CommonLib/TypeDef.h | 4 + source/Lib/CommonLib/Unit.cpp | 41 + source/Lib/CommonLib/Unit.h | 18 + source/Lib/CommonLib/UnitTools.cpp | 2087 ++++++++- source/Lib/CommonLib/UnitTools.h | 52 +- source/Lib/DecoderLib/CABACReader.cpp | 54 + source/Lib/DecoderLib/DecCu.cpp | 375 +- source/Lib/DecoderLib/VLCReader.cpp | 65 + source/Lib/EncoderLib/CABACWriter.cpp | 52 + source/Lib/EncoderLib/EncCfg.h | 51 + source/Lib/EncoderLib/EncCu.cpp | 1794 +++++++- source/Lib/EncoderLib/EncCu.h | 45 + source/Lib/EncoderLib/EncLib.cpp | 58 + source/Lib/EncoderLib/EncModeCtrl.cpp | 100 + source/Lib/EncoderLib/InterSearch.cpp | 35 + source/Lib/EncoderLib/InterSearch.h | 31 + source/Lib/EncoderLib/VLCWriter.cpp | 54 + 33 files changed, 9623 insertions(+), 1316 deletions(-) diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index dc9ed416f..f8fbb124d 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -811,6 +811,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setAffineType ( m_AffineType ); #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT m_cEncLib.setUseAffineTM ( m_useAffineTM ); +#if JVET_AG0276_NLIC + m_cEncLib.setUseAffAltLMTM ( m_useAffAltLMTM ); +#endif #endif #if AFFINE_MMVD m_cEncLib.setAffineMmvdMode ( m_AffineMmvdMode ); @@ -852,6 +855,15 @@ void EncApp::xInitLibCfg() m_cEncLib.setBIO (m_BIO); #if JVET_W0090_ARMC_TM m_cEncLib.setAML ( m_AML ); +#if JVET_AG0276_NLIC + m_cEncLib.setAltLM ( m_altLM ); + m_cEncLib.setAffAltLM ( m_affAltLM ); +#endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + m_cEncLib.setMergeOppositeLic ( m_mergeOppositeLic ); + m_cEncLib.setMergeTMOppositeLic ( m_mergeTMOppositeLic ); + m_cEncLib.setMergeAffOppositeLic ( m_mergeAffOppositeLic ); #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC m_cEncLib.setArmcRefinedMotion ( m_iQP < 25 ? false : m_armcRefinedMotion ); @@ -1132,6 +1144,10 @@ void EncApp::xInitLibCfg() } m_cEncLib.setMaxNumMergeCand ( m_maxNumMergeCand ); +#if JVET_AG0276_LIC_FLAG_SIGNALING + m_cEncLib.setMaxNumOppositeLicMergeCand ( m_maxNumOppositeLicMergeCand ); + m_cEncLib.setMaxNumAffineOppositeLicMergeCand ( m_maxNumAffineOppositeLicMergeCand); +#endif #if JVET_X0049_ADAPT_DMVR m_cEncLib.setMaxNumBMMergeCand ( m_maxNumBMMergeCand ); #endif @@ -1489,6 +1505,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setFastLicAffine(true); } } +#if JVET_AG0276_LIC_SLOPE_ADJUST + m_cEncLib.setUseLicSlopeAdjust ( m_lic ? m_licSlopeAdjust : false ); +#endif #endif #endif #if DUMP_BEFORE_INLOOP diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index fd1e68618..93ca7833e 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1036,6 +1036,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("AffineType", m_AffineType, true, "Enable affine type prediction (0:off, 1:on) [default: on]" ) #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT ("AffineTM", m_useAffineTM, true, "Enable TM-based subblock motion refinement (0:off, 1:on) [default: on]") +#if JVET_AG0276_NLIC + ("AffAltLMTM", m_useAffAltLMTM, true, "Enable TM-based subblock motion refinement for affine AltLM") +#endif #endif #if AFFINE_MMVD ("AffineMMVD", m_AffineMmvdMode, true, "Affine MMVD mode (0:off, 1:on) [default: on]" ) @@ -1077,6 +1080,15 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("BIO", m_BIO, false, "Enable bi-directional optical flow") #if JVET_W0090_ARMC_TM ("AML", m_AML, true, "Enable adaptive merge list") +#if JVET_AG0276_NLIC + ("AltLM", m_altLM, true, "Enable altLM") + ("AffAltLM", m_affAltLM, true, "Enable affine altLM") +#endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + ("MergeOppositeLic", m_mergeOppositeLic, true, "Enable opposite LIC flag for merge") + ("MergeTMOppositeLic", m_mergeTMOppositeLic, true, "Enable opposite LIC flag for TM merge") + ("MergeAffOppositeLic", m_mergeAffOppositeLic, true, "Enable opposite LIC flag for Affine merge") #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC ("ArmcRefinedMotion", m_armcRefinedMotion, true, "Enable adaptive re-ordering of merge candidates with refined motion") @@ -1555,6 +1567,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) #else ("MaxNumMergeCand", m_maxNumMergeCand, 5u, "Maximum number of merge candidates") #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + ("MaxNumOppositeLicMergeCand", m_maxNumOppositeLicMergeCand, (uint32_t)(REG_MRG_MAX_NUM_CANDS_OPPOSITELIC), "Maximum number of merge candidates with opposite LIC flag") +#endif #if JVET_X0049_ADAPT_DMVR ("MaxNumBMMergeCand", m_maxNumBMMergeCand, 4u, "Maximum number of BM merge candidates") #endif @@ -1563,6 +1578,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) #else ("MaxNumAffineMergeCand", m_maxNumAffineMergeCand, 5u, "Maximum number of affine merge candidates") #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + ("MaxNumAffineOppositeLicMergeCand", m_maxNumAffineOppositeLicMergeCand, (uint32_t)(AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC), "Maximum number of affine merge candidates with opposite LIC flag") +#endif #if NON_ADJACENT_MRG_CAND ("MaxNumGeoCand", m_maxNumGeoCand, 10u, "Maximum number of geometric partitioning mode candidates") #else @@ -1826,6 +1844,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) #if INTER_LIC ("LIC", m_lic, true, "Local illumination compensation [LIC] (0:disabled, 1:enabled) [default: 1]") ("FastPicLevelLIC", m_fastPicLevelLIC, true, "Fast picture level LIC decision (0:disabled, 1:enabled) [default: 1]") +#if JVET_AG0276_LIC_SLOPE_ADJUST + ("LicSlopeAdjust", m_licSlopeAdjust, true, "LIC with slope adjustment (0:disabled, 1:enabled) [default: 1]") +#endif #endif ( "ScalingRatioHor", m_scalingRatioHor, 1.0, "Scaling ratio in hor direction" ) ( "ScalingRatioVer", m_scalingRatioVer, 1.0, "Scaling ratio in ver direction" ) @@ -4002,6 +4023,9 @@ bool EncAppCfg::xCheckParameter() xConfirmPara(m_maxNumAffineMergeCand < (m_sbTmvpEnableFlag ? 1 : 0), "MaxNumAffineMergeCand must be greater than 0 when SbTMVP is enabled"); xConfirmPara( m_maxNumAffineMergeCand > AFFINE_MRG_MAX_NUM_CANDS, "MaxNumAffineMergeCand must be no more than AFFINE_MRG_MAX_NUM_CANDS." ); +#if JVET_AG0276_LIC_FLAG_SIGNALING + xConfirmPara(m_maxNumAffineOppositeLicMergeCand > AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC, "MaxNumAffineOppositeLicMergeCand must be no more than AFF_MRG_MAX_NUM_CANDS_OPPOLIC."); +#endif #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL if (!m_tmNoninterToolsEnableFlag) { @@ -4092,6 +4116,9 @@ bool EncAppCfg::xCheckParameter() m_maxNumAffineMergeCand = m_sbTmvpEnableFlag ? 1 : 0; if (m_PROF) msg(WARNING, "PROF is forcefully disabled when Affine is off \n"); m_PROF = false; +#if JVET_AG0276_LIC_FLAG_SIGNALING + m_maxNumAffineOppositeLicMergeCand = 0; +#endif } #if MULTI_PASS_DMVR if (m_DMVR && m_DMVDMode) @@ -4200,6 +4227,24 @@ bool EncAppCfg::xCheckParameter() #endif } #endif +#if JVET_AG0276_NLIC + if (!m_AML) + { + msg(WARNING, "AltLM is forcefully disabled since ARMC is set off\n"); + m_altLM = false; + m_affAltLM = false; + } + if (!m_affAltLM) + { + msg(WARNING, "Affine AltLM TM is disabled since affine AltLM is set off\n"); + m_useAffAltLMTM = false; + } + if (!m_useAffineTM) + { + msg(WARNING, "Affine AltLM TM is disabled since TM-based affine TM is set off\n"); + m_useAffAltLMTM = false; + } +#endif #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_W0097_GPM_MMVD_TM && TM_MRG if (!m_Geo && m_tmGPMMode) { @@ -5788,6 +5833,9 @@ void EncAppCfg::xPrintParameter() if( m_lic ) { msg( VERBOSE, "FastPicLevelLIC:%d ", m_fastPicLevelLIC ); +#if JVET_AG0276_LIC_SLOPE_ADJUST + msg( VERBOSE, "LicSlopeAdust:%d ", m_licSlopeAdjust ); +#endif } #endif #if JVET_AE0059_INTER_CCCM diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 55b44ac41..2f41e4ed7 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -399,6 +399,9 @@ protected: bool m_AffineType; #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT bool m_useAffineTM; +#if JVET_AG0276_NLIC + bool m_useAffAltLMTM; +#endif #endif #if JVET_AG0135_AFFINE_CIIP bool m_useCiipAffine; @@ -440,6 +443,15 @@ protected: bool m_BIO; #if JVET_W0090_ARMC_TM bool m_AML; +#if JVET_AG0276_NLIC + bool m_altLM; + bool m_affAltLM; +#endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool m_mergeOppositeLic; + bool m_mergeTMOppositeLic; + bool m_mergeAffOppositeLic; #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC bool m_armcRefinedMotion; @@ -913,6 +925,10 @@ protected: uint32_t m_log2ParallelMergeLevel; ///< Parallel merge estimation region uint32_t m_maxNumMergeCand; ///< Max number of merge candidates +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t m_maxNumOppositeLicMergeCand; ///< Max number of merge candidates with opposite LIC flag + uint32_t m_maxNumAffineOppositeLicMergeCand; ///< Max number of affine merge candidates with opposite LIC flag +#endif #if JVET_X0049_ADAPT_DMVR uint32_t m_maxNumBMMergeCand; ///< Max number of BM merge candidates #endif @@ -1013,6 +1029,9 @@ protected: #if INTER_LIC bool m_lic; bool m_fastPicLevelLIC; +#if JVET_AG0276_LIC_SLOPE_ADJUST + bool m_licSlopeAdjust; +#endif #endif double m_scalingRatioHor; diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp index 989b7b740..3cd17e9a7 100644 --- a/source/Lib/CommonLib/Buffer.cpp +++ b/source/Lib/CommonLib/Buffer.cpp @@ -1951,6 +1951,9 @@ void AreaBuf<Pel>::linearTransform( const int scale, const int shift, const int { const Pel* src = buf; Pel* dst = buf; +#if JVET_AG0276_NLIC + const uint32_t areaT = area(); +#endif #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING if (width == 0) @@ -1963,6 +1966,16 @@ void AreaBuf<Pel>::linearTransform( const int scale, const int shift, const int THROW( "Blocks of width = 1 not supported" ); } #endif +#if JVET_AG0276_NLIC + else if (width == stride && (areaT & 7) == 0) + { + g_pelBufOP.linTf8(src, areaT, dst, areaT, areaT, 1, scale, shift, offset, clpRng, bClip); + } + else if (width == stride && (areaT & 3) == 0) + { + g_pelBufOP.linTf4(src, areaT, dst, areaT, areaT, 1, scale, shift, offset, clpRng, bClip); + } +#endif #if ENABLE_SIMD_OPT_BUFFER && defined(TARGET_SIMD_X86) else if( ( width & 7 ) == 0 ) { diff --git a/source/Lib/CommonLib/Common.h b/source/Lib/CommonLib/Common.h index 1fa2461c0..17ea3c597 100644 --- a/source/Lib/CommonLib/Common.h +++ b/source/Lib/CommonLib/Common.h @@ -654,4 +654,35 @@ struct DecoderDerivedCcpCandidate }; #endif +#if JVET_AG0276_NLIC +struct AltLMInterUnit +{ + int scale[MAX_NUM_COMPONENT]; + int offset[MAX_NUM_COMPONENT]; + + void resetAltLinearModel() + { + for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) + { + scale[comp] = 32; + offset[comp] = 0; + } + } + + AltLMInterUnit() + { + resetAltLinearModel(); + } + + AltLMInterUnit &operator=(const AltLMInterUnit &other) + { + for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) + { + scale[comp] = other.scale[comp]; + offset[comp] = other.offset[comp]; + } + return *this; + } +}; +#endif #endif diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index f260da955..3f025d71c 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -233,6 +233,11 @@ static const int RMVF_NUM_SUBBLK_THRED = 255; static const int RMVF_PARAM_THRED = (1 << 20); #endif #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +static const int AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC = 8; +static const int REG_MRG_MAX_NUM_CANDS_OPPOSITELIC = 5; +static const int TM_MRG_MAX_NUM_CANDS_OPPOSITELIC = 3; +#endif static const int IBC_MRG_MAX_NUM_CANDS = 6; ///< IBC MERGE #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV static const int IBC_MRG_MAX_NUM_CANDS_MEM = 28; ///< IBC AMVP- max number of candidates @@ -1158,6 +1163,14 @@ static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF = AF_MMVD_MAX_REFINE_NUM; #endif #endif +#if JVET_AG0276_NLIC +static const int ALT_MRG_MAX_NUM_CANDS = 16; +static const int ALT_AFF_MRG_MAX_NUM_CANDS = 6; +#endif +#if JVET_AG0276_LIC_SLOPE_ADJUST +static const int LIC_SLOPE_MAX_NUM_DELTA = 2; +#endif + #if JVET_AA0057_CCCM || JVET_AB0092_GLM_WITH_LUMA || JVET_AC0119_LM_CHROMA_FUSION static const int CCCM_WINDOW_SIZE = 6; static const int CCCM_NUM_PARAMS = 7; diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index bd590a97e..62437f961 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -514,6 +514,22 @@ unsigned DeriveCtx::CtxSkipFlag( const CodingUnit& cu ) return ctxId; } +#if JVET_AG0276_LIC_SLOPE_ADJUST +unsigned DeriveCtx::CtxLicFlag( const CodingUnit& cu ) +{ + const CodingStructure *cs = cu.cs; + unsigned ctxId = 0; + + const CodingUnit *cuLeft = cs->getCURestricted( cu.lumaPos().offset( -1, 0 ), cu, CH_L ); + ctxId = ( cuLeft && !cuLeft->firstPU->mergeFlag && !cuLeft->firstPU->amvpMergeModeFlag[0] && !cuLeft->firstPU->amvpMergeModeFlag[1] ) ? 1 : 0; + + const CodingUnit *cuAbove = cs->getCURestricted( cu.lumaPos().offset( 0, -1 ), cu, CH_L ); + ctxId += ( cuAbove && !cuAbove->firstPU->mergeFlag && !cuAbove->firstPU->amvpMergeModeFlag[0] && !cuAbove->firstPU->amvpMergeModeFlag[1] ) ? 1 : 0; + + return ctxId; +} +#endif + #if ENABLE_DIMD unsigned DeriveCtx::CtxDIMDFlag(const CodingUnit& cu) { @@ -630,6 +646,10 @@ void MergeCtx::copyRegularMergeCand(int dstCandIdx, MergeCtx& srcCtx, int srcCan mvFieldNeighbours[ dstCandIdx << 1 ] = srcCtx.mvFieldNeighbours[ srcCandIdx << 1 ]; mvFieldNeighbours[(dstCandIdx << 1) + 1] = srcCtx.mvFieldNeighbours[(srcCandIdx << 1) + 1]; bcwIdx [dstCandIdx] = srcCtx.bcwIdx [srcCandIdx]; +#if JVET_AG0276_NLIC + altLMFlag[dstCandIdx] = srcCtx.altLMFlag[srcCandIdx]; + altLMParaNeighbours[dstCandIdx] = srcCtx.altLMParaNeighbours[srcCandIdx]; +#endif #if INTER_LIC licFlags [dstCandIdx] = srcCtx.licFlags [srcCandIdx]; #endif @@ -701,6 +721,16 @@ void MergeCtx::saveMergeInfo(PredictionUnit& puTmp, PredictionUnit pu) puTmp.mmvdEncOptMode = pu.mmvdEncOptMode; puTmp.cu->licFlag = pu.cu->licFlag; +#if JVET_AG0276_NLIC + puTmp.cu->altLMFlag = pu.cu->altLMFlag; + puTmp.cu->altLMParaUnit = pu.cu->altLMParaUnit; +#if JVET_AG0276_LIC_FLAG_SIGNALING + puTmp.cu->altLMBRParaUnit = pu.cu->altLMBRParaUnit; +#endif +#endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + puTmp.cu->licDelta = pu.cu->licDelta; +#endif } #endif void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) @@ -732,6 +762,10 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) #endif pu.refIdx[REF_PIC_LIST_0] = mvFieldNeighbours[(candIdx << 1) + 0].refIdx; pu.refIdx[REF_PIC_LIST_1] = mvFieldNeighbours[(candIdx << 1) + 1].refIdx; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = altLMFlag[candIdx]; + pu.cu->altLMParaUnit = altLMParaNeighbours[candIdx]; +#endif if (CU::isIBC(*pu.cu)) { @@ -800,6 +834,9 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) #if INTER_LIC pu.cu->licFlag = pu.cs->slice->getUseLIC() ? licFlags[candIdx] : false; +#if JVET_AG0276_LIC_SLOPE_ADJUST + pu.cu->licDelta = 0; +#endif #if !JVET_AD0213_LIC_IMP if (pu.interDir == 3) { @@ -1006,6 +1043,10 @@ bool MergeCtx::xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThr void MergeCtx::initMrgCand(int cnt) { bcwIdx[cnt] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + altLMFlag[cnt] = false; + altLMParaNeighbours[cnt].resetAltLinearModel(); +#endif #if INTER_LIC licFlags[cnt] = false; #endif @@ -1370,8 +1411,15 @@ void MergeCtx::setGeoMmvdMergeInfo(PredictionUnit& pu, int mergeIdx, int mmvdIdx #endif pu.mmvdEncOptMode = 0; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = altLMFlag[mergeIdx]; + pu.cu->altLMParaUnit = altLMParaNeighbours[mergeIdx]; +#endif #if INTER_LIC pu.cu->licFlag = pu.cs->slice->getUseLIC() ? licFlags[mergeIdx] : false; +#if JVET_AG0276_LIC_SLOPE_ADJUST + pu.cu->licDelta = 0; +#endif if (pu.interDir == 3) { CHECK(pu.cu->licFlag, "LIC is not used with bi-prediction in merge"); @@ -1655,8 +1703,15 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx) pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; pu.cu->imv = mmvdUseAltHpelIf[fPosBaseIdx] ? IMV_HPEL : 0; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = altLMFlag[fPosBaseIdx]; + pu.cu->altLMParaUnit = altLMParaNeighbours[fPosBaseIdx]; +#endif #if INTER_LIC pu.cu->licFlag = licFlags[fPosBaseIdx]; +#if JVET_AG0276_LIC_SLOPE_ADJUST + pu.cu->licDelta = 0; +#endif #endif pu.cu->bcwIdx = (interDirNeighbours[fPosBaseIdx] == 3) ? bcwIdx[fPosBaseIdx] : BCW_DEFAULT; @@ -1829,6 +1884,145 @@ bool AffineMergeCtx::xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilar return false; } #endif +#if JVET_AG0276_NLIC +bool AffineMergeCtx::xCheckSimilarMotion1(int mergeCandIndex, uint32_t mvdSimilarityThresh, bool isAlt) const +{ + if (mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx < 0 && mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx < 0) + { + return true; + } + + if (mvdSimilarityThresh > 1) + { + int mvdTh = mvdSimilarityThresh; + for (uint32_t ui = 0; ui < mergeCandIndex; ui++) + { + if (!isAlt && altLMFlag[ui]) + { + continue; + } + if (isAlt && !altLMFlag[ui]) + { + continue; + } + if (interDirNeighbours[ui] == interDirNeighbours[mergeCandIndex]) + { + if (interDirNeighbours[ui] == 3) + { + if (mvFieldNeighbours[(ui << 1)][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx && + mvFieldNeighbours[(ui << 1) + 1][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx) + { + Mv mvDiff0L0 = mvFieldNeighbours[(ui << 1)][0].mv - mvFieldNeighbours[(mergeCandIndex << 1)][0].mv; + Mv mvDiff0L1 = mvFieldNeighbours[(ui << 1) + 1][0].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].mv; + + Mv mvDiff1L0 = mvFieldNeighbours[(ui << 1)][1].mv - mvFieldNeighbours[(mergeCandIndex << 1)][1].mv; + Mv mvDiff1L1 = mvFieldNeighbours[(ui << 1) + 1][1].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][1].mv; + + Mv mvDiff2L0 = mvFieldNeighbours[(ui << 1)][2].mv - mvFieldNeighbours[(mergeCandIndex << 1)][2].mv; + Mv mvDiff2L1 = mvFieldNeighbours[(ui << 1) + 1][2].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][2].mv; + if (mvDiff0L0.getAbsHor() < mvdTh && mvDiff0L0.getAbsVer() < mvdTh + && mvDiff0L1.getAbsHor() < mvdTh && mvDiff0L1.getAbsVer() < mvdTh + &&mvDiff1L0.getAbsHor() < mvdTh && mvDiff1L0.getAbsVer() < mvdTh + && mvDiff1L1.getAbsHor() < mvdTh && mvDiff1L1.getAbsVer() < mvdTh + &&mvDiff2L0.getAbsHor() < mvdTh && mvDiff2L0.getAbsVer() < mvdTh + && mvDiff2L1.getAbsHor() < mvdTh && mvDiff2L1.getAbsVer() < mvdTh + ) + { + return true; + } + } + } + else if (interDirNeighbours[ui] == 1) + { + if (mvFieldNeighbours[(ui << 1)][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx) + { + Mv mvDiff0 = mvFieldNeighbours[(ui << 1)][0].mv - mvFieldNeighbours[(mergeCandIndex << 1)][0].mv; + Mv mvDiff1 = mvFieldNeighbours[(ui << 1)][1].mv - mvFieldNeighbours[(mergeCandIndex << 1)][1].mv; + Mv mvDiff2 = mvFieldNeighbours[(ui << 1)][2].mv - mvFieldNeighbours[(mergeCandIndex << 1)][2].mv; + if (mvDiff0.getAbsHor() < mvdTh && mvDiff0.getAbsVer() < mvdTh + &&mvDiff1.getAbsHor() < mvdTh && mvDiff1.getAbsVer() < mvdTh + &&mvDiff2.getAbsHor() < mvdTh && mvDiff2.getAbsVer() < mvdTh + ) + { + return true; + } + } + } + else if (interDirNeighbours[ui] == 2) + { + if (mvFieldNeighbours[(ui << 1) + 1][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx) + { + Mv mvDiff0 = mvFieldNeighbours[(ui << 1) + 1][0].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].mv; + Mv mvDiff1 = mvFieldNeighbours[(ui << 1) + 1][1].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][1].mv; + Mv mvDiff2 = mvFieldNeighbours[(ui << 1) + 1][2].mv - mvFieldNeighbours[(mergeCandIndex << 1) + 1][2].mv; + if (mvDiff0.getAbsHor() < mvdTh && mvDiff0.getAbsVer() < mvdTh + &&mvDiff1.getAbsHor() < mvdTh && mvDiff1.getAbsVer() < mvdTh + && mvDiff2.getAbsHor() < mvdTh && mvDiff2.getAbsVer() < mvdTh + ) + { + return true; + } + } + } + } + } + return false; + } + + for (uint32_t ui = 0; ui < mergeCandIndex; ui++) + { + if (!isAlt && altLMFlag[ui]) + { + continue; + } + if (isAlt && !altLMFlag[ui]) + { + continue; + } + if (interDirNeighbours[ui] == interDirNeighbours[mergeCandIndex]) + { + if (interDirNeighbours[ui] == 3) + { + if (mvFieldNeighbours[(ui << 1)][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx && + mvFieldNeighbours[(ui << 1) + 1][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx && + mvFieldNeighbours[(ui << 1)][0].mv == mvFieldNeighbours[(mergeCandIndex << 1)][0].mv && + mvFieldNeighbours[(ui << 1) + 1][0].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].mv&& + mvFieldNeighbours[(ui << 1)][1].mv == mvFieldNeighbours[(mergeCandIndex << 1)][1].mv && + mvFieldNeighbours[(ui << 1) + 1][1].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][1].mv&& + mvFieldNeighbours[(ui << 1)][2].mv == mvFieldNeighbours[(mergeCandIndex << 1)][2].mv && + mvFieldNeighbours[(ui << 1) + 1][2].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][2].mv + ) + { + return true; + } + } + else if (interDirNeighbours[ui] == 1) + { + if (mvFieldNeighbours[(ui << 1)][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1)][0].refIdx && + mvFieldNeighbours[(ui << 1)][0].mv == mvFieldNeighbours[(mergeCandIndex << 1)][0].mv&& + mvFieldNeighbours[(ui << 1)][1].mv == mvFieldNeighbours[(mergeCandIndex << 1)][1].mv&& + mvFieldNeighbours[(ui << 1)][2].mv == mvFieldNeighbours[(mergeCandIndex << 1)][2].mv + ) + { + return true; + } + } + else if (interDirNeighbours[ui] == 2) + { + if (mvFieldNeighbours[(ui << 1) + 1][0].refIdx == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].refIdx && + mvFieldNeighbours[(ui << 1) + 1][0].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][0].mv && + mvFieldNeighbours[(ui << 1) + 1][1].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][1].mv && + mvFieldNeighbours[(ui << 1) + 1][2].mv == mvFieldNeighbours[(mergeCandIndex << 1) + 1][2].mv + ) + { + return true; + } + } + } + } + return false; +} +#endif #if JVET_AA0061_IBC_MBVD #if JVET_AE0169_BIPREDICTIVE_IBC bool MergeCtx::setIbcMbvdMergeCandiInfo(PredictionUnit& pu, int candIdx, int candIdxMaped, int candIdx1, int candIdxMaped1) @@ -2067,6 +2261,309 @@ bool MergeCtx::setIbcMbvdMergeCandiInfo(PredictionUnit& pu, int candIdx, int can } #endif +#if JVET_AG0276_NLIC +void AltLMMergeCtx::initAltLMMergeCtx(int idx) +{ + altLMParaNeighbours[idx].resetAltLinearModel(); + mvFieldNeighbours[(idx << 1) + 0].setMvField(Mv(), -1); + mvFieldNeighbours[(idx << 1) + 1].setMvField(Mv(), -1); + interDirNeighbours[idx] = 0; + bcwIdx[idx] = BCW_DEFAULT; + useAltHpelIf[idx] = false; +} + +bool AltLMMergeCtx::xCheckSameMotion(int mrgCandIdx, uint32_t mvdSimilarityThresh) +{ + for (int ui = 0; ui < mrgCandIdx; ui++) + { + bool sameMotion = false; + bool sameInterDir = (interDirNeighbours[ui] == interDirNeighbours[mrgCandIdx]); + if (sameInterDir && interDirNeighbours[mrgCandIdx] == 3) + { + sameInterDir = (bcwIdx[ui] == bcwIdx[mrgCandIdx]); + } + + if (sameInterDir) + { + if (interDirNeighbours[ui] == 3) + { + if (mvFieldNeighbours[(ui << 1)].refIdx == mvFieldNeighbours[(mrgCandIdx << 1)].refIdx && + mvFieldNeighbours[(ui << 1) + 1].refIdx == mvFieldNeighbours[(mrgCandIdx << 1) + 1].refIdx) + { + Mv mvDiffL0 = mvFieldNeighbours[(ui << 1)].mv - mvFieldNeighbours[(mrgCandIdx << 1)].mv; + Mv mvDiffL1 = mvFieldNeighbours[(ui << 1) + 1].mv - mvFieldNeighbours[(mrgCandIdx << 1) + 1].mv; + + if (mvDiffL0.getAbsHor() < mvdSimilarityThresh && mvDiffL0.getAbsVer() < mvdSimilarityThresh + && mvDiffL1.getAbsHor() < mvdSimilarityThresh && mvDiffL1.getAbsVer() < mvdSimilarityThresh) + { + sameMotion = true; + } + } + } + else if (interDirNeighbours[ui] == 1) + { + if (mvFieldNeighbours[(ui << 1)].refIdx == mvFieldNeighbours[(mrgCandIdx << 1)].refIdx) + { + Mv mvDiff = mvFieldNeighbours[(ui << 1)].mv - mvFieldNeighbours[(mrgCandIdx << 1)].mv; + if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh) + { + sameMotion = true; + } + } + } + else if (interDirNeighbours[ui] == 2) + { + if (mvFieldNeighbours[(ui << 1) + 1].refIdx == mvFieldNeighbours[(mrgCandIdx << 1) + 1].refIdx) + { + Mv mvDiff = mvFieldNeighbours[(ui << 1) + 1].mv - mvFieldNeighbours[(mrgCandIdx << 1) + 1].mv; + if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh) + { + sameMotion = true; + } + } + } + } + + if (sameMotion) + { + return true; + } + } + return false; +} +#endif + +#if JVET_AG0276_NLIC +bool AltLMAffineMergeCtx::xCheckSameAffMotion(const PredictionUnit& pu, int cnt) +{ + if (cnt < 1) + { + return true; + } + + const int CPMV_SIMILARITY_THREH = 1; + const int PARA_SIMILARITY_THREH = 1; + + const int lastIdx = cnt; + for (int idx = 0; idx < cnt; idx++) + { + if (affineType[idx] != affineType[lastIdx]) + { + continue; + } + + if (interDirNeighbours[idx] != interDirNeighbours[lastIdx]) + { + continue; + } + + if (interDirNeighbours[idx] == 3 && bcwIdx[idx] != bcwIdx[lastIdx]) + { + continue; + } + + if ((interDirNeighbours[lastIdx] & 1) != 0) + { + if (mvFieldNeighbours[(idx << 1)][0].refIdx != mvFieldNeighbours[(lastIdx << 1)][0].refIdx) + { + continue; + } + Mv acMvTemp[3]; + int affinePara[4], affineParaLast[4]; + acMvTemp[0] = mvFieldNeighbours[(idx << 1)][0].mv; + acMvTemp[1] = mvFieldNeighbours[(idx << 1)][1].mv; + acMvTemp[2] = mvFieldNeighbours[(idx << 1)][2].mv; + PU::deriveAffineParametersFromMVs(pu, acMvTemp, affinePara, affineType[idx]); + acMvTemp[0] = mvFieldNeighbours[(lastIdx << 1)][0].mv; + acMvTemp[1] = mvFieldNeighbours[(lastIdx << 1)][1].mv; + acMvTemp[2] = mvFieldNeighbours[(lastIdx << 1)][2].mv; + PU::deriveAffineParametersFromMVs(pu, acMvTemp, affineParaLast, affineType[idx]); + + if ( + abs(mvFieldNeighbours[(idx << 1)][0].mv.getHor() - mvFieldNeighbours[(lastIdx << 1)][0].mv.getHor()) > CPMV_SIMILARITY_THREH || + abs(mvFieldNeighbours[(idx << 1)][0].mv.getVer() - mvFieldNeighbours[(lastIdx << 1)][0].mv.getVer()) > CPMV_SIMILARITY_THREH || + abs(affinePara[0] - affineParaLast[0]) > PARA_SIMILARITY_THREH || + abs(affinePara[2] - affineParaLast[2]) > PARA_SIMILARITY_THREH + ) + { + continue; + } + + + if (affineType[idx] == AFFINEMODEL_6PARAM) + { + if (abs(affinePara[1] - affineParaLast[1]) > PARA_SIMILARITY_THREH || + abs(affinePara[3] - affineParaLast[3]) > PARA_SIMILARITY_THREH) + { + continue; + } + } + } + + if ((interDirNeighbours[lastIdx] & 2) != 0) + { + if (mvFieldNeighbours[(idx << 1) + 1][0].refIdx != mvFieldNeighbours[(lastIdx << 1) + 1][0].refIdx) + { + continue; + } + Mv acMvTemp[3]; + int affinePara[4], affineParaLast[4]; + acMvTemp[0] = mvFieldNeighbours[(idx << 1) + 1][0].mv; + acMvTemp[1] = mvFieldNeighbours[(idx << 1) + 1][1].mv; + acMvTemp[2] = mvFieldNeighbours[(idx << 1) + 1][2].mv; + PU::deriveAffineParametersFromMVs(pu, acMvTemp, affinePara, affineType[idx]); + acMvTemp[0] = mvFieldNeighbours[(lastIdx << 1) + 1][0].mv; + acMvTemp[1] = mvFieldNeighbours[(lastIdx << 1) + 1][1].mv; + acMvTemp[2] = mvFieldNeighbours[(lastIdx << 1) + 1][2].mv; + PU::deriveAffineParametersFromMVs(pu, acMvTemp, affineParaLast, affineType[idx]); + + if ( + abs(mvFieldNeighbours[(idx << 1) + 1][0].mv.getHor() - mvFieldNeighbours[(lastIdx << 1) + 1][0].mv.getHor()) > CPMV_SIMILARITY_THREH || + abs(mvFieldNeighbours[(idx << 1) + 1][0].mv.getVer() - mvFieldNeighbours[(lastIdx << 1) + 1][0].mv.getVer()) > CPMV_SIMILARITY_THREH || + abs(affinePara[0] - affineParaLast[0]) > PARA_SIMILARITY_THREH || + abs(affinePara[2] - affineParaLast[2]) > PARA_SIMILARITY_THREH) + { + continue; + } + + if (affineType[idx] == AFFINEMODEL_6PARAM) + { + if (abs(affinePara[1] - affineParaLast[1]) > PARA_SIMILARITY_THREH || + abs(affinePara[3] - affineParaLast[3]) > PARA_SIMILARITY_THREH) + { + continue; + } + } + } + return false; + } + return true; +} + +void AltLMAffineMergeCtx::initAltLMAffMergeCtx(int idx) +{ + altLMParaNeighbours[idx].resetAltLinearModel(); + for (int mvNum = 0; mvNum < 3; mvNum++) + { + mvFieldNeighbours[(idx << 1) + 0][mvNum].setMvField(Mv(), -1); + mvFieldNeighbours[(idx << 1) + 1][mvNum].setMvField(Mv(), -1); + } + interDirNeighbours[idx] = 0; + affineType[idx] = AFFINEMODEL_4PARAM; + bcwIdx[idx] = BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + obmcFlags[idx] = true; +#endif +} + +void AltLMAffineMergeCtx::init() +{ + for (int i = 0; i < ALT_AFF_MRG_MAX_NUM_CANDS; i++) + { + initAltLMAffMergeCtx(i); + } + numValidMergeCand = 0; +} + +bool AltLMAffineMergeCtx::xCheckSameAffMotion(const PredictionUnit& pu, int cnt, AltLMAffineMergeCtx& altAffMrgCtx1) +{ + const int cpmvSimilarityThresh = 1; + const int paraSimilarityThresh = 1; + + const int lastIdx = cnt; + for (int idx = 0; idx < altAffMrgCtx1.numValidMergeCand; idx++) + { + if (altAffMrgCtx1.affineType[idx] != affineType[lastIdx]) + { + continue; + } + + if (altAffMrgCtx1.interDirNeighbours[idx] != interDirNeighbours[lastIdx]) + { + continue; + } + + if (altAffMrgCtx1.interDirNeighbours[idx] == 3 && altAffMrgCtx1.bcwIdx[idx] != bcwIdx[lastIdx]) + { + continue; + } + + if ((interDirNeighbours[lastIdx] & 1) != 0) + { + if (altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][0].refIdx != mvFieldNeighbours[(lastIdx << 1)][0].refIdx) + { + continue; + } + Mv acMvTemp[3]; + int affinePara[4], affineParaLast[4]; + acMvTemp[0] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][0].mv; + acMvTemp[1] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][1].mv; + acMvTemp[2] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][2].mv; + PU::deriveAffineParametersFromMVs(pu, acMvTemp, affinePara, affineType[idx]); + acMvTemp[0] = mvFieldNeighbours[(lastIdx << 1)][0].mv; + acMvTemp[1] = mvFieldNeighbours[(lastIdx << 1)][1].mv; + acMvTemp[2] = mvFieldNeighbours[(lastIdx << 1)][2].mv; + PU::deriveAffineParametersFromMVs(pu, acMvTemp, affineParaLast, affineType[idx]); + + if (abs(altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][0].mv.getHor() - mvFieldNeighbours[(lastIdx << 1)][0].mv.getHor()) > cpmvSimilarityThresh || + abs(altAffMrgCtx1.mvFieldNeighbours[(idx << 1)][0].mv.getVer() - mvFieldNeighbours[(lastIdx << 1)][0].mv.getVer()) > cpmvSimilarityThresh || + abs(affinePara[0] - affineParaLast[0]) > paraSimilarityThresh || + abs(affinePara[2] - affineParaLast[2]) > paraSimilarityThresh) + { + continue; + } + + + if (affineType[idx] == AFFINEMODEL_6PARAM) + { + if (abs(affinePara[1] - affineParaLast[1]) > paraSimilarityThresh || + abs(affinePara[3] - affineParaLast[3]) > paraSimilarityThresh) + { + continue; + } + } + } + + if ((interDirNeighbours[lastIdx] & 2) != 0) + { + if (altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][0].refIdx != mvFieldNeighbours[(lastIdx << 1) + 1][0].refIdx) + { + continue; + } + Mv acMvTemp[3]; + int affinePara[4], affineParaLast[4]; + acMvTemp[0] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][0].mv; + acMvTemp[1] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][1].mv; + acMvTemp[2] = altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][2].mv; + PU::deriveAffineParametersFromMVs(pu, acMvTemp, affinePara, affineType[idx]); + acMvTemp[0] = mvFieldNeighbours[(lastIdx << 1) + 1][0].mv; + acMvTemp[1] = mvFieldNeighbours[(lastIdx << 1) + 1][1].mv; + acMvTemp[2] = mvFieldNeighbours[(lastIdx << 1) + 1][2].mv; + PU::deriveAffineParametersFromMVs(pu, acMvTemp, affineParaLast, affineType[idx]); + + if (abs(altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][0].mv.getHor() - mvFieldNeighbours[(lastIdx << 1) + 1][0].mv.getHor()) > cpmvSimilarityThresh || + abs(altAffMrgCtx1.mvFieldNeighbours[(idx << 1) + 1][0].mv.getVer() - mvFieldNeighbours[(lastIdx << 1) + 1][0].mv.getVer()) > cpmvSimilarityThresh || + abs(affinePara[0] - affineParaLast[0]) > paraSimilarityThresh || + abs(affinePara[2] - affineParaLast[2]) > paraSimilarityThresh) + { + continue; + } + + if (affineType[idx] == AFFINEMODEL_6PARAM) + { + if (abs(affinePara[1] - affineParaLast[1]) > paraSimilarityThresh || + abs(affinePara[3] - affineParaLast[3]) > paraSimilarityThresh) + { + continue; + } + } + } + return false; + } + return true; +} +#endif + #if JVET_AD0086_ENHANCED_INTRA_TMP unsigned DeriveCtx::CtxTmpFusionFlag(const CodingUnit& cu) { @@ -2205,6 +2702,10 @@ void AffineMergeCtx::setAffMergeInfo(PredictionUnit &pu, int candIdx, int8_t mmv pu.interDir = interDirNeighbours[candIdx]; pu.cu->affineType = affineType[candIdx]; pu.cu->bcwIdx = bcwIdx[candIdx]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = altLMFlag[candIdx]; + pu.cu->altLMParaUnit = altLMParaNeighbours[candIdx]; +#endif #if INTER_LIC pu.cu->licFlag = licFlags[candIdx]; #endif @@ -2252,4 +2753,4 @@ void AffineMergeCtx::setAffMergeInfo(PredictionUnit &pu, int candIdx, int8_t mmv } } } -#endif \ No newline at end of file +#endif diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index ccba64a50..a0ea15254 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -793,6 +793,10 @@ public: MultiHypVec addHypNeighbours[NUM_MERGE_CANDS]; #endif Distortion candCost[NUM_MERGE_CANDS]; +#if JVET_AG0276_NLIC + bool altLMFlag[NUM_MERGE_CANDS]; + AltLMInterUnit altLMParaNeighbours[NUM_MERGE_CANDS]; +#endif #else MergeCtx() : numValidMergeCand( 0 ), hasMergedCandList( false ) { } ~MergeCtx() {} @@ -928,6 +932,10 @@ public: unsigned char interDirNeighbours[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; Distortion candCost[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; EAffineModel affineType[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; +#if JVET_AG0276_NLIC + bool altLMFlag[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; + AltLMInterUnit altLMParaNeighbours[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; +#endif #if INTER_LIC bool licFlags[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; #endif @@ -952,6 +960,9 @@ public: int m_isGPMAff; void setAffMergeInfo(PredictionUnit &pu, int candIdx, int8_t mmvdIdx = -1) const; #endif +#if JVET_AG0276_NLIC + bool xCheckSimilarMotion1(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1, bool isAltLM = false) const; +#endif }; #else class AffineMergeCtx @@ -981,6 +992,41 @@ public: }; #endif +#if JVET_AG0276_NLIC +class AltLMMergeCtx +{ +public: + AltLMInterUnit altLMParaNeighbours[ALT_MRG_MAX_NUM_CANDS]; + MvField mvFieldNeighbours[ALT_MRG_MAX_NUM_CANDS << 1]; + uint8_t bcwIdx[ALT_MRG_MAX_NUM_CANDS]; + unsigned char interDirNeighbours[ALT_MRG_MAX_NUM_CANDS]; + bool useAltHpelIf[ALT_MRG_MAX_NUM_CANDS]; + int numValidMergeCand; + + void initAltLMMergeCtx(int idx); + bool xCheckSameMotion(int cnt, uint32_t mvdSimilarityThresh); +}; + +class AltLMAffineMergeCtx +{ +public: + AltLMInterUnit altLMParaNeighbours[ALT_AFF_MRG_MAX_NUM_CANDS]; + MvField mvFieldNeighbours[ALT_AFF_MRG_MAX_NUM_CANDS << 1][3]; // double length for mv of both lists + unsigned char interDirNeighbours[ALT_AFF_MRG_MAX_NUM_CANDS]; + EAffineModel affineType[ALT_AFF_MRG_MAX_NUM_CANDS]; + uint8_t bcwIdx[ALT_AFF_MRG_MAX_NUM_CANDS]; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + bool obmcFlags[ALT_AFF_MRG_MAX_NUM_CANDS]; +#endif + int numValidMergeCand; + + bool xCheckSameAffMotion(const PredictionUnit& pu, int cnt); + void initAltLMAffMergeCtx(int idx); + void init(); + bool xCheckSameAffMotion(const PredictionUnit& pu, int cnt, AltLMAffineMergeCtx& altAffMrgCtx1); +}; +#endif + namespace DeriveCtx { void CtxSplit ( const CodingStructure& cs, Partitioner& partitioner, unsigned& ctxSpl, unsigned& ctxQt, unsigned& ctxHv, unsigned& ctxHorBt, unsigned& ctxVerBt, bool* canSplit = nullptr ); @@ -990,6 +1036,9 @@ unsigned CtxModeConsFlag( const CodingStructure& cs, Partitioner& partitioner ); unsigned CtxQtCbf ( const ComponentID compID, const bool prevCbf = false, const int ispIdx = 0 ); unsigned CtxInterDir ( const PredictionUnit& pu ); unsigned CtxSkipFlag ( const CodingUnit& cu ); +#if JVET_AG0276_LIC_SLOPE_ADJUST +unsigned CtxLicFlag ( const CodingUnit& cu ); +#endif unsigned CtxAffineFlag( const CodingUnit& cu ); #if JVET_AG0135_AFFINE_CIIP unsigned CtxCiipAffineFlag(const CodingUnit& cu); diff --git a/source/Lib/CommonLib/Contexts.h b/source/Lib/CommonLib/Contexts.h index 9d35cd333..3dd1551e2 100644 --- a/source/Lib/CommonLib/Contexts.h +++ b/source/Lib/CommonLib/Contexts.h @@ -500,6 +500,11 @@ public: #endif static const CtxSet SkipFlag; static const CtxSet MergeFlag; +#if JVET_AG0276_LIC_FLAG_SIGNALING + static const CtxSet MergeFlagOppositeLic; + static const CtxSet TmMergeFlagOppositeLic; + static const CtxSet AffineFlagOppositeLic; +#endif static const CtxSet RegularMergeFlag; static const CtxSet MergeIdx; #if JVET_AG0164_AFFINE_GPM @@ -783,6 +788,9 @@ public: static const CtxSet JointCbCrFlag; #if INTER_LIC static const CtxSet LICFlag; +#if JVET_AG0276_LIC_SLOPE_ADJUST + static const CtxSet LicDelta; +#endif #endif #if SIGN_PREDICTION static const CtxSet signPred[2]; diff --git a/source/Lib/CommonLib/Contexts_ecm12.inl b/source/Lib/CommonLib/Contexts_ecm12.inl index 781e9995f..4942aeb1e 100644 --- a/source/Lib/CommonLib/Contexts_ecm12.inl +++ b/source/Lib/CommonLib/Contexts_ecm12.inl @@ -111,6 +111,63 @@ const CtxSet ContextSetCfg::MergeFlag = ContextSetCfg::addCtxSet({ { 109 }, }); +#if JVET_AG0276_LIC_FLAG_SIGNALING +const CtxSet ContextSetCfg::MergeFlagOppositeLic = ContextSetCfg::addCtxSet +({ + { 12, }, + { 4, }, + { CNU, }, + { 5, }, + { 5, }, + { DWS, }, + { 11, }, + { 4, }, + { DWE, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + }); +const CtxSet ContextSetCfg::AffineFlagOppositeLic = ContextSetCfg::addCtxSet +({ + { 12, }, + { 4, }, + { CNU, }, + { 5, }, + { 5, }, + { DWS, }, + { 11, }, + { 4, }, + { DWE, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + }); +const CtxSet ContextSetCfg::TmMergeFlagOppositeLic = ContextSetCfg::addCtxSet +({ + { 12, }, + { 4, }, + { CNU, }, + { 5, }, + { 5, }, + { DWS, }, + { 11, }, + { 4, }, + { DWE, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + { 132, }, + }); +#endif + const CtxSet ContextSetCfg::RegularMergeFlag = ContextSetCfg::addCtxSet({ { 30, 14 }, { 23, 6 }, @@ -1170,6 +1227,23 @@ const CtxSet ContextSetCfg::AffMergeIdx = ContextSetCfg::addCtxSet({ }); const CtxSet ContextSetCfg::LICFlag = ContextSetCfg::addCtxSet({ +#if JVET_AG0276_LIC_SLOPE_ADJUST + { 26, CNU, CNU, }, + { 11, CNU, CNU, }, + { 35, CNU, CNU, }, + { 5, DWS, DWS, }, + { 5, DWS, DWS, }, + { 8, DWS, DWS, }, + { 18, DWE, DWE, }, + { 4, DWE, DWE, }, + { 18, DWE, DWE, }, + { 108, DWO, DWO, }, + { 122, DWO, DWO, }, + { 116, 119, 119, }, + { 148, 119, 119, }, + { 119, 119, 119, }, + { 119, 119, 119, }, +#else { 26 }, { 11 }, { 35 }, @@ -1185,8 +1259,28 @@ const CtxSet ContextSetCfg::LICFlag = ContextSetCfg::addCtxSet({ { 148 }, { 119 }, { 119 }, +#endif }); +#if JVET_AG0276_LIC_SLOPE_ADJUST +const CtxSet ContextSetCfg::LicDelta = ContextSetCfg::addCtxSet +({ + { CNU, CNU, }, + { CNU, CNU, }, + { CNU, CNU, }, + { DWS, DWS, }, + { DWS, DWS, }, + { DWS, DWS, }, + { DWE, DWE, }, + { DWE, DWE, }, + { DWE, DWE, }, + { DWO, DWO, }, + { DWO, DWO, }, + { 119, 119, }, + { 119, 119, }, + }); +#endif + const CtxSet ContextSetCfg::BcwIdx = ContextSetCfg::addCtxSet({ { 12 }, { 5 }, diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index a5b74de30..ce5e4e83c 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -341,6 +341,9 @@ InterPrediction::InterPrediction() m_mbvdSearchCandsList = nullptr; m_mbvdTestedCandsList = nullptr; #endif +#if JVET_AG0276_NLIC + m_skipDoLic = false; +#endif } InterPrediction::~InterPrediction() @@ -586,7 +589,7 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, cons m_dmvrBottomBoundary[c] = (Pel*)xMalloc( Pel, 16 ); } #endif - + for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ ) { #if IF_12TAP || MULTI_PASS_DMVR @@ -1100,6 +1103,28 @@ void InterPrediction::xSubPuMC( PredictionUnit& pu, PelUnitBuf& predBuf, const R { m_subPuMC = false; pu.cu->affine = isAffine; +#if JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) + { + ComponentID compID = (ComponentID)comp; + if (!luma && isLuma(compID)) + { + continue; + } + if (!chroma && isChroma(compID)) + { + continue; + } + + int scale = pu.cu->altLMParaUnit.scale[comp]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[comp]; + predBuf.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID)); + } + } +#endif return; } #endif @@ -1635,7 +1660,11 @@ void InterPrediction::xPredInterUni(const PredictionUnit &pu, const RefPicList & continue; } #if MULTI_PASS_DMVR +#if JVET_AG0276_LIC_BDOF_BDMVR + if (compID != COMPONENT_Y && bioApplied && isBdofMvRefine && pu.cu->licFlag == false) +#else if (compID != COMPONENT_Y && bioApplied && isBdofMvRefine) +#endif { continue; } @@ -1751,7 +1780,11 @@ void InterPrediction::xPredInterBiSubPuBDOF(PredictionUnit &pu, PelUnitBuf &pcYu } else #endif +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.bdmvrRefine == true && pu.cu->licFlag == false) +#else if (pu.bdmvrRefine) +#endif { bioDx2 = bioDx; bioDy2 = bioDy; @@ -1784,7 +1817,11 @@ void InterPrediction::xPredInterBiSubPuBDOF(PredictionUnit &pu, PelUnitBuf &pcYu } else #endif +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.bdmvrRefine == true && pu.cu->licFlag == false) +#else if (pu.bdmvrRefine) +#endif { const int bdmvrSubPuIdx = (yStart >> DMVR_SUBCU_HEIGHT_LOG2) * DMVR_SUBPU_STRIDE + (xStart >> DMVR_SUBCU_WIDTH_LOG2); subPu.mv[0] = m_bdmvrSubPuMvBuf[0][bdmvrSubPuIdx] + bioMv; @@ -2044,6 +2081,24 @@ void InterPrediction::xPredInterBiBDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvPre } } +#if JVET_AG0276_NLIC + if (bioApplied && pu.cu->altLMFlag) + { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (m_subPuMC) + { + bioApplied = true; + } + else + { +#endif + bioApplied = false; +#if JVET_AG0276_LIC_BDOF_BDMVR + } +#endif + } +#endif + if (bioApplied && pu.ciipFlag) { bioApplied = false; @@ -2636,6 +2691,19 @@ void InterPrediction::xPredInterBiBDMVR2(PredictionUnit &pu, PelUnitBuf &pcYuvPr bioApplied = true; } } +#if JVET_AG0276_NLIC + if (bioApplied && pu.cu->altLMFlag) + { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (m_subPuMC) + { + bioApplied = true; + } + else +#endif + bioApplied = false; + } +#endif if (bioApplied && pu.ciipFlag) { bioApplied = false; @@ -2778,7 +2846,11 @@ void InterPrediction::xPredInterBiBDMVR2(PredictionUnit &pu, PelUnitBuf &pcYuvPr } else #endif +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.bdmvrRefine == true && pu.cu->licFlag == false) +#else if (pu.bdmvrRefine) +#endif { const int bdmvrSubPuIdx = (yStart >> DMVR_SUBCU_HEIGHT_LOG2) * DMVR_SUBPU_STRIDE + (xStart >> DMVR_SUBCU_WIDTH_LOG2); subPu.mv[0] = m_bdmvrSubPuMvBuf[0][bdmvrSubPuIdx] + bioMv; @@ -2955,7 +3027,11 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co const PPS &pps = *pu.cs->pps; const Slice &slice = *pu.cs->slice; #if MULTI_PASS_DMVR +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.bdmvrRefine && pu.cu->licFlag == false) +#else if ( pu.bdmvrRefine ) +#endif { if (yuvPredTmp && (pu.lwidth() > DMVR_SUBCU_WIDTH || pu.lheight() > DMVR_SUBCU_HEIGHT)) // pre-do MC for yuvPredTmp to avoid MC for yuvPredTmp within the subblock loop { @@ -3045,6 +3121,16 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co return; } #endif +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.bdmvrRefine == true) + { + if (pu.amvpMergeModeFlag[0] == false && pu.amvpMergeModeFlag[1] == false) + { + pu.mv[0] = m_bdmvrSubPuMvBuf[REF_PIC_LIST_0][0]; + pu.mv[1] = m_bdmvrSubPuMvBuf[REF_PIC_LIST_1][0]; + } + } +#endif #if !INTER_RM_SIZE_CONSTRAINTS #if ENABLE_OBMC if (pu.cu->isobmcMC == false) @@ -3060,7 +3146,7 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co bool bioApplied = false; if (pu.cs->sps->getBDOFEnabledFlag() && (!pu.cs->picHeader->getDisBdofFlag())) { -#if INTER_LIC +#if INTER_LIC && !JVET_AG0276_LIC_BDOF_BDMVR if (pu.cu->affine || m_subPuMC || pu.cu->licFlag) #else if (pu.cu->affine || m_subPuMC) @@ -3087,6 +3173,13 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co } } +#if JVET_AG0276_NLIC && !JVET_AG0276_LIC_BDOF_BDMVR + if (bioApplied && pu.cu->altLMFlag) + { + bioApplied = false; + } +#endif + if (bioApplied && pu.ciipFlag) { bioApplied = false; @@ -3263,6 +3356,13 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr())) ); const bool lumaOnly = luma && !chroma; const bool chromaOnly = !luma && chroma; +#if JVET_AG0276_LIC_BDOF_BDMVR + if (bioApplied == true && pu.cu->licFlag == true) + { + xLicCompAdjBdof(pu, pcYuvPred, lumaOnly, chromaOnly); + } + else +#endif #if JVET_AD0213_LIC_IMP xLicCompAdj(pu, pcYuvPred, lumaOnly, chromaOnly); #endif @@ -3395,6 +3495,32 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co slice.getSPS()->getBitDepths(), slice.clpRngs(), bioApplied, lumaOnly, chromaOnly, yuvPredTmp ); #endif #endif +#if JVET_AG0276_NLIC +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->altLMFlag && !bioApplied) +#else + if (pu.cu->altLMFlag) +#endif + { + for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) + { + ComponentID compID = (ComponentID)comp; + if (!luma && isLuma(compID)) + { + continue; + } + if (!chroma && isChroma(compID)) + { + continue; + } + + int scale = pu.cu->altLMParaUnit.scale[comp]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[comp]; + pcYuvPred.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID)); + } + } +#endif #if JVET_AD0213_LIC_IMP if (m_storeBeforeLIC) { @@ -3459,6 +3585,120 @@ void InterPrediction::xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, co } } +#if JVET_AG0276_NLIC +void InterPrediction::xPredWoRefinement(PredictionUnit& pu, PelUnitBuf &pcYuvPred, const bool luma, const bool chroma) +{ + if (xCheckIdenticalMotion(pu)) + { + xPredInterUni(pu, REF_PIC_LIST_0, pcYuvPred, false, false, luma, chroma); + return; + } + + const PPS &pps = *pu.cs->pps; + const Slice &slice = *pu.cs->slice; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + if (pu.refIdx[refList] < 0) + { + continue; + } + + RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + m_iRefListIdx = refList; + + PelUnitBuf pcMbBuf = (pu.chromaFormat == CHROMA_400 ? + PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[refList][0], pcYuvPred.Y())) : + PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[refList][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[refList][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[refList][2], pcYuvPred.Cr()))); + + if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0) + { + xPredInterUni(pu, eRefPicList, pcMbBuf, true, false, luma, chroma); + } + else + { + if (((pps.getUseWP() && slice.getSliceType() == P_SLICE) || (pps.getWPBiPred() && slice.getSliceType() == B_SLICE))) + { + xPredInterUni(pu, eRefPicList, pcMbBuf, true, false, luma, chroma); + } + else + { + xPredInterUni(pu, eRefPicList, pcMbBuf, false, false, luma, chroma); + } + } + } + CPelUnitBuf srcPred0 = (pu.chromaFormat == CHROMA_400 ? + CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y())) : + CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[0][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[0][2], pcYuvPred.Cr()))); + CPelUnitBuf srcPred1 = (pu.chromaFormat == CHROMA_400 ? + CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y())) : + CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr()))); + const bool lumaOnly = luma && !chroma; + const bool chromaOnly = !luma && chroma; + if (pps.getWPBiPred() && slice.getSliceType() == B_SLICE && pu.cu->bcwIdx == BCW_DEFAULT) + { + xWeightedPredictionBi(pu, srcPred0, srcPred1, pcYuvPred, m_maxCompIDToPred, lumaOnly, chromaOnly); + } + else if (pps.getUseWP() && slice.getSliceType() == P_SLICE) + { + xWeightedPredictionUni(pu, srcPred0, REF_PIC_LIST_0, pcYuvPred, -1, m_maxCompIDToPred, lumaOnly, chromaOnly); + } + else + { +#if JVET_Z0136_OOB + bool isOOB[2] = { false,false }; + if (pu.interDir == 3) + { + if (pu.cu->affine && pu.mergeType != MRG_TYPE_SUBPU_ATMVP) // affine + { + bool *pMcMask0 = pu.cs->mcMask[0]; + bool *pMcMask1 = pu.cs->mcMask[1]; + for (int h = 0; h < (int)pu.lumaSize().height && (!isOOB[0] || !isOOB[1]); h++) + { + for (int w = 0; w < (int)pu.lumaSize().width && (!isOOB[0] || !isOOB[1]); w++) + { + isOOB[0] |= pMcMask0[w]; + isOOB[1] |= pMcMask1[w]; + } + pMcMask0 += (int)pu.lumaSize().width; + pMcMask1 += (int)pu.lumaSize().width; + } + } + else + { +#if JVET_AA0146_WRAP_AROUND_FIX + if (pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->isWrapAroundEnabled(pu.cs->pps)) + { + isOOB[0] = false; + } + else +#endif + isOOB[0] = isMvOOB(pu.mv[0], pu.Y().topLeft(), pu.lumaSize(), pu.cu->slice->getSPS(), pu.cu->slice->getPPS(), pu.cs->mcMask[0], pu.cs->mcMaskChroma[0]); +#if JVET_AA0146_WRAP_AROUND_FIX + if (pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1])->isWrapAroundEnabled(pu.cs->pps)) + { + isOOB[1] = false; + } + else +#endif + isOOB[1] = isMvOOB(pu.mv[1], pu.Y().topLeft(), pu.lumaSize(), pu.cu->slice->getSPS(), pu.cu->slice->getPPS(), pu.cs->mcMask[1], pu.cs->mcMaskChroma[1]); + } + xWeightedAverage(false/*isBdofMvRefine*/, 0/*bioSubPuOffset*/, pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), false, lumaOnly, chromaOnly, NULL, pu.cs->mcMask, pcYuvPred.Y().width, pu.cs->mcMaskChroma, pu.chromaFormat == CHROMA_400 ? 0 : pcYuvPred.Cb().width, isOOB); + } + else + { + xWeightedAverage(false/*isBdofMvRefine*/, 0/*bioSubPuOffset*/, pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), false, lumaOnly, chromaOnly, NULL, pu.cs->mcMask, pcYuvPred.Y().width, pu.cs->mcMaskChroma, pu.chromaFormat == CHROMA_400 ? 0 : pcYuvPred.Cb().width, isOOB); + } +#else +#if MULTI_PASS_DMVR + xWeightedAverage(false/*isBdofMvRefine*/, 0/*bioSubPuOffset*/, pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), false, lumaOnly, chromaOnly); +#else + xWeightedAverage(pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), false, lumaOnly, chromaOnly); +#endif +#endif + } +} +#endif + void InterPrediction::xPredInterBlk ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng , const bool& bioApplied , bool isIBC @@ -3480,6 +3720,140 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio #endif ) { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (bioApplied == true && pu.cu->licFlag == true && isAML == false && isIBC == false && fastOBMC == false && bilinearMC == false) + { + int filterIdx = 0; + JVET_J0090_SET_REF_PICTURE(refPic, compID); + const ChromaFormat chFmt = pu.chromaFormat; + const bool rndRes = !bi; + int shiftHor = MV_FRACTIONAL_BITS_INTERNAL + ::getComponentScaleX(compID, chFmt); + int shiftVer = MV_FRACTIONAL_BITS_INTERNAL + ::getComponentScaleY(compID, chFmt); + + bool wrapRef = false; + Mv mv(_mv); + if (!isIBC && refPic->isWrapAroundEnabled(pu.cs->pps)) + { + wrapRef = wrapClipMv(mv, pu.blocks[0].pos(), pu.blocks[0].size(), pu.cs->sps, pu.cs->pps); + } + + bool useAltHpelIf = pu.cu->imv == IMV_HPEL; + int xFrac = mv.hor & ((1 << shiftHor) - 1); + int yFrac = mv.ver & ((1 << shiftVer) - 1); + PelBuf & dstBuf = dstPic.bufs[compID]; + unsigned width = dstBuf.width; + unsigned height = dstBuf.height; + CPelBuf refBuf; + Position offset = pu.blocks[compID].pos().offset(mv.getHor() >> shiftHor, mv.getVer() >> shiftVer); + int refBufExtendSize = 0; + if (bioApplied && compID == COMPONENT_Y) + { + refBufExtendSize = ((BIO_EXTEND_SIZE + 1) << 1); // trick to use SIMD filter + offset.x -= (BIO_EXTEND_SIZE + 1); + offset.y -= (BIO_EXTEND_SIZE + 1); + } + if (dmvrWidth) + { + refBuf = refPic->getRecoBuf(CompArea(compID, chFmt, offset, Size(dmvrWidth + refBufExtendSize, dmvrHeight + refBufExtendSize)), wrapRef); + } + else + { + refBuf = refPic->getRecoBuf(CompArea(compID, chFmt, offset, Size(pu.blocks[compID].width + refBufExtendSize, pu.blocks[compID].height + refBufExtendSize)), wrapRef); + } + + int backupWidth = width; + int backupHeight = height; + Pel *backupDstBufPtr = dstBuf.buf; + int backupDstBufStride = dstBuf.stride; + + if (bioApplied && compID == COMPONENT_Y) + { + backupWidth += ((BIO_EXTEND_SIZE + 1) << 1); + backupHeight += ((BIO_EXTEND_SIZE + 1) << 1); + dstBuf.stride = backupWidth; + dstBuf.buf = m_filteredBlockTmp[2 + m_iRefListIdx][compID]; + } + if (yFrac == 0) + { + m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng, filterIdx, bilinearMC, useAltHpelIf); + } + else if (xFrac == 0) + { + m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng, filterIdx, bilinearMC, useAltHpelIf); + } + else + { +#if SIMD_4x4_12 && defined(TARGET_SIMD_X86) + if (compID == COMPONENT_Y + && backupWidth == 4 + && backupHeight == 4 + && !((xFrac == 8 || yFrac == 8) && useAltHpelIf) + && dmvrWidth == 0 + ) + m_if.filter4x4(clpRng, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, xFrac, yFrac, rndRes); + else + { +#endif + PelBuf tmpBuf = dmvrWidth ? PelBuf(m_filteredBlockTmp[0][compID], Size(dmvrWidth, dmvrHeight)) : PelBuf(m_filteredBlockTmp[0][compID], pu.blocks[compID]); + if (dmvrWidth == 0) + { + tmpBuf.stride = dstBuf.stride; + } +#if MULTI_PASS_DMVR || SAMPLE_BASED_BDOF + if (bioApplied && compID == COMPONENT_Y) + { + tmpBuf = PelBuf(m_filteredBlockTmp[0][compID], Size(backupWidth, backupWidth)); + tmpBuf.stride = dstBuf.stride; + } +#endif + int vFilterSize = isLuma(compID) ? NTAPS_LUMA(0) : NTAPS_CHROMA; + if (isLuma(compID) && filterIdx == 1) + { + vFilterSize = NTAPS_BILINEAR; + } + m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng, filterIdx, bilinearMC, useAltHpelIf); + JVET_J0090_SET_CACHE_ENABLE(false); + m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng, filterIdx, bilinearMC, useAltHpelIf); +#if SIMD_4x4_12 && defined(TARGET_SIMD_X86) + } +#endif + } + JVET_J0090_SET_CACHE_ENABLE((srcPadStride == 0) && (bioApplied == false)); + + if (bioApplied && compID == COMPONENT_Y) + { + dstBuf.buf = backupDstBufPtr; + dstBuf.stride = backupDstBufStride; + } + if (m_storeBeforeLIC) + { + UnitArea localUnitArea(chFmt, Area(0, 0, pu.lumaSize().width, pu.lumaSize().height)); + PelUnitBuf predBeforeLICBuffer = m_acPredBeforeLICBuffer[m_iRefListIdx].getBuf(localUnitArea); + predBeforeLICBuffer.bufs[compID].copyFrom(dstBuf); + if (compID == COMPONENT_Y) + { + const int realSrcBufStride = pu.lwidth() + ((BIO_EXTEND_SIZE + 1) << 1); + const int realSrcBufStart = (BIO_EXTEND_SIZE + 1) * (realSrcBufStride + 1); + for (int y = 0; y < predBeforeLICBuffer.bufs[compID].height; y++) + { + for (int x = 0; x < predBeforeLICBuffer.bufs[compID].width; x++) + { + const int curSrcIdx = x + y * predBeforeLICBuffer.bufs[compID].stride; + const int realSrcIdx = x + y * realSrcBufStride + realSrcBufStart; + *(predBeforeLICBuffer.bufs[compID].buf + curSrcIdx) = *(m_filteredBlockTmp[2 + m_iRefListIdx][compID] + realSrcIdx); + } + } + } + } + xGetSublkTemplateAndRef(*pu.cu, compID, *refPic, _mv, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, m_numTemplate[compID], m_pcLICRefLeftTemplate[m_iRefListIdx][compID], m_pcLICRefAboveTemplate[m_iRefListIdx][compID], m_pcLICRecLeftTemplate[compID], m_pcLICRecAboveTemplate[compID], (m_iRefListIdx == 0 ? true : false), true); + + if (m_iRefListIdx == 0) + { + m_fillLicTpl[compID] = true; + } + return; + } +#endif #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC int filterIdx = 0; #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED @@ -3936,6 +4310,10 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio #if JVET_W0090_ARMC_TM if (isAML) { +#if JVET_AG0276_NLIC + if (!m_skipDoLic) + { +#endif if (m_iRefListIdx == 0) { m_numTemplate[compID][0] = 0; @@ -3945,6 +4323,9 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio xGetSublkTemplateAndRef(*pu.cu, compID, *refPic, mvCurr, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, m_numTemplate[compID], m_pcLICRefLeftTemplate[m_iRefListIdx][compID], m_pcLICRefAboveTemplate[m_iRefListIdx][compID], m_pcLICRecLeftTemplate[compID], m_pcLICRecAboveTemplate[compID], (m_iRefListIdx == 0 ? true : false), true, &scalingRatio); #else xGetSublkTemplateAndRef(*pu.cu, compID, *refPic, mvCurr, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, m_numTemplate[compID], m_pcLICRefLeftTemplate[m_iRefListIdx][compID], m_pcLICRefAboveTemplate[m_iRefListIdx][compID], m_pcLICRecLeftTemplate[compID], m_pcLICRecAboveTemplate[compID], (m_iRefListIdx == 0 ? true : false), true); +#endif +#if JVET_AG0276_NLIC + } #endif } else @@ -5419,13 +5800,36 @@ void InterPrediction::xPredAffineBlk(const ComponentID &compID, const Prediction PelBuf &dstBuf = dstPic.bufs[compID]; int LICshift = 0, scale = 0, offset = 0; #if !JVET_AD0213_LIC_IMP - xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset); +#if JVET_AG0276_LIC_SLOPE_ADJUST + int midVal[1] = {0}; +#if JVET_AE0078_IBC_LIC_EXTENSION + xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset, nullptr, nullptr, nullptr, nullptr, midVal); +#else + xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset, midVal); +#endif + xUpdateLicModel(scale, offset, LICshift, midVal[0], pu.cu->licDelta); +#else + xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset); +#endif #endif const ClpRng& clpRng = pu.cu->cs->slice->clpRng(compID); #if JVET_AD0213_LIC_IMP if (!bi) { +#if JVET_AG0276_LIC_SLOPE_ADJUST + if (pu.cu->licFlag) + { + int midVal[1] = {0}; +#if JVET_AE0078_IBC_LIC_EXTENSION + xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset, nullptr, nullptr, nullptr, nullptr, midVal); +#else + xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset, midVal); +#endif + xUpdateLicModel(scale, offset, LICshift, midVal[0], pu.cu->licDelta); + } + else +#endif xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, LICshift, scale, offset); if (!m_isAddHypMC) { @@ -5542,6 +5946,12 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf { iteIdx = 1; } +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag) + { + iteIdx = 0; + } +#endif int bdofSubPuAreaThre = (iter == iteIdx) ? ((m_subPuMC == true) ? BDOF_SUBPU_AREA_THRESHOLDAFFINE0 : BDOF_SUBPU_AREA_THRESHOLD0) : ((m_subPuMC == true) ? BDOF_SUBPU_AREA_THRESHOLD2 : BDOF_SUBPU_AREA_THRESHOLD1); #else int bdofSubPuAreaThre = (iter == 0) ? BDOF_SUBPU_AREA_THRESHOLD0 : ((m_subPuMC == true) ? BDOF_SUBPU_AREA_THRESHOLD2 : BDOF_SUBPU_AREA_THRESHOLD1); @@ -5549,9 +5959,17 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf #else int bdofSubPuAreaThre = (iter == 0) ? BDOF_SUBPU_AREA_THRESHOLD0 : BDOF_SUBPU_AREA_THRESHOLD1; #endif +#if JVET_AG0276_LIC_BDOF_BDMVR + if ((!m_subPuMC && isBdofMvRefine && pu.bdmvrRefine && pu.cu->licFlag == false && (ww*hh < bdofSubPuAreaThre)) || (!m_subPuMC && !isBdofMvRefine && ((width % 8 == 4) && (width != 4)))) +#else if ((isBdofMvRefine && pu.bdmvrRefine && (ww*hh < bdofSubPuAreaThre)) || (!isBdofMvRefine && ((width % 8 == 4) && (width != 4) ))) +#endif +#else +#if JVET_AG0276_LIC_BDOF_BDMVR + if ((!m_subPuMC && isBdofMvRefine && pu.bdmvrRefine && pu.cu->licFlag == false && (ww*hh < BDOF_SUBPU_AREA_THRE)) || (!m_subPuMC && !isBdofMvRefine && ((width % 8 == 4) && (width != 4)))) #else if ((isBdofMvRefine && pu.bdmvrRefine && (ww*hh < BDOF_SUBPU_AREA_THRESHOLD)) || (!isBdofMvRefine && ((width % 8 == 4) && (width != 4) ))) +#endif #endif { scaleBDOF = 1; @@ -5565,7 +5983,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf } #endif #if JVET_AG0067_DMVR_EXTENSIONS - if (iter == 0 && isBdofMvRefine && !m_subPuMC) + if (iter == 0 && isBdofMvRefine && !m_subPuMC +#if JVET_AG0276_LIC_BDOF_BDMVR + && !pu.cu->licFlag +#endif + ) { scaleBDOF = 4; scaleBDOFLog2 = 2; @@ -5589,7 +6011,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf { #if JVET_AD0195_HIGH_PRECISION_BDOF_CORE bool simBIOParameter = false; +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.bdmvrRefine == true && pu.cu->licFlag == false) +#else if (pu.bdmvrRefine) +#endif { g_pelBufOP.calcBIOParameterHighPrecision(srcY0, srcY1, gradX0, gradX1, gradY0, gradY1, widthG, heightG, src0Stride, src1Stride, widthG, bitDepth, m_piDotProduct1, m_piDotProduct2, m_piDotProduct3, m_piDotProduct5, m_piDotProduct6, m_dI @@ -5608,12 +6034,20 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf g_pelBufOP.calcBIOParameter(srcY0, srcY1, gradX0, gradX1, gradY0, gradY1, widthG, heightG, src0Stride, src1Stride, widthG, bitDepth, m_absGx, m_absGy, m_dIx, m_dIy, m_signGxGy, m_dI); #endif +#if JVET_AG0276_LIC_BDOF_BDMVR + m_bdofMvRefined = (pu.cu->licFlag == false); +#else m_bdofMvRefined = true; +#endif int bioSubPuMvIndex = 0; const int bioSubPuMvIndexIncrementY = BDOF_SUBPU_STRIDE - std::max(1, (width >> BDOF_SUBPU_DIM_LOG2)); #if JVET_AE0091_ITERATIVE_BDOF #if JVET_AG0067_DMVR_EXTENSIONS +#if JVET_AG0276_LIC_BDOF_BDMVR + const int bioBlockDistTh = (m_subPuMC || (iter == 2) || pu.cu->licFlag) ? ((bioDx * bioDy) << (6 - 4)) : ((bioDx * bioDy) << (6 - 4 + ((pu.cu->slice->getPPS()->getPicInitQPMinus26() + 26) >> 5))); +#else const int bioBlockDistTh = (m_subPuMC || (iter == 2)) ? ((bioDx * bioDy) << (6 - 4)) : ((bioDx * bioDy) << (6 - 4 + ((pu.cu->slice->getPPS()->getPicInitQPMinus26() + 26) >> 5))); +#endif #else const int bioBlockDistTh = (iter == 0) ? ((bioDx * bioDy) << (6 - 4)) : ((bioDx * bioDy) << (6 - 4)); #endif @@ -5730,7 +6164,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf #endif #endif #if JVET_AG0067_DMVR_EXTENSIONS - if ((iter != 0) || !pu.bdmvrRefine || m_subPuMC) + if ((iter != 0) || !pu.bdmvrRefine || m_subPuMC +#if JVET_AG0276_LIC_BDOF_BDMVR + || pu.cu->licFlag +#endif + ) { #endif if (bioDx == 4) @@ -5775,7 +6213,11 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf #endif continue; } +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.bdmvrRefine == false || pu.cu->licFlag == true) +#else if (!pu.bdmvrRefine) +#endif { #if JVET_AG0067_DMVR_EXTENSIONS if (iter == 0) @@ -5881,6 +6323,16 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf #endif continue; } +#if JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC + Mv bioMv; + if (m_subPuMC && pu.cu->altLMFlag) + { + bioMv.hor = 0; + bioMv.ver = 0; + } + else + { +#endif #if JVET_AD0195_HIGH_PRECISION_BDOF_CORE int32_t sumS1 = 0, sumS2 = 0, sumS3 = 0, sumS5 = 0, sumS6 = 0; #if JVET_AG0067_DMVR_EXTENSIONS @@ -5948,7 +6400,9 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf #endif tmpXblock = Clip3(-256, 256, tmpXblock); tmpYblock = Clip3(-256, 256, tmpYblock); +#if !(JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC) Mv bioMv; +#endif #if JVET_AD0195_HIGH_PRECISION_BDOF_CORE if (tmpXblock >= 0) { @@ -5985,6 +6439,9 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf bioMv.ver = (-1) * ((((-1) * tmpYblock) + 4) >> 3); } #endif +#if JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC + } +#endif #if JVET_AG0067_DMVR_EXTENSIONS if (iter == 0) { @@ -6016,6 +6473,7 @@ void InterPrediction::applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf } } #else + #if JVET_AE0091_ITERATIVE_BDOF if (iter == 0) { @@ -6527,6 +6985,12 @@ void InterPrediction::xWeightedAverage( pcYuvDst.addAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, bioApplied); #endif } +#if JVET_AG0276_LIC_BDOF_BDMVR + else if (isBdofMvRefine == true && pu.cu->licFlag == true) + { + pcYuvDst.addWeightedAvg(pcYuvSrc0, pcYuvSrc1, clpRngs, BCW_DEFAULT, true/*chromaOnly*/, false/*lumaOnly*/, mcMask, mcStride, mcMaskChroma, mcCStride, isOOB); + } +#endif if (yuvDstTmp) { if (bioApplied) @@ -7285,6 +7749,28 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu else if( xCheckIdenticalMotion( pu ) ) { xPredInterUni( pu, REF_PIC_LIST_0, predBuf, false, false, luma, chroma ); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) + { + ComponentID compID = (ComponentID)comp; + if (!luma && isLuma(compID)) + { + continue; + } + if (!chroma && isChroma(compID)) + { + continue; + } + + int scale = pu.cu->altLMParaUnit.scale[comp]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[comp]; + predBuf.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID)); + } + } +#endif #if JVET_AD0213_LIC_IMP Slice* slice = pu.cu->slice; if (m_storeBeforeLIC) @@ -7333,6 +7819,28 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu if (m_bdofMvRefined) { xPredInterBiSubPuBDOF(pu, predBuf, luma, chroma); // do not change the predBufWOBIO +#if JVET_AG0276_LIC_BDOF_BDMVR && JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) + { + ComponentID compID = (ComponentID)comp; + if (!luma && isLuma(compID)) + { + continue; + } + if (!chroma && isChroma(compID)) + { + continue; + } + + int scale = pu.cu->altLMParaUnit.scale[comp]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[comp]; + predBuf.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID)); + } + } +#endif m_bdofMvRefined = false; } #else @@ -7430,6 +7938,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) MotionInfo NeighMi = MotionInfo(); int bcwIdx = pu.cu->bcwIdx; +#if JVET_AG0276_NLIC + bool altLMFlag = pu.cu->altLMFlag; + AltLMInterUnit altLMParaUnit = pu.cu->altLMParaUnit; +#endif #if JVET_AD0213_LIC_IMP bool licFlag = pu.cu->licFlag; int licScale[2][3], licOffset[2][3]; @@ -7477,6 +7989,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) { int iLength = 0; Position curOffset = (iBlkBoundary == 0) ? Position(iSub * uiMinCUW, 0) : Position(0, iSub * uiMinCUW); +#if JVET_AG0276_NLIC + subPu.cu->altLMFlag = altLMFlag; + subPu.cu->altLMParaUnit = altLMParaUnit; +#endif #if JVET_AD0213_LIC_IMP Position posNeighbor; subPu.cu->licFlag = licFlag; @@ -7538,6 +8054,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) } } #endif +#if JVET_AG0276_NLIC + subPu.cu->altLMFlag = neighPu->cu->altLMFlag; + subPu.cu->altLMParaUnit = neighPu->cu->secAltLMParaUnit; +#endif #if JVET_AA0132_CONFIGURABLE_TM_TOOLS if (iOBMCmode == -1) { @@ -7618,6 +8138,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) #endif { pu.cu->bcwIdx = bcwIdx; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = altLMFlag; + pu.cu->altLMParaUnit = altLMParaUnit; +#endif #if JVET_AD0213_LIC_IMP pu.cu->licFlag = licFlag; for (int refList = 0; refList < 2; refList++) @@ -7634,6 +8158,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) return; } +#if JVET_AG0276_NLIC + subPu.cu->altLMFlag = altLMFlag; + subPu.cu->altLMParaUnit = altLMParaUnit; +#endif #if JVET_AD0213_LIC_IMP subPu.cu->licFlag = licFlag; for (int refList = 0; refList < 2; refList++) @@ -7721,6 +8249,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) } } pu.cu->bcwIdx = bcwIdx; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = altLMFlag; + pu.cu->altLMParaUnit = altLMParaUnit; +#endif #if JVET_AD0213_LIC_IMP pu.cu->licFlag = licFlag; for (int refList = 0; refList < 2; refList++) @@ -8105,6 +8637,20 @@ void InterPrediction::xSubBlockMotionCompensation(PredictionUnit &pu, PelUnitBuf if (xCheckIdenticalMotion(pu)) { xPredInterUni(pu, REF_PIC_LIST_0, pcYuvPred, false, false, true, true); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) + { + ComponentID compID = (ComponentID)comp; + + int scale = pu.cu->altLMParaUnit.scale[comp]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[comp]; + pcYuvPred.bufs[comp].linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(compID)); + } + } +#endif } else { @@ -11298,6 +11844,10 @@ void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx const int refList0 = mrgCtx.mmvdBaseMv[fPosBaseIdx][0].refIdx; const int refList1 = mrgCtx.mmvdBaseMv[fPosBaseIdx][1].refIdx; pu.cu->imv = mrgCtx.mmvdUseAltHpelIf[fPosBaseIdx] ? IMV_HPEL : 0; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = mrgCtx.altLMFlag[fPosBaseIdx]; + pu.cu->altLMParaUnit = mrgCtx.altLMParaNeighbours[fPosBaseIdx]; +#endif #if INTER_LIC pu.cu->licFlag = mrgCtx.licFlags[fPosBaseIdx]; #endif @@ -11800,6 +12350,10 @@ void InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC pu.interDir = affMrgCtx.interDirNeighbours[pu.mergeIdx]; pu.cu->affineType = affMrgCtx.affineType[pu.mergeIdx]; pu.cu->bcwIdx = affMrgCtx.bcwIdx[pu.mergeIdx]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affMrgCtx.altLMFlag[pu.mergeIdx]; + pu.cu->altLMParaUnit = affMrgCtx.altLMParaNeighbours[pu.mergeIdx]; +#endif #if JVET_AD0213_LIC_IMP pu.cu->licFlag = affMrgCtx.licFlags[pu.mergeIdx]; #endif @@ -12777,6 +13331,12 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& #else xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); #endif +#endif +#if JVET_AG0276_NLIC + if (m_bAMLTemplateAvailabe[1]) + { + m_skipDoLic = true; + } #endif } if (m_bAMLTemplateAvailabe[1]) @@ -12811,6 +13371,9 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& #else xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); #endif +#endif +#if JVET_AG0276_NLIC + m_skipDoLic = false; #endif } } @@ -12822,6 +13385,12 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& uiCost = 0; const int origWeight = getBcwWeight(origBcwIdx, REF_PIC_LIST_0); bool bioApplied = pu.cs->sps->getBDOFEnabledFlag() && !pu.cs->picHeader->getDisBdofFlag() && PU::isBiPredFromDifferentDirEqDistPoc(pu) ? true : false; +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + bioApplied = false; + } +#endif #if JVET_AD0213_LIC_IMP if (pu.cu->licFlag) { @@ -12842,6 +13411,15 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y())); CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y())); xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); uiCost += cDistParam.distFunc(cDistParam); } @@ -12850,6 +13428,15 @@ void InterPrediction::adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y())); CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y())); xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeftTranspose.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); uiCost += cDistParam.distFunc(cDistParam); } @@ -13151,7 +13738,10 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer pairMergeCand.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID); pairMergeCand.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID); - +#if JVET_AG0276_NLIC + pairMergeCand.altLMFlag[cnt] = false; + pairMergeCand.altLMParaNeighbours[cnt].resetAltLinearModel(); +#endif #if INTER_LIC pairMergeCand.licFlags[cnt] = mvpMergeCandCtx.licFlags[rdCandList[0]]; #endif @@ -13389,108 +13979,59 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer } #endif -#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC -void InterPrediction::updateCandInTwoCandidateGroups(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory, MergeCtx mrgCtx2) +#if JVET_AG0276_NLIC +void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMergeCandCtx, AltLMMergeCtx& altLMMrgCtx, int numRetrievedMergeCand) { - MergeCtx mrgCtxTmp; - for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++) - { - mrgCtxTmp.bcwIdx[uiMergeCand] = mrgCtx.bcwIdx[uiMergeCand]; - mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand]; - mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; - mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; - mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; -#if INTER_LIC - mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; -#endif -#if MULTI_HYP_PRED - mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; -#endif - - } - //update - for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) - { - if (rdCandList[uiMergeCand] >= mrgCtx.numValidMergeCand) - { - mrgCtx.bcwIdx[uiMergeCand] = mrgCtx2.bcwIdx[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; - mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtx2.interDirNeighbours[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx2.mvFieldNeighbours[((rdCandList[uiMergeCand] -mrgCtx.numValidMergeCand) << 1)]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx2.mvFieldNeighbours[((rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand) << 1) + 1]; - mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtx2.useAltHpelIf[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; -#if INTER_LIC - mrgCtx.licFlags[uiMergeCand] = mrgCtx2.licFlags[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; -#endif -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtx2.addHypNeighbours[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; -#endif - - } - else - { - mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]]; - mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; - mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]]; -#if INTER_LIC - mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]]; -#endif -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]]; -#endif + MergeCtx altLMMergeCand; + altLMMergeCand.numValidMergeCand = 0; + altLMMergeCand.numCandToTestEnc = 0; + for (uint32_t mrgIdx = 0; mrgIdx < altLMMrgCtx.numValidMergeCand; mrgIdx++) + { + altLMMergeCand.altLMFlag[altLMMergeCand.numValidMergeCand] = true; + altLMMergeCand.altLMParaNeighbours[altLMMergeCand.numValidMergeCand] = altLMMrgCtx.altLMParaNeighbours[mrgIdx]; + altLMMergeCand.licFlags[altLMMergeCand.numValidMergeCand] = false; + altLMMergeCand.interDirNeighbours[altLMMergeCand.numValidMergeCand] = altLMMrgCtx.interDirNeighbours[mrgIdx]; + altLMMergeCand.mvFieldNeighbours[(altLMMergeCand.numValidMergeCand << 1) + 0] = altLMMrgCtx.mvFieldNeighbours[(mrgIdx << 1) + 0]; + altLMMergeCand.mvFieldNeighbours[(altLMMergeCand.numValidMergeCand << 1) + 1] = altLMMrgCtx.mvFieldNeighbours[(mrgIdx << 1) + 1]; + altLMMergeCand.useAltHpelIf[altLMMergeCand.numValidMergeCand] = altLMMrgCtx.useAltHpelIf[mrgIdx]; + altLMMergeCand.bcwIdx[altLMMergeCand.numValidMergeCand] = altLMMrgCtx.bcwIdx[mrgIdx]; + altLMMergeCand.addHypNeighbours[altLMMergeCand.numValidMergeCand].clear(); + altLMMergeCand.candCost[altLMMergeCand.numValidMergeCand] = MAX_UINT64; + + altLMMergeCand.numValidMergeCand++; + altLMMergeCand.numCandToTestEnc++; + } + + if (mvpMergeCandCtx.numValidMergeCand + altLMMergeCand.numValidMergeCand <= 1) + { + for (uint32_t mrgIdx = 0; mrgIdx < altLMMergeCand.numValidMergeCand; mrgIdx++) + { + mvpMergeCandCtx.altLMFlag[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.altLMFlag[mrgIdx]; + mvpMergeCandCtx.altLMParaNeighbours[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.altLMParaNeighbours[mrgIdx]; + mvpMergeCandCtx.licFlags[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.licFlags[mrgIdx]; + mvpMergeCandCtx.interDirNeighbours[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.interDirNeighbours[mrgIdx]; + mvpMergeCandCtx.mvFieldNeighbours[(mvpMergeCandCtx.numValidMergeCand << 1) + 0] = altLMMergeCand.mvFieldNeighbours[(mrgIdx << 1) + 0]; + mvpMergeCandCtx.mvFieldNeighbours[(mvpMergeCandCtx.numValidMergeCand << 1) + 1] = altLMMergeCand.mvFieldNeighbours[(mrgIdx << 1) + 1]; + mvpMergeCandCtx.useAltHpelIf[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.useAltHpelIf[mrgIdx]; + mvpMergeCandCtx.bcwIdx[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.bcwIdx[mrgIdx]; + mvpMergeCandCtx.addHypNeighbours[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.addHypNeighbours[mrgIdx]; + mvpMergeCandCtx.candCost[mvpMergeCandCtx.numValidMergeCand] = altLMMergeCand.candCost[mrgIdx]; + mvpMergeCandCtx.numValidMergeCand++; } + return; } -} -#endif -void InterPrediction::updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory) -{ - MergeCtx mrgCtxTmp; - for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++) - { - mrgCtxTmp.bcwIdx[uiMergeCand] = mrgCtx.bcwIdx[uiMergeCand]; - mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand]; - mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; - mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; - mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; -#if INTER_LIC - mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; -#endif -#if MULTI_HYP_PRED - mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; -#endif - } - //update - for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) - { - mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]]; - mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; - mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]]; -#if INTER_LIC - mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]]; -#endif -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]]; -#endif - } -} -#endif + int numCandInCategory = MAX_INT; -void InterPrediction::adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx) -{ - uint32_t rdCandList[MRG_MAX_NUM_CANDS][MRG_MAX_NUM_CANDS]; - Distortion candCostList[MRG_MAX_NUM_CANDS][MRG_MAX_NUM_CANDS]; + uint32_t rdCandList[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS]; + uint32_t candCategory[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS]; + Distortion candCostList[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS]; - for (uint32_t i = 0; i < MRG_MAX_NUM_CANDS; i++) + for (uint32_t j = 0; j < NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS; j++) { - for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++) - { - rdCandList[i][j] = j; - candCostList[i][j] = MAX_UINT; - } + rdCandList[j] = MAX_UINT; + candCategory[j] = MAX_UINT; + candCostList[j] = MAX_UINT64; } Distortion uiCost; @@ -13498,144 +14039,34 @@ void InterPrediction::adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx& DistParam cDistParam; cDistParam.applyWeight = false; - /*const SPS &sps = *pu.cs->sps; - Position puPos = pu.lumaPos();*/ int nWidth = pu.lumaSize().width; int nHeight = pu.lumaSize().height; - if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)) - { - return; - } + auto origMergeIdx = pu.mergeIdx; -#if JVET_X0049_ADAPT_DMVR -#if JVET_AA0093_ENHANCED_MMVD_EXTENSION - uint16_t origMergeIdx = pu.mergeIdx; -#else - uint8_t origMergeIdx = pu.mergeIdx; -#endif -#endif - for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE)*ADAPTIVE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE)); ++uiMergeCand) + PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + + for (uint32_t uiMergeCand = 0; uiMergeCand < mvpMergeCandCtx.numValidMergeCand; uiMergeCand++) { - bool firstGroup = (uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE) == 0 ? true : false; - bool lastGroup = ((uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE >= mrgCtx.numValidMergeCand) ? true : false; - if (lastGroup && !firstGroup) + if (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand) { - break; + if (uiMergeCand >= mvpMergeCandCtx.numCandToTestEnc) + { + mvpMergeCandCtx.candCost[uiMergeCand] = MAX_UINT64 - 1; + } } - uiCost = 0; - - mrgCtx.setMergeInfo(pu, uiMergeCand); - PU::spanMotionInfo(pu, mrgCtx); - - PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); - PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); - PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); - PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], nHeight, AML_MERGE_TEMPLATE_SIZE))); -#if JVET_Y0128_NON_CTC -#if !JVET_AF0190_RPR_TMP_REORDER_LIC - bool bRefIsRescaled = false; - for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) - { - const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0; - bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false; - } - if ( !bRefIsRescaled ) -#endif + if (mvpMergeCandCtx.candCost[uiMergeCand] == MAX_UINT64) { -#endif - getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + uiCost = 0; - if (m_bAMLTemplateAvailabe[0]) - { - m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + mvpMergeCandCtx.setMergeInfo(pu, uiMergeCand); - uiCost += cDistParam.distFunc(cDistParam); - } + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); - if (m_bAMLTemplateAvailabe[1]) - { - m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); - - uiCost += cDistParam.distFunc(cDistParam); - } -#if JVET_Y0128_NON_CTC - } -#endif - - updateCandList(uiMergeCand, uiCost, ADAPTIVE_SUB_GROUP_SIZE, rdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE]); - } -#if JVET_X0049_ADAPT_DMVR - pu.mergeIdx = origMergeIdx; -#else - pu.mergeIdx = mrgCandIdx; //restore the merge index -#endif - updateCandInfo(mrgCtx, rdCandList - , mrgCandIdx - ); - -} -#endif - -#if JVET_W0090_ARMC_TM -#if JVET_AA0093_REFINED_MOTION_FOR_ARMC -void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& mvpMergeCandCtx, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, int numRetrievedMergeCand, bool subRefineList[][2], bool subRefineListTmp[][2], int mrgCandIdx) -{ - if (mvpMergeCandCtx.numValidMergeCand <= 1) - { - return; - } - if (!xAMLIsTopTempAvailable(pu) && !xAMLIsLeftTempAvailable(pu)) - { - return; - } - - const int numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand); - - uint32_t rdCandList[10]; - Distortion candCostList[10]; - for (uint32_t j = 0; j < 10; j++) - { - rdCandList[j] = j; - candCostList[j] = MAX_UINT; - } - - Distortion uiCost; - DistParam cDistParam; - cDistParam.applyWeight = false; - auto origMergeIdx = pu.mergeIdx; - for (uint32_t uiMergeCand = 0; uiMergeCand < mvpMergeCandCtx.numValidMergeCand; uiMergeCand++) - { - if (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand) - { - if (uiMergeCand > mvpMergeCandCtx.numCandToTestEnc) - { - mvpMergeCandCtx.candCost[uiMergeCand] = MAX_UINT64 - 1; - } - } -#if TM_MRG - if (( -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS - pu.cs->sps->getUseTMMrgMode() && -#endif - pu.tmMergeFlag) || (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc )) -#else - if ((mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc )) -#endif - { - uiCost = mvpMergeCandCtx.candCost[uiMergeCand]; - } - else - { - uiCost = 0; - mvpMergeCandCtx.setMergeInfo(pu, uiMergeCand); - PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], pu.lwidth(), AML_MERGE_TEMPLATE_SIZE))); - PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], pu.lwidth(), AML_MERGE_TEMPLATE_SIZE))); - PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, pu.lheight()))); - PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], pu.lheight(), AML_MERGE_TEMPLATE_SIZE))); #if JVET_Z0067_RPR_ENABLE -#if !JVET_AF0190_RPR_TMP_REORDER_LIC bool bRefIsRescaled = false; for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) { @@ -13647,210 +14078,361 @@ void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &p uiCost = std::numeric_limits<Distortion>::max(); } else -#endif { #endif + getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[1]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } +#if JVET_Z0067_RPR_ENABLE + } +#endif - getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); - if (m_bAMLTemplateAvailabe[0]) +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) { - m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); - uiCost += cDistParam.distFunc(cDistParam); + uiCost += (uiCost * nHeight) / nWidth; } - if (m_bAMLTemplateAvailabe[1]) + if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) { - m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); - uiCost += cDistParam.distFunc(cDistParam); - } -#if JVET_Z0067_RPR_ENABLE + uiCost += (uiCost * nWidth) / nHeight; } #endif - } - updateCandList(uiMergeCand, uiCost, numCandInCategory, rdCandList, candCostList); + else + { + uiCost = mvpMergeCandCtx.candCost[uiMergeCand]; + } + + updateCandList(uiMergeCand, 0, uiCost, mvpMergeCandCtx.numValidMergeCand, rdCandList, candCategory, candCostList); } pu.mergeIdx = origMergeIdx; - updateCandInOneCandidateGroup(mvpMergeCandCtx, rdCandList, applyBDMVR, mvBufBDMVR, mvBufBDMVRTmp, subRefineList, subRefineListTmp, numCandInCategory); -} + MergeCtx pairMergeCand; + pairMergeCand.numValidMergeCand = 0; + pairMergeCand.numCandToTestEnc = 0; + bool pairAdded = false; -void InterPrediction::updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, bool subRefineList[][2], bool subRefineListTmp[][2],int numCandInCategory) -{ - bool applyBDMVRTmp[10]; - MergeCtx mrgCtxTmp; - for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++) + if (mvpMergeCandCtx.numCandToTestEnc > 1) { - mrgCtxTmp.bcwIdx[uiMergeCand] = mrgCtx.bcwIdx[uiMergeCand]; - mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand]; - mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; - mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; - mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; -#if INTER_LIC - mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; -#endif -#if MULTI_HYP_PRED - mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; -#endif - if (applyBDMVR) + int cnt = 0; + int maxPairToBeAdded = std::min(mvpMergeCandCtx.numCandToTestEnc, std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand)); + + int cand1 = 0; + cnt = 0; + for (int cand2 = 1; cand2 < std::min(maxPairToBeAdded, MRG_MAX_NUM_CANDS); cand2++) { - applyBDMVRTmp[uiMergeCand] = applyBDMVR[uiMergeCand]; - } - } - //update - for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) - { - mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]]; - mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; - mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]]; + if (cand1 == cand2) + { + continue; + } + + pairMergeCand.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID); + pairMergeCand.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID); +#if JVET_AG0276_NLIC + pairMergeCand.altLMFlag[cnt] = false; + pairMergeCand.altLMParaNeighbours[cnt].resetAltLinearModel(); +#endif #if INTER_LIC - mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]]; + pairMergeCand.licFlags[cnt] = mvpMergeCandCtx.licFlags[rdCandList[0]]; #endif + pairMergeCand.bcwIdx[cnt] = mvpMergeCandCtx.bcwIdx[rdCandList[0]]; + pairMergeCand.useAltHpelIf[cnt] = mvpMergeCandCtx.useAltHpelIf[rdCandList[0]]; + pairMergeCand.candCost[cnt] = MAX_UINT64; #if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]]; -#endif - if (applyBDMVR) - { - applyBDMVR[uiMergeCand] = applyBDMVRTmp[rdCandList[uiMergeCand]]; - } - if (mvBufBDMVR && mvBufBDMVRTmp) - { - mvBufBDMVRTmp[(uiMergeCand << 1)] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1)]; - mvBufBDMVRTmp[(uiMergeCand << 1) + 1] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1) + 1]; - } - if (subRefineList && subRefineListTmp) - { - subRefineList[uiMergeCand][0] = subRefineListTmp[rdCandList[uiMergeCand]][0]; - subRefineList[uiMergeCand][1] = subRefineListTmp[rdCandList[uiMergeCand]][1]; - } - } - if (mvBufBDMVR && mvBufBDMVRTmp) - { - for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) - { - mvBufBDMVR[(uiMergeCand << 1)] = mvBufBDMVRTmp[(uiMergeCand << 1)]; - mvBufBDMVR[(uiMergeCand << 1) + 1] = mvBufBDMVRTmp[(uiMergeCand << 1) + 1]; - } - } -} -#endif + pairMergeCand.addHypNeighbours[cnt].clear(); #endif -#if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC || JVET_AA0061_IBC_MBVD || JVET_Y0058_IBC_LIST_MODIFY -bool InterPrediction::xAMLGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWidth, int nCurBlkHeight) -{ - m_bAMLTemplateAvailabe[0] = xAMLIsTopTempAvailable(pu); - m_bAMLTemplateAvailabe[1] = xAMLIsLeftTempAvailable(pu); - - if (!m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) - { - return false; - } - - /* const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; - const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); - const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat));*/ - const Picture& currPic = *pu.cs->picture; - const CPelBuf recBuf = currPic.getRecoBuf(pu.cs->picture->blocks[COMPONENT_Y]); - std::vector<Pel>& invLUT = m_pcReshape->getInvLUT(); - -#if JVET_Z0054_BLK_REF_PIC_REORDER - if(!m_fillCurTplAboveARMC) + // calculate average MV for L0 and L1 seperately + unsigned char interDir = 0; +#if JVET_AD0213_LIC_IMP + bool averageUsed = false; #endif - if (m_bAMLTemplateAvailabe[0]) - { - const Pel* rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(0, -AML_MERGE_TEMPLATE_SIZE)); - Pel* pcY = m_acYuvCurAMLTemplate[0][0]; - for (int k = 0; k < nCurBlkWidth; k++) - { - for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++) + for (int refListId = 0; refListId < (pu.cu->slice->isInterB() ? 2 : 1); refListId++) { - int recVal = rec[k + l * recBuf.stride]; + const short refIdxI = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand1] * 2 + refListId].refIdx; + const short refIdxJ = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand2] * 2 + refListId].refIdx; - if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) + // both MVs are invalid, skip + if ((refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID)) { - recVal = invLUT[recVal]; + continue; } - pcY[k + l * nCurBlkWidth] = recVal; - } - } -#if JVET_Z0054_BLK_REF_PIC_REORDER - m_fillCurTplAboveARMC = true; -#endif - } + interDir += 1 << refListId; + // both MVs are valid, average these two MVs + if ((refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID) && refIdxI == refIdxJ) + { + const Mv& mvI = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand1] * 2 + refListId].mv; + const Mv& mvJ = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand2] * 2 + refListId].mv; -#if JVET_Z0054_BLK_REF_PIC_REORDER - if(!m_fillCurTplLeftARMC) -#endif - if (m_bAMLTemplateAvailabe[1]) - { - Pel* pcY = m_acYuvCurAMLTemplate[1][0]; - const Pel* rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(-AML_MERGE_TEMPLATE_SIZE, 0)); - for (int k = 0; k < nCurBlkHeight; k++) - { - for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++) - { - int recVal = rec[recBuf.stride * k + l]; + // average two MVs + Mv avgMv = mvI; + avgMv += mvJ; + roundAffineMv(avgMv.hor, avgMv.ver, 1); - if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) + pairMergeCand.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI); +#if JVET_AD0213_LIC_IMP + averageUsed = true; +#endif + } + // only one MV is valid, take the only one MV + else if (refIdxI != NOT_VALID) { - recVal = invLUT[recVal]; + Mv singleMv = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand1] * 2 + refListId].mv; + pairMergeCand.mvFieldNeighbours[cnt * 2 + refListId].setMvField(singleMv, refIdxI); + } + else if (refIdxJ != NOT_VALID) + { + Mv singleMv = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand2] * 2 + refListId].mv; + pairMergeCand.mvFieldNeighbours[cnt * 2 + refListId].setMvField(singleMv, refIdxJ); } + } - pcY[AML_MERGE_TEMPLATE_SIZE * k + l] = recVal; + pairMergeCand.interDirNeighbours[cnt] = interDir; +#if JVET_AD0213_LIC_IMP + if (averageUsed && !(((pu.cu->slice->getPOC() - pu.cu->slice->getRefPOC(REF_PIC_LIST_0, 0)) == 1) && pu.cu->slice->getPicHeader()->getMvdL1ZeroFlag())) + { + pairMergeCand.licFlags[cnt] = false; } - } -#if JVET_Z0054_BLK_REF_PIC_REORDER - m_fillCurTplLeftARMC = true; #endif - } + + if (interDir > 0) + { +#if INTER_LIC && !JVET_AD0213_LIC_IMP + if (interDir == 3) + { + pairMergeCand.licFlags[cnt] = false; + } +#endif + uint32_t mvdSimilarityThresh = 1; + if (!pairMergeCand.xCheckSimilarMotion(cnt, mvdSimilarityThresh)) + { + if (!mvpMergeCandCtx.xCheckSimilarMotion2Lists(cnt, &pairMergeCand, mvdSimilarityThresh)) + { + pairAdded = true; + cnt++; + pairMergeCand.numValidMergeCand++; + pairMergeCand.numCandToTestEnc++; + if (pairMergeCand.numValidMergeCand == MAX_PAIR_CANDS) + { + break; + } + } #if JVET_AD0213_LIC_IMP - if (!m_fillLicTpl[COMPONENT_Y]) - { - const int precShift = std::max(0, pu.cu->slice->clpRng(COMPONENT_Y).bd - 12); - if (!precShift) + else + { + pairMergeCand.initMrgCand(cnt); + } +#endif + } +#if JVET_AD0213_LIC_IMP + else + { + pairMergeCand.initMrgCand(cnt); + } +#endif + } + } + + if (pairAdded) { - if (m_bAMLTemplateAvailabe[0]) + for (uint32_t uiMergeCand = 0; uiMergeCand < pairMergeCand.numValidMergeCand; uiMergeCand++) { - memcpy(m_pcLICRecAboveTemplate[0], m_acYuvCurAMLTemplate[0][0], nCurBlkWidth * sizeof(Pel)); + if (pairMergeCand.candCost[uiMergeCand] == MAX_UINT64) + { + uiCost = 0; + pairMergeCand.setMergeInfo(pu, uiMergeCand); + + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + + getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[1]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nHeight) / nWidth; + } + if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nWidth) / nHeight; + } + } + else + { + uiCost = pairMergeCand.candCost[uiMergeCand]; + } + updateCandList(uiMergeCand, 1, uiCost, (mvpMergeCandCtx.numValidMergeCand + pairMergeCand.numValidMergeCand), rdCandList, candCategory, candCostList); } + pu.mergeIdx = origMergeIdx; + } - if (m_bAMLTemplateAvailabe[1]) + if (altLMMergeCand.numValidMergeCand) + { + for (uint32_t uiMergeCand = 0; uiMergeCand < altLMMergeCand.numValidMergeCand; uiMergeCand++) { - memcpy(m_pcLICRecLeftTemplate[0], m_acYuvCurAMLTemplate[1][0], nCurBlkHeight * sizeof(Pel)); + if (altLMMergeCand.candCost[uiMergeCand] == MAX_UINT64) + { + uiCost = 0; + altLMMergeCand.setMergeInfo(pu, uiMergeCand); + + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + + getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[1]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nHeight) / nWidth; + } + if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nWidth) / nHeight; + } + } + else + { + uiCost = altLMMergeCand.candCost[uiMergeCand]; + } + updateCandList(uiMergeCand, 2, uiCost, (mvpMergeCandCtx.numValidMergeCand + pairMergeCand.numValidMergeCand + altLMMergeCand.numValidMergeCand), rdCandList, candCategory, candCostList); } + pu.mergeIdx = origMergeIdx; + } - m_fillLicTpl[COMPONENT_Y] = true; + Distortion cost = pu.cs->slice->getCostForARMC(); + uint32_t candToBeRemoved = NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS + ALT_MRG_MAX_NUM_CANDS; + Distortion min = MAX_UINT64; + + numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand + pairMergeCand.numValidMergeCand + altLMMergeCand.numValidMergeCand); + for (int sizeCandList = mvpMergeCandCtx.numCandToTestEnc + pairMergeCand.numValidMergeCand + altLMMergeCand.numValidMergeCand; sizeCandList > 1; sizeCandList--) + { + min = MAX_UINT64; + for (uint32_t uiMergeCand = 0; uiMergeCand < sizeCandList - 1; ++uiMergeCand) + { + if (min > abs((int)(candCostList[uiMergeCand + 1] - candCostList[uiMergeCand]))) + { + min = abs((int)(candCostList[uiMergeCand + 1] - candCostList[uiMergeCand])); + candToBeRemoved = uiMergeCand + 1; + } + } + if (min < cost) + { + uint32_t candToBeReplaced = sizeCandList - 1; + + for (uint32_t uiMergeCand = candToBeRemoved + 1; uiMergeCand < sizeCandList; ++uiMergeCand) + { + if (cost < abs((int)((int)candCostList[uiMergeCand] - (int)candCostList[candToBeRemoved]))) + { + candToBeReplaced = uiMergeCand; + break; + } + } + + if (sizeCandList > numCandInCategory) + { + candToBeReplaced = sizeCandList - 1; + } + + uint32_t rdCand = rdCandList[candToBeRemoved]; + uint32_t candGrp = candCategory[candToBeRemoved]; + Distortion candCost = candCostList[(candToBeRemoved)]; + for (int ui = candToBeRemoved; ui < (candToBeReplaced > sizeCandList - 1 ? sizeCandList - 1 : candToBeReplaced); ui++) + { + candCostList[ui] = candCostList[(ui + 1)]; + rdCandList[ui] = rdCandList[(ui + 1)]; + candCategory[ui] = candCategory[(ui + 1)]; + } + candCostList[candToBeReplaced] = candCost; + rdCandList[candToBeReplaced] = rdCand; + candCategory[candToBeReplaced] = candGrp; + } + else + { + break; + } } } -#endif + else + { + if (altLMMergeCand.numValidMergeCand) + { + for (uint32_t uiMergeCand = 0; uiMergeCand < altLMMergeCand.numValidMergeCand; uiMergeCand++) + { + if (altLMMergeCand.candCost[uiMergeCand] == MAX_UINT64) + { + uiCost = 0; + altLMMergeCand.setMergeInfo(pu, uiMergeCand); - return true; -} + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); -bool InterPrediction::xAMLIsTopTempAvailable(PredictionUnit& pu) -{ - const CodingStructure &cs = *pu.cs; - Position posRT = pu.Y().topRight(); - const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); + getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[1]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nHeight) / nWidth; + } + if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nWidth) / nHeight; + } + } + else + { + uiCost = altLMMergeCand.candCost[uiMergeCand]; + } + updateCandList(uiMergeCand, 2, uiCost, (mvpMergeCandCtx.numValidMergeCand + altLMMergeCand.numValidMergeCand), rdCandList, candCategory, candCostList); + } + pu.mergeIdx = origMergeIdx; + } + numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand + altLMMergeCand.numValidMergeCand); + } - return (puAbove && pu.cu != puAbove->cu); -} + updateCandInThreeCandidateGroups(mvpMergeCandCtx, pairMergeCand, altLMMergeCand, rdCandList, candCategory, numCandInCategory); -bool InterPrediction::xAMLIsLeftTempAvailable(PredictionUnit& pu) -{ - const CodingStructure &cs = *pu.cs; - Position posLB = pu.Y().bottomLeft(); - const PredictionUnit *puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + for (int idx = 0; idx < numCandInCategory; idx++) + { + mvpMergeCandCtx.candCost[idx] = candCostList[idx]; + } - return (puLeft && pu.cu != puLeft->cu); + mvpMergeCandCtx.numValidMergeCand = numCandInCategory; } -#endif -#if JVET_W0090_ARMC_TM || JVET_AA0070_RRIBC -void InterPrediction::updateCandList(uint32_t uiCand, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, Distortion* candCostList) +void InterPrediction::updateCandList(uint32_t uiCand, uint32_t uiCandGrp, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, uint32_t* rdCandGrpList, Distortion* candCostList) { uint32_t i; uint32_t shift = 0; @@ -13865,937 +14447,2271 @@ void InterPrediction::updateCandList(uint32_t uiCand, Distortion uiCost, uint32_ for (i = 1; i < shift; i++) { rdCandList[uiMrgCandNum - i] = rdCandList[uiMrgCandNum - 1 - i]; + rdCandGrpList[uiMrgCandNum - i] = rdCandGrpList[uiMrgCandNum - 1 - i]; candCostList[uiMrgCandNum - i] = candCostList[uiMrgCandNum - 1 - i]; } rdCandList[uiMrgCandNum - shift] = uiCand; + rdCandGrpList[uiMrgCandNum - shift] = uiCandGrp; candCostList[uiMrgCandNum - shift] = uiCost; } } -#endif -#if JVET_W0090_ARMC_TM -void InterPrediction::updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MRG_MAX_NUM_CANDS], int mrgCandIdx) +void InterPrediction::updateCandInThreeCandidateGroups(MergeCtx& mrgCtx, MergeCtx mrgCtx2, MergeCtx mrgCtx3, uint32_t* rdCandList, uint32_t* rdCandGrpList, int numCandInCategory) { MergeCtx mrgCtxTmp; - for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS; ++ui) + for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++) { - mrgCtxTmp.bcwIdx[ui] = BCW_DEFAULT; - mrgCtxTmp.interDirNeighbours[ui] = 0; - mrgCtxTmp.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; - mrgCtxTmp.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; - mrgCtxTmp.useAltHpelIf[ui] = false; -#if INTER_LIC - mrgCtxTmp.licFlags[ui] = false; + mrgCtxTmp.bcwIdx[uiMergeCand] = mrgCtx.bcwIdx[uiMergeCand]; + mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand]; + mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; + mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; + mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; + mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand]; + mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand]; +#if INTER_LIC + mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; #endif #if MULTI_HYP_PRED - mrgCtxTmp.addHypNeighbours[ui].clear(); + mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; #endif } - for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE)*ADAPTIVE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE)); ++uiMergeCand) + //update + for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) { - bool firstGroup = (uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE) == 0 ? true : false; - bool lastGroup = ((uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE >= mrgCtx.numValidMergeCand) ? true : false; - if (lastGroup && !firstGroup) + if (rdCandGrpList[uiMergeCand] == 2) { - break; + mrgCtx.bcwIdx[uiMergeCand] = mrgCtx3.bcwIdx[rdCandList[uiMergeCand]]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtx3.interDirNeighbours[rdCandList[uiMergeCand]]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx3.mvFieldNeighbours[rdCandList[uiMergeCand] << 1]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx3.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; + mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtx3.useAltHpelIf[rdCandList[uiMergeCand]]; + mrgCtx.altLMFlag[uiMergeCand] = mrgCtx3.altLMFlag[rdCandList[uiMergeCand]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtx3.altLMParaNeighbours[rdCandList[uiMergeCand]]; +#if INTER_LIC + mrgCtx.licFlags[uiMergeCand] = mrgCtx3.licFlags[rdCandList[uiMergeCand]]; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtx3.addHypNeighbours[rdCandList[uiMergeCand]]; +#endif + } + else if (rdCandGrpList[uiMergeCand] == 1) + { + mrgCtx.bcwIdx[uiMergeCand] = mrgCtx2.bcwIdx[rdCandList[uiMergeCand]]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtx2.interDirNeighbours[rdCandList[uiMergeCand]]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx2.mvFieldNeighbours[rdCandList[uiMergeCand] << 1]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx2.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; + mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtx2.useAltHpelIf[rdCandList[uiMergeCand]]; + mrgCtx.altLMFlag[uiMergeCand] = mrgCtx2.altLMFlag[rdCandList[uiMergeCand]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtx2.altLMParaNeighbours[rdCandList[uiMergeCand]]; +#if INTER_LIC + mrgCtx.licFlags[uiMergeCand] = mrgCtx2.licFlags[rdCandList[uiMergeCand]]; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtx2.addHypNeighbours[rdCandList[uiMergeCand]]; +#endif + } + else + { + mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; + mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]]; +#endif +#if INTER_LIC + mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]]; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]]; +#endif } + } +} +#endif + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC +void InterPrediction::updateCandInTwoCandidateGroups(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory, MergeCtx mrgCtx2) +{ + MergeCtx mrgCtxTmp; + for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++) + { mrgCtxTmp.bcwIdx[uiMergeCand] = mrgCtx.bcwIdx[uiMergeCand]; mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand]; mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand]; + mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; #endif #if MULTI_HYP_PRED mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; #endif + } //update - for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE)*ADAPTIVE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE)); ++uiMergeCand) + for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) { - bool firstGroup = (uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE) == 0 ? true : false; - bool lastGroup = ((uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE >= mrgCtx.numValidMergeCand) ? true : false; - if (lastGroup && !firstGroup) + if (rdCandList[uiMergeCand] >= mrgCtx.numValidMergeCand) { - break; - } + mrgCtx.bcwIdx[uiMergeCand] = mrgCtx2.bcwIdx[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtx2.interDirNeighbours[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx2.mvFieldNeighbours[((rdCandList[uiMergeCand] -mrgCtx.numValidMergeCand) << 1)]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx2.mvFieldNeighbours[((rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand) << 1) + 1]; + mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtx2.useAltHpelIf[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtx2.altLMFlag[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtx2.altLMParaNeighbours[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; +#endif +#if INTER_LIC + mrgCtx.licFlags[uiMergeCand] = mrgCtx2.licFlags[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtx2.addHypNeighbours[rdCandList[uiMergeCand] - mrgCtx.numValidMergeCand]; +#endif - mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; - mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE] << 1)]; - mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE] << 1) + 1]; - mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; + } + else + { + mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; + mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]]; +#endif #if INTER_LIC - mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; + mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]]; #endif #if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]]; #endif + } } } #endif -#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION -void InterPrediction::getBlkAMLRefTemplateSubTMVP(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft) -{ - Mv mvCurr; - const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; - const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); - const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat)); - if (xCheckIdenticalMotionSubTMVP(pu)) +void InterPrediction::updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory) +{ + MergeCtx mrgCtxTmp; + for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++) { - mvCurr = pu.mv[0]; - /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift; - const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift; - Mv subPelMv(horIntMv << horShift, verIntMv << verShift);*/ - Mv subPelMv = mvCurr; - clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); - CHECK(pu.refIdx[0] < 0, "invalid ref idx"); - - if (m_bAMLTemplateAvailabe[0]) - { - Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); - mvTop += subPelMv; - - clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); - -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); + mrgCtxTmp.bcwIdx[uiMergeCand] = mrgCtx.bcwIdx[uiMergeCand]; + mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand]; + mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; + mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; + mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand]; + mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand]; #endif -#else -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvTop, pcBufPredRefTop, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, - mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvTop, pcBufPredRefTop, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#if INTER_LIC + mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; #endif +#if MULTI_HYP_PRED + mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; #endif - } - if (m_bAMLTemplateAvailabe[1]) - { - Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); - mvLeft += subPelMv; - - clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); - -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); + } + //update + for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) + { + mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; + mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]]; #endif -#else #if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvLeft, pcBufPredRefLeft, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, - mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvLeft, pcBufPredRefLeft, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); + mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]]; #endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]]; #endif - } } - else +} +#endif + +void InterPrediction::adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx) +{ + uint32_t rdCandList[MRG_MAX_NUM_CANDS][MRG_MAX_NUM_CANDS]; + Distortion candCostList[MRG_MAX_NUM_CANDS][MRG_MAX_NUM_CANDS]; + + for (uint32_t i = 0; i < MRG_MAX_NUM_CANDS; i++) { - for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++) { - if (!(pu.interDir & (1 << refList))) - { - continue; - } - RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); - CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); + rdCandList[i][j] = j; + candCostList[i][j] = MAX_UINT; + } + } - m_iRefListIdx = refList; - mvCurr = pu.mv[refList]; - Mv subPelMv = mvCurr; - clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + Distortion uiCost; - if (m_bAMLTemplateAvailabe[0]) - { - Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); - mvTop += subPelMv; + DistParam cDistParam; + cDistParam.applyWeight = false; - clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + /*const SPS &sps = *pu.cs->sps; + Position puPos = pu.lumaPos();*/ + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; - PelUnitBuf pcMbBuf = - PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y())); + if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)) + { + return; + } - if (pu.interDir == 3) - { -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, - pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, - pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); -#endif -#else -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, - pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, - mvCurr); +#if JVET_X0049_ADAPT_DMVR +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t origMergeIdx = pu.mergeIdx; #else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, - pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); + uint8_t origMergeIdx = pu.mergeIdx; #endif #endif - } - else - { -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); -#endif -#else -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); -#endif -#endif - } - } - if (m_bAMLTemplateAvailabe[1]) - { - Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); - mvLeft += subPelMv; + for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE)*ADAPTIVE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE)); ++uiMergeCand) + { + bool firstGroup = (uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE) == 0 ? true : false; + bool lastGroup = ((uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE >= mrgCtx.numValidMergeCand) ? true : false; + if (lastGroup && !firstGroup) + { + break; + } + uiCost = 0; - clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + mrgCtx.setMergeInfo(pu, uiMergeCand); + PU::spanMotionInfo(pu, mrgCtx); - PelUnitBuf pcMbBuf = - PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], pcBufPredRefLeft.Y())); + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], nHeight, AML_MERGE_TEMPLATE_SIZE))); - if (pu.interDir == 3) - { -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, - true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, - true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); -#endif -#else -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, - true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, - true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); -#endif -#endif - } - else - { -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); -#endif -#else -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, - false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#if JVET_Y0128_NON_CTC +#if !JVET_AF0190_RPR_TMP_REORDER_LIC + bool bRefIsRescaled = false; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0; + bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false; + } + if ( !bRefIsRescaled ) #endif + { #endif - } - } - } + getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + if (m_bAMLTemplateAvailabe[0]) { - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y())); - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y())); - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + + uiCost += cDistParam.distFunc(cDistParam); } + if (m_bAMLTemplateAvailabe[1]) { - PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y())); - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y())); - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + + uiCost += cDistParam.distFunc(cDistParam); + } +#if JVET_Y0128_NON_CTC } - } -} #endif -#if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING -#if JVET_AA0093_ENHANCED_MMVD_EXTENSION -void InterPrediction::getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1) + + updateCandList(uiMergeCand, uiCost, ADAPTIVE_SUB_GROUP_SIZE, rdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE]); + } +#if JVET_X0049_ADAPT_DMVR + pu.mergeIdx = origMergeIdx; #else -void InterPrediction::getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft) -#endif -{ -#if JVET_AA0093_ENHANCED_MMVD_EXTENSION - bool bLoadSave = (posList0 != -1); + pu.mergeIdx = mrgCandIdx; //restore the merge index #endif - Mv mvCurr; - const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; - const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); - const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat)); + updateCandInfo(mrgCtx, rdCandList + , mrgCandIdx + ); -#if JVET_AA0093_ENHANCED_MMVD_EXTENSION - if (!bLoadSave && xCheckIdenticalMotion(pu)) -#else - if (xCheckIdenticalMotion(pu)) +} #endif - { - mvCurr = pu.mv[0]; - /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift; - const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift; - Mv subPelMv(horIntMv << horShift, verIntMv << verShift);*/ - Mv subPelMv = mvCurr; - clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); - CHECK(pu.refIdx[0] < 0, "invalid ref idx"); - if (m_bAMLTemplateAvailabe[0]) - { - Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); - mvTop += subPelMv; +#if JVET_W0090_ARMC_TM +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC +void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& mvpMergeCandCtx, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, int numRetrievedMergeCand, bool subRefineList[][2], bool subRefineListTmp[][2], int mrgCandIdx) +{ + if (mvpMergeCandCtx.numValidMergeCand <= 1) + { + return; + } + if (!xAMLIsTopTempAvailable(pu) && !xAMLIsLeftTempAvailable(pu)) + { + return; + } - clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + const int numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand); -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); -#else - xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); + uint32_t rdCandList[10]; + Distortion candCostList[10]; + for (uint32_t j = 0; j < 10; j++) + { + rdCandList[j] = j; + candCostList[j] = MAX_UINT; + } + + Distortion uiCost; + DistParam cDistParam; + cDistParam.applyWeight = false; + auto origMergeIdx = pu.mergeIdx; + for (uint32_t uiMergeCand = 0; uiMergeCand < mvpMergeCandCtx.numValidMergeCand; uiMergeCand++) + { + if (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand) + { + if (uiMergeCand > mvpMergeCandCtx.numCandToTestEnc) + { + mvpMergeCandCtx.candCost[uiMergeCand] = MAX_UINT64 - 1; + } + } +#if TM_MRG + if (( +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + pu.cs->sps->getUseTMMrgMode() && #endif + pu.tmMergeFlag) || (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc )) #else -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvTop, pcBufPredRefTop, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, - mvCurr ); -#else - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvTop, pcBufPredRefTop, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); + if ((mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc )) +#endif + { + uiCost = mvpMergeCandCtx.candCost[uiMergeCand]; + } + else + { + uiCost = 0; + mvpMergeCandCtx.setMergeInfo(pu, uiMergeCand); + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], pu.lwidth(), AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], pu.lwidth(), AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, pu.lheight()))); + PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], pu.lheight(), AML_MERGE_TEMPLATE_SIZE))); +#if JVET_Z0067_RPR_ENABLE +#if !JVET_AF0190_RPR_TMP_REORDER_LIC + bool bRefIsRescaled = false; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0; + bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false; + } + if (bRefIsRescaled) + { + uiCost = std::numeric_limits<Distortion>::max(); + } + else #endif + { #endif + + getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); } if (m_bAMLTemplateAvailabe[1]) { - Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); - mvLeft += subPelMv; - - clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } +#if JVET_Z0067_RPR_ENABLE + } +#endif + + } + updateCandList(uiMergeCand, uiCost, numCandInCategory, rdCandList, candCostList); + } + pu.mergeIdx = origMergeIdx; + + updateCandInOneCandidateGroup(mvpMergeCandCtx, rdCandList, applyBDMVR, mvBufBDMVR, mvBufBDMVRTmp, subRefineList, subRefineListTmp, numCandInCategory); +} + +void InterPrediction::updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, bool subRefineList[][2], bool subRefineListTmp[][2],int numCandInCategory) +{ + bool applyBDMVRTmp[10]; + MergeCtx mrgCtxTmp; + for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++) + { + mrgCtxTmp.bcwIdx[uiMergeCand] = mrgCtx.bcwIdx[uiMergeCand]; + mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand]; + mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; + mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; + mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand]; + mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand]; +#endif +#if INTER_LIC + mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; +#endif +#if MULTI_HYP_PRED + mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; +#endif + if (applyBDMVR) + { + applyBDMVRTmp[uiMergeCand] = applyBDMVR[uiMergeCand]; + } + } + //update + for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) + { + mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1)]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1]; + mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[rdCandList[uiMergeCand]]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]]; +#endif +#if INTER_LIC + mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[rdCandList[uiMergeCand]]; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]]; +#endif + if (applyBDMVR) + { + applyBDMVR[uiMergeCand] = applyBDMVRTmp[rdCandList[uiMergeCand]]; + } + if (mvBufBDMVR && mvBufBDMVRTmp) + { + mvBufBDMVRTmp[(uiMergeCand << 1)] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1)]; + mvBufBDMVRTmp[(uiMergeCand << 1) + 1] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1) + 1]; + } + if (subRefineList && subRefineListTmp) + { + subRefineList[uiMergeCand][0] = subRefineListTmp[rdCandList[uiMergeCand]][0]; + subRefineList[uiMergeCand][1] = subRefineListTmp[rdCandList[uiMergeCand]][1]; + } + } + if (mvBufBDMVR && mvBufBDMVRTmp) + { + for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) + { + mvBufBDMVR[(uiMergeCand << 1)] = mvBufBDMVRTmp[(uiMergeCand << 1)]; + mvBufBDMVR[(uiMergeCand << 1) + 1] = mvBufBDMVRTmp[(uiMergeCand << 1) + 1]; + } + } +} +#endif +#endif + +#if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC || JVET_AA0061_IBC_MBVD || JVET_Y0058_IBC_LIST_MODIFY +bool InterPrediction::xAMLGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWidth, int nCurBlkHeight) +{ + m_bAMLTemplateAvailabe[0] = xAMLIsTopTempAvailable(pu); + m_bAMLTemplateAvailabe[1] = xAMLIsLeftTempAvailable(pu); + + if (!m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) + { + return false; + } + + /* const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; + const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); + const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat));*/ + const Picture& currPic = *pu.cs->picture; + const CPelBuf recBuf = currPic.getRecoBuf(pu.cs->picture->blocks[COMPONENT_Y]); + std::vector<Pel>& invLUT = m_pcReshape->getInvLUT(); + +#if JVET_Z0054_BLK_REF_PIC_REORDER + if(!m_fillCurTplAboveARMC) +#endif + if (m_bAMLTemplateAvailabe[0]) + { + const Pel* rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(0, -AML_MERGE_TEMPLATE_SIZE)); + Pel* pcY = m_acYuvCurAMLTemplate[0][0]; + for (int k = 0; k < nCurBlkWidth; k++) + { + for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++) + { + int recVal = rec[k + l * recBuf.stride]; + + if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) + { + recVal = invLUT[recVal]; + } + + pcY[k + l * nCurBlkWidth] = recVal; + } + } +#if JVET_Z0054_BLK_REF_PIC_REORDER + m_fillCurTplAboveARMC = true; +#endif + } + +#if JVET_Z0054_BLK_REF_PIC_REORDER + if(!m_fillCurTplLeftARMC) +#endif + if (m_bAMLTemplateAvailabe[1]) + { + Pel* pcY = m_acYuvCurAMLTemplate[1][0]; + const Pel* rec = recBuf.bufAt(pu.blocks[COMPONENT_Y].pos().offset(-AML_MERGE_TEMPLATE_SIZE, 0)); + for (int k = 0; k < nCurBlkHeight; k++) + { + for (int l = 0; l < AML_MERGE_TEMPLATE_SIZE; l++) + { + int recVal = rec[recBuf.stride * k + l]; + + if (m_pcReshape->getSliceReshaperInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag()) + { + recVal = invLUT[recVal]; + } + + pcY[AML_MERGE_TEMPLATE_SIZE * k + l] = recVal; + } + } +#if JVET_Z0054_BLK_REF_PIC_REORDER + m_fillCurTplLeftARMC = true; +#endif + } +#if JVET_AD0213_LIC_IMP + if (!m_fillLicTpl[COMPONENT_Y]) + { + const int precShift = std::max(0, pu.cu->slice->clpRng(COMPONENT_Y).bd - 12); + if (!precShift) + { + if (m_bAMLTemplateAvailabe[0]) + { + memcpy(m_pcLICRecAboveTemplate[0], m_acYuvCurAMLTemplate[0][0], nCurBlkWidth * sizeof(Pel)); + } + + if (m_bAMLTemplateAvailabe[1]) + { + memcpy(m_pcLICRecLeftTemplate[0], m_acYuvCurAMLTemplate[1][0], nCurBlkHeight * sizeof(Pel)); + } + + m_fillLicTpl[COMPONENT_Y] = true; + } + } +#endif + + return true; +} + +bool InterPrediction::xAMLIsTopTempAvailable(PredictionUnit& pu) +{ + const CodingStructure &cs = *pu.cs; + Position posRT = pu.Y().topRight(); + const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); + + return (puAbove && pu.cu != puAbove->cu); +} + +bool InterPrediction::xAMLIsLeftTempAvailable(PredictionUnit& pu) +{ + const CodingStructure &cs = *pu.cs; + Position posLB = pu.Y().bottomLeft(); + const PredictionUnit *puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + + return (puLeft && pu.cu != puLeft->cu); +} +#endif + +#if JVET_W0090_ARMC_TM || JVET_AA0070_RRIBC +void InterPrediction::updateCandList(uint32_t uiCand, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, Distortion* candCostList) +{ + uint32_t i; + uint32_t shift = 0; + + while (shift < uiMrgCandNum && uiCost < candCostList[uiMrgCandNum - 1 - shift]) + { + shift++; + } + + if (shift != 0) + { + for (i = 1; i < shift; i++) + { + rdCandList[uiMrgCandNum - i] = rdCandList[uiMrgCandNum - 1 - i]; + candCostList[uiMrgCandNum - i] = candCostList[uiMrgCandNum - 1 - i]; + } + rdCandList[uiMrgCandNum - shift] = uiCand; + candCostList[uiMrgCandNum - shift] = uiCost; + } +} +#endif + +#if JVET_W0090_ARMC_TM +void InterPrediction::updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MRG_MAX_NUM_CANDS], int mrgCandIdx) +{ + MergeCtx mrgCtxTmp; + for (uint32_t ui = 0; ui < MRG_MAX_NUM_CANDS; ++ui) + { + mrgCtxTmp.bcwIdx[ui] = BCW_DEFAULT; + mrgCtxTmp.interDirNeighbours[ui] = 0; + mrgCtxTmp.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; + mrgCtxTmp.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; + mrgCtxTmp.useAltHpelIf[ui] = false; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[ui] = false; + mrgCtxTmp.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif +#if INTER_LIC + mrgCtxTmp.licFlags[ui] = false; +#endif +#if MULTI_HYP_PRED + mrgCtxTmp.addHypNeighbours[ui].clear(); +#endif + } + for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE)*ADAPTIVE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE)); ++uiMergeCand) + { + bool firstGroup = (uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE) == 0 ? true : false; + bool lastGroup = ((uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE >= mrgCtx.numValidMergeCand) ? true : false; + if (lastGroup && !firstGroup) + { + break; + } + mrgCtxTmp.bcwIdx[uiMergeCand] = mrgCtx.bcwIdx[uiMergeCand]; + mrgCtxTmp.interDirNeighbours[uiMergeCand] = mrgCtx.interDirNeighbours[uiMergeCand]; + mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; + mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; + mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand]; + mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand]; +#endif +#if INTER_LIC + mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; +#endif +#if MULTI_HYP_PRED + mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; +#endif + } + //update + for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE)*ADAPTIVE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE > mrgCtx.numValidMergeCand)) ? mrgCtx.numValidMergeCand : ((mrgCandIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE)); ++uiMergeCand) + { + bool firstGroup = (uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE) == 0 ? true : false; + bool lastGroup = ((uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE >= mrgCtx.numValidMergeCand) ? true : false; + if (lastGroup && !firstGroup) + { + break; + } + +#if JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR + int srcCand = RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]; + mrgCtx.bcwIdx [uiMergeCand] = mrgCtxTmp.bcwIdx [srcCand]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[srcCand]; + mrgCtx.mvFieldNeighbours [(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours [(srcCand << 1)]; + mrgCtx.mvFieldNeighbours [(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours [(srcCand << 1) + 1]; + mrgCtx.useAltHpelIf [uiMergeCand] = mrgCtxTmp.useAltHpelIf [srcCand]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[srcCand]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[srcCand]; +#endif +#if INTER_LIC + mrgCtx.licFlags [uiMergeCand] = mrgCtxTmp.licFlags [srcCand]; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours [uiMergeCand] = mrgCtxTmp.addHypNeighbours [srcCand]; +#endif +#else + mrgCtx.bcwIdx[uiMergeCand] = mrgCtxTmp.bcwIdx[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; + mrgCtx.interDirNeighbours[uiMergeCand] = mrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE] << 1)]; + mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE] << 1) + 1]; + mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; +#endif +#if INTER_LIC + mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[RdCandList[uiMergeCand / ADAPTIVE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_SUB_GROUP_SIZE]]; +#endif +#endif + } +} +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void InterPrediction::getBlkAMLRefTemplateSubTMVP(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft) +{ + Mv mvCurr; + const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; + const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); + const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat)); + + if (xCheckIdenticalMotionSubTMVP(pu)) + { + mvCurr = pu.mv[0]; + /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift; + const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift; + Mv subPelMv(horIntMv << horShift, verIntMv << verShift);*/ + Mv subPelMv = mvCurr; + clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + CHECK(pu.refIdx[0] < 0, "invalid ref idx"); + + if (m_bAMLTemplateAvailabe[0]) + { + Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); + mvTop += subPelMv; + + clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + if (m_bAMLTemplateAvailabe[1]) + { + Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); + mvLeft += subPelMv; + + clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + } + else + { + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + if (!(pu.interDir & (1 << refList))) + { + continue; + } + RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); + + m_iRefListIdx = refList; + mvCurr = pu.mv[refList]; + Mv subPelMv = mvCurr; + clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + if (m_bAMLTemplateAvailabe[0]) + { + Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); + mvTop += subPelMv; + + clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + PelUnitBuf pcMbBuf = + PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y())); + + if (pu.interDir == 3) + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, + pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, + pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, + pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, + pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + else + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + } + if (m_bAMLTemplateAvailabe[1]) + { + Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); + mvLeft += subPelMv; + + clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + PelUnitBuf pcMbBuf = + PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], pcBufPredRefLeft.Y())); + + if (pu.interDir == 3) + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + else + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + } + } + if (m_bAMLTemplateAvailabe[0]) + { + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y())); + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y())); + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); + } + if (m_bAMLTemplateAvailabe[1]) + { + PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y())); + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y())); + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); + } + } +} +#endif +#if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +void InterPrediction::getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1) +#else +void InterPrediction::getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft) +#endif +{ +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + bool bLoadSave = (posList0 != -1); +#endif + Mv mvCurr; + const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; + const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); + const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat)); + +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (!bLoadSave && xCheckIdenticalMotion(pu)) +#else + if (xCheckIdenticalMotion(pu)) +#endif + { + mvCurr = pu.mv[0]; + /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift; + const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift; + Mv subPelMv(horIntMv << horShift, verIntMv << verShift);*/ + Mv subPelMv = mvCurr; + clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + CHECK(pu.refIdx[0] < 0, "invalid ref idx"); + + if (m_bAMLTemplateAvailabe[0]) + { + Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); + mvTop += subPelMv; + + clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#endif +#else +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); +#endif +#endif +#if JVET_AG0276_NLIC + if (m_bAMLTemplateAvailabe[1]) + { + m_skipDoLic = true; + } + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif + } + if (m_bAMLTemplateAvailabe[1]) + { + Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); + mvLeft += subPelMv; + + clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#endif +#else +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); +#endif +#endif +#if JVET_AG0276_NLIC + m_skipDoLic = false; + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); + pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif + } + } + else + { +#if JVET_AD0213_LIC_IMP + const int biShift = IF_INTERNAL_PREC - pu.cu->slice->clpRng(COMPONENT_Y).bd; + const Pel biOffset = -IF_INTERNAL_OFFS; +#endif + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + if (pu.refIdx[refList] < 0) + { + continue; + } +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)) )// changed + { + continue; + } +#endif + RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); + + m_iRefListIdx = refList; + mvCurr = pu.mv[refList]; + /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift; + const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift; + Mv subPelMv(horIntMv << horShift, verIntMv << verShift);*/ + Mv subPelMv = mvCurr; + clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + if (m_bAMLTemplateAvailabe[0]) + { + Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); + mvTop += subPelMv; + + clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0; + PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0] + offsetA, pcBufPredRefTop.Y())); // changed +#else + PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y())); +#endif + + if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0) + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, + pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, + pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#endif +#else +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, true, + pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, true, + pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); +#endif +#endif + } + else + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#endif +#else +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); +#endif +#endif + } +#if JVET_AG0276_NLIC + if (m_bAMLTemplateAvailabe[1]) + { + m_skipDoLic = true; + } +#endif + } + if (m_bAMLTemplateAvailabe[1]) + { + Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); + mvLeft += subPelMv; + + clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0; + PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeft.Y())); // changed +#else + PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], pcBufPredRefLeft.Y())); +#endif + + if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0) + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio( eRefPicList, pu.refIdx[refList] ); +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + else + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#endif +#else +#if INTER_LIC + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr ); +#else + xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); +#endif +#endif + } +#if JVET_AG0276_NLIC + m_skipDoLic = false; +#endif + } + } +#if JVET_AD0213_LIC_IMP + if (pu.cu->licFlag && pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0) + { + const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y); + int cWidth = pu.Y().width; + int cHeight = pu.Y().height; + +#if !JVET_AF0190_RPR_TMP_REORDER_LIC + if (!pu.cs->sps->getRprEnabledFlag()) + { +#endif + if (m_bAMLTemplateAvailabe[0]) + { + CHECK(m_numTemplate[COMPONENT_Y][0] != cWidth, "invalid template width"); + } + if (m_bAMLTemplateAvailabe[1]) + { + CHECK(m_numTemplate[COMPONENT_Y][1] != cHeight, "invalid template height"); + } + for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++) + { + int licRefList = (licIdx % 2); + xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx); + xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y], m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]); + if (licIdx < (NUM_LIC_ITERATION - 1)) + { + if (m_numTemplate[COMPONENT_Y][0]) + { + PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + curAboveTemplate.copyFrom(aboveTemplate); + curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + if (m_numTemplate[COMPONENT_Y][1]) + { + PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + curLeftTemplate.copyFrom(leftTemplate); + curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + } + } + + for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + if (m_bAMLTemplateAvailabe[0]) + { + PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], Size(cWidth, 1))); + curSrcPred.bufs[COMPONENT_Y].toLast(clpRng); + curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng); + curSrcPred.bufs[COMPONENT_Y].linearTransform(1, -biShift, biOffset, false, clpRng); + } + if (m_bAMLTemplateAvailabe[1]) + { + PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], Size(cHeight, 1))); + curSrcPred.bufs[COMPONENT_Y].toLast(clpRng); + curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng); + curSrcPred.bufs[COMPONENT_Y].linearTransform(1, -biShift, biOffset, false, clpRng); + } + } +#if !JVET_AF0190_RPR_TMP_REORDER_LIC + } +#endif + } +#endif +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int offset0 = 0; + int offset1 = 0; + if (bLoadSave) + { + offset0 = posList0 * MAX_CU_SIZE; + offset1 = posList1 * MAX_CU_SIZE; + } + if (m_bAMLTemplateAvailabe[0]) + { + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0] + offset0, pcBufPredRefTop.Y())); // changed + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y())); // changed + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif + } + if (m_bAMLTemplateAvailabe[1]) + { + PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeftTranspose.Y())); // changed + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y())); // changed + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif + } + +#else + if (m_bAMLTemplateAvailabe[0]) + { + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y())); + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y())); + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); + } + if (m_bAMLTemplateAvailabe[1]) + { + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y())); + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y())); + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); + } +#endif + } +} +#if JVET_AD0213_LIC_IMP +void InterPrediction::getBlkAMLRefTemplateAlt(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1) +{ + bool bLoadSave = (posList0 != -1); + CHECK(!bLoadSave, "invalid bLoadSave value"); + Mv mvCurr; + const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; + const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); + const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat)); + + CHECK(pu.refIdx[REF_PIC_LIST_0] < 0 || pu.refIdx[REF_PIC_LIST_1] < 0, "the function only deals with MMVD bi-pred reordering"); + + PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); + + const int biShift = IF_INTERNAL_PREC - pu.cu->slice->clpRng(COMPONENT_Y).bd; + const Pel biOffset = -IF_INTERNAL_OFFS; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)))// changed + { + continue; + } + RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); + + m_iRefListIdx = refList; + mvCurr = pu.mv[refList]; + Mv subPelMv = mvCurr; + clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + if (m_bAMLTemplateAvailabe[0]) + { + Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); + mvTop += subPelMv; + + clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0; + PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0] + offsetA, pcBufPredRefTop.Y())); // changed #if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); + if (pu.cu->licFlag) + { + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); + pcMbBuf.bufs[0].linearTransform(1, -biShift, biOffset, false, pu.cu->slice->clpRng(COMPONENT_Y)); + } + else + { + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); + } #else - xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#endif +#if JVET_AG0276_NLIC + if (m_bAMLTemplateAvailabe[1]) + { + m_skipDoLic = true; + } +#endif + } + if (m_bAMLTemplateAvailabe[1]) + { + Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); + mvLeft += subPelMv; + + clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0; + PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeft.Y())); // changed + +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); + if (pu.cu->licFlag) + { + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); + PelUnitBuf pcMbBufTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeftTranspose.Y())); // changed + pcMbBufTranspose.bufs[0].linearTransform(1, -biShift, biOffset, false, pu.cu->slice->clpRng(COMPONENT_Y)); + } + else + { + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); + } +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#endif +#if JVET_AG0276_NLIC + m_skipDoLic = false; +#endif + } + } + + int offset0 = 0; + int offset1 = 0; + if (bLoadSave) + { + offset0 = posList0 * MAX_CU_SIZE; + offset1 = posList1 * MAX_CU_SIZE; + } + if (m_bAMLTemplateAvailabe[0]) + { + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0] + offset0, pcBufPredRefTop.Y())); // changed + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y())); // changed + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif + } + if (m_bAMLTemplateAvailabe[1]) + { + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeftTranspose.Y())); // changed + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y())); // changed + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif + } +} +#endif +#endif + +#if JVET_W0090_ARMC_TM +void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, int mrgCandIdx +#if JVET_Z0139_NA_AFF + , int sortedCandNum +#endif +) +{ +#if JVET_Z0139_NA_AFF + const uint32_t maxNumAffineMergeCand = (sortedCandNum > 0) ? sortedCandNum: pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand(); +#endif +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + uint32_t rdCandList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE][RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; + Distortion candCostList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE][RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; +#else + uint32_t rdCandList[AFFINE_MRG_MAX_NUM_CANDS][AFFINE_MRG_MAX_NUM_CANDS]; + Distortion candCostList[AFFINE_MRG_MAX_NUM_CANDS][AFFINE_MRG_MAX_NUM_CANDS]; +#endif +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + for (uint32_t i = 0; i < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; i++) + { + for (uint32_t j = 0; j < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; j++) +#else + for (uint32_t i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++) + { + for (uint32_t j = 0; j < AFFINE_MRG_MAX_NUM_CANDS; j++) +#endif + { + rdCandList[i][j] = j; + candCostList[i][j] = MAX_UINT; + } + } + + Distortion uiCost; + + DistParam cDistParam; + cDistParam.applyWeight = false; + + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + + if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)) + { + return; + } + + for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand) + { + bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false; + bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false; + if (lastGroup && !firstGroup) + { + break; + } +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + bool lowPrio = false; + if (uiMergeCand >= affMrgCtx.numAffCandToTestEnc) + { + affMrgCtx.candCost[uiMergeCand] = MAX_UINT64 >> 1; + uiCost = MAX_UINT >> 1; + lowPrio = true; + } + if (affMrgCtx.candCost[uiMergeCand] == MAX_UINT64) + { +#endif + uiCost = 0; + + // set merge information + pu.interDir = affMrgCtx.interDirNeighbours[uiMergeCand]; + pu.mergeFlag = true; + pu.regularMergeFlag = false; + pu.mergeIdx = uiMergeCand; + pu.cu->affine = true; + pu.cu->affineType = affMrgCtx.affineType[uiMergeCand]; +#if AFFINE_MMVD + pu.afMmvdFlag = false; +#endif + pu.cu->bcwIdx = affMrgCtx.bcwIdx[uiMergeCand]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affMrgCtx.altLMFlag[uiMergeCand]; + pu.cu->altLMParaUnit = affMrgCtx.altLMParaNeighbours[uiMergeCand]; #endif -#else #if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvLeft, pcBufPredRefLeft, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, - mvCurr ); + pu.cu->licFlag = affMrgCtx.licFlags[uiMergeCand]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + pu.cu->obmcFlag = affMrgCtx.obmcFlags[uiMergeCand]; +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affMrgCtx.colIdx[uiMergeCand]; +#endif + pu.mergeType = affMrgCtx.mergeType[uiMergeCand]; +#if JVET_Z0139_NA_AFF +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +#if JVET_AG0135_AFFINE_CIIP + if ((pu.cu->slice->getTLayer() < 4 && PU::checkAffineTMCondition(pu)) || ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand))) #else - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( REF_PIC_LIST_0, pu.refIdx[0] ), mvLeft, pcBufPredRefLeft, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); + if ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand)) #endif +#else + if (pu.mergeType == MRG_TYPE_DEFAULT_N) #endif - } +#else + if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) + { + pu.refIdx[0] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx; + pu.refIdx[1] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx; + PU::spanMotionInfo(pu, *affMrgCtx.mrgCtx); } else - { -#if JVET_AD0213_LIC_IMP - const int biShift = IF_INTERNAL_PREC - pu.cu->slice->clpRng(COMPONENT_Y).bd; - const Pel biOffset = -IF_INTERNAL_OFFS; #endif + { for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) { - if (pu.refIdx[refList] < 0) + for (int i = 0; i < 3; i++) { - continue; + pu.mvAffi[refList][i] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv; } -#if JVET_AA0093_ENHANCED_MMVD_EXTENSION - if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)) )// changed + pu.refIdx[refList] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx; + } + + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], nHeight, AML_MERGE_TEMPLATE_SIZE))); + +#if RPR_ENABLE && !JVET_AF0190_RPR_TMP_REORDER_LIC + bool bRefIsRescaled = false; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0; +#if JVET_Z0118_GDR + Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr; + if (refPic) { - continue; + bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps); } +#else + bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false; +#endif + } + + if ( !bRefIsRescaled ) + { #endif - RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); - CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); - - m_iRefListIdx = refList; - mvCurr = pu.mv[refList]; - /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift; - const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift; - Mv subPelMv(horIntMv << horShift, verIntMv << verShift);*/ - Mv subPelMv = mvCurr; - clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); - - if (m_bAMLTemplateAvailabe[0]) - { - Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); - mvTop += subPelMv; - - clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); - -#if JVET_AA0093_ENHANCED_MMVD_EXTENSION - int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0; - PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0] + offsetA, pcBufPredRefTop.Y())); // changed + + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx +#endif + ); + + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + + uiCost += cDistParam.distFunc(cDistParam); + } + + if (m_bAMLTemplateAvailabe[1]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + + uiCost += cDistParam.distFunc(cDistParam); + } + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nHeight) / nWidth; + } + if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nWidth) / nHeight; + } +#endif + +#if RPR_ENABLE && !JVET_AF0190_RPR_TMP_REORDER_LIC + } +#endif + } +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + } + else if (!lowPrio) + { + uiCost = affMrgCtx.candCost[uiMergeCand]; + } +#endif +#if JVET_Z0139_NA_AFF + updateCandList(uiMergeCand, uiCost, maxNumAffineMergeCand, rdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE]); #else - PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y())); + updateCandList(uiMergeCand, uiCost, ADAPTIVE_AFFINE_SUB_GROUP_SIZE, RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE]); #endif - - if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0) + } + pu.mergeIdx = mrgCandIdx; //restore the merge index +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (maxNumAffineMergeCand > 2) + { + Distortion cost = pu.cs->slice->getCostForARMC(); + uint32_t candToBeRemoved = AFFINE_MRG_MAX_NUM_CANDS - 1; + Distortion min = MAX_UINT64; + + for (int sizeCandList = maxNumAffineMergeCand; sizeCandList > 1; sizeCandList--) + { + min = MAX_UINT64; + for (uint32_t uiMergeCand = 0; uiMergeCand < sizeCandList - 1; ++uiMergeCand) + { + if (min > abs((int)(candCostList[0][uiMergeCand + 1] - candCostList[0][uiMergeCand]))) + { + min = abs((int)(candCostList[0][uiMergeCand + 1] - candCostList[0][uiMergeCand])); + candToBeRemoved = uiMergeCand + 1; + } + } + if (candToBeRemoved > AFFINE_MRG_MAX_NUM_CANDS - 2) + { + continue; + } + if (min < cost) + { + uint32_t candToBeReplaced = sizeCandList - 1; + + for (uint32_t uiMergeCand = std::min( (int) (candToBeRemoved + 1), (int) (AFFINE_MRG_MAX_NUM_CANDS - 1) ); uiMergeCand < std::min((int)sizeCandList, (int)(AFFINE_MRG_MAX_NUM_CANDS - 1)); ++uiMergeCand) + { + if (cost < abs((int)(candCostList[0][uiMergeCand] - candCostList[0][candToBeRemoved]))) { -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, - pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); + candToBeReplaced = uiMergeCand; + break; + } + } + + if (sizeCandList > maxNumAffineMergeCand) + { + candToBeReplaced = sizeCandList - 1; + } + + uint32_t rdCand = rdCandList[0][candToBeRemoved]; + Distortion candCost = candCostList[0][(candToBeRemoved)]; + for (int ui = candToBeRemoved; ui < (candToBeReplaced > sizeCandList - 1 ? sizeCandList - 1 : candToBeReplaced); ui++) + { + candCostList[0][ui] = candCostList[0][(ui + 1)]; + rdCandList[0][ui] = rdCandList[0][(ui + 1)]; + } + candCostList[0][candToBeReplaced] = candCost; + rdCandList[0][candToBeReplaced] = rdCand; + } + else + { + break; + } + } + } +#endif + updateAffineCandInfo(pu, affMrgCtx, rdCandList + , mrgCandIdx + ); + +} + +void InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + uint32_t(*RdCandList)[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE], #else - xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, - pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); + uint32_t(*RdCandList)[AFFINE_MRG_MAX_NUM_CANDS], +#endif + int mrgCandIdx) +{ + AffineMergeCtx affMrgCtxTmp; +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand() + ADDITIONAL_AFFINE_CAND_NUM; + const uint32_t outputListSize = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand(); +#else + const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand(); +#endif + for (int i = 0; i < maxNumAffineMergeCand; i++) + { + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtxTmp.mvFieldNeighbours[(i << 1) + 0][mvNum].setMvField(Mv(), -1); + affMrgCtxTmp.mvFieldNeighbours[(i << 1) + 1][mvNum].setMvField(Mv(), -1); + } + affMrgCtxTmp.interDirNeighbours[i] = 0; + affMrgCtxTmp.affineType[i] = AFFINEMODEL_4PARAM; + affMrgCtxTmp.mergeType[i] = MRG_TYPE_DEFAULT_N; + affMrgCtxTmp.bcwIdx[i] = BCW_DEFAULT; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtxTmp.colIdx[i] = 0; +#endif +#if JVET_AG0276_NLIC + affMrgCtxTmp.altLMFlag[i] = false; + affMrgCtxTmp.altLMParaNeighbours[i].resetAltLinearModel(); +#endif +#if INTER_LIC + affMrgCtxTmp.licFlags[i] = false; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtxTmp.obmcFlags[i] = true; +#endif + } + for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand) + { + bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false; + bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false; + if (lastGroup && !firstGroup) + { + break; + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum]; + affMrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum]; + } + affMrgCtxTmp.interDirNeighbours[uiMergeCand] = affMrgCtx.interDirNeighbours[uiMergeCand]; + affMrgCtxTmp.affineType[uiMergeCand] = affMrgCtx.affineType[uiMergeCand]; + affMrgCtxTmp.mergeType[uiMergeCand] = affMrgCtx.mergeType[uiMergeCand]; + affMrgCtxTmp.bcwIdx[uiMergeCand] = affMrgCtx.bcwIdx[uiMergeCand]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtxTmp.colIdx[uiMergeCand] = affMrgCtx.colIdx[uiMergeCand]; #endif -#else -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, true, - pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, - mvCurr ); -#else - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, true, - pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); +#if JVET_AG0276_NLIC + affMrgCtxTmp.altLMFlag[uiMergeCand] = affMrgCtx.altLMFlag[uiMergeCand]; + affMrgCtxTmp.altLMParaNeighbours[uiMergeCand] = affMrgCtx.altLMParaNeighbours[uiMergeCand]; #endif +#if INTER_LIC + affMrgCtxTmp.licFlags[uiMergeCand] = affMrgCtx.licFlags[uiMergeCand]; #endif - } - else - { -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); -#else - xPredInterBlk( COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtxTmp.obmcFlags[uiMergeCand] = affMrgCtx.obmcFlags[uiMergeCand]; #endif -#else -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr ); -#else - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvTop, pcMbBuf, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); + } + //update + for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand) + { + bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false; + bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false; + if (lastGroup && !firstGroup) + { + break; + } +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + if (uiMergeCand == outputListSize) + { + break; + } #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR + int srcCand = (int)RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand % ADAPTIVE_AFFINE_SUB_GROUP_SIZE]; + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(srcCand << 1) + 0][mvNum]; + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(srcCand << 1) + 1][mvNum]; + } + affMrgCtx.interDirNeighbours[uiMergeCand] = affMrgCtxTmp.interDirNeighbours[srcCand]; + affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[srcCand]; + affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[srcCand]; + affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[srcCand]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[srcCand]; #endif - } - } - if (m_bAMLTemplateAvailabe[1]) - { - Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); - mvLeft += subPelMv; - - clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); - -#if JVET_AA0093_ENHANCED_MMVD_EXTENSION - int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0; - PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeft.Y())); // changed -#else - PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], pcBufPredRefLeft.Y())); +#if JVET_AG0276_NLIC + affMrgCtx.altLMFlag[uiMergeCand] = affMrgCtxTmp.altLMFlag[srcCand]; + affMrgCtx.altLMParaNeighbours[uiMergeCand] = affMrgCtxTmp.altLMParaNeighbours[srcCand]; #endif - - if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0) - { -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio( eRefPicList, pu.refIdx[refList] ); -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, - true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); -#else - xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, - true, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#if INTER_LIC + affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[srcCand]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[uiMergeCand] = affMrgCtxTmp.obmcFlags[srcCand]; #endif #else -#if INTER_LIC - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, - true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); -#else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, - true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE] << 1) + 0][mvNum]; + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE] << 1) + 1][mvNum]; + } + affMrgCtx.interDirNeighbours[uiMergeCand] = affMrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; + affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; + affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; + affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; #endif +#if JVET_AG0276_NLIC + affMrgCtx.altLMFlag[uiMergeCand] = affMrgCtxTmp.altLMFlag[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; + affMrgCtx.altLMParaNeighbours[uiMergeCand] = affMrgCtxTmp.altLMParaNeighbours[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; #endif - } - else - { -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr ); -#else - xPredInterBlk( COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, scalingRatio, 0, 0, false, NULL, 0, true ); +#if INTER_LIC + affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; #endif -#else -#if INTER_LIC - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvLeft, pcMbBuf, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr ); -#else - xPredInterBlk( COMPONENT_Y, pu, pu.cu->slice->getRefPic( eRefPicList, pu.refIdx[refList] ), mvLeft, pcMbBuf, - false, pu.cu->slice->clpRng( COMPONENT_Y ), false, false, SCALE_1X, 0, 0, false, NULL, 0, true ); +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[uiMergeCand] = affMrgCtxTmp.obmcFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand % ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; #endif #endif - } - } - } -#if JVET_AD0213_LIC_IMP - if (pu.cu->licFlag && pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0) - { - const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y); - int cWidth = pu.Y().width; - int cHeight = pu.Y().height; + } +} -#if !JVET_AF0190_RPR_TMP_REORDER_LIC - if (!pu.cs->sps->getRprEnabledFlag()) - { -#endif - if (m_bAMLTemplateAvailabe[0]) - { - CHECK(m_numTemplate[COMPONENT_Y][0] != cWidth, "invalid template width"); - } - if (m_bAMLTemplateAvailabe[1]) - { - CHECK(m_numTemplate[COMPONENT_Y][1] != cHeight, "invalid template height"); - } - for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++) - { - int licRefList = (licIdx % 2); - xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx); - xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y], m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]); - if (licIdx < (NUM_LIC_ITERATION - 1)) - { - if (m_numTemplate[COMPONENT_Y][0]) - { - PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); - PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); - curAboveTemplate.copyFrom(aboveTemplate); - curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); - } - if (m_numTemplate[COMPONENT_Y][1]) - { - PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); - PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); - curLeftTemplate.copyFrom(leftTemplate); - curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); - } - } - } +#if JVET_AG0276_NLIC +void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, AltLMAffineMergeCtx& altLMAffMrgCtx, AltLMAffineMergeCtx& altLMRMVFMrgCtx) +{ + const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand(); - for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) - { - if (m_bAMLTemplateAvailabe[0]) - { - PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], Size(cWidth, 1))); - curSrcPred.bufs[COMPONENT_Y].toLast(clpRng); - curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng); - curSrcPred.bufs[COMPONENT_Y].linearTransform(1, -biShift, biOffset, false, clpRng); - } - if (m_bAMLTemplateAvailabe[1]) - { - PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], Size(cHeight, 1))); - curSrcPred.bufs[COMPONENT_Y].toLast(clpRng); - curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng); - curSrcPred.bufs[COMPONENT_Y].linearTransform(1, -biShift, biOffset, false, clpRng); - } - } -#if !JVET_AF0190_RPR_TMP_REORDER_LIC - } -#endif - } -#endif -#if JVET_AA0093_ENHANCED_MMVD_EXTENSION - int offset0 = 0; - int offset1 = 0; - if (bLoadSave) - { - offset0 = posList0 * MAX_CU_SIZE; - offset1 = posList1 * MAX_CU_SIZE; - } - if (m_bAMLTemplateAvailabe[0]) - { - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0] + offset0, pcBufPredRefTop.Y())); // changed - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y())); // changed - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); - } - if (m_bAMLTemplateAvailabe[1]) + AffineMergeCtx altLMAffMergeCand; + altLMAffMergeCand.numValidMergeCand = 0; + altLMAffMergeCand.numAffCandToTestEnc = 0; + for (uint32_t mrgIdx = 0; mrgIdx < altLMAffMrgCtx.numValidMergeCand; mrgIdx++) + { + altLMAffMergeCand.altLMFlag[altLMAffMergeCand.numValidMergeCand] = true; + altLMAffMergeCand.altLMParaNeighbours[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.altLMParaNeighbours[mrgIdx]; + altLMAffMergeCand.licFlags[altLMAffMergeCand.numValidMergeCand] = false; + altLMAffMergeCand.interDirNeighbours[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.interDirNeighbours[mrgIdx]; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + for (int i = 0; i < 3; i++) { - PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeftTranspose.Y())); // changed - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y())); // changed - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); + altLMAffMergeCand.mvFieldNeighbours[(altLMAffMergeCand.numValidMergeCand << 1) + refList][i] = altLMAffMrgCtx.mvFieldNeighbours[(mrgIdx << 1) + refList][i]; } + } + altLMAffMergeCand.mergeType[altLMAffMergeCand.numValidMergeCand] = MRG_TYPE_DEFAULT_N; + altLMAffMergeCand.affineType[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.affineType[mrgIdx]; + altLMAffMergeCand.bcwIdx[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.bcwIdx[mrgIdx]; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + altLMAffMergeCand.obmcFlags[altLMAffMergeCand.numValidMergeCand] = altLMAffMrgCtx.obmcFlags[mrgIdx]; +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + altLMAffMergeCand.colIdx[altLMAffMergeCand.numValidMergeCand] = 0; +#endif + altLMAffMergeCand.candCost[altLMAffMergeCand.numValidMergeCand] = MAX_UINT64; -#else - if (m_bAMLTemplateAvailabe[0]) - { - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y())); - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y())); - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); - } - if (m_bAMLTemplateAvailabe[1]) + altLMAffMergeCand.numValidMergeCand++; + altLMAffMergeCand.numAffCandToTestEnc++; + } + AffineMergeCtx altLMRMVFCand; + altLMRMVFCand.numValidMergeCand = 0; + altLMRMVFCand.numAffCandToTestEnc = 0; + for (uint32_t mrgIdx = 0; mrgIdx < altLMRMVFMrgCtx.numValidMergeCand; mrgIdx++) + { + if (!altLMRMVFMrgCtx.xCheckSameAffMotion(pu, mrgIdx, altLMAffMrgCtx)) + { + continue; + } + + altLMRMVFCand.altLMFlag[altLMRMVFCand.numValidMergeCand] = true; + altLMRMVFCand.altLMParaNeighbours[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.altLMParaNeighbours[mrgIdx]; + altLMRMVFCand.licFlags[altLMRMVFCand.numValidMergeCand] = false; + altLMRMVFCand.interDirNeighbours[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.interDirNeighbours[mrgIdx]; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + for (int i = 0; i < 3; i++) { - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeftTranspose.Y())); - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeftTranspose.Y())); - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); + altLMRMVFCand.mvFieldNeighbours[(altLMRMVFCand.numValidMergeCand << 1) + refList][i] = altLMRMVFMrgCtx.mvFieldNeighbours[(mrgIdx << 1) + refList][i]; } -#endif } -} -#if JVET_AD0213_LIC_IMP -void InterPrediction::getBlkAMLRefTemplateAlt(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1) -{ - bool bLoadSave = (posList0 != -1); - CHECK(!bLoadSave, "invalid bLoadSave value"); - Mv mvCurr; - const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; - const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); - const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat)); + altLMRMVFCand.mergeType[altLMRMVFCand.numValidMergeCand] = MRG_TYPE_DEFAULT_N; + altLMRMVFCand.affineType[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.affineType[mrgIdx]; + altLMRMVFCand.bcwIdx[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.bcwIdx[mrgIdx]; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + altLMRMVFCand.obmcFlags[altLMRMVFCand.numValidMergeCand] = altLMRMVFMrgCtx.obmcFlags[mrgIdx]; +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + altLMRMVFCand.colIdx[altLMRMVFCand.numValidMergeCand] = 0; +#endif + altLMRMVFCand.candCost[altLMRMVFCand.numValidMergeCand] = MAX_UINT64; - CHECK(pu.refIdx[REF_PIC_LIST_0] < 0 || pu.refIdx[REF_PIC_LIST_1] < 0, "the function only deals with MMVD bi-pred reordering"); + altLMRMVFCand.numValidMergeCand++; + altLMRMVFCand.numAffCandToTestEnc++; + } - PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); + uint32_t rdCandList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE + (ALT_AFF_MRG_MAX_NUM_CANDS << 1)]; + uint32_t candCategory[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE + (ALT_AFF_MRG_MAX_NUM_CANDS << 1)]; + Distortion candCostList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE + (ALT_AFF_MRG_MAX_NUM_CANDS << 1)]; - const int biShift = IF_INTERNAL_PREC - pu.cu->slice->clpRng(COMPONENT_Y).bd; - const Pel biOffset = -IF_INTERNAL_OFFS; - for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + for (uint32_t i = 0; i < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE + (ALT_AFF_MRG_MAX_NUM_CANDS << 1); i++) { - if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)))// changed - { - continue; - } - RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); - CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); + rdCandList[i] = MAX_UINT; + candCategory[i] = MAX_UINT; + candCostList[i] = MAX_UINT64; + } - m_iRefListIdx = refList; - mvCurr = pu.mv[refList]; - Mv subPelMv = mvCurr; - clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + Distortion uiCost; - if (m_bAMLTemplateAvailabe[0]) - { - Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); - mvTop += subPelMv; + DistParam cDistParam; + cDistParam.applyWeight = false; - clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; - int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0; - PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0] + offsetA, pcBufPredRefTop.Y())); // changed + if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)) + { + return; + } -#if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); - if (pu.cu->licFlag) + auto origMergeIdx = pu.mergeIdx; + for (uint32_t uiMergeCand = 0; uiMergeCand < affMrgCtx.numValidMergeCand; ++uiMergeCand) + { +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + bool lowPrio = false; + if (uiMergeCand >= affMrgCtx.numAffCandToTestEnc) + { + affMrgCtx.candCost[uiMergeCand] = MAX_UINT64 >> 1; + uiCost = MAX_UINT >> 1; + lowPrio = true; + } + if (affMrgCtx.candCost[uiMergeCand] == MAX_UINT64) + { +#endif + uiCost = 0; + + // set merge information + pu.interDir = affMrgCtx.interDirNeighbours[uiMergeCand]; + pu.mergeFlag = true; + pu.regularMergeFlag = false; + pu.mergeIdx = uiMergeCand; + pu.cu->affine = true; + pu.cu->affineType = affMrgCtx.affineType[uiMergeCand]; +#if AFFINE_MMVD + pu.afMmvdFlag = false; +#endif + pu.cu->bcwIdx = affMrgCtx.bcwIdx[uiMergeCand]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affMrgCtx.altLMFlag[uiMergeCand]; + pu.cu->altLMParaUnit = affMrgCtx.altLMParaNeighbours[uiMergeCand]; +#endif +#if INTER_LIC + pu.cu->licFlag = affMrgCtx.licFlags[uiMergeCand]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + pu.cu->obmcFlag = affMrgCtx.obmcFlags[uiMergeCand]; +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affMrgCtx.colIdx[uiMergeCand]; +#endif + pu.mergeType = affMrgCtx.mergeType[uiMergeCand]; +#if JVET_Z0139_NA_AFF +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand)) +#else + if (pu.mergeType == MRG_TYPE_DEFAULT_N) +#endif +#else + if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) { - xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); - pcMbBuf.bufs[0].linearTransform(1, -biShift, biOffset, false, pu.cu->slice->clpRng(COMPONENT_Y)); + pu.refIdx[0] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx; + pu.refIdx[1] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx; + PU::spanMotionInfo(pu, *affMrgCtx.mrgCtx); } else +#endif { - xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); - } + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + for (int i = 0; i < 3; i++) + { + pu.mvAffi[refList][i] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv; + } + pu.refIdx[refList] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx; + } + + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + +#if RPR_ENABLE + bool bRefIsRescaled = false; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0; +#if JVET_Z0118_GDR + Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr; + if (refPic) + { + bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps); + } #else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); + bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false; +#endif + } + if (!bRefIsRescaled) + { #endif - } - if (m_bAMLTemplateAvailabe[1]) - { - Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); - mvLeft += subPelMv; + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx +#endif + ); - clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); - int offsetA = bLoadSave ? (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE : 0; - PelUnitBuf pcMbBuf = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeft.Y())); // changed + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[1]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nHeight) / nWidth; + } + if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nWidth) / nHeight; + } +#endif #if RPR_ENABLE - const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; - const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); - if (pu.cu->licFlag) - { - xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); - PelUnitBuf pcMbBufTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0] + offsetA, pcBufPredRefLeftTranspose.Y())); // changed - pcMbBufTranspose.bufs[0].linearTransform(1, -biShift, biOffset, false, pu.cu->slice->clpRng(COMPONENT_Y)); - } - else - { - xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); - } -#else - xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); + } #endif + } +#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION + } + else if (!lowPrio) + { + uiCost = affMrgCtx.candCost[uiMergeCand]; } +#endif + updateCandList(uiMergeCand, 0, uiCost, maxNumAffineMergeCand, rdCandList, candCategory, candCostList); } + pu.mergeIdx = origMergeIdx; //restore the merge index - int offset0 = 0; - int offset1 = 0; - if (bLoadSave) - { - offset0 = posList0 * MAX_CU_SIZE; - offset1 = posList1 * MAX_CU_SIZE; - } - if (m_bAMLTemplateAvailabe[0]) - { - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0] + offset0, pcBufPredRefTop.Y())); // changed - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y())); // changed - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); - } - if (m_bAMLTemplateAvailabe[1]) + if (altLMRMVFCand.numValidMergeCand) { - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeftTranspose.Y())); // changed - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y())); // changed - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); - } -} + for (uint32_t uiMergeCand = 0; uiMergeCand < altLMRMVFCand.numValidMergeCand; uiMergeCand++) + { + if (altLMRMVFCand.candCost[uiMergeCand] == MAX_UINT64) + { + uiCost = 0; + pu.interDir = altLMRMVFCand.interDirNeighbours[uiMergeCand]; + pu.mergeFlag = true; + pu.regularMergeFlag = false; + pu.mergeIdx = uiMergeCand; + pu.cu->affine = true; + pu.cu->affineType = altLMRMVFCand.affineType[uiMergeCand]; +#if AFFINE_MMVD + pu.afMmvdFlag = false; #endif + pu.cu->bcwIdx = altLMRMVFCand.bcwIdx[uiMergeCand]; + pu.cu->altLMFlag = altLMRMVFCand.altLMFlag[uiMergeCand]; + pu.cu->altLMParaUnit = altLMRMVFCand.altLMParaNeighbours[uiMergeCand]; +#if INTER_LIC + pu.cu->licFlag = altLMRMVFCand.licFlags[uiMergeCand]; #endif - -#if JVET_W0090_ARMC_TM -void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, int mrgCandIdx -#if JVET_Z0139_NA_AFF - , int sortedCandNum +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + pu.cu->obmcFlag = altLMRMVFCand.obmcFlags[uiMergeCand]; #endif -) -{ -#if JVET_Z0139_NA_AFF - const uint32_t maxNumAffineMergeCand = (sortedCandNum > 0) ? sortedCandNum: pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand(); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = altLMRMVFCand.colIdx[uiMergeCand]; #endif -#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION - uint32_t rdCandList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE][RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; - Distortion candCostList[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE][RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; + pu.mergeType = altLMRMVFCand.mergeType[uiMergeCand]; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + for (int i = 0; i < 3; i++) + { + pu.mvAffi[refList][i] = altLMRMVFCand.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv; + } + pu.refIdx[refList] = altLMRMVFCand.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx; + } + + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + +#if RPR_ENABLE + bool bRefIsRescaled = false; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0; +#if JVET_Z0118_GDR + Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr; + if (refPic) + { + bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps); + } #else - uint32_t rdCandList[AFFINE_MRG_MAX_NUM_CANDS][AFFINE_MRG_MAX_NUM_CANDS]; - Distortion candCostList[AFFINE_MRG_MAX_NUM_CANDS][AFFINE_MRG_MAX_NUM_CANDS]; + bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false; +#endif + } + if (!bRefIsRescaled) + { #endif -#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION - for (uint32_t i = 0; i < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; i++) - { - for (uint32_t j = 0; j < RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; j++) -#else - for (uint32_t i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++) - { - for (uint32_t j = 0; j < AFFINE_MRG_MAX_NUM_CANDS; j++) + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx +#endif + ); + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[1]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + + uiCost += cDistParam.distFunc(cDistParam); + } + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nHeight) / nWidth; + } + if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nWidth) / nHeight; + } +#endif +#if RPR_ENABLE + } #endif - { - rdCandList[i][j] = j; - candCostList[i][j] = MAX_UINT; + } + else + { + uiCost = altLMRMVFCand.candCost[uiMergeCand]; + } + updateCandList(uiMergeCand, 2, uiCost, maxNumAffineMergeCand, rdCandList, candCategory, candCostList); } + pu.mergeIdx = origMergeIdx; } - Distortion uiCost; - - DistParam cDistParam; - cDistParam.applyWeight = false; - - int nWidth = pu.lumaSize().width; - int nHeight = pu.lumaSize().height; - - if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)) - { - return; - } - - for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand) + if (altLMAffMergeCand.numValidMergeCand) { - bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false; - bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false; - if (lastGroup && !firstGroup) - { - break; - } -#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION - bool lowPrio = false; - if (uiMergeCand >= affMrgCtx.numAffCandToTestEnc) - { - affMrgCtx.candCost[uiMergeCand] = MAX_UINT64 >> 1; - uiCost = MAX_UINT >> 1; - lowPrio = true; - } - if (affMrgCtx.candCost[uiMergeCand] == MAX_UINT64) + for (uint32_t uiMergeCand = 0; uiMergeCand < altLMAffMergeCand.numValidMergeCand; uiMergeCand++) { -#endif - uiCost = 0; - - // set merge information - pu.interDir = affMrgCtx.interDirNeighbours[uiMergeCand]; - pu.mergeFlag = true; - pu.regularMergeFlag = false; - pu.mergeIdx = uiMergeCand; - pu.cu->affine = true; - pu.cu->affineType = affMrgCtx.affineType[uiMergeCand]; + if (altLMAffMergeCand.candCost[uiMergeCand] == MAX_UINT64) + { + uiCost = 0; + pu.interDir = altLMAffMergeCand.interDirNeighbours[uiMergeCand]; + pu.mergeFlag = true; + pu.regularMergeFlag = false; + pu.mergeIdx = uiMergeCand; + pu.cu->affine = true; + pu.cu->affineType = altLMAffMergeCand.affineType[uiMergeCand]; #if AFFINE_MMVD - pu.afMmvdFlag = false; + pu.afMmvdFlag = false; #endif - pu.cu->bcwIdx = affMrgCtx.bcwIdx[uiMergeCand]; + pu.cu->bcwIdx = altLMAffMergeCand.bcwIdx[uiMergeCand]; + pu.cu->altLMFlag = altLMAffMergeCand.altLMFlag[uiMergeCand]; + pu.cu->altLMParaUnit = altLMAffMergeCand.altLMParaNeighbours[uiMergeCand]; #if INTER_LIC - pu.cu->licFlag = affMrgCtx.licFlags[uiMergeCand]; + pu.cu->licFlag = altLMAffMergeCand.licFlags[uiMergeCand]; #endif #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL - pu.cu->obmcFlag = affMrgCtx.obmcFlags[uiMergeCand]; -#endif -#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION - pu.colIdx = affMrgCtx.colIdx[uiMergeCand]; + pu.cu->obmcFlag = altLMAffMergeCand.obmcFlags[uiMergeCand]; #endif - pu.mergeType = affMrgCtx.mergeType[uiMergeCand]; -#if JVET_Z0139_NA_AFF #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION -#if JVET_AG0135_AFFINE_CIIP - if ((pu.cu->slice->getTLayer() < 4 && PU::checkAffineTMCondition(pu)) || ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand))) -#else - if ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand)) -#endif -#else - if (pu.mergeType == MRG_TYPE_DEFAULT_N) + pu.colIdx = altLMAffMergeCand.colIdx[uiMergeCand]; #endif -#else - if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) - { - pu.refIdx[0] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx; - pu.refIdx[1] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx; - PU::spanMotionInfo(pu, *affMrgCtx.mrgCtx); - } - else -#endif - { + pu.mergeType = altLMAffMergeCand.mergeType[uiMergeCand]; for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) { for (int i = 0; i < 3; i++) { - pu.mvAffi[refList][i] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv; + pu.mvAffi[refList][i] = altLMAffMergeCand.mvFieldNeighbours[(uiMergeCand << 1) + refList][i].mv; } - pu.refIdx[refList] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx; + pu.refIdx[refList] = altLMAffMergeCand.mvFieldNeighbours[(uiMergeCand << 1) + refList][0].refIdx; } - PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); - PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); - PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); - PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], nHeight, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredCurTop = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[0][0], nWidth, AML_MERGE_TEMPLATE_SIZE))); + PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); + PelUnitBuf pcBufPredCurLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvCurAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); -#if RPR_ENABLE && !JVET_AF0190_RPR_TMP_REORDER_LIC - bool bRefIsRescaled = false; - for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) - { - const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0; -#if JVET_Z0118_GDR - Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr; - if (refPic) +#if RPR_ENABLE + bool bRefIsRescaled = false; + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) { - bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps); - } + const RefPicList eRefPicList = refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0; +#if JVET_Z0118_GDR + Picture *refPic = pu.refIdx[refList] >= 0 ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]) : nullptr; + if (refPic) + { + bRefIsRescaled |= pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps); + } #else - bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false; + bRefIsRescaled |= (pu.refIdx[refList] >= 0) ? pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->isRefScaled(pu.cs->pps) : false; #endif - } - - if ( !bRefIsRescaled ) - { + } + if (!bRefIsRescaled) + { #endif - - getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION - , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx + , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx #endif - ); - - if (m_bAMLTemplateAvailabe[0]) - { - m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + ); + if (m_bAMLTemplateAvailabe[0]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); - uiCost += cDistParam.distFunc(cDistParam); - } + uiCost += cDistParam.distFunc(cDistParam); + } + if (m_bAMLTemplateAvailabe[1]) + { + m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); - if (m_bAMLTemplateAvailabe[1]) - { - m_pcRdCost->setDistParam(cDistParam, pcBufPredCurLeft.Y(), pcBufPredRefLeft.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); + uiCost += cDistParam.distFunc(cDistParam); + } - uiCost += cDistParam.distFunc(cDistParam); - } - #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC - if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) - { - uiCost += (uiCost * nHeight) / nWidth; + if (m_bAMLTemplateAvailabe[0] && !m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nHeight) / nWidth; + } + if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) + { + uiCost += (uiCost * nWidth) / nHeight; + } +#endif +#if RPR_ENABLE + } +#endif } - if (!m_bAMLTemplateAvailabe[0] && m_bAMLTemplateAvailabe[1]) + else { - uiCost += (uiCost * nWidth) / nHeight; + uiCost = altLMAffMergeCand.candCost[uiMergeCand]; } -#endif - -#if RPR_ENABLE && !JVET_AF0190_RPR_TMP_REORDER_LIC - } -#endif - } -#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION - } - else if (!lowPrio) - { - uiCost = affMrgCtx.candCost[uiMergeCand]; + updateCandList(uiMergeCand, 1, uiCost, maxNumAffineMergeCand, rdCandList, candCategory, candCostList); } -#endif -#if JVET_Z0139_NA_AFF - updateCandList(uiMergeCand, uiCost, maxNumAffineMergeCand, rdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE]); -#else - updateCandList(uiMergeCand, uiCost, ADAPTIVE_AFFINE_SUB_GROUP_SIZE, RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE], candCostList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE]); -#endif + pu.mergeIdx = origMergeIdx; } - pu.mergeIdx = mrgCandIdx; //restore the merge index + #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (maxNumAffineMergeCand > 2) { @@ -14808,9 +16724,9 @@ void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer min = MAX_UINT64; for (uint32_t uiMergeCand = 0; uiMergeCand < sizeCandList - 1; ++uiMergeCand) { - if (min > abs((int)(candCostList[0][uiMergeCand + 1] - candCostList[0][uiMergeCand]))) + if (min > abs((int)(candCostList[uiMergeCand + 1] - candCostList[uiMergeCand]))) { - min = abs((int)(candCostList[0][uiMergeCand + 1] - candCostList[0][uiMergeCand])); + min = abs((int)(candCostList[uiMergeCand + 1] - candCostList[uiMergeCand])); candToBeRemoved = uiMergeCand + 1; } } @@ -14822,9 +16738,9 @@ void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer { uint32_t candToBeReplaced = sizeCandList - 1; - for (uint32_t uiMergeCand = std::min( (int) (candToBeRemoved + 1), (int) (AFFINE_MRG_MAX_NUM_CANDS - 1) ); uiMergeCand < std::min((int)sizeCandList, (int)(AFFINE_MRG_MAX_NUM_CANDS - 1)); ++uiMergeCand) + for (uint32_t uiMergeCand = std::min((int)(candToBeRemoved + 1), (int)(AFFINE_MRG_MAX_NUM_CANDS - 1)); uiMergeCand < std::min((int)sizeCandList, (int)(AFFINE_MRG_MAX_NUM_CANDS - 1)); ++uiMergeCand) { - if (cost < abs((int)(candCostList[0][uiMergeCand] - candCostList[0][candToBeRemoved]))) + if (cost < abs((int)(candCostList[uiMergeCand] - candCostList[candToBeRemoved]))) { candToBeReplaced = uiMergeCand; break; @@ -14836,15 +16752,18 @@ void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer candToBeReplaced = sizeCandList - 1; } - uint32_t rdCand = rdCandList[0][candToBeRemoved]; - Distortion candCost = candCostList[0][(candToBeRemoved)]; + uint32_t rdCand = rdCandList[candToBeRemoved]; + uint32_t candGrp = candCategory[candToBeRemoved]; + Distortion candCost = candCostList[candToBeRemoved]; for (int ui = candToBeRemoved; ui < (candToBeReplaced > sizeCandList - 1 ? sizeCandList - 1 : candToBeReplaced); ui++) { - candCostList[0][ui] = candCostList[0][(ui + 1)]; - rdCandList[0][ui] = rdCandList[0][(ui + 1)]; + candCostList[ui] = candCostList[ui + 1]; + rdCandList[ui] = rdCandList[ui + 1]; + candCategory[ui] = candCategory[ui + 1]; } - candCostList[0][candToBeReplaced] = candCost; - rdCandList[0][candToBeReplaced] = rdCand; + candCostList[candToBeReplaced] = candCost; + rdCandList[candToBeReplaced] = rdCand; + candCategory[candToBeReplaced] = candGrp; } else { @@ -14853,56 +16772,15 @@ void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer } } #endif - updateAffineCandInfo(pu, affMrgCtx, rdCandList - , mrgCandIdx - ); - + updateAffineCandInThreeGrp(pu, affMrgCtx, altLMAffMergeCand, altLMRMVFCand, rdCandList, candCategory, maxNumAffineMergeCand); } -void InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, -#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION - uint32_t(*RdCandList)[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE], -#else - uint32_t(*RdCandList)[AFFINE_MRG_MAX_NUM_CANDS], -#endif - int mrgCandIdx) +void InterPrediction::updateAffineCandInThreeGrp(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, AffineMergeCtx& altLMAffMrgCtx, AffineMergeCtx& altLMAffMrgCtx1, uint32_t* rdCandList, uint32_t* rdCandGrpList, int listsize) { AffineMergeCtx affMrgCtxTmp; -#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION - const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand() + ADDITIONAL_AFFINE_CAND_NUM; - const uint32_t outputListSize = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand(); -#else - const uint32_t maxNumAffineMergeCand = pu.cs->slice->getPicHeader()->getMaxNumAffineMergeCand(); -#endif - for (int i = 0; i < maxNumAffineMergeCand; i++) - { - for (int mvNum = 0; mvNum < 3; mvNum++) - { - affMrgCtxTmp.mvFieldNeighbours[(i << 1) + 0][mvNum].setMvField(Mv(), -1); - affMrgCtxTmp.mvFieldNeighbours[(i << 1) + 1][mvNum].setMvField(Mv(), -1); - } - affMrgCtxTmp.interDirNeighbours[i] = 0; - affMrgCtxTmp.affineType[i] = AFFINEMODEL_4PARAM; - affMrgCtxTmp.mergeType[i] = MRG_TYPE_DEFAULT_N; - affMrgCtxTmp.bcwIdx[i] = BCW_DEFAULT; -#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION - affMrgCtxTmp.colIdx[i] = 0; -#endif -#if INTER_LIC - affMrgCtxTmp.licFlags[i] = false; -#endif -#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL - affMrgCtxTmp.obmcFlags[i] = true; -#endif - } - for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand) + + for (uint32_t uiMergeCand = 0; uiMergeCand < affMrgCtx.numValidMergeCand; ++uiMergeCand) { - bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false; - bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false; - if (lastGroup && !firstGroup) - { - break; - } for (int mvNum = 0; mvNum < 3; mvNum++) { affMrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum]; @@ -14915,6 +16793,8 @@ void InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION affMrgCtxTmp.colIdx[uiMergeCand] = affMrgCtx.colIdx[uiMergeCand]; #endif + affMrgCtxTmp.altLMFlag[uiMergeCand] = affMrgCtx.altLMFlag[uiMergeCand]; + affMrgCtxTmp.altLMParaNeighbours[uiMergeCand] = affMrgCtx.altLMParaNeighbours[uiMergeCand]; #if INTER_LIC affMrgCtxTmp.licFlags[uiMergeCand] = affMrgCtx.licFlags[uiMergeCand]; #endif @@ -14923,40 +16803,80 @@ void InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& #endif } //update - for (uint32_t uiMergeCand = ((mrgCandIdx < 0) ? 0 : (mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE); uiMergeCand < (((mrgCandIdx < 0) || ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE > affMrgCtx.maxNumMergeCand)) ? affMrgCtx.maxNumMergeCand : ((mrgCandIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE)); ++uiMergeCand) + for (uint32_t uiMergeCand = 0; uiMergeCand < listsize; ++uiMergeCand) { - bool firstGroup = (uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0 ? true : false; - bool lastGroup = ((uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE >= affMrgCtx.maxNumMergeCand) ? true : false; - if (lastGroup && !firstGroup) + if (rdCandGrpList[uiMergeCand] == 0) { - break; + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 0][mvNum]; + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1][mvNum]; + } + affMrgCtx.interDirNeighbours[uiMergeCand] = affMrgCtxTmp.interDirNeighbours[rdCandList[uiMergeCand]]; + affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[rdCandList[uiMergeCand]]; + affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[rdCandList[uiMergeCand]]; + affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[rdCandList[uiMergeCand]]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[rdCandList[uiMergeCand]]; +#endif + affMrgCtx.altLMFlag[uiMergeCand] = affMrgCtxTmp.altLMFlag[rdCandList[uiMergeCand]]; + affMrgCtx.altLMParaNeighbours[uiMergeCand] = affMrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand]]; +#if INTER_LIC + affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[rdCandList[uiMergeCand]]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[uiMergeCand] = affMrgCtxTmp.obmcFlags[rdCandList[uiMergeCand]]; +#endif } -#if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION - if (uiMergeCand == outputListSize) + else if (rdCandGrpList[uiMergeCand] == 2) { - break; - } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = altLMAffMrgCtx1.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 0][mvNum]; + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = altLMAffMrgCtx1.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1][mvNum]; + } + affMrgCtx.interDirNeighbours[uiMergeCand] = altLMAffMrgCtx1.interDirNeighbours[rdCandList[uiMergeCand]]; + affMrgCtx.affineType[uiMergeCand] = altLMAffMrgCtx1.affineType[rdCandList[uiMergeCand]]; + affMrgCtx.mergeType[uiMergeCand] = altLMAffMrgCtx1.mergeType[rdCandList[uiMergeCand]]; + affMrgCtx.bcwIdx[uiMergeCand] = altLMAffMrgCtx1.bcwIdx[rdCandList[uiMergeCand]]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[uiMergeCand] = altLMAffMrgCtx1.colIdx[rdCandList[uiMergeCand]]; +#endif + affMrgCtx.altLMFlag[uiMergeCand] = altLMAffMrgCtx1.altLMFlag[rdCandList[uiMergeCand]]; + affMrgCtx.altLMParaNeighbours[uiMergeCand] = altLMAffMrgCtx1.altLMParaNeighbours[rdCandList[uiMergeCand]]; +#if INTER_LIC + affMrgCtx.licFlags[uiMergeCand] = altLMAffMrgCtx1.licFlags[rdCandList[uiMergeCand]]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[uiMergeCand] = altLMAffMrgCtx1.obmcFlags[rdCandList[uiMergeCand]]; #endif - for (int mvNum = 0; mvNum < 3; mvNum++) - { - affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE] << 1) + 0][mvNum]; - affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = affMrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE] << 1) + 1][mvNum]; } - affMrgCtx.interDirNeighbours[uiMergeCand] = affMrgCtxTmp.interDirNeighbours[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; - affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; - affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; - affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; + else + { + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][mvNum] = altLMAffMrgCtx.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 0][mvNum]; + affMrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][mvNum] = altLMAffMrgCtx.mvFieldNeighbours[(rdCandList[uiMergeCand] << 1) + 1][mvNum]; + } + affMrgCtx.interDirNeighbours[uiMergeCand] = altLMAffMrgCtx.interDirNeighbours[rdCandList[uiMergeCand]]; + affMrgCtx.affineType[uiMergeCand] = altLMAffMrgCtx.affineType[rdCandList[uiMergeCand]]; + affMrgCtx.mergeType[uiMergeCand] = altLMAffMrgCtx.mergeType[rdCandList[uiMergeCand]]; + affMrgCtx.bcwIdx[uiMergeCand] = altLMAffMrgCtx.bcwIdx[rdCandList[uiMergeCand]]; #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION - affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; + affMrgCtx.colIdx[uiMergeCand] = altLMAffMrgCtx.colIdx[rdCandList[uiMergeCand]]; #endif + affMrgCtx.altLMFlag[uiMergeCand] = altLMAffMrgCtx.altLMFlag[rdCandList[uiMergeCand]]; + affMrgCtx.altLMParaNeighbours[uiMergeCand] = altLMAffMrgCtx.altLMParaNeighbours[rdCandList[uiMergeCand]]; #if INTER_LIC - affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; + affMrgCtx.licFlags[uiMergeCand] = altLMAffMrgCtx.licFlags[rdCandList[uiMergeCand]]; #endif #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL - affMrgCtx.obmcFlags[uiMergeCand] = affMrgCtxTmp.obmcFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand % ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; + affMrgCtx.obmcFlags[uiMergeCand] = altLMAffMrgCtx.obmcFlags[rdCandList[uiMergeCand]]; #endif + } } } +#endif #if JVET_AD0140_MVD_PREDICTION template <int iAbove1Left2All3> @@ -15315,11 +17235,37 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf } if (m_bAMLTemplateAvailabe[1]) { +#if JVET_AG0276_NLIC + PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); + PelBuf & dstBuf = pcBufPredRefLeftTranspose.bufs[0]; +#else PelBuf & dstBuf = pcBufPredRefLeft.bufs[0]; +#endif const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng); } } +#endif +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + + const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); + if (m_bAMLTemplateAvailabe[0]) + { + PelBuf & dstBuf = pcBufPredRefTop.bufs[0]; + dstBuf.linearTransform(scale, shift, offset, true, clpRng); + } + if (m_bAMLTemplateAvailabe[1]) + { + PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(pu.chromaFormat, PelBuf(pcBufPredRefLeft.Y().buf, pcBufPredRefLeft.Y().height, pcBufPredRefLeft.Y().width)); + PelBuf & dstBuf = pcBufPredRefLeftTranspose.bufs[0]; + dstBuf.linearTransform(scale, shift, offset, true, clpRng); + } + } #endif } else @@ -15393,8 +17339,13 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf // buffer setting PelBuf srcRecAboveTemplate(m_acYuvCurAMLTemplate[0][0], Size(cWidth, 1)); PelBuf dstRecAboveTemplate(m_pcLICRecAboveTemplate[0], Size(cWidth, 1)); +#if JVET_AG0276_NLIC + PelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(cHeight, 1)); + PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(cHeight, 1)); +#else PelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(1, cHeight)); PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(1, cHeight)); +#endif dstRecAboveTemplate.copyFrom(srcRecAboveTemplate); dstRecLeftTemplate.copyFrom(srcRecLeftTemplate); @@ -15402,8 +17353,13 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf { PelBuf srcRefAboveTemplate(m_acYuvRefAboveTemplate[refList][0], Size(cWidth, 1)); PelBuf dstRefAboveTemplate(m_pcLICRefAboveTemplate[refList][0], Size(cWidth, 1)); +#if JVET_AG0276_NLIC + PelBuf srcRefLeftTemplate(m_acYuvRefLeftTemplate[refList][0], Size(cHeight, 1)); + PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(cHeight, 1)); +#else PelBuf srcRefLeftTemplate(m_acYuvRefLeftTemplate[refList][0], Size(1, cHeight)); PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(1, cHeight)); +#endif dstRefAboveTemplate.copyFrom(srcRefAboveTemplate); dstRefLeftTemplate.copyFrom(srcRefLeftTemplate); @@ -15506,6 +17462,15 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf } xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif } if (m_bAMLTemplateAvailabe[1]) { @@ -15559,6 +17524,15 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf } xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif } } #if JVET_AD0140_MVD_PREDICTION @@ -15670,6 +17644,15 @@ void InterPrediction::getAffAMLRefTemplateAlt(PredictionUnit &pu, PelUnitBuf &pc srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y())); //changed xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefTop.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif } if (m_bAMLTemplateAvailabe[1]) { @@ -15681,6 +17664,15 @@ void InterPrediction::getAffAMLRefTemplateAlt(PredictionUnit &pu, PelUnitBuf &pc srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeftTranspose.Y())); //changed xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefLeftTranspose, pu.cu->slice->getSPS()->getBitDepths(), pu.cu->slice->clpRngs()); +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + int scale = pu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = pu.cu->altLMParaUnit.offset[0]; + pcBufPredRefLeftTranspose.Y().linearTransform(scale, shift, offset, true, pu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif } } #endif @@ -15776,6 +17768,10 @@ void InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u mrgCtxTmp.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; mrgCtxTmp.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; mrgCtxTmp.useAltHpelIf[ui] = false; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[ui] = false; + mrgCtxTmp.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtxTmp.licFlags[ui] = false; #endif @@ -15807,6 +17803,10 @@ void InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)]; mrgCtxTmp.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand]; + mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; #endif @@ -15839,6 +17839,10 @@ void InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u mrgCtx.mvFieldNeighbours[(uiMergeCand << 1)] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE] << 1)]; mrgCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mrgCtxTmp.mvFieldNeighbours[(RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE] << 1) + 1]; mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]]; +#endif #if INTER_LIC mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]]; #endif @@ -15980,6 +17984,10 @@ void InterPrediction::adjustAffineMergeCandidatesOneGroup(PredictionUnit &pu, A pu.afMmvdFlag = false; #endif pu.cu->bcwIdx = affMrgCtx.bcwIdx[uiMergeCand]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affMrgCtx.altLMFlag[uiMergeCand]; + pu.cu->altLMParaUnit = affMrgCtx.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC pu.cu->licFlag = affMrgCtx.licFlags[uiMergeCand]; #endif @@ -16081,6 +18089,10 @@ void InterPrediction::updateAffineCandInfo2(PredictionUnit &pu, AffineMergeCtx& #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION affMrgCtxTmp.colIdx[uiMergeCand] = affMrgCtx.colIdx[uiMergeCand]; #endif +#if JVET_AG0276_NLIC + affMrgCtxTmp.altLMFlag[uiMergeCand] = affMrgCtx.altLMFlag[uiMergeCand]; + affMrgCtxTmp.altLMParaNeighbours[uiMergeCand] = affMrgCtx.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC affMrgCtxTmp.licFlags[uiMergeCand] = affMrgCtx.licFlags[uiMergeCand]; #endif @@ -16100,6 +18112,10 @@ void InterPrediction::updateAffineCandInfo2(PredictionUnit &pu, AffineMergeCtx& affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]]; affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]]; affMrgCtx.bcwIdx[uiMergeCand] = affMrgCtxTmp.bcwIdx[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]]; +#if JVET_AG0276_NLIC + affMrgCtx.altLMFlag[uiMergeCand] = affMrgCtxTmp.altLMFlag[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]]; + affMrgCtx.altLMParaNeighbours[uiMergeCand] = affMrgCtxTmp.altLMParaNeighbours[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]]; +#endif #if INTER_LIC affMrgCtx.licFlags[uiMergeCand] = affMrgCtxTmp.licFlags[rdCandList[uiMergeCand / listsize][uiMergeCand%listsize]]; #endif @@ -16122,6 +18138,10 @@ void InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtxTmp.mvFieldNeighbours[( ui << 1 )].refIdx = NOT_VALID; mrgCtxTmp.mvFieldNeighbours[( ui << 1 ) + 1].refIdx = NOT_VALID; mrgCtxTmp.useAltHpelIf[ui] = false; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[ui] = false; + mrgCtxTmp.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtxTmp.licFlags[ui] = false; #endif @@ -16147,6 +18167,10 @@ void InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtxTmp.mvFieldNeighbours[( uiMergeCand << 1 )] = mrgCtx.mvFieldNeighbours[( uiMergeCand << 1 )]; mrgCtxTmp.mvFieldNeighbours[( uiMergeCand << 1 ) + 1] = mrgCtx.mvFieldNeighbours[( uiMergeCand << 1 ) + 1]; mrgCtxTmp.useAltHpelIf[uiMergeCand] = mrgCtx.useAltHpelIf[uiMergeCand]; +#if JVET_AG0276_NLIC + mrgCtxTmp.altLMFlag[uiMergeCand] = mrgCtx.altLMFlag[uiMergeCand]; + mrgCtxTmp.altLMParaNeighbours[uiMergeCand] = mrgCtx.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC mrgCtxTmp.licFlags[uiMergeCand] = mrgCtx.licFlags[uiMergeCand]; #endif @@ -16173,6 +18197,10 @@ void InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mvFieldNeighbours[( uiMergeCand << 1 )] = mrgCtxTmp.mvFieldNeighbours[RdCandList[uiMergeCand - startPos] << 1]; mrgCtx.mvFieldNeighbours[( uiMergeCand << 1 ) + 1] = mrgCtxTmp.mvFieldNeighbours[( RdCandList[uiMergeCand - startPos] << 1 ) + 1]; mrgCtx.useAltHpelIf[uiMergeCand] = mrgCtxTmp.useAltHpelIf[RdCandList[uiMergeCand - startPos]]; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[uiMergeCand] = mrgCtxTmp.altLMFlag[RdCandList[uiMergeCand - startPos]]; + mrgCtx.altLMParaNeighbours[uiMergeCand] = mrgCtxTmp.altLMParaNeighbours[RdCandList[uiMergeCand - startPos]]; +#endif #if INTER_LIC mrgCtx.licFlags[uiMergeCand] = mrgCtxTmp.licFlags[RdCandList[uiMergeCand - startPos]]; #endif @@ -16304,6 +18332,10 @@ int InterPrediction::selectOBMCmode(PredictionUnit &pu, PredictionUnit &subblock candCostList[0] = uiCost; // 1: use neighbour mv to do MC for template; +#if JVET_AG0276_NLIC + subblockPu.cu->altLMFlag = tmpPu->cu->altLMFlag; + subblockPu.cu->altLMParaUnit = tmpPu->cu->secAltLMParaUnit; +#endif #if JVET_AD0213_LIC_IMP subblockPu.cu->licFlag = tmpPu->cu->licFlag; subblockPu.cu->bcwIdx = tmpPu->cu->bcwIdx; @@ -16386,6 +18418,10 @@ int InterPrediction::selectOBMCmode(PredictionUnit &pu, PredictionUnit &subblock candCostList[0] = uiCost; // 1: use neighbour mv to do MC for template; +#if JVET_AG0276_NLIC + subblockPu.cu->altLMFlag = tmpPu->cu->altLMFlag; + subblockPu.cu->altLMParaUnit = tmpPu->cu->secAltLMParaUnit; +#endif #if JVET_AD0213_LIC_IMP subblockPu.cu->licFlag = tmpPu->cu->licFlag; subblockPu.cu->bcwIdx = tmpPu->cu->bcwIdx; @@ -16532,6 +18568,15 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB #endif #endif , true); +#endif +#if JVET_AG0276_NLIC + if (subblockPu.cu->altLMFlag) + { + int scale = subblockPu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = subblockPu.cu->altLMParaUnit.offset[0]; + pcBufPredRef.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y)); + } #endif } @@ -16565,6 +18610,16 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB #endif #endif , true); +#endif +#if JVET_AG0276_NLIC + if (subblockPu.cu->altLMFlag) + { + int scale = subblockPu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = subblockPu.cu->altLMParaUnit.offset[0]; + PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(subblockPu.chromaFormat, PelBuf(pcBufPredRef.Y().buf, pcBufPredRef.Y().height, pcBufPredRef.Y().width)); + pcBufPredRefLeftTranspose.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y)); + } #endif } } @@ -16648,6 +18703,15 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB xOBMCWeightedAverageY(subblockPu, srcPred0, srcPred1, pcBufPredRef, subblockPu.cu->slice->getSPS()->getBitDepths(), subblockPu.cu->slice->clpRngs(), tryMi); +#if JVET_AG0276_NLIC + if (subblockPu.cu->altLMFlag) + { + int scale = subblockPu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = subblockPu.cu->altLMParaUnit.offset[0]; + pcBufPredRef.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif } } else @@ -16677,6 +18741,15 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB #endif #endif , true); +#endif +#if JVET_AG0276_NLIC + if (subblockPu.cu->altLMFlag) + { + int scale = subblockPu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = subblockPu.cu->altLMParaUnit.offset[0]; + pcBufPredRef.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y)); + } #endif } } @@ -16742,6 +18815,15 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB xOBMCWeightedAverageY(subblockPu, srcPred0, srcPred1, pcBufPredRefLeftTranspose, subblockPu.cu->slice->getSPS()->getBitDepths(), subblockPu.cu->slice->clpRngs(), tryMi); +#if JVET_AG0276_NLIC + if (subblockPu.cu->altLMFlag) + { + int scale = subblockPu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = subblockPu.cu->altLMParaUnit.offset[0]; + pcBufPredRefLeftTranspose.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y)); + } +#endif } } else @@ -16771,6 +18853,16 @@ void InterPrediction::getBlkOBMCRefTemplate(PredictionUnit &subblockPu, PelUnitB #endif #endif , true); +#endif +#if JVET_AG0276_NLIC + if (subblockPu.cu->altLMFlag) + { + int scale = subblockPu.cu->altLMParaUnit.scale[0]; + int shift = 5; + int offset = subblockPu.cu->altLMParaUnit.offset[0]; + PelUnitBuf pcBufPredRefLeftTranspose = PelUnitBuf(subblockPu.chromaFormat, PelBuf(pcBufPredRef.Y().buf, pcBufPredRef.Y().height, pcBufPredRef.Y().width)); + pcBufPredRefLeftTranspose.bufs[COMPONENT_Y].linearTransform(scale, shift, offset, true, subblockPu.cu->slice->clpRng(COMPONENT_Y)); + } #endif } } @@ -17603,6 +19695,10 @@ void InterPrediction::xLocalIlluComp(const PredictionUnit& pu, Pel* recAboveTemplate = m_pcLICRecAboveTemplate; #endif int numTemplate[2] = { 0 , 0 }; // 0:Above, 1:Left +#if JVET_AG0276_NLIC + static int shift_s, scale_s, offset_s; + if (!m_skipDoLic) +#endif #if JVET_AA0146_WRAP_AROUND_FIX #if JVET_AF0190_RPR_TMP_REORDER_LIC xGetSublkTemplate(*pu.cu, compID, refPic, mv, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, wrapRef, scalingRatio); @@ -17617,7 +19713,29 @@ void InterPrediction::xLocalIlluComp(const PredictionUnit& pu, #endif int shift = 0, scale = 0, offset = 0; +#if JVET_AG0276_NLIC + if (m_skipDoLic) + { + shift = shift_s; scale = scale_s; offset = offset_s; + } + else + { +#endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + int midVal[1] = {0}; +#if JVET_AE0078_IBC_LIC_EXTENSION + xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, shift, scale, offset, nullptr, nullptr, nullptr, nullptr, midVal); +#else + xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, shift, scale, offset, midVal); +#endif + xUpdateLicModel(scale, offset, shift, midVal[0], pu.cu->licDelta); +#else xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, shift, scale, offset); +#endif +#if JVET_AG0276_NLIC + shift_s = shift; scale_s = scale; offset_s = offset; + } +#endif #if JVET_AD0213_LIC_IMP if (!biPred) { @@ -17715,7 +19833,6 @@ void InterPrediction::xGetSublkTemplate(const CodingUnit& cu, } #else const Pel* rec = recBuf.bufAt(cu.blocks[compID].pos().offset(0, -1)); - for (int k = posW; k < posW + sublkWidth; k++) { int refVal = refAboveTemplate[k]; @@ -18105,6 +20222,88 @@ void InterPrediction::xLicCompAdj(const PredictionUnit& pu, PelUnitBuf& pcYuvPre #endif } } +#if JVET_AG0276_LIC_BDOF_BDMVR +void InterPrediction::xLicCompAdjBdof(const PredictionUnit& pu, PelUnitBuf& pcYuvPred, const bool lumaOnly, const bool chromaOnly) +{ + for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++) + { + int licRefList = (licIdx % 2); + + for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++) + { + if (isLuma(ComponentID(compID)) && chromaOnly) + { + continue; + } + if (isChroma(ComponentID(compID)) && lumaOnly) + { + continue; + } + + xLicRemHighFreq(*pu.cu, compID, licIdx); + xGetLICParamGeneral(*pu.cu, ComponentID(compID), m_numTemplate[compID], m_pcLICRefLeftTemplate[licRefList][compID], m_pcLICRefAboveTemplate[licRefList][compID], m_curLICRecLeftTemplate[compID], m_curLICRecAboveTemplate[compID], m_shift[licRefList][compID], m_scale[licRefList][compID], m_offset[licRefList][compID]); + + const ClpRng& clpRng = pu.cu->slice->clpRng(ComponentID(compID)); + if (licIdx < (NUM_LIC_ITERATION - 1)) + { + if (m_numTemplate[compID][0]) + { + int cWidth = pu.blocks[compID].width; + PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][compID], Size(cWidth, 1)); + PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][compID], Size(cWidth, 1)); + curAboveTemplate.copyFrom(aboveTemplate); + curAboveTemplate.linearTransform(m_scale[licRefList][compID], m_shift[licRefList][compID], m_offset[licRefList][compID], true, clpRng); + } + if (m_numTemplate[compID][1]) + { + int cHeight = pu.blocks[compID].height; + PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][compID], Size(cHeight, 1)); + PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][compID], Size(cHeight, 1)); + curLeftTemplate.copyFrom(leftTemplate); + curLeftTemplate.linearTransform(m_scale[licRefList][compID], m_shift[licRefList][compID], m_offset[licRefList][compID], true, clpRng); + } + } + } + } + + const Pel biOffset = -IF_INTERNAL_OFFS; + for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + PelUnitBuf curSrcPred = (refList == 0) ? PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[0][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[0][2], pcYuvPred.Cr())) : + PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr())); + for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++) + { + if (isLuma(ComponentID(compID)) && chromaOnly) + { + continue; + } + if (isChroma(ComponentID(compID)) && lumaOnly) + { + continue; + } + if (compID == COMPONENT_Y) + { + curSrcPred.bufs[compID].height += ((BIO_EXTEND_SIZE + 1) << 1); + curSrcPred.bufs[compID].width += ((BIO_EXTEND_SIZE + 1) << 1); + curSrcPred.bufs[compID].stride += ((BIO_EXTEND_SIZE + 1) << 1); + curSrcPred.bufs[compID].buf = m_filteredBlockTmp[2 + refList][compID]; + } + const ClpRng& clpRng = pu.cu->slice->clpRng(ComponentID(compID)); + const int biShift = IF_INTERNAL_PREC - clpRng.bd; + curSrcPred.bufs[compID].toLast(clpRng); + curSrcPred.bufs[compID].linearTransform(m_scale[refList][compID], m_shift[refList][compID], m_offset[refList][compID], true, clpRng); + curSrcPred.bufs[compID].linearTransform(1, -biShift, biOffset, false, clpRng); + if (compID == COMPONENT_Y) + { + if (refList == 1) + { + m_fillLicTpl[compID] = false; + } + } + } + } +} +#endif #endif #if INTER_LIC || JVET_AC0112_IBC_LIC @@ -18124,6 +20323,9 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu, int* offset2, int* mean #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + , int *midVal +#endif ) { const int cuWidth = cu.blocks[compID].width; @@ -18150,6 +20352,10 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu, int recSamples[MAX_CU_SIZE] = { 0 }; int startPos = (numTemplate[0] != 0) ? numSteps : 0; #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + int sumVal = 0; + int numPels = numTemplate[0] != 0 && numTemplate[1] != 0 ? 2*numSteps : (numTemplate[0] != 0 || numTemplate[1] != 0 ? numSteps : 0); +#endif // above if (numTemplate[0] != 0) @@ -18168,6 +20374,9 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu, y += recVal; xx += refVal * refVal; xy += refVal * recVal; +#if JVET_AG0276_LIC_SLOPE_ADJUST + sumVal += refVal; +#endif } cntShift = dimShift; @@ -18190,10 +20399,19 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu, y += recVal; xx += refVal * refVal; xy += refVal * recVal; +#if JVET_AG0276_LIC_SLOPE_ADJUST + sumVal += refVal; +#endif } cntShift += (cntShift ? 1 : dimShift); } +#if JVET_AG0276_LIC_SLOPE_ADJUST + if (midVal) + { + *midVal = numPels ? PU::getMeanValue( sumVal + (numPels >> 1), numPels ) : 1 << (bitDepth - 1); + } +#endif //----- determine scale and offset ----- #if JVET_AE0078_IBC_LIC_EXTENSION @@ -18661,6 +20879,28 @@ void InterPrediction::xGenerateIbcFilterPred(PelBuf& piPred, unsigned int uiBlkW } #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST +void InterPrediction::xUpdateLicModel(int &scale, int &offset, int &shift, int midVal, int delta) +{ + if ( delta ) + { + const int dShift = 3; + delta = scale > 0 ? -delta : delta; + if ( shift < dShift ) + { + scale <<= ( dShift - shift ); + shift = dShift; + } + else if ( shift > dShift ) + { + delta <<= ( shift - dShift ); + } + scale += delta; + offset -= ( delta * midVal ) >> shift; + } +} +#endif + #if INTER_LIC template <bool trueAfalseL> void InterPrediction::xGetPredBlkTpl(const CodingUnit& cu, const ComponentID compID, const CPelBuf& refBuf, const Mv& mv, const int posW, const int posH, const int tplSize, Pel* predBlkTpl @@ -23095,11 +25335,136 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu) else #endif { +#if JVET_AG0276_LIC_FLAG_SIGNALING && JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true) + { + m_numTemplate[COMPONENT_Y][0] = 0; + m_numTemplate[COMPONENT_Y][1] = 0; + m_fillLicTpl[COMPONENT_Y] = false; + m_scale[0][COMPONENT_Y] = 1; + m_scale[1][COMPONENT_Y] = 1; + m_shift[0][COMPONENT_Y] = 0; + m_shift[1][COMPONENT_Y] = 0; + m_offset[0][COMPONENT_Y] = 0; + m_offset[1][COMPONENT_Y] = 0; + + Mv mv0Clip = pu.mv[0], mv1Clip = pu.mv[1]; + clipMv(mv0Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + clipMv(mv1Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mv0Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[0][COMPONENT_Y], m_pcLICRefAboveTemplate[0][COMPONENT_Y], + m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], true, true); + xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1]), mv1Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[1][COMPONENT_Y], m_pcLICRefAboveTemplate[1][COMPONENT_Y], + m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], false, true); + if (m_numTemplate[COMPONENT_Y][0] + m_numTemplate[COMPONENT_Y][1] > 0) + { + for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++) + { + int licRefList = (licIdx % 2); + xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx); + xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], + m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y], + m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]); + const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y); + if (licIdx < (NUM_LIC_ITERATION - 1)) + { + if (m_numTemplate[COMPONENT_Y][0]) + { + int cWidth = pu.blocks[COMPONENT_Y].width; + PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + curAboveTemplate.copyFrom(aboveTemplate); + curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + if (m_numTemplate[COMPONENT_Y][1]) + { + int cHeight = pu.blocks[COMPONENT_Y].height; + PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + curLeftTemplate.copyFrom(leftTemplate); + curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + } + } + } + } +#endif minCost = xBDMVRMvSquareSearch<false>( mvFinal_PU, minCost, pu, mvInitial_PU, BDMVR_INTME_SQUARE_SEARCH_MAX_NUM_ITERATIONS, MV_FRACTIONAL_BITS_INTERNAL, bUseMR, false ); if (minCost > 0) { +#if JVET_AG0276_LIC_FLAG_SIGNALING && JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true) + { + pu.mv[0] = mvFinal_PU[0]; + pu.mv[1] = mvFinal_PU[1]; + + m_numTemplate[COMPONENT_Y][0] = 0; + m_numTemplate[COMPONENT_Y][1] = 0; + m_fillLicTpl[COMPONENT_Y] = false; + m_scale[0][COMPONENT_Y] = 1; + m_scale[1][COMPONENT_Y] = 1; + m_shift[0][COMPONENT_Y] = 0; + m_shift[1][COMPONENT_Y] = 0; + m_offset[0][COMPONENT_Y] = 0; + m_offset[1][COMPONENT_Y] = 0; + Mv mv0Clip = pu.mv[0], mv1Clip = pu.mv[1]; + clipMv(mv0Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + clipMv(mv1Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mv0Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[0][COMPONENT_Y], m_pcLICRefAboveTemplate[0][COMPONENT_Y], + m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], true, true); + xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1]), mv1Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[1][COMPONENT_Y], m_pcLICRefAboveTemplate[1][COMPONENT_Y], + m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], false, true); + if (m_numTemplate[COMPONENT_Y][0] + m_numTemplate[COMPONENT_Y][1] > 0) + { + for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++) + { + int licRefList = (licIdx % 2); + xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx); + xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], + m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y], + m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]); + const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y); + if (licIdx < (NUM_LIC_ITERATION - 1)) + { + if (m_numTemplate[COMPONENT_Y][0]) + { + int cWidth = pu.blocks[COMPONENT_Y].width; + PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + curAboveTemplate.copyFrom(aboveTemplate); + curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + if (m_numTemplate[COMPONENT_Y][1]) + { + int cHeight = pu.blocks[COMPONENT_Y].height; + PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + curLeftTemplate.copyFrom(leftTemplate); + curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + } + } + } + } +#endif minCost = xBDMVRMvSquareSearch<true>(mvFinal_PU, minCost, pu, mvInitial_PU, 2, MV_FRACTIONAL_BITS_INTERNAL - 1, bUseMR, false); } +#if JVET_AG0276_LIC_FLAG_SIGNALING && JVET_AG0276_LIC_BDOF_BDMVR + m_numTemplate[COMPONENT_Y][0] = 0; + m_numTemplate[COMPONENT_Y][1] = 0; + m_fillLicTpl[COMPONENT_Y] = false; + m_scale[0][COMPONENT_Y] = 1; + m_scale[1][COMPONENT_Y] = 1; + m_shift[0][COMPONENT_Y] = 0; + m_shift[1][COMPONENT_Y] = 0; + m_offset[0][COMPONENT_Y] = 0; + m_offset[1][COMPONENT_Y] = 0; +#endif } #else minCost = xBDMVRMvSquareSearch( mvFinal_PU, minCost, pu, mvInitial_PU, BDMVR_INTME_SQUARE_SEARCH_MAX_NUM_ITERATIONS, MV_FRACTIONAL_BITS_INTERNAL, bUseMR, false ); @@ -23141,7 +25506,12 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu) return true; } #endif - +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag == true) + { + subPURefine = false; + } +#endif if (!subPURefine) { // span motion to subPU @@ -24232,6 +26602,12 @@ Distortion InterPrediction::xBDMVRMvSquareSearch(Mv (&curBestMv)[2], Distortion for( int nIdx = nDirectStart ; nIdx <= nDirectEnd ; nIdx++ ) { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (curBestCost == 0) + { + return curBestCost; + } +#endif int nDirect = ( nIdx + nDirectRounding ) & nDirectMask; Mv mvOffset(cSearchOffset[nDirect].getHor() << searchStepShift, cSearchOffset[nDirect].getVer() << searchStepShift); @@ -25048,6 +27424,48 @@ Distortion InterPrediction::xBDMVRGetMatchingError(const PredictionUnit& pu, con xBDMVRPreInterpolation( pu, mvCenter, searchStepShift == MV_FRACTIONAL_BITS_INTERNAL, searchStepShift == MV_FRACTIONAL_BITS_INTERNAL - 1 ); #endif doPreInterpolation = false; +#if JVET_AG0276_LIC_BDOF_BDMVR + bool applyLicToDmvr = false; + applyLicToDmvr |= (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]); +#if JVET_AG0276_LIC_FLAG_SIGNALING + applyLicToDmvr |= (pu.amvpMergeModeFlag[0] == false && pu.amvpMergeModeFlag[1] == false && pu.bmMergeFlag == false); +#endif + applyLicToDmvr &= (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true); + applyLicToDmvr &= (m_scale[0][COMPONENT_Y] != 0 && m_scale[1][COMPONENT_Y] != 0); + if (applyLicToDmvr == true) + { + const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y); + for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + if (searchStepShift == MV_FRACTIONAL_BITS_INTERNAL) + { + int dstStride = MAX_CU_SIZE + (BDMVR_INTME_RANGE << 1) + (BDMVR_SIMD_IF_FACTOR - 2); + int iWidthExt = (int)pu.lwidth() + (BDMVR_INTME_RANGE << 1); + int iHeightExt = (int)pu.lheight() + (BDMVR_INTME_RANGE << 1); + int iWidthOffset = BDMVR_SIMD_IF_FACTOR - (iWidthExt & (BDMVR_SIMD_IF_FACTOR - 1)); + iWidthOffset &= (BDMVR_SIMD_IF_FACTOR - 1); + iWidthExt += iWidthOffset; // This ensures that iWidthExt is a factor-of-n number, assuming BDMVR_SIMD_IF_FACTOR is equal to n + PelUnitBuf curSrcPred = (PelUnitBuf(pu.chromaFormat, PelBuf(m_filteredBlock[3][refList][0], dstStride, iWidthExt, iHeightExt))); + curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng); + } + if (searchStepShift == MV_FRACTIONAL_BITS_INTERNAL - 1) + { + for (int phaseIdx = 0; phaseIdx < 3; phaseIdx++) + { + int iRefStride = MAX_CU_SIZE + (BDMVR_INTME_RANGE << 1) + (BDMVR_SIMD_IF_FACTOR - 2); + int iWidthExt = (int)pu.lwidth() + 1 - (phaseIdx >> 1); + int iHeightExt = (int)pu.lheight() + 1 - ((2 - phaseIdx) >> 1); + int iWidthOffset = BDMVR_SIMD_IF_FACTOR - (iWidthExt & (BDMVR_SIMD_IF_FACTOR - 1)); + iWidthOffset &= (BDMVR_SIMD_IF_FACTOR - 1); + iWidthExt += iWidthOffset; // This ensures that iWidthExt is a factor-of-n number, assuming BDMVR_SIMD_IF_FACTOR is equal to n + PelUnitBuf curSrcPred = PelUnitBuf(pu.chromaFormat, PelBuf(m_filteredBlock[phaseIdx][refList][0], iRefStride, iWidthExt, iHeightExt)); + curSrcPred.bufs[COMPONENT_Y].linearTransform(m_scale[refList][COMPONENT_Y], m_shift[refList][COMPONENT_Y], m_offset[refList][COMPONENT_Y], true, clpRng); + } + } + } + + } +#endif } // Locate L0'a and L1's prediction blocks in pre-interpolation buffer @@ -25159,6 +27577,10 @@ void InterPrediction::xAddHypMC(PredictionUnit& pu, PelUnitBuf& predBuf, PelUnit PelUnitBuf tempBuf = m_additionalHypothesisStorage.getBuf(unitAreaFromPredBuf); const auto savedAffine = pu.cu->affine; const auto savedIMV = pu.cu->imv; +#if JVET_AG0276_NLIC + auto savedAltLMFlag = pu.cu->altLMFlag; + auto savedAltLMParaUnit = pu.cu->altLMParaUnit; +#endif #if INTER_LIC auto savedLICFlag = pu.cu->licFlag; #endif @@ -25195,6 +27617,10 @@ void InterPrediction::xAddHypMC(PredictionUnit& pu, PelUnitBuf& predBuf, PelUnit fakePredData.mv[iRefPicList] = mhData.mv; fakePredData.refIdx[iRefPicList] = iRefIdx; fakePredData.refIdx[1 - iRefPicList] = -1; +#if JVET_AG0276_NLIC + fakePredData.cu->altLMFlag = false; + fakePredData.cu->altLMParaUnit.resetAltLinearModel(); +#endif #if INTER_LIC fakePredData.cu->licFlag = mhData.licFlag; #if JVET_AD0213_LIC_IMP @@ -25212,6 +27638,10 @@ void InterPrediction::xAddHypMC(PredictionUnit& pu, PelUnitBuf& predBuf, PelUnit CHECK(mhData.weightIdx >= MULTI_HYP_PRED_NUM_WEIGHTS, "Multi Hyp: mhData.weightIdx >= MULTI_HYP_PRED_NUM_WEIGHTS"); predBuf.addHypothesisAndClip(tempBuf, g_addHypWeight[mhData.weightIdx], pu.cs->slice->clpRngs(), lumaOnly); } +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = savedAltLMFlag; + pu.cu->altLMParaUnit = savedAltLMParaUnit; +#endif #if INTER_LIC pu.cu->licFlag = savedLICFlag; #endif @@ -25255,6 +27685,7 @@ void InterPrediction::getAmvpMergeModeMergeList(PredictionUnit& pu, MvField* mvF #if !JVET_Y0128_NON_CTC const int curPoc = pu.cu->slice->getPOC(); #endif + #if JVET_AD0213_LIC_IMP bool orgLICFlag = pu.cu->licFlag; #endif @@ -25629,7 +28060,11 @@ void InterPrediction::amvpMergeModeMvRefinement(PredictionUnit& pu, MvField* mvF { #endif #if JVET_AD0213_LIC_IMP +#if JVET_AG0276_LIC_BDOF_BDMVR + if ((mergeRefPoc - curPoc) == (curPoc - amvpRefPoc)) +#else if ((mergeRefPoc - curPoc) == (curPoc - amvpRefPoc) && !pu.cu->licFlag) +#endif #else if ((mergeRefPoc - curPoc) == (curPoc - amvpRefPoc)) #endif @@ -25640,15 +28075,143 @@ void InterPrediction::amvpMergeModeMvRefinement(PredictionUnit& pu, MvField* mvF Mv mvFinal[2] = { mvInitial[0], mvInitial[1] }; Distortion curBmCost = std::numeric_limits<Distortion>::max(); #if JVET_X0049_BDMVR_SW_OPT +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true) + { + m_numTemplate[COMPONENT_Y][0] = 0; + m_numTemplate[COMPONENT_Y][1] = 0; + m_fillLicTpl[COMPONENT_Y] = false; + m_scale[0][COMPONENT_Y] = 1; + m_scale[1][COMPONENT_Y] = 1; + m_shift[0][COMPONENT_Y] = 0; + m_shift[1][COMPONENT_Y] = 0; + m_offset[0][COMPONENT_Y] = 0; + m_offset[1][COMPONENT_Y] = 0; + Mv mv0Clip = pu.mv[0], mv1Clip = pu.mv[1]; + clipMv(mv0Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + clipMv(mv1Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mv0Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[0][COMPONENT_Y], m_pcLICRefAboveTemplate[0][COMPONENT_Y], + m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], true, true); + xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1]), mv1Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[1][COMPONENT_Y], m_pcLICRefAboveTemplate[1][COMPONENT_Y], + m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], false, true); + if (m_numTemplate[COMPONENT_Y][0] + m_numTemplate[COMPONENT_Y][1] > 0) + { + for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++) + { + int licRefList = (licIdx % 2); + xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx); + xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], + m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y], + m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]); + const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y); + if (licIdx < (NUM_LIC_ITERATION - 1)) + { + if (m_numTemplate[COMPONENT_Y][0]) + { + int cWidth = pu.blocks[COMPONENT_Y].width; + PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + curAboveTemplate.copyFrom(aboveTemplate); + curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + if (m_numTemplate[COMPONENT_Y][1]) + { + int cHeight = pu.blocks[COMPONENT_Y].height; + PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + curLeftTemplate.copyFrom(leftTemplate); + curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + } + } + } + } +#endif curBmCost = xBDMVRMvSquareSearch<false>(mvFinal, curBmCost, pu, mvInitial, AMVP_MERGE_MODE_REDUCED_MV_REFINE_SEARCH_ROUND, MV_FRACTIONAL_BITS_INTERNAL, useMR, false); - curBmCost = xBDMVRMvSquareSearch<true>(mvFinal, curBmCost, pu, mvInitial, - 2, MV_FRACTIONAL_BITS_INTERNAL - 1, useMR, false); +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag == true && pu.cu->slice->getUseLIC() == true && curBmCost > 0) + { + pu.mv[0] = mvFinal[0]; + pu.mv[1] = mvFinal[1]; + m_numTemplate[COMPONENT_Y][0] = 0; + m_numTemplate[COMPONENT_Y][1] = 0; + m_fillLicTpl[COMPONENT_Y] = false; + m_scale[0][COMPONENT_Y] = 1; + m_scale[1][COMPONENT_Y] = 1; + m_shift[0][COMPONENT_Y] = 0; + m_shift[1][COMPONENT_Y] = 0; + m_offset[0][COMPONENT_Y] = 0; + m_offset[1][COMPONENT_Y] = 0; + Mv mv0Clip = pu.mv[0], mv1Clip = pu.mv[1]; + clipMv(mv0Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + clipMv(mv1Clip, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mv0Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[0][COMPONENT_Y], m_pcLICRefAboveTemplate[0][COMPONENT_Y], + m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], true, true); + xGetSublkTemplateAndRef(*pu.cu, COMPONENT_Y, *pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1]), mv1Clip, pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height, 0, 0, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[1][COMPONENT_Y], m_pcLICRefAboveTemplate[1][COMPONENT_Y], + m_pcLICRecLeftTemplate[COMPONENT_Y], m_pcLICRecAboveTemplate[COMPONENT_Y], false, true); + if (m_numTemplate[COMPONENT_Y][0] + m_numTemplate[COMPONENT_Y][1] > 0) + { + for (uint32_t licIdx = 0; licIdx < NUM_LIC_ITERATION; licIdx++) + { + int licRefList = (licIdx % 2); + xLicRemHighFreq(*pu.cu, COMPONENT_Y, licIdx); + xGetLICParamGeneral(*pu.cu, COMPONENT_Y, m_numTemplate[COMPONENT_Y], + m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], + m_curLICRecLeftTemplate[COMPONENT_Y], m_curLICRecAboveTemplate[COMPONENT_Y], + m_shift[licRefList][COMPONENT_Y], m_scale[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y]); + const ClpRng& clpRng = pu.cu->slice->clpRng(COMPONENT_Y); + if (licIdx < (NUM_LIC_ITERATION - 1)) + { + if (m_numTemplate[COMPONENT_Y][0]) + { + int cWidth = pu.blocks[COMPONENT_Y].width; + PelBuf aboveTemplate(m_pcLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + PelBuf curAboveTemplate(m_curLICRefAboveTemplate[licRefList][COMPONENT_Y], Size(cWidth, 1)); + curAboveTemplate.copyFrom(aboveTemplate); + curAboveTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + if (m_numTemplate[COMPONENT_Y][1]) + { + int cHeight = pu.blocks[COMPONENT_Y].height; + PelBuf leftTemplate(m_pcLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + PelBuf curLeftTemplate(m_curLICRefLeftTemplate[licRefList][COMPONENT_Y], Size(cHeight, 1)); + curLeftTemplate.copyFrom(leftTemplate); + curLeftTemplate.linearTransform(m_scale[licRefList][COMPONENT_Y], m_shift[licRefList][COMPONENT_Y], m_offset[licRefList][COMPONENT_Y], true, clpRng); + } + } + } + } + } +#endif +#if JVET_AG0276_LIC_BDOF_BDMVR + if (curBmCost > 0) +#endif + { + curBmCost = xBDMVRMvSquareSearch<true>(mvFinal, curBmCost, pu, mvInitial, + 2, MV_FRACTIONAL_BITS_INTERNAL - 1, useMR, false); + } #else curBmCost = xBDMVRMvSquareSearch( mvFinal, curBmCost, pu, mvInitial, AMVP_MERGE_MODE_REDUCED_MV_REFINE_SEARCH_ROUND, MV_FRACTIONAL_BITS_INTERNAL, useMR, false ); curBmCost = xBDMVRMvSquareSearch( mvFinal, curBmCost, pu, mvInitial, 2, MV_FRACTIONAL_BITS_INTERNAL - 1, useMR, false ); +#endif +#if JVET_AG0276_LIC_BDOF_BDMVR + m_numTemplate[COMPONENT_Y][0] = 0; + m_numTemplate[COMPONENT_Y][1] = 0; + m_fillLicTpl[COMPONENT_Y] = false; + m_scale[0][COMPONENT_Y] = 1; + m_scale[1][COMPONENT_Y] = 1; + m_shift[0][COMPONENT_Y] = 0; + m_shift[1][COMPONENT_Y] = 0; + m_offset[0][COMPONENT_Y] = 0; + m_offset[1][COMPONENT_Y] = 0; #endif pu.mv[refListMerge] = mvFinal[refListMerge]; pu.mv[refListAmvp] = mvFinal[refListAmvp]; @@ -27254,8 +29817,13 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP // buffer setting CPelBuf srcRecAboveTemplate(m_acYuvCurAMLTemplate[0][0], Size(cWidth, 1)); PelBuf dstRecAboveTemplate(m_pcLICRecAboveTemplate[0], Size(cWidth, 1)); +#if JVET_AG0276_NLIC + CPelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(cHeight, 1)); + PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(cHeight, 1)); +#else CPelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(1, cHeight)); PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(1, cHeight)); +#endif dstRecAboveTemplate.copyFrom(srcRecAboveTemplate); dstRecLeftTemplate.copyFrom(srcRecLeftTemplate); @@ -27270,8 +29838,13 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP CPelBuf srcRefAboveTemplate(srcTplAbovePtr[refList], Size(cWidth, 1)); PelBuf dstRefAboveTemplate(m_pcLICRefAboveTemplate[refList][0], Size(cWidth, 1)); +#if JVET_AG0276_NLIC + CPelBuf srcRefLeftTemplate(srcTplLeftPtr[refList], Size(cHeight, 1)); + PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(cHeight, 1)); +#else CPelBuf srcRefLeftTemplate(srcTplLeftPtr[refList], Size(1, cHeight)); PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(1, cHeight)); +#endif const ClpRng& clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); if (m_bAMLTemplateAvailabe[0]) @@ -27660,8 +30233,13 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP // buffer setting CPelBuf srcRecAboveTemplate(m_acYuvCurAMLTemplate[0][0], Size(cWidth, 1)); PelBuf dstRecAboveTemplate(m_pcLICRecAboveTemplate[0], Size(cWidth, 1)); +#if JVET_AG0276_NLIC + CPelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(cHeight, 1)); + PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(cHeight, 1)); +#else CPelBuf srcRecLeftTemplate(m_acYuvCurAMLTemplate[1][0], Size(1, cHeight)); PelBuf dstRecLeftTemplate(m_pcLICRecLeftTemplate[0], Size(1, cHeight)); +#endif dstRecAboveTemplate.copyFrom(srcRecAboveTemplate); dstRecLeftTemplate.copyFrom(srcRecLeftTemplate); @@ -27676,8 +30254,13 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP CPelBuf srcRefAboveTemplate(srcTplAbovePtr[refList], Size(cWidth, 1)); PelBuf dstRefAboveTemplate(m_pcLICRefAboveTemplate[refList][0], Size(cWidth, 1)); +#if JVET_AG0276_NLIC + CPelBuf srcRefLeftTemplate(srcTplLeftPtr[refList], Size(cHeight, 1)); + PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(cHeight, 1)); +#else CPelBuf srcRefLeftTemplate(srcTplLeftPtr[refList], Size(1, cHeight)); PelBuf dstRefLeftTemplate(m_pcLICRefLeftTemplate[refList][0], Size(1, cHeight)); +#endif const ClpRng& clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); if (m_bAMLTemplateAvailabe[0]) diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index f4bcf5ac6..e569089bb 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -173,6 +173,9 @@ public: bool m_isAddHypMC; #endif bool m_storeBeforeLIC; +#if JVET_AG0276_NLIC + bool m_skipDoLic; +#endif #endif #if JVET_AD0140_MVD_PREDICTION struct MvdDerivedInfo @@ -1066,6 +1069,10 @@ public: , int sortedCandNum = -1 #endif ); +#if JVET_AG0276_NLIC + void adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, AltLMAffineMergeCtx& altLMAffMrgCtx, AltLMAffineMergeCtx& altLMRMVFMrgCtx); + void updateAffineCandInThreeGrp(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, AffineMergeCtx& altLMAffMrgCtx, AffineMergeCtx& altLMAffMrgCtx1, uint32_t* rdCandList, uint32_t* rdCandGrpList, int listsize); +#endif void updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION uint32_t(*RdCandList)[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE], @@ -1146,6 +1153,9 @@ public: #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND void adjustMergeCandidates(PredictionUnit& pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand); #endif +#if JVET_AG0276_NLIC + void adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMergeCandCtx, AltLMMergeCtx& altLMMrgCtx, int numRetrievedMergeCand); +#endif #if JVET_AB0079_TM_BCW_MRG void adjustMergeCandidatesBcwIdx(PredictionUnit& pu, MergeCtx& mrgCtx, const int mergeIdx = -1); #endif @@ -1163,6 +1173,10 @@ public: void updateCandInTwoCandidateGroups(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory, MergeCtx mrgCtx2); #endif #endif +#if JVET_AG0276_NLIC + void updateCandList(uint32_t uiCand, uint32_t uiCandGrp, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, uint32_t* rdCandGrpList, Distortion* candCostList); + void updateCandInThreeCandidateGroups(MergeCtx& mrgCtx, MergeCtx mrgCtx2, MergeCtx mrgCtx3, uint32_t* rdCandList, uint32_t* rdCandGrpList, int numCandInCategory); +#endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC void adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& smvpMergeCandCtx, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, int numRetrievedMergeCand, bool subRefineList[][2] = NULL, bool subRefineListTmp[][2] = NULL, int mrgCandIdx = -1); void updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* rdCandList, bool* applyBDMVR, Mv** mvBufBDMVR, Mv** mvBufBDMVRTmp, bool subRefineList[][2] = NULL, bool subRefineListTmp[][2] = NULL, int numCandInCategory = -1); @@ -1265,11 +1279,19 @@ public: #endif #if INTER_LIC || JVET_AC0112_IBC_LIC #if JVET_AE0078_IBC_LIC_EXTENSION +#if JVET_AG0276_LIC_SLOPE_ADJUST + void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset, int* shift2 = nullptr, int* scale2 = nullptr, int* offset2 = nullptr, int* mean = nullptr, int *midVal = nullptr); +#else void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset, int* shift2 = nullptr, int* scale2 = nullptr, int* offset2 = nullptr, int* mean = nullptr); +#endif +#else +#if JVET_AG0276_LIC_SLOPE_ADJUST + void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset, int *midVal = nullptr); #else void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset); #endif #endif +#endif #if JVET_AE0159_FIBC void xGetIbcFilterRefBuf(PelBuf& piPred, CodingUnit* pcCU, const ComponentID compID, const Mv& mv, unsigned int uiBlkWidth, unsigned int uiBlkHeight ); void xCalIbcFilterParam(PelBuf& piPred, CodingUnit* pcCU, const ComponentID compID, const Mv& mv, unsigned int uiBlkWidth, unsigned int uiBlkHeight ); @@ -1301,6 +1323,9 @@ public: void setLicParam(int refList, int compID, int& licScale, int& licOffset) { licScale = m_scale[refList][compID]; licOffset = m_offset[refList][compID]; } void resetFillLicTpl() { m_fillLicTpl[COMPONENT_Y] = m_fillLicTpl[COMPONENT_Cb] = m_fillLicTpl[COMPONENT_Cr] = false; } void xLicCompAdj(const PredictionUnit& pu, PelUnitBuf& pcYuvPred, const bool lumaOnly, const bool chromaOnly); +#if JVET_AG0276_LIC_BDOF_BDMVR + void xLicCompAdjBdof(const PredictionUnit& pu, PelUnitBuf& pcYuvPred, const bool lumaOnly, const bool chromaOnly); +#endif #endif template <bool trueAfalseL> void xGetPredBlkTpl(const CodingUnit& cu, const ComponentID compID, const CPelBuf& refBuf, const Mv& mv, const int posW, const int posH, const int tplSize, Pel* predBlkTpl @@ -1313,6 +1338,9 @@ public: #endif ); #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + void xUpdateLicModel (int &scale, int &offset, int &shift, int midVal, int delta); +#endif #if JVET_AC0112_IBC_LIC void xGetSublkTemplate (const CodingUnit& cu, const ComponentID compID, const Mv& bv, const int sublkWidth, const int sublkHeight, const int posW, const int posH, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate); @@ -1509,6 +1537,141 @@ public: void setFillCurTplLeftARMC(bool b) { m_fillCurTplLeftARMC = b; } #endif +#if JVET_AG0276_NLIC +public: + void xPredWoRefinement(PredictionUnit& pu, PelUnitBuf &pcYuvPred, const bool luma = true, const bool chroma = true); +#if JVET_AG0276_LIC_FLAG_SIGNALING + template <bool isBRcand> +#endif + void xDevSecLicPara(CodingUnit& cu, PelUnitBuf& predBuf, PelUnitBuf& dstBuf) + { + for (int comp = 0; comp < MAX_NUM_COMPONENT; comp++) + { + ComponentID compID = ComponentID(comp); + Pel* pred = predBuf.get(compID).buf; + int predStride = predBuf.get(compID).stride; + Pel* rec = dstBuf.get(compID).buf; + int recStride = dstBuf.get(compID).stride; + + const int cuWidth = cu.blocks[compID].width; + const int cuHeight = cu.blocks[compID].height; + + const int bitDepth = cu.cs->sps->getBitDepth(toChannelType(compID)); + const int precShift = std::max(0, bitDepth - 12); +#if JVET_AG0276_LIC_FLAG_SIGNALING + const int maxNumMinus1 = isBRcand ? (30 - 2 * std::min(bitDepth, 12) - 1) : (30 - 2 * std::min(bitDepth, 12)); +#else + const int maxNumMinus1 = 30 - 2 * std::min(bitDepth, 12); +#endif + const int minDimBit = floorLog2(std::min(cuHeight, cuWidth)); + const int minDim = 1 << minDimBit; + int minStepBit = minDim > 8 ? 1 : 0; +#if JVET_AG0276_LIC_FLAG_SIGNALING + while (isBRcand ? (minDimBit > minStepBit + maxNumMinus1) : (((minDimBit - minStepBit) << 1) > maxNumMinus1)) +#else + while (((minDimBit - minStepBit) << 1) > maxNumMinus1) +#endif + { minStepBit++; } //make sure 2*log2(minDim/tmpStep) + 2*min(bitDepth,12) <= 30 + const int numSteps = minDim >> minStepBit; + const int dimShift = minDimBit - minStepBit; + + //----- get correlation data ----- + int x = 0, y = 0, xx = 0, xy = 0; +#if JVET_AG0276_LIC_FLAG_SIGNALING + int cntShift = 0; + if (isBRcand) + { + Pel* refBottom = pred + (cuHeight - 1) * predStride; + Pel* recBottom = rec + (cuHeight - 1) * recStride; + for (int k = 0; k < numSteps; k++) + { + int idx = (k * cuWidth) >> dimShift; + int refVal = refBottom[idx]; + int recVal = recBottom[idx]; + x += refVal; + y += recVal; + xx += refVal * refVal; + xy += refVal * recVal; + } + cntShift = dimShift; + + Pel* refRight = pred + cuWidth - 1; + Pel* recRight = rec + cuWidth - 1; + for (int k = 0; k < numSteps; k++) + { + int idx = (k * cuHeight) >> dimShift; + int refVal = refRight[idx * predStride]; + int recVal = recRight[idx * recStride]; + x += refVal; + y += recVal; + xx += refVal * refVal; + xy += refVal * recVal; + } + cntShift += (cntShift ? 1 : dimShift); + } + else +#endif + { + for (int h = 0; h < numSteps; h++) + { + int vDim = ((h * cuHeight) >> dimShift); + + for (int w = 0; w < numSteps; w++) + { + int hDim = ((w * cuWidth) >> dimShift); + + int predVal = pred[vDim * predStride + hDim] >> precShift; + int recVal = rec[vDim * recStride + hDim] >> precShift; + + x += predVal; + y += recVal; + xx += predVal * predVal; + xy += predVal * recVal; + } + } + } + + int shift = m_LICShift; +#if JVET_AG0276_LIC_FLAG_SIGNALING + int& scale = isBRcand ? cu.altLMBRParaUnit.scale[compID] : cu.altLMParaUnit.scale[compID]; + int& offset = isBRcand ? cu.altLMBRParaUnit.offset[compID] : cu.altLMParaUnit.offset[compID]; + if (!isBRcand) + { + cntShift = (dimShift << 1); + CHECK(!cntShift, "cntShift == 0"); + } +#else + int& scale = cu.altLMParaUnit.scale[compID]; + int& offset = cu.altLMParaUnit.offset[compID]; + cntShift = (dimShift << 1); CHECK(!cntShift, "cntShift == 0"); +#endif + const int cropShift = std::max(0, bitDepth - precShift + cntShift - 15); + const int xzOffset = (xx >> m_LICRegShift); + const int sumX = (x << precShift); + const int sumY = (y << precShift); + const int sumXX = ((xx + xzOffset) >> (cropShift << 1)) << cntShift; + const int sumXY = ((xy + xzOffset) >> (cropShift << 1)) << cntShift; + const int sumXsumX = (x >> cropShift) * (x >> cropShift); + const int sumXsumY = (x >> cropShift) * (y >> cropShift); + int a1 = sumXY - sumXsumY; + int a2 = sumXX - sumXsumX; + int scaleShiftA2 = getMSB(abs(a2)) - 6; + int scaleShiftA1 = scaleShiftA2 - m_LICShiftDiff; + scaleShiftA2 = std::max(0, scaleShiftA2); + scaleShiftA1 = std::max(0, scaleShiftA1); + const int scaleShiftA = scaleShiftA2 + 15 - shift - scaleShiftA1; + a1 = a1 >> scaleShiftA1; + a2 = Clip3(0, 63, a2 >> scaleShiftA2); + scale = int((int64_t(a1) * int64_t(m_LICMultApprox[a2])) >> scaleShiftA); + scale = Clip3(0, 1 << (shift + 2), scale); + const int maxOffset = (1 << (bitDepth - 1)) - 1; + const int minOffset = -1 - maxOffset; + offset = (sumY - ((scale * sumX) >> shift) + ((1 << (cntShift)) >> 1)) >> cntShift; + offset = Clip3(minOffset, maxOffset, offset); + } + } +#endif + #if JVET_AA0096_MC_BOUNDARY_PADDING void mcFramePad(Picture *pcCurPic, Slice &slice); #if JVET_Z0118_GDR diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index 7f6117709..5468f1c27 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -5597,4 +5597,7 @@ const int8_t g_amvpSbTmvp_mvd_offset[6] = { 4, 8, 12, 16, 24, 32 }; uint32_t g_picAmvpSbTmvpEnabledArea = 0; #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST +const int g_licSlopeDeltaSet[LIC_SLOPE_MAX_NUM_DELTA + 1] = {0, 1, -1}; +#endif //! \} diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h index 2a73e75db..575cf0f82 100644 --- a/source/Lib/CommonLib/Rom.h +++ b/source/Lib/CommonLib/Rom.h @@ -450,5 +450,8 @@ extern uint32_t g_picAmvpSbTmvpEnabledArea; extern const Position g_eipFilter[NUM_EIP_SHAPE][EIP_FILTER_TAP]; extern const EIPInfo g_eipInfoLut[4][4][9]; #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST +extern const int g_licSlopeDeltaSet[LIC_SLOPE_MAX_NUM_DELTA + 1]; +#endif #endif //__TCOMROM__ diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index d5f231c6b..8f02b685a 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -3446,6 +3446,9 @@ PicHeader::PicHeader() , m_picColFromL0Flag ( true ) , m_mvdL1ZeroFlag ( 0 ) , m_maxNumAffineMergeCand ( AFFINE_MRG_MAX_NUM_CANDS ) +#if JVET_AG0276_LIC_FLAG_SIGNALING +, m_maxNumAffineOppositeLicMergeCand ( AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC ) +#endif , m_disFracMMVD ( 0 ) , m_disBdofFlag ( 0 ) , m_disDmvrFlag ( 0 ) @@ -3544,6 +3547,9 @@ void PicHeader::initPicHeader() m_picColFromL0Flag = true; m_mvdL1ZeroFlag = 0; m_maxNumAffineMergeCand = AFFINE_MRG_MAX_NUM_CANDS; +#if JVET_AG0276_LIC_FLAG_SIGNALING + m_maxNumAffineOppositeLicMergeCand = AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC; +#endif m_disFracMMVD = 0; m_disBdofFlag = 0; m_disDmvrFlag = 0; @@ -3851,6 +3857,9 @@ SPS::SPS() , m_AffineType ( false ) #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT , m_useAffineTM ( false ) +#if JVET_AG0276_NLIC +, m_useAffAltLMTM ( false ) +#endif #endif , m_PROF ( false ) #if ENABLE_DIMD @@ -3923,6 +3932,15 @@ SPS::SPS() , m_MIP ( false ) #if JVET_W0090_ARMC_TM , m_AML ( false ) +#if JVET_AG0276_NLIC +, m_altLM ( false ) +, m_affAltLM ( false ) +#endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +, m_mergeOppositeLic ( false ) +, m_mergeTMOppositeLic ( false ) +, m_mergeAffOppositeLic ( false ) #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC , m_armcRefinedMotion ( false ) @@ -3936,10 +3954,16 @@ SPS::SPS() , m_rprSwitchingQPOffsetOrderList{ 0 } #endif , m_maxNumMergeCand(MRG_MAX_NUM_CANDS) +#if JVET_AG0276_LIC_FLAG_SIGNALING +, m_maxNumOppositeLicMergeCand(REG_MRG_MAX_NUM_CANDS_OPPOSITELIC) +#endif #if JVET_X0049_ADAPT_DMVR , m_maxNumBMMergeCand(BM_MRG_MAX_NUM_CANDS) #endif , m_maxNumAffineMergeCand(AFFINE_MRG_MAX_NUM_CANDS) +#if JVET_AG0276_LIC_FLAG_SIGNALING +, m_maxNumAffineOppositeLicMergeCand(AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC) +#endif , m_maxNumIBCMergeCand(IBC_MRG_MAX_NUM_CANDS) , m_maxNumGeoCand(0) #if JVET_AG0164_AFFINE_GPM diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index fa47841c5..eb783dc3e 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1777,6 +1777,9 @@ private: bool m_AffineType; #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT bool m_useAffineTM; +#if JVET_AG0276_NLIC + bool m_useAffAltLMTM; +#endif #endif bool m_PROF; bool m_bcw; // @@ -1836,6 +1839,9 @@ private: bool m_Geo; #if INTER_LIC bool m_licEnabledFlag; +#if JVET_AG0276_LIC_SLOPE_ADJUST + bool m_licSlopeAdjustEnabledFlag; +#endif #endif #if JVET_AE0059_INTER_CCCM @@ -1867,6 +1873,15 @@ private: #if JVET_W0090_ARMC_TM || JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0075_IBC_HMVP_ENLARGE bool m_AML; #endif +#if JVET_AG0276_NLIC + bool m_altLM; + bool m_affAltLM; +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool m_mergeOppositeLic; + bool m_mergeTMOppositeLic; + bool m_mergeAffOppositeLic; +#endif #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION bool m_fastSubTmvp; #endif @@ -1892,10 +1907,16 @@ private: bool m_ppsValidFlag[64]; Size m_scalingWindowSizeInPPS[64]; uint32_t m_maxNumMergeCand; +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t m_maxNumOppositeLicMergeCand; +#endif #if JVET_X0049_ADAPT_DMVR uint32_t m_maxNumBMMergeCand; #endif uint32_t m_maxNumAffineMergeCand; +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t m_maxNumAffineOppositeLicMergeCand; +#endif uint32_t m_maxNumIBCMergeCand; uint32_t m_maxNumGeoCand; #if JVET_AG0164_AFFINE_GPM @@ -2320,7 +2341,15 @@ void setCCALFEnabledFlag( bool b ) #if TM_MRG uint32_t getMaxNumTMMergeCand() const { return std::min((uint32_t)TM_MRG_MAX_NUM_CANDS, m_maxNumMergeCand); } #endif - +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t getMaxNumOppositeLicMergeCand() const { return m_maxNumOppositeLicMergeCand; } + void setMaxNumOppositeLicMergeCand(uint32_t u) { m_maxNumOppositeLicMergeCand = u; } +#endif +#if TM_MRG +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t getMaxNumTMOppositeLicMergeCand() const { return std::min((uint32_t)TM_MRG_MAX_NUM_CANDS_OPPOSITELIC, m_maxNumOppositeLicMergeCand); } +#endif +#endif #if JVET_X0141_CIIP_TIMD_TM && TM_MRG uint32_t getMaxNumCiipTMMergeCand() const { return std::min((uint32_t)CIIP_TM_MRG_MAX_NUM_CANDS, m_maxNumMergeCand); } #endif @@ -2330,6 +2359,10 @@ void setCCALFEnabledFlag( bool b ) #endif uint32_t getMaxNumAffineMergeCand() const { return m_maxNumAffineMergeCand; } void setMaxNumAffineMergeCand(uint32_t u) { m_maxNumAffineMergeCand = u; } +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t getMaxNumAffineOppositeLicMergeCand() const { return m_maxNumAffineOppositeLicMergeCand; } + void setMaxNumAffineOppositeLicMergeCand(uint32_t u) { m_maxNumAffineOppositeLicMergeCand = u; } +#endif uint32_t getMaxNumIBCMergeCand() const { return m_maxNumIBCMergeCand; } void setMaxNumIBCMergeCand(uint32_t u) { m_maxNumIBCMergeCand = u; } uint32_t getMaxNumGeoCand() const { CHECK( m_maxNumGeoCand >= GEO_MAX_NUM_UNI_CANDS, "Number of GEO candidates exceed GEO_MAX_NUM_CANDS" ); return m_maxNumGeoCand; } @@ -2519,6 +2552,10 @@ void setCCALFEnabledFlag( bool b ) #if INTER_LIC void setLicEnabledFlag ( bool b ) { m_licEnabledFlag = b; } bool getLicEnabledFlag () const { return m_licEnabledFlag; } +#if JVET_AG0276_LIC_SLOPE_ADJUST + void setLicSlopeAdjustEnabledFlag ( bool b ) { m_licSlopeAdjustEnabledFlag = b; } + bool getLicSlopeAdjustEnabledFlag () const { return m_licSlopeAdjustEnabledFlag; } +#endif #endif #if JVET_AE0059_INTER_CCCM void setUseInterCccm ( bool b ) { m_interCccm = b; } @@ -2536,9 +2573,23 @@ void setCCALFEnabledFlag( bool b ) void setUseCiipAffine ( bool b ) { m_ciipAffine = b; } bool getUseCiipAffine () const { return m_ciipAffine; } #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + void setUseMergeOppositeLic( bool b ) { m_mergeOppositeLic = b; } + bool getUseMergeOppositeLic() const { return m_mergeOppositeLic; } + void setUseTMMergeOppositeLic( bool b ) { m_mergeTMOppositeLic = b; } + bool getUseTMMergeOppositeLic() const { return m_mergeTMOppositeLic; } + void setUseAffMergeOppositeLic( bool b ) { m_mergeAffOppositeLic = b; } + bool getUseAffMergeOppositeLic() const { return m_mergeAffOppositeLic; } +#endif #if JVET_W0090_ARMC_TM || JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0075_IBC_HMVP_ENLARGE void setUseAML ( bool b ) { m_AML = b; } bool getUseAML () const { return m_AML; } +#if JVET_AG0276_NLIC + void setUseAltLM ( bool b ) { m_altLM = b; } + bool getUseAltLM () const { return m_altLM; } + void setUseAffAltLM ( bool b ) { m_affAltLM = b; } + bool getUseAffAltLM () const { return m_affAltLM; } +#endif #endif #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION void setUseFastSubTmvp ( bool b ) { m_fastSubTmvp = b; } @@ -2547,6 +2598,10 @@ void setCCALFEnabledFlag( bool b ) #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT void setUseAffineTM ( bool b ) { m_useAffineTM = b; } bool getUseAffineTM () const { return m_useAffineTM; } +#if JVET_AG0276_NLIC + void setUseAffAltLMTM ( bool b ) { m_useAffAltLMTM = b; } + bool getUseAffAltLMTM () const { return m_useAffAltLMTM; } +#endif #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC void setUseArmcRefinedMotion ( bool b ) { m_armcRefinedMotion = b; } @@ -3149,6 +3204,9 @@ private: #endif bool m_mvdL1ZeroFlag; //!< L1 MVD set to zero flag uint32_t m_maxNumAffineMergeCand; //!< max number of sub-block merge candidates +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t m_maxNumAffineOppositeLicMergeCand; //!< max number of sub-block merge candidates with opposite LIC flag +#endif bool m_disFracMMVD; //!< fractional MMVD offsets disabled flag bool m_disBdofFlag; //!< picture level BDOF disable flag bool m_disDmvrFlag; //!< picture level DMVR disable flag @@ -3305,6 +3363,10 @@ public: bool getMvdL1ZeroFlag() const { return m_mvdL1ZeroFlag; } void setMaxNumAffineMergeCand( uint32_t val ) { m_maxNumAffineMergeCand = val; } uint32_t getMaxNumAffineMergeCand() const { return m_maxNumAffineMergeCand; } +#if JVET_AG0276_LIC_FLAG_SIGNALING + void setMaxNumAffineOppositeLicMergeCand( uint32_t val ) { m_maxNumAffineOppositeLicMergeCand = val; } + uint32_t getMaxNumAffineOppositeLicMergeCand() const { return m_maxNumAffineOppositeLicMergeCand; } +#endif void setDisFracMMVD( bool val ) { m_disFracMMVD = val; } bool getDisFracMMVD() const { return m_disFracMMVD; } void setDisBdofFlag( bool val ) { m_disBdofFlag = val; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 9bf23afb6..4430937f5 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -255,6 +255,10 @@ #if INTER_LIC #define JVET_AD0213_LIC_IMP 1 // JVET-AD0213: bi-predictive LIC and the combination of LIC and OBMC #define JVET_AF0128_LIC_MERGE_TM 1 // JVET-AF0128: LIC flag derivation for merge candidates with template costs +#define JVET_AG0276_NLIC 1 // JVET-AG0276: non-local LIC +#define JVET_AG0276_LIC_FLAG_SIGNALING 1 // JVET-AG0276: signal LIC flag for merge mode +#define JVET_AG0276_LIC_BDOF_BDMVR 1 // JVET-AG0276: LIC BDOF and BDMVR +#define JVET_AG0276_LIC_SLOPE_ADJUST 1 // JVET-AG0276: LIC with slope adjustment #endif #define NON_ADJACENT_MRG_CAND 1 // Add non-adjacent merge candidates #define MULTI_HYP_PRED 1 // Multiple hypothesis prediction diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 41fea8671..0c38590f1 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -413,6 +413,16 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) dimdDerivedIntraDir = other.dimdDerivedIntraDir; #endif #endif +#if JVET_AG0276_NLIC + altLMFlag = other.altLMFlag; + altLMParaUnit = other.altLMParaUnit; +#if JVET_AG0276_LIC_FLAG_SIGNALING + altLMBRParaUnit = other.altLMBRParaUnit; +#endif +#if ENABLE_OBMC + secAltLMParaUnit = other.secAltLMParaUnit; +#endif +#endif #if INTER_LIC licFlag = other.licFlag; #if JVET_AD0213_LIC_IMP @@ -425,6 +435,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) } } #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + licDelta = other.licDelta; +#endif #endif #if JVET_AC0112_IBC_LIC ibcLicFlag = other.ibcLicFlag; @@ -643,6 +656,16 @@ void CodingUnit::initData() dimdDerivedIntraDir = 0; #endif #endif +#if JVET_AG0276_NLIC + altLMFlag = false; + altLMParaUnit.resetAltLinearModel(); +#if JVET_AG0276_LIC_FLAG_SIGNALING + altLMBRParaUnit.resetAltLinearModel(); +#endif +#if ENABLE_OBMC + secAltLMParaUnit.resetAltLinearModel(); +#endif +#endif #if INTER_LIC licFlag = false; #if JVET_AD0213_LIC_IMP @@ -655,6 +678,9 @@ void CodingUnit::initData() } } #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + licDelta = 0; +#endif #endif #if JVET_AC0112_IBC_LIC ibcLicFlag = false; @@ -967,6 +993,11 @@ void PredictionUnit::initData() colIdx = 0; #endif mergeFlag = false; +#if JVET_AG0276_LIC_FLAG_SIGNALING + mergeOppositeLic = false; + affineOppositeLic = false; + tmMergeFlagOppositeLic = false; +#endif regularMergeFlag = false; mergeIdx = MAX_UCHAR; geoSplitDir = MAX_UCHAR; @@ -1185,6 +1216,11 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData) colIdx = predData.colIdx; #endif mergeFlag = predData.mergeFlag; +#if JVET_AG0276_LIC_FLAG_SIGNALING + mergeOppositeLic = predData.mergeOppositeLic; + affineOppositeLic = predData.affineOppositeLic; + tmMergeFlagOppositeLic = predData.tmMergeFlagOppositeLic; +#endif regularMergeFlag = predData.regularMergeFlag; mergeIdx = predData.mergeIdx; geoSplitDir = predData.geoSplitDir; @@ -1400,6 +1436,11 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other ) ccpMergeFusionType = other.ccpMergeFusionType; #endif mergeFlag = other.mergeFlag; +#if JVET_AG0276_LIC_FLAG_SIGNALING + mergeOppositeLic = other.mergeOppositeLic; + affineOppositeLic = other.affineOppositeLic; + tmMergeFlagOppositeLic = other.tmMergeFlagOppositeLic; +#endif regularMergeFlag = other.regularMergeFlag; #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION colIdx = other.colIdx; diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index df7240fc1..806a4e4c0 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -431,12 +431,25 @@ struct CodingUnit : public UnitArea int intraTmpDimdMode; #endif #endif +#if JVET_AG0276_NLIC + bool altLMFlag; + AltLMInterUnit altLMParaUnit; +#if JVET_AG0276_LIC_FLAG_SIGNALING + AltLMInterUnit altLMBRParaUnit; +#endif +#if ENABLE_OBMC + AltLMInterUnit secAltLMParaUnit; +#endif +#endif #if INTER_LIC bool licFlag; #if JVET_AD0213_LIC_IMP int licScale[2][3]; int licOffset[2][3]; #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + int licDelta; +#endif #endif #if JVET_AC0112_IBC_LIC bool ibcLicFlag; @@ -658,6 +671,11 @@ struct InterPredictionData #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) bool tmMergeFlag; #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool tmMergeFlagOppositeLic; + bool mergeOppositeLic; + bool affineOppositeLic; +#endif #if JVET_X0049_ADAPT_DMVR uint8_t bmMergeFlag; uint8_t bmDir; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 86e9a16d3..188c81d8b 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -357,6 +357,163 @@ void CU::checkConformanceILRP(Slice *slice) return; } +#if JVET_AG0276_NLIC +bool CU::isSecLicParaNeeded(const CodingUnit &cu) +{ + if (!isInter(cu)) + { + return false; + } + if (cu.geoFlag) + { + return false; + } + if (cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP) + { + return false; + } +#if JVET_AG0098_AMVP_WITH_SBTMVP + if (cu.firstPU->amvpSbTmvpFlag) + { + return false; + } +#endif + return true; +} + +bool CU::isPredRefined(const CodingUnit &cu) +{ + PredictionUnit* pu = cu.firstPU; + +#if INTER_LIC + if (cu.licFlag) + { + return true; + } +#endif + if (cu.altLMFlag) + { + return true; + } +#if MULTI_PASS_DMVR + if (pu->bdmvrRefine) + { + return true; + } +#endif + if (pu->ciipFlag) + { + return true; + } +#if MULTI_HYP_PRED + if (!pu->addHypData.empty()) + { + return true; + } +#endif + + bool bioApplied = false; +#if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT + if (pu->cu->affine) + { + bioApplied = PU::checkDoAffineBdofRefine(*pu, NULL); + } + else + { +#endif + if (pu->cs->sps->getBDOFEnabledFlag() && !pu->cs->picHeader->getDisBdofFlag()) + { +#if INTER_LIC + if (cu.affine || (pu->mergeFlag && (pu->mergeType == MRG_TYPE_SUBPU_ATMVP)) || cu.licFlag) +#else + if (cu.affine || (pu->mergeFlag && (pu->mergeType == MRG_TYPE_SUBPU_ATMVP))) +#endif + { + bioApplied = false; + } + else + { + int refIdx0 = pu->refIdx[REF_PIC_LIST_0]; + int refIdx1 = pu->refIdx[REF_PIC_LIST_1]; + const WPScalingParam *wp0 = cu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0); + const WPScalingParam *wp1 = cu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1); + + const bool biocheck0 = !((WPScalingParam::isWeighted(wp0) || WPScalingParam::isWeighted(wp1)) && cu.cs->slice->getSliceType() == B_SLICE); + const bool biocheck1 = !(cu.cs->pps->getUseWP() && cu.cs->slice->getSliceType() == P_SLICE); + if (biocheck0 && biocheck1 + && PU::isBiPredFromDifferentDirEqDistPoc(*pu) +#if !BDOF_RM_CONSTRAINTS + && (cu.Y().height >= 8) + && (cu.Y().width >= 8) + && ((cu.Y().height * cu.Y().width) >= 128) +#endif + ) + { + bioApplied = true; + } + if (bioApplied && pu->ciipFlag) + { + bioApplied = false; + } + if (bioApplied && cu.smvdMode) + { + bioApplied = false; + } + if (cu.cs->sps->getUseBcw() && bioApplied && cu.bcwIdx != BCW_DEFAULT) + { + bioApplied = false; + } + } + } +#if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT + } +#endif + if (bioApplied) + { + return true; + } + + return false; +} +bool CU::isAllowSecLicPara(const CodingUnit &cu) +{ + if (!cu.slice->getSPS()->getUseAltLM()) + { + if (!cu.slice->getSPS()->getUseAffAltLM()) + { + return false; + } + else + { + if (!cu.affine) + { + return false; + } + } + } + if (isTLCond(cu)) + { + return false; + } + return true; +} +bool CU::isTLCond(const CodingUnit &cu) +{ + if (!cu.slice->getSPS()->getUseAltLM() && !cu.slice->getSPS()->getUseAffAltLM()) + { + return false; + } + if (cu.slice->getTLayer() >= 5) + { + return true; + } + else + { + return false; + } +} +#endif + bool CU::isIntra(const CodingUnit &cu) { return cu.predMode == MODE_INTRA; @@ -3084,6 +3241,32 @@ bool PU::checkIsChromaBvCandidateValid(const PredictionUnit &pu, const Mv chroma return true; } #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +bool PU::isOppositeLIC(const PredictionUnit &pu) +{ + return pu.mergeOppositeLic + || pu.tmMergeFlagOppositeLic + || pu.affineOppositeLic + ; +} + +bool PU::hasOppositeLICFlag(const PredictionUnit &pu) +{ + if (pu.cu->slice->getUseLIC() && pu.cs->slice->getTLayer() < 5) + { + int blkArea = pu.lumaSize().area(); + if (pu.cu->affine) + { + return blkArea > 64 && blkArea < 8192; + } + else + { + return blkArea >= 32 && blkArea < 16384; + } + } + return false; +} +#endif #if JVET_AD0120_LBCCP bool PU::isModetobeFiltered(int intraMode) { @@ -5703,6 +5886,10 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.mvFieldNeighbours[ui * 2].refIdx = NOT_VALID; mrgCtx.mvFieldNeighbours[ui * 2 + 1].refIdx = NOT_VALID; mrgCtx.useAltHpelIf[ui] = false; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -8149,6 +8336,10 @@ void PU::getInterMergeCandidatesSubTMVP(const PredictionUnit &pu, MergeCtx& mrgC for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -8589,6 +8780,10 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -8705,7 +8900,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // get Mv from Above mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT; #if INTER_LIC +#if JVET_AG0276_NLIC + mrgCtx.licFlags[cnt] = miAbove.usesLIC || (puAbove->cu->altLMFlag && slice.getUseLIC()); +#else mrgCtx.licFlags[cnt] = miAbove.usesLIC; +#endif #endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]); @@ -8792,7 +8991,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf; mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT; #if INTER_LIC +#if JVET_AG0276_NLIC + mrgCtx.licFlags[cnt] = miLeft.usesLIC || (puLeft->cu->altLMFlag && slice.getUseLIC()); +#else mrgCtx.licFlags[cnt] = miLeft.usesLIC; +#endif #endif // get Mv from Left mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); @@ -8880,7 +9083,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // get Mv from Above-right mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT; #if INTER_LIC +#if JVET_AG0276_NLIC + mrgCtx.licFlags[cnt] = miAboveRight.usesLIC || (puAboveRight->cu->altLMFlag && slice.getUseLIC()); +#else mrgCtx.licFlags[cnt] = miAboveRight.usesLIC; +#endif #endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] ); @@ -8965,7 +9172,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf; mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT; #if INTER_LIC +#if JVET_AG0276_NLIC + mrgCtx.licFlags[cnt] = miBelowLeft.usesLIC || (puLeftBottom->cu->altLMFlag && slice.getUseLIC()); +#else mrgCtx.licFlags[cnt] = miBelowLeft.usesLIC; +#endif #endif // get Mv from Bottom-Left mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] ); @@ -9066,7 +9277,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf; mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT; #if INTER_LIC +#if JVET_AG0276_NLIC + mrgCtx.licFlags[cnt] = miAboveLeft.usesLIC || (puAboveLeft->cu->altLMFlag && slice.getUseLIC()); +#else mrgCtx.licFlags[cnt] = miAboveLeft.usesLIC; +#endif #endif // get Mv from Above-Left mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveLeft.mv[0], miAboveLeft.refIdx[0] ); @@ -9499,7 +9714,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // get Mv from Above-right mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; #if INTER_LIC +#if JVET_AG0276_NLIC + mrgCtx.licFlags[cnt] = miNeighbor.usesLIC || (puNonAdjacent->cu->altLMFlag && slice.getUseLIC()); +#else mrgCtx.licFlags[cnt] = miNeighbor.usesLIC; +#endif #endif if (slice.isInterB()) { @@ -10457,6 +10676,12 @@ void PU::xCalcRMVFParameters(std::vector<RMVFInfo> &mvpInfoVec, int64_t dMatrix[ void PU::getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit &abovePU, AffineMergeCtx &affMrgCtx , std::vector<RMVFInfo> mvp[NUM_REF_PIC_LIST_01][MAX_NUM_REF] , int mrgCandIdx +#if JVET_AG0276_NLIC + , AltLMAffineMergeCtx* altAffineMergeCtx +#if JVET_AG0276_LIC_FLAG_SIGNALING + , AltLMAffineMergeCtx* altBRAffineMergeCtx +#endif +#endif ) { const CodingStructure &cs = *pu.cs; @@ -10855,6 +11080,50 @@ void PU::getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit & #if JVET_AB0189_RMVF_BITLENGTH_CONTROL if (enoughBlk[0] || enoughBlk[1]) { +#endif +#if JVET_AG0276_NLIC + if (PU::isValidAltMergeCandidate(abovePU) && (altAffineMergeCtx->numValidMergeCand < ALT_AFF_MRG_MAX_NUM_CANDS)) + { + int cnt = altAffineMergeCtx->numValidMergeCand; + altAffineMergeCtx->affineType[cnt] = AFFINEMODEL_6PARAM; + for (int mvNum = 0; mvNum < 3; mvNum++) + { + altAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMVOri[0][mvNum], referenceidx[0]); + altAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMVOri[1][mvNum], referenceidx[1]); + } + altAffineMergeCtx->interDirNeighbours[cnt] = abovePU.interDir; + altAffineMergeCtx->bcwIdx[cnt] = abovePU.cu->bcwIdx; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + altAffineMergeCtx->obmcFlags[cnt] = abovePU.cu->affine ? abovePU.cu->obmcFlag : true; +#endif + altAffineMergeCtx->altLMParaNeighbours[cnt] = abovePU.cu->altLMParaUnit; + if (altAffineMergeCtx->xCheckSameAffMotion(pu, cnt)) + { + altAffineMergeCtx->numValidMergeCand++; + } + } +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (PU::isValidAltMergeCandidate(abovePU, true) && (altBRAffineMergeCtx->numValidMergeCand < ALT_AFF_MRG_MAX_NUM_CANDS)) + { + int cnt = altBRAffineMergeCtx->numValidMergeCand; + altBRAffineMergeCtx->affineType[cnt] = AFFINEMODEL_6PARAM; + for (int mvNum = 0; mvNum < 3; mvNum++) + { + altBRAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMVOri[0][mvNum], referenceidx[0]); + altBRAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMVOri[1][mvNum], referenceidx[1]); + } + altBRAffineMergeCtx->interDirNeighbours[cnt] = abovePU.interDir; + altBRAffineMergeCtx->bcwIdx[cnt] = abovePU.cu->bcwIdx; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + altBRAffineMergeCtx->obmcFlags[cnt] = abovePU.cu->affine ? abovePU.cu->obmcFlag : true; +#endif + altBRAffineMergeCtx->altLMParaNeighbours[cnt] = abovePU.cu->altLMBRParaUnit; + if (altBRAffineMergeCtx->xCheckSameAffMotion(pu, cnt)) + { + altBRAffineMergeCtx->numValidMergeCand++; + } + } +#endif #endif if (!xCPMVSimCheck(pu, affMrgCtx, cMVOri, abovePU.interDir, referenceidx, AFFINEMODEL_6PARAM, abovePU.cu->bcwIdx, abovePU.cu->licFlag)) { @@ -10894,6 +11163,50 @@ void PU::getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit & #endif if (available[REF_PIC_LIST_0] || available[REF_PIC_LIST_1]) { +#if JVET_AG0276_NLIC + if (PU::isValidAltMergeCandidate(abovePU) && (altAffineMergeCtx->numValidMergeCand < ALT_AFF_MRG_MAX_NUM_CANDS)) + { + int cnt = altAffineMergeCtx->numValidMergeCand; + altAffineMergeCtx->affineType[cnt] = AFFINEMODEL_6PARAM; + for (int mvNum = 0; mvNum < 3; mvNum++) + { + altAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMV[0][mvNum], referenceidx[0]); + altAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMV[1][mvNum], referenceidx[1]); + } + altAffineMergeCtx->interDirNeighbours[cnt] = abovePU.interDir; + altAffineMergeCtx->bcwIdx[cnt] = abovePU.cu->bcwIdx; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + altAffineMergeCtx->obmcFlags[cnt] = abovePU.cu->affine ? abovePU.cu->obmcFlag : true; +#endif + altAffineMergeCtx->altLMParaNeighbours[cnt] = abovePU.cu->altLMParaUnit; + if (altAffineMergeCtx->xCheckSameAffMotion(pu, cnt)) + { + altAffineMergeCtx->numValidMergeCand++; + } + } +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (PU::isValidAltMergeCandidate(abovePU, true) && (altBRAffineMergeCtx->numValidMergeCand < ALT_AFF_MRG_MAX_NUM_CANDS)) + { + int cnt = altBRAffineMergeCtx->numValidMergeCand; + altBRAffineMergeCtx->affineType[cnt] = AFFINEMODEL_6PARAM; + for (int mvNum = 0; mvNum < 3; mvNum++) + { + altBRAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMV[0][mvNum], referenceidx[0]); + altBRAffineMergeCtx->mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMV[1][mvNum], referenceidx[1]); + } + altBRAffineMergeCtx->interDirNeighbours[cnt] = abovePU.interDir; + altBRAffineMergeCtx->bcwIdx[cnt] = abovePU.cu->bcwIdx; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + altBRAffineMergeCtx->obmcFlags[cnt] = abovePU.cu->affine ? abovePU.cu->obmcFlag : true; +#endif + altBRAffineMergeCtx->altLMParaNeighbours[cnt] = abovePU.cu->altLMBRParaUnit; + if (altBRAffineMergeCtx->xCheckSameAffMotion(pu, cnt)) + { + altBRAffineMergeCtx->numValidMergeCand++; + } + } +#endif +#endif if (!xCPMVSimCheck(pu, affMrgCtx, cMV, abovePU.interDir, referenceidx, AFFINEMODEL_6PARAM, BCW_DEFAULT, false)) { int i = affMrgCtx.numValidMergeCand; @@ -11160,6 +11473,10 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -11914,6 +12231,10 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -12133,6 +12454,10 @@ void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -12304,6 +12629,10 @@ void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -12837,6 +13166,10 @@ void PU::getNonAdjacentMergeCandSubTMVP(const PredictionUnit &pu, MergeCtx& mrgC for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -13044,6 +13377,10 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -13093,52 +13430,1381 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); -#if JVET_Y0065_GPM_INTRA - bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter; -#else +#if JVET_Y0065_GPM_INTRA + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter; +#else + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); +#endif + + if (isAvailableNonAdjacent) + { + miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + // get Mv from Above-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + // get Mv from Above-right + mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; +#if INTER_LIC +#if JVET_AG0276_NLIC + mrgCtx.licFlags[cnt] = miNeighbor.usesLIC || (puNonAdjacent->cu->altLMFlag && slice.getUseLIC()); +#else + mrgCtx.licFlags[cnt] = miNeighbor.usesLIC; +#endif +#endif + if (slice.isInterB()) + { + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData; +#endif + } + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) +#endif + { + cnt++; + } +#if JVET_AD0213_LIC_IMP + else + { + mrgCtx.initMrgCand(cnt); + } +#endif + } + + } + } + + const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap2[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; + case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; + case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + +#if JVET_Y0065_GPM_INTRA + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter; +#else + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); +#endif + + if (isAvailableNonAdjacent) + { + miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + // get Mv from Above-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + // get Mv from Above-right + mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; +#if INTER_LIC +#if JVET_AG0276_NLIC + mrgCtx.licFlags[cnt] = miNeighbor.usesLIC || (puNonAdjacent->cu->altLMFlag && slice.getUseLIC()); +#else + mrgCtx.licFlags[cnt] = miNeighbor.usesLIC; +#endif +#endif + if (slice.isInterB()) + { + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData; +#endif + } + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) +#endif + { + cnt++; + } +#if JVET_AD0213_LIC_IMP + else + { + mrgCtx.initMrgCand(cnt); + } +#endif + } + } + } + + mrgCtx.numValidMergeCand = cnt; +} +#endif + +#if JVET_AG0276_NLIC +uint32_t PU::getAltMergeMvdThreshold(const PredictionUnit &pu) +{ + uint32_t numPixels = pu.lwidth() * pu.lheight(); + if (numPixels < 64) + { + return 1 << MV_FRACTIONAL_BITS_INTERNAL; + } + else if (numPixels < 256) + { + return 2 << MV_FRACTIONAL_BITS_INTERNAL; + } + else + { + return 4 << MV_FRACTIONAL_BITS_INTERNAL; + } +} + +#if JVET_AG0276_LIC_FLAG_SIGNALING +bool PU::isValidAltMergeCandidate(const PredictionUnit &pu, bool isBRCand) +#else +bool PU::isValidAltMergeCandidate(const PredictionUnit &pu) +#endif +{ + bool valid = true; + if (!CU::isInter(*pu.cu)) + { + valid = false; + } + if (pu.cu->geoFlag) + { + valid = false; + } + if (pu.mergeFlag && pu.mergeType == MRG_TYPE_SUBPU_ATMVP) + { + valid = false; + } + + if (!valid) + { + return false; + } + +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool trivial = false; + if (!isBRCand) + { + trivial = (pu.cu->altLMParaUnit.scale[0] == 32 && pu.cu->altLMParaUnit.offset[0] == 0); + } + else + { + trivial = (pu.cu->altLMBRParaUnit.scale[0] == 32 && pu.cu->altLMBRParaUnit.offset[0] == 0); + } +#else + bool trivial = (pu.cu->altLMParaUnit.scale[0] == 32 && pu.cu->altLMParaUnit.offset[0] == 0); +#endif + + if (trivial) + { + return false; + } + return true; +} + +void PU::getAltMergeCandidates(const PredictionUnit &pu, AltLMMergeCtx& cMrgCtx) +{ + const uint32_t maxNumMergeCand = ALT_MRG_MAX_NUM_CANDS; + const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; + const CodingStructure& cs = *pu.cs; + const Slice& slice = *pu.cs->slice; + const uint32_t mvdSimilarityThresh = getAltMergeMvdThreshold(pu); + + for (int i = 0; i < maxNumMergeCand; i++) + { + cMrgCtx.initAltLMMergeCtx(i); + } + + int cnt = 0; + + const Position posLT = pu.Y().topLeft(); + const Position posRT = pu.Y().topRight(); + const Position posLB = pu.Y().bottomLeft(); + + // above + const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); + bool isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && CU::isInter(*puAbove->cu); + if (isAvailableB1 && PU::isValidAltMergeCandidate(*puAbove)) + { + MotionInfo miAbove = puAbove->getMotionInfo(posRT.offset(0, -1)); + cMrgCtx.interDirNeighbours[cnt] = miAbove.interDir; + cMrgCtx.useAltHpelIf[cnt] = miAbove.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAbove.mv[1], miAbove.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puAbove->cu->altLMParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + //left + const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && CU::isInter(*puLeft->cu); + if (isAvailableA1 && PU::isValidAltMergeCandidate(*puLeft)) + { + MotionInfo miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0)); + cMrgCtx.interDirNeighbours[cnt] = miLeft.interDir; + cMrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puLeft->cu->altLMParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + // above right + const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType); + const bool isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu); + if (isAvailableB0 && PU::isValidAltMergeCandidate(*puAboveRight)) + { + MotionInfo miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1)); + cMrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir; + cMrgCtx.useAltHpelIf[cnt] = miAboveRight.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveRight.mv[1], miAboveRight.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puAboveRight->cu->altLMParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + //left bottom + const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); + bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu); + if (isAvailableA0 && PU::isValidAltMergeCandidate(*puLeftBottom)) + { + MotionInfo miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1)); + cMrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; + cMrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miBelowLeft.mv[1], miBelowLeft.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puLeftBottom->cu->altLMParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + // above left + const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType); + bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu); + if (isAvailableB2 && PU::isValidAltMergeCandidate(*puAboveLeft)) + { + MotionInfo miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1)); + cMrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; + cMrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveLeft.mv[1], miAboveLeft.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puAboveLeft->cu->altLMParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + int offsetX = 0; + int offsetY = 0; + int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1; + int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1; + + const int numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 }; + const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break; + case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX2; offsetY = offsetY1; break; + case 3:offsetX = offsetX0; offsetY = offsetY2; break; + case 4:offsetX = offsetX0; offsetY = offsetY1; break; + case 5:offsetX = -1; offsetY = offsetY0; break; + case 6:offsetX = offsetX1; offsetY = -1; break; + case 7:offsetX = offsetX0 >> 1; offsetY = offsetY0; break; + case 8:offsetX = offsetX1; offsetY = offsetY1 >> 1; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + if (isAvailableNonAdjacent && PU::isValidAltMergeCandidate(*puNonAdjacent)) + { + MotionInfo miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + cMrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + cMrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + } + } + + const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap2[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; + case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; + case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + if (isAvailableNonAdjacent && PU::isValidAltMergeCandidate(*puNonAdjacent)) + { + MotionInfo miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + cMrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + cMrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + } + } + + cMrgCtx.numValidMergeCand = cnt; + return; +} +#if JVET_AG0276_LIC_FLAG_SIGNALING +void PU::getAltBRMergeCandidates(const PredictionUnit &pu, AltLMMergeCtx& cMrgCtx) +{ + const uint32_t maxNumMergeCand = ALT_MRG_MAX_NUM_CANDS; + const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; + const CodingStructure& cs = *pu.cs; + const Slice& slice = *pu.cs->slice; + const uint32_t mvdSimilarityThresh = getAltMergeMvdThreshold(pu); + + for (int i = 0; i < maxNumMergeCand; i++) + { + cMrgCtx.initAltLMMergeCtx(i); + } + + int cnt = 0; + + const Position posLT = pu.Y().topLeft(); + const Position posRT = pu.Y().topRight(); + const Position posLB = pu.Y().bottomLeft(); + + const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); + bool isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && CU::isInter(*puAbove->cu); + if (isAvailableB1 && PU::isValidAltMergeCandidate(*puAbove, true)) + { + MotionInfo miAbove = puAbove->getMotionInfo(posRT.offset(0, -1)); + cMrgCtx.interDirNeighbours[cnt] = miAbove.interDir; + cMrgCtx.useAltHpelIf[cnt] = miAbove.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAbove.mv[1], miAbove.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puAbove->cu->altLMBRParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && CU::isInter(*puLeft->cu); + if (isAvailableA1 && PU::isValidAltMergeCandidate(*puLeft, true)) + { + MotionInfo miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0)); + cMrgCtx.interDirNeighbours[cnt] = miLeft.interDir; + cMrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puLeft->cu->altLMBRParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType); + const bool isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu); + if (isAvailableB0 && PU::isValidAltMergeCandidate(*puAboveRight, true)) + { + MotionInfo miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1)); + cMrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir; + cMrgCtx.useAltHpelIf[cnt] = miAboveRight.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveRight.mv[1], miAboveRight.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puAboveRight->cu->altLMBRParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); + bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu); + if (isAvailableA0 && PU::isValidAltMergeCandidate(*puLeftBottom, true)) + { + MotionInfo miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1)); + cMrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; + cMrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miBelowLeft.mv[1], miBelowLeft.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puLeftBottom->cu->altLMBRParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType); + bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu); + if (isAvailableB2 && PU::isValidAltMergeCandidate(*puAboveLeft, true)) + { + MotionInfo miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1)); + cMrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; + cMrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveLeft.mv[1], miAboveLeft.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puAboveLeft->cu->altLMBRParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + int offsetX = 0; + int offsetY = 0; + int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1; + int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1; + + const int numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 }; + const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break; + case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX2; offsetY = offsetY1; break; + case 3:offsetX = offsetX0; offsetY = offsetY2; break; + case 4:offsetX = offsetX0; offsetY = offsetY1; break; + case 5:offsetX = -1; offsetY = offsetY0; break; + case 6:offsetX = offsetX1; offsetY = -1; break; + case 7:offsetX = offsetX0 >> 1; offsetY = offsetY0; break; + case 8:offsetX = offsetX1; offsetY = offsetY1 >> 1; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + if (isAvailableNonAdjacent && PU::isValidAltMergeCandidate(*puNonAdjacent, true)) + { + MotionInfo miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + cMrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + cMrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMBRParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + } + } + + const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap2[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; + case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; + case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + if (isAvailableNonAdjacent && PU::isValidAltMergeCandidate(*puNonAdjacent, true)) + { + MotionInfo miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + cMrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + cMrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + cMrgCtx.bcwIdx[cnt] = (cMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; + cMrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + if (slice.isInterB()) + { + cMrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); + } + cMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMBRParaUnit; + if (!cMrgCtx.xCheckSameMotion(cnt, mvdSimilarityThresh)) + { + cnt++; + } + else + { + cMrgCtx.initAltLMMergeCtx(cnt); + } + } + } + } + + cMrgCtx.numValidMergeCand = cnt; + return; +} +#endif +#endif + +#if JVET_AG0276_NLIC +void PU::getAltLMAffineMergeCand(const PredictionUnit &pu, AltLMAffineMergeCtx& affMrgCtx) +{ + const uint32_t maxNumMergeCand = ALT_AFF_MRG_MAX_NUM_CANDS; + const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; + const CodingStructure& cs = *pu.cs; + const Slice& slice = *pu.cs->slice; + + for (int i = 0; i < maxNumMergeCand; i++) + { + affMrgCtx.initAltLMAffMergeCtx(i); + } + + int cnt = 0; + + const Position posLT = pu.Y().topLeft(); + const Position posRT = pu.Y().topRight(); + const Position posLB = pu.Y().bottomLeft(); + + // above + const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); + bool isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && CU::isInter(*puAbove->cu); + if (isAvailableB1 && puAbove->cu->affine && (puAbove->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAbove)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puAbove->cu->affineType; + pu.cu->affineType = puAbove->cu->affineType; + if (puAbove->interDir != 2) + { + xInheritedAffineMv(pu, puAbove, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puAbove->interDir != 1) + { + xInheritedAffineMv(pu, puAbove, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAbove->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAbove->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puAbove->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puAbove->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puAbove->cu->altLMParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + //left + const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && CU::isInter(*puLeft->cu); + if (isAvailableA1 && puLeft->cu->affine && (puLeft->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puLeft)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puLeft->cu->affineType; + pu.cu->affineType = puLeft->cu->affineType; + if (puLeft->interDir != 2) + { + xInheritedAffineMv(pu, puLeft, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puLeft->interDir != 1) + { + xInheritedAffineMv(pu, puLeft, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puLeft->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puLeft->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puLeft->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puLeft->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puLeft->cu->altLMParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + // above right + const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType); + const bool isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu); + if (isAvailableB0 && puAboveRight->cu->affine && (puAboveRight->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAboveRight)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puAboveRight->cu->affineType; + pu.cu->affineType = puAboveRight->cu->affineType; + if (puAboveRight->interDir != 2) + { + xInheritedAffineMv(pu, puAboveRight, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puAboveRight->interDir != 1) + { + xInheritedAffineMv(pu, puAboveRight, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAboveRight->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAboveRight->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puAboveRight->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puAboveRight->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puAboveRight->cu->altLMParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + //left bottom + const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); + bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu); + if (isAvailableA0 && puLeftBottom->cu->affine && (puLeftBottom->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puLeftBottom)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puLeftBottom->cu->affineType; + pu.cu->affineType = puLeftBottom->cu->affineType; + if (puLeftBottom->interDir != 2) + { + xInheritedAffineMv(pu, puLeftBottom, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puLeftBottom->interDir != 1) + { + xInheritedAffineMv(pu, puLeftBottom, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puLeftBottom->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puLeftBottom->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puLeftBottom->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puLeftBottom->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puLeftBottom->cu->altLMParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + // above left + const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType); + bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu); + if (isAvailableB2 && puAboveLeft->cu->affine && (puAboveLeft->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAboveLeft)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puAboveLeft->cu->affineType; + pu.cu->affineType = puAboveLeft->cu->affineType; + if (puAboveLeft->interDir != 2) + { + xInheritedAffineMv(pu, puAboveLeft, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puAboveLeft->interDir != 1) + { + xInheritedAffineMv(pu, puAboveLeft, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAboveLeft->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAboveLeft->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puAboveLeft->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puAboveLeft->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puAboveLeft->cu->altLMParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + int offsetX = 0; + int offsetY = 0; + int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1; + int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1; + + const int numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 }; + const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break; + case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX2; offsetY = offsetY1; break; + case 3:offsetX = offsetX0; offsetY = offsetY2; break; + case 4:offsetX = offsetX0; offsetY = offsetY1; break; + case 5:offsetX = -1; offsetY = offsetY0; break; + case 6:offsetX = offsetX1; offsetY = -1; break; + case 7:offsetX = offsetX0 >> 1; offsetY = offsetY0; break; + case 8:offsetX = offsetX1; offsetY = offsetY1 >> 1; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + if (isAvailableNonAdjacent && puNonAdjacent->cu->affine && (puNonAdjacent->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puNonAdjacent)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puNonAdjacent->cu->affineType; + pu.cu->affineType = puNonAdjacent->cu->affineType; + if (puNonAdjacent->interDir != 2) + { + xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puNonAdjacent->interDir != 1) + { + xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puNonAdjacent->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puNonAdjacent->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puNonAdjacent->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puNonAdjacent->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + } + } + + const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap2[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; + case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; + case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + if (isAvailableNonAdjacent && puNonAdjacent->cu->affine && (puNonAdjacent->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puNonAdjacent)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puNonAdjacent->cu->affineType; + pu.cu->affineType = puNonAdjacent->cu->affineType; + if (puNonAdjacent->interDir != 2) + { + xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puNonAdjacent->interDir != 1) + { + xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puNonAdjacent->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puNonAdjacent->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puNonAdjacent->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puNonAdjacent->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + } + } + + affMrgCtx.numValidMergeCand = cnt; + return; +} +#if JVET_AG0276_LIC_FLAG_SIGNALING +void PU::getAltLMBRAffineMergeCand(const PredictionUnit &pu, AltLMAffineMergeCtx& affMrgCtx) +{ + const uint32_t maxNumMergeCand = ALT_AFF_MRG_MAX_NUM_CANDS; + const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; + const CodingStructure& cs = *pu.cs; + const Slice& slice = *pu.cs->slice; + + for (int i = 0; i < maxNumMergeCand; i++) + { + affMrgCtx.initAltLMAffMergeCtx(i); + } + + int cnt = 0; + + const Position posLT = pu.Y().topLeft(); + const Position posRT = pu.Y().topRight(); + const Position posLB = pu.Y().bottomLeft(); + + const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); + bool isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && CU::isInter(*puAbove->cu); + if (isAvailableB1 && puAbove->cu->affine && (puAbove->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAbove, true)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puAbove->cu->affineType; + pu.cu->affineType = puAbove->cu->affineType; + if (puAbove->interDir != 2) + { + xInheritedAffineMv(pu, puAbove, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puAbove->interDir != 1) + { + xInheritedAffineMv(pu, puAbove, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAbove->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAbove->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puAbove->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puAbove->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puAbove->cu->altLMBRParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && CU::isInter(*puLeft->cu); + if (isAvailableA1 && puLeft->cu->affine && (puLeft->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puLeft, true)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puLeft->cu->affineType; + pu.cu->affineType = puLeft->cu->affineType; + if (puLeft->interDir != 2) + { + xInheritedAffineMv(pu, puLeft, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puLeft->interDir != 1) + { + xInheritedAffineMv(pu, puLeft, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puLeft->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puLeft->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puLeft->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puLeft->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puLeft->cu->altLMBRParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType); + const bool isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu); + if (isAvailableB0 && puAboveRight->cu->affine && (puAboveRight->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAboveRight, true)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puAboveRight->cu->affineType; + pu.cu->affineType = puAboveRight->cu->affineType; + if (puAboveRight->interDir != 2) + { + xInheritedAffineMv(pu, puAboveRight, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puAboveRight->interDir != 1) + { + xInheritedAffineMv(pu, puAboveRight, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAboveRight->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAboveRight->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puAboveRight->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puAboveRight->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puAboveRight->cu->altLMBRParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); + bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu); + if (isAvailableA0 && puLeftBottom->cu->affine && (puLeftBottom->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puLeftBottom, true)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puLeftBottom->cu->affineType; + pu.cu->affineType = puLeftBottom->cu->affineType; + if (puLeftBottom->interDir != 2) + { + xInheritedAffineMv(pu, puLeftBottom, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puLeftBottom->interDir != 1) + { + xInheritedAffineMv(pu, puLeftBottom, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puLeftBottom->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puLeftBottom->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puLeftBottom->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puLeftBottom->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puLeftBottom->cu->altLMBRParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType); + bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu); + if (isAvailableB2 && puAboveLeft->cu->affine && (puAboveLeft->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puAboveLeft, true)) + { + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puAboveLeft->cu->affineType; + pu.cu->affineType = puAboveLeft->cu->affineType; + if (puAboveLeft->interDir != 2) + { + xInheritedAffineMv(pu, puAboveLeft, REF_PIC_LIST_0, cMv[0]); + } + if (slice.isInterB()) + { + if (puAboveLeft->interDir != 1) + { + xInheritedAffineMv(pu, puAboveLeft, REF_PIC_LIST_1, cMv[1]); + } + } + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puAboveLeft->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puAboveLeft->refIdx[1]); + } + affMrgCtx.interDirNeighbours[cnt] = puAboveLeft->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puAboveLeft->cu->obmcFlag; +#endif + affMrgCtx.altLMParaNeighbours[cnt] = puAboveLeft->cu->altLMBRParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } + } + + if (cnt == maxNumMergeCand) + { + return; + } + + int offsetX = 0; + int offsetY = 0; + int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1; + int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1; + + const int numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 }; + const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break; + case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX2; offsetY = offsetY1; break; + case 3:offsetX = offsetX0; offsetY = offsetY2; break; + case 4:offsetX = offsetX0; offsetY = offsetY1; break; + case 5:offsetX = -1; offsetY = offsetY0; break; + case 6:offsetX = offsetX1; offsetY = -1; break; + case 7:offsetX = offsetX0 >> 1; offsetY = offsetY0; break; + case 8:offsetX = offsetX1; offsetY = offsetY1 >> 1; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); -#endif - - if (isAvailableNonAdjacent) + if (isAvailableNonAdjacent && puNonAdjacent->cu->affine && (puNonAdjacent->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puNonAdjacent, true)) { - miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); - - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; - // get Mv from Above-Left - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); - mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; - // get Mv from Above-right - mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; -#if INTER_LIC - mrgCtx.licFlags[cnt] = miNeighbor.usesLIC; -#endif - if (slice.isInterB()) + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puNonAdjacent->cu->affineType; + pu.cu->affineType = puNonAdjacent->cu->affineType; + if (puNonAdjacent->interDir != 2) { - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData; -#endif + xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_0, cMv[0]); } - -#if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt -#if TM_MRG - , mvdSimilarityThresh -#endif - )) -#endif + if (slice.isInterB()) { - cnt++; + if (puNonAdjacent->interDir != 1) + { + xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_1, cMv[1]); + } } -#if JVET_AD0213_LIC_IMP - else + for (int mvNum = 0; mvNum < 3; mvNum++) { - mrgCtx.initMrgCand(cnt); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puNonAdjacent->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puNonAdjacent->refIdx[1]); } + affMrgCtx.interDirNeighbours[cnt] = puNonAdjacent->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puNonAdjacent->cu->obmcFlag; #endif + affMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMBRParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } } - } } @@ -13154,66 +14820,56 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) { switch (idxMap2[iDistanceIndex][iNASPIdx]) { - case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; - case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; - case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; - case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; - default: printf("error!"); exit(0); break; + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; + case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; + case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; + default: printf("error!"); exit(0); break; } const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); -#if JVET_Y0065_GPM_INTRA - bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter; -#else bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); -#endif - - if (isAvailableNonAdjacent) + if (isAvailableNonAdjacent && puNonAdjacent->cu->affine && (puNonAdjacent->mergeType == MRG_TYPE_DEFAULT_N) && PU::isValidAltMergeCandidate(*puNonAdjacent, true)) { - miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); - - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; - // get Mv from Above-Left - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); - mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; - // get Mv from Above-right - mrgCtx.bcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; -#if INTER_LIC - mrgCtx.licFlags[cnt] = miNeighbor.usesLIC; -#endif - if (slice.isInterB()) + Mv cMv[2][3]; + affMrgCtx.affineType[cnt] = (EAffineModel)puNonAdjacent->cu->affineType; + pu.cu->affineType = puNonAdjacent->cu->affineType; + if (puNonAdjacent->interDir != 2) { - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData; -#endif + xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_0, cMv[0]); } - -#if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt -#if TM_MRG - , mvdSimilarityThresh -#endif - )) -#endif + if (slice.isInterB()) { - cnt++; + if (puNonAdjacent->interDir != 1) + { + xInheritedAffineMv(pu, puNonAdjacent, REF_PIC_LIST_1, cMv[1]); + } } -#if JVET_AD0213_LIC_IMP - else + for (int mvNum = 0; mvNum < 3; mvNum++) { - mrgCtx.initMrgCand(cnt); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField(cMv[0][mvNum], puNonAdjacent->refIdx[0]); + affMrgCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum].setMvField(cMv[1][mvNum], puNonAdjacent->refIdx[1]); } + affMrgCtx.interDirNeighbours[cnt] = puNonAdjacent->interDir; + affMrgCtx.bcwIdx[cnt] = (affMrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->bcwIdx : BCW_DEFAULT; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affMrgCtx.obmcFlags[cnt] = puNonAdjacent->cu->obmcFlag; #endif + affMrgCtx.altLMParaNeighbours[cnt] = puNonAdjacent->cu->altLMBRParaUnit; + if (affMrgCtx.xCheckSameAffMotion(pu, cnt)) + { + cnt++; + } } } } - mrgCtx.numValidMergeCand = cnt; + affMrgCtx.numValidMergeCand = cnt; + return; } #endif +#endif bool PU::checkDMVRCondition(const PredictionUnit& pu) { @@ -13378,6 +15034,35 @@ bool PU::checkBDMVRCondition(const PredictionUnit& pu) const bool ref1IsScaled = refIdx1 < 0 || refIdx1 >= MAX_NUM_REF ? false : isResamplingPossible && pu.cu->slice->getRefPic( REF_PIC_LIST_1, refIdx1 )->isRefScaled( pu.cs->pps ); +#if JVET_AG0276_LIC_BDOF_BDMVR + bool meetBdmvrCondition = ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.mmvdMergeFlag + && !pu.cu->mmvdSkip +#if JVET_AG0067_DMVR_EXTENSIONS + && (PU::isBiPredFromDifferentDirEqDistPoc( pu ) || (PU::isBiPredFromDifferentDirGenDistPoc( pu ) && !pu.cu->geoFlag)) +#else + && PU::isBiPredFromDifferentDirEqDistPoc(pu) +#endif + && !WPScalingParam::isWeighted(wp0) && !WPScalingParam::isWeighted(wp1) && !ref0IsScaled && !ref1IsScaled; + if (pu.cu->geoFlag || pu.cu->affine) + { + meetBdmvrCondition &= (pu.cu->licFlag == false); + } + if (pu.cu->licFlag == true) + { + meetBdmvrCondition &= (pu.tmMergeFlag == false); + } +#if JVET_AG0276_NLIC + if (pu.cu->altLMFlag) + { + meetBdmvrCondition = false; + } +#endif + return meetBdmvrCondition +#if JVET_AG0276_LIC_FLAG_SIGNALING + && !PU::isOppositeLIC(pu) +#endif + ; +#else #if JVET_AB0112_AFFINE_DMVR #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS return ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.mmvdMergeFlag @@ -13395,19 +15080,79 @@ bool PU::checkBDMVRCondition(const PredictionUnit& pu) #else && PU::isBiPredFromDifferentDirEqDistPoc( pu ) #endif +#if JVET_AG0276_NLIC + && !pu.cu->altLMFlag +#endif #if JVET_AD0213_LIC_IMP && !pu.cu->licFlag +#if JVET_AG0276_LIC_FLAG_SIGNALING + && !PU::isOppositeLIC(pu) +#endif #endif #if !JVET_Y0089_DMVR_BCW && ( pu.cu->bcwIdx == BCW_DEFAULT ) #endif && !WPScalingParam::isWeighted( wp0 ) && !WPScalingParam::isWeighted( wp1 ) && !ref0IsScaled && !ref1IsScaled; +#endif + } + else + { + return false; + } +} +#if JVET_AG0276_LIC_BDOF_BDMVR +bool PU::checkBDMVRCondition4Aff(const PredictionUnit& pu) +{ + if (pu.cs->sps->getUseDMVDMode()) + { + const int refIdx0 = pu.refIdx[REF_PIC_LIST_0]; + const int refIdx1 = pu.refIdx[REF_PIC_LIST_1]; + + const WPScalingParam *wp0 = pu.cu->slice->getWpScaling(REF_PIC_LIST_0, refIdx0); + const WPScalingParam *wp1 = pu.cu->slice->getWpScaling(REF_PIC_LIST_1, refIdx1); + + const bool isResamplingPossible = pu.cs->sps->getRprEnabledFlag(); + + const bool ref0IsScaled = refIdx0 < 0 || refIdx0 >= MAX_NUM_REF + ? false + : isResamplingPossible && pu.cu->slice->getRefPic(REF_PIC_LIST_0, refIdx0)->isRefScaled(pu.cs->pps); + const bool ref1IsScaled = refIdx1 < 0 || refIdx1 >= MAX_NUM_REF + ? false + : isResamplingPossible && pu.cu->slice->getRefPic(REF_PIC_LIST_1, refIdx1)->isRefScaled(pu.cs->pps); +#if JVET_AB0112_AFFINE_DMVR +#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS + return ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.mmvdMergeFlag +#else + return ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N && (!pu.cu->affine || !pu.afMmvdFlag)) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.mmvdMergeFlag +#endif +#elif JVET_X0083_BM_AMVP_MERGE_MODE + return ((pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1])) && !pu.ciipFlag && !pu.cu->affine && !pu.mmvdMergeFlag +#else + return pu.mergeFlag && pu.mergeType == MRG_TYPE_DEFAULT_N && !pu.ciipFlag && !pu.cu->affine && !pu.mmvdMergeFlag +#endif + && !pu.cu->mmvdSkip +#if JVET_AG0067_DMVR_EXTENSIONS + && (PU::isBiPredFromDifferentDirEqDistPoc(pu) || (PU::isBiPredFromDifferentDirGenDistPoc(pu) && !pu.cu->geoFlag)) +#else + && PU::isBiPredFromDifferentDirEqDistPoc(pu) +#endif +#if JVET_AG0276_NLIC + && !pu.cu->altLMFlag +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + && !PU::isOppositeLIC(pu) +#endif +#if !JVET_Y0089_DMVR_BCW + && (pu.cu->bcwIdx == BCW_DEFAULT) +#endif + && !WPScalingParam::isWeighted(wp0) && !WPScalingParam::isWeighted(wp1) && !ref0IsScaled && !ref1IsScaled; } else { return false; } } +#endif #if JVET_AG0135_AFFINE_CIIP #if JVET_AE0046_BI_GPM bool PU::checkBDMVRConditionCIIPAffine(const PredictionUnit& pu, bool disregardGpmFlag) @@ -13457,9 +15202,13 @@ bool PU::checkBDMVRConditionCIIPAffine(const PredictionUnit& pu) #else && PU::isBiPredFromDifferentDirEqDistPoc(pu) #endif -#if JVET_AD0213_LIC_IMP +#if JVET_AD0213_LIC_IMP && !JVET_AG0276_LIC_BDOF_BDMVR && !pu.cu->licFlag #endif +#if JVET_AG0276_NLIC + && !pu.cu->altLMFlag +#endif + #if !JVET_Y0089_DMVR_BCW && (pu.cu->bcwIdx == BCW_DEFAULT) #endif @@ -15762,7 +17511,11 @@ bool PU::addMergeHMVPCandFromAffModel(const PredictionUnit& pu, MergeCtx& mrgCtx #endif #if INTER_LIC #if JVET_AD0213_LIC_IMP +#if JVET_AG0276_NLIC + , puNei->cu->licFlag || (puNei->cu->altLMFlag && puNei->cu->slice->getUseLIC()) +#else , puNei->cu->licFlag +#endif #else , mvInfo.interDir != 3 ? puNei->cu->licFlag : false #endif @@ -15834,7 +17587,11 @@ bool PU::addMergeHMVPCandFromAffModel(const PredictionUnit& pu, MergeCtx& mrgCtx #endif #if INTER_LIC #if JVET_AD0213_LIC_IMP +#if JVET_AG0276_NLIC + , puNei->cu->licFlag || (puNei->cu->altLMFlag && puNei->cu->slice->getUseLIC()) +#else , puNei->cu->licFlag +#endif #else , mvInfo.interDir != 3 ? puNei->cu->licFlag : false #endif @@ -17829,6 +19586,10 @@ void PU::getNonAdjCstMergeCand(const PredictionUnit &pu, AffineMergeCtx &affMrgC affMrgCtx.affineType[i] = AFFINEMODEL_4PARAM; affMrgCtx.mergeType[i] = MRG_TYPE_DEFAULT_N; affMrgCtx.bcwIdx[i] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + affMrgCtx.altLMFlag[i] = false; + affMrgCtx.altLMParaNeighbours[i].resetAltLinearModel(); +#endif #if INTER_LIC affMrgCtx.licFlags[i] = false; #endif @@ -18005,7 +19766,6 @@ const int getAvailableAffineNeighboursForAbovePredictor( const PredictionUnit &p return num; } - void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx, #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION MergeCtx mrgCtxIn[2], @@ -18065,6 +19825,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx affMrgCtx.affineType[i] = AFFINEMODEL_4PARAM; affMrgCtx.mergeType[i] = MRG_TYPE_DEFAULT_N; affMrgCtx.bcwIdx[i] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + affMrgCtx.altLMFlag[i] = false; + affMrgCtx.altLMParaNeighbours[i].resetAltLinearModel(); +#endif #if INTER_LIC affMrgCtx.licFlags[i] = false; #endif @@ -18554,6 +20318,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx affMrgCtxTemp.affineType[i] = AFFINEMODEL_4PARAM; affMrgCtxTemp.mergeType[i] = MRG_TYPE_DEFAULT_N; affMrgCtxTemp.bcwIdx[i] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + affMrgCtxTemp.altLMFlag[i] = false; + affMrgCtxTemp.altLMParaNeighbours[i].resetAltLinearModel(); +#endif #if INTER_LIC affMrgCtxTemp.licFlags[i] = false; #endif @@ -18599,6 +20367,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = EAffineModel(affMrgCtxTemp.affineType[i]); affMrgCtx.mergeType[affMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N; affMrgCtx.bcwIdx[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.bcwIdx[i]; +#if JVET_AG0276_NLIC + affMrgCtx.altLMFlag[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.altLMFlag[i]; + affMrgCtx.altLMParaNeighbours[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.altLMParaNeighbours[i]; +#endif #if INTER_LIC affMrgCtx.licFlags[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.licFlags[i]; #endif @@ -18651,6 +20423,10 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = EAffineModel(affMrgCtxTemp.affineType[i]); affMrgCtx.mergeType[affMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N; affMrgCtx.bcwIdx[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.bcwIdx[i]; +#if JVET_AG0276_NLIC + affMrgCtx.altLMFlag[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.altLMFlag[i]; + affMrgCtx.altLMParaNeighbours[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.altLMParaNeighbours[i]; +#endif #if INTER_LIC affMrgCtx.licFlags[affMrgCtx.numValidMergeCand] = affMrgCtxTemp.licFlags[i]; #endif @@ -19372,6 +21148,10 @@ void PU::getBMAffineMergeCand(const PredictionUnit &pu, AffineMergeCtx& affineBM affineBMMergeCtx.affineType[i] = AFFINEMODEL_4PARAM; affineBMMergeCtx.mergeType[i] = MRG_TYPE_DEFAULT_N; affineBMMergeCtx.bcwIdx[i] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + affineBMMergeCtx.altLMFlag[i] = false; + affineBMMergeCtx.altLMParaNeighbours[i].resetAltLinearModel(); +#endif #if INTER_LIC affineBMMergeCtx.licFlags[i] = false; #endif @@ -19537,6 +21317,10 @@ void PU::getBMAffineMergeCand(const PredictionUnit &pu, AffineMergeCtx& affineBM affineBMMergeCtx.affineType[affineBMMergeCtx.numValidMergeCand] = EAffineModel(affineMergeRMVFCtx.affineType[i]); affineBMMergeCtx.mergeType[affineBMMergeCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N; affineBMMergeCtx.bcwIdx[affineBMMergeCtx.numValidMergeCand] = affineMergeRMVFCtx.bcwIdx[i]; +#if JVET_AG0276_NLIC + affineBMMergeCtx.altLMFlag[affineBMMergeCtx.numValidMergeCand] = affineMergeRMVFCtx.altLMFlag[i]; + affineBMMergeCtx.altLMParaNeighbours[affineBMMergeCtx.numValidMergeCand] = affineMergeRMVFCtx.altLMParaNeighbours[i]; +#endif #if INTER_LIC affineBMMergeCtx.licFlags[affineBMMergeCtx.numValidMergeCand] = affineMergeRMVFCtx.licFlags[i]; #endif @@ -20244,7 +22028,15 @@ void PU::getBMAffineMergeCand(const PredictionUnit &pu, AffineMergeCtx& affineBM affineBMMergeCtx.numValidMergeCand++; } } -void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMergeRMVFCtx, AffineMergeCtx& affineMergeRMVFOriCtx, InterPrediction* m_pcInterSearch, uint16_t &numCand) +void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMergeRMVFCtx, AffineMergeCtx& affineMergeRMVFOriCtx, InterPrediction* m_pcInterSearch + , uint16_t &numCand +#if JVET_AG0276_NLIC + , AltLMAffineMergeCtx& altAffineMergeRMVFCtx +#if JVET_AG0276_LIC_FLAG_SIGNALING + , AltLMAffineMergeCtx& altBRAffineMergeRMVFCtx +#endif +#endif +) { const int CHECKED_NEI_NUM = 7; const PredictionUnit *npu[CHECKED_NEI_NUM + AFF_MAX_NON_ADJACENT_INHERITED_CANDS + MAX_NUM_AFF_INHERIT_HMVP_CANDS]; @@ -20260,6 +22052,10 @@ void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMerge affMrgCtxTemp.affineType[i] = AFFINEMODEL_4PARAM; affMrgCtxTemp.mergeType[i] = MRG_TYPE_DEFAULT_N; affMrgCtxTemp.bcwIdx[i] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + affMrgCtxTemp.altLMFlag[i] = false; + affMrgCtxTemp.altLMParaNeighbours[i].resetAltLinearModel(); +#endif #if INTER_LIC affMrgCtxTemp.licFlags[i] = false; #endif @@ -20285,7 +22081,14 @@ void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMerge { for (int i = 0; i < numAffNeighExtend2; i++) { - getRMVFAffineGuideCand(pu, *npu[i], affMrgCtxTemp, mvpInfoVec); + getRMVFAffineGuideCand(pu, *npu[i], affMrgCtxTemp, mvpInfoVec, -1 +#if JVET_AG0276_NLIC + , &altAffineMergeRMVFCtx +#if JVET_AG0276_LIC_FLAG_SIGNALING + , &altBRAffineMergeRMVFCtx +#endif +#endif + ); if (affMrgCtxTemp.numValidMergeCand == affMrgCtxTemp.maxNumMergeCand) { break; @@ -20324,7 +22127,14 @@ void PU::getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMerge #endif for (int i = 0; i < numAffNeighExtend2; i++) { - getRMVFAffineGuideCand(pu, *npu[i], affMrgCtxTemp, mvpInfoVec, -1); + getRMVFAffineGuideCand(pu, *npu[i], affMrgCtxTemp, mvpInfoVec, -1 +#if JVET_AG0276_NLIC + , &altAffineMergeRMVFCtx +#if JVET_AG0276_LIC_FLAG_SIGNALING + , &altBRAffineMergeRMVFCtx +#endif +#endif + ); if (affMrgCtxTemp.numValidMergeCand == affMrgCtxTemp.maxNumMergeCand) { break; @@ -20897,6 +22707,12 @@ void PU::setAffineBdofRefinedMotion(PredictionUnit &pu, Mv* mvBufDecAffineBDOF) } bool PU::checkDoAffineBdofRefine(const PredictionUnit &pu, InterPrediction *interPred) { +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.affineOppositeLic) + { + return false; + } +#endif #if JVET_AG0098_AMVP_WITH_SBTMVP if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP || pu.amvpSbTmvpFlag) #else @@ -20909,6 +22725,12 @@ bool PU::checkDoAffineBdofRefine(const PredictionUnit &pu, InterPrediction *inte { return false; } +#if JVET_AG0276_NLIC && !JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->altLMFlag) + { + return false; + } +#endif const WPScalingParam *wp0 = pu.cu->slice->getWpScaling( REF_PIC_LIST_0, pu.refIdx[0] ); const WPScalingParam *wp1 = pu.cu->slice->getWpScaling( REF_PIC_LIST_1, pu.refIdx[1] ); const bool isResamplingPossible = pu.cs->sps->getRprEnabledFlag(); @@ -21001,6 +22823,10 @@ void PU::getTMVPCandOpt(const PredictionUnit &pu, RefPicList refList, int refIdx for (uint32_t ui = 0; ui < pu.cs->sps->getMaxNumMergeCand(); ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -22585,6 +24411,10 @@ void PU::getGeoMergeCandidates( const PredictionUnit &pu, MergeCtx& geoMrgCtx ) geoMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv(); geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv(); geoMrgCtx.useAltHpelIf[i] = false; +#if JVET_AG0276_NLIC + geoMrgCtx.altLMFlag[i] = false; + geoMrgCtx.altLMParaNeighbours[i].resetAltLinearModel(); +#endif #if INTER_LIC geoMrgCtx.licFlags[i] = false; #endif @@ -22634,6 +24464,10 @@ void PU::getGeoMergeCandidates( const PredictionUnit &pu, MergeCtx& geoMrgCtx ) { geoMrgCtx.useAltHpelIf[i] = false; geoMrgCtx.bcwIdx[i] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + geoMrgCtx.altLMFlag[i] = false; + geoMrgCtx.altLMParaNeighbours[i].resetAltLinearModel(); +#endif #if INTER_LIC geoMrgCtx.licFlags[i] = false; #endif @@ -25154,6 +26988,22 @@ unsigned int PU::getSameNeigMotion(PredictionUnit &pu, MotionInfo& mi, Position } } } +#endif +#if JVET_AG0276_NLIC + if (bIsSimilarMV) + { + if (tmpPu->cu->altLMFlag != pu.cu->altLMFlag) + { + bIsSimilarMV = false; + } + else if (tmpPu->cu->altLMFlag) + { + if (tmpPu->cu->secAltLMParaUnit.scale[0] != pu.cu->altLMParaUnit.scale[0] || tmpPu->cu->secAltLMParaUnit.offset[0] != pu.cu->altLMParaUnit.offset[0]) + { + bIsSimilarMV = false; + } + } + } #endif for (unsigned int idx = 1; idx < iMaxLength; idx++) { @@ -25234,6 +27084,22 @@ unsigned int PU::getSameNeigMotion(PredictionUnit &pu, MotionInfo& mi, Position } } } +#endif +#if JVET_AG0276_NLIC + if (bSameMv) + { + if (tmpPu1->cu->altLMFlag != tmpPu->cu->altLMFlag) + { + bSameMv = false; + } + else if (tmpPu1->cu->altLMFlag) + { + if (tmpPu1->cu->secAltLMParaUnit.scale[0] != tmpPu->cu->secAltLMParaUnit.scale[0] || tmpPu1->cu->secAltLMParaUnit.offset[0] != tmpPu->cu->secAltLMParaUnit.offset[0]) + { + bSameMv = false; + } + } + } #endif } #if JVET_AD0213_LIC_IMP @@ -25673,6 +27539,37 @@ void PU::spanLicFlags(PredictionUnit &pu, const bool LICFlag) motionInfo += mb.stride; } } + +#if JVET_AG0276_LIC_SLOPE_ADJUST +bool CU::isLicSlopeAllowed(const CodingUnit& cu) +{ + if (!cu.cs->sps->getLicSlopeAdjustEnabledFlag()) + { + return false; + } + if (!cu.lx() && !cu.ly()) + { + return false; + } + if (!licSlopeSizeTlCond(cu.lwidth(), cu.lheight(), cu.cs->slice->getTLayer())) + { + return false; + } + return true; +} +bool CU::licSlopeSizeTlCond(const int bw, const int bh, const int layerId) +{ + if (bw*bh > 4096 || bw*bh < 64 || bw >= 128 || bh >= 128 || bw == 4 || bh == 4 || (bw >= 64 && bh >=64)) + { + return false; + } + if (layerId >= 5) + { + return false; + } + return true; +} +#endif #endif #if SIGN_PREDICTION @@ -26767,6 +28664,10 @@ void PU::getGeoAffMergeCandidates(PredictionUnit& pu, AffineMergeCtx& gpmAffMrgC gpmAffMrgCtx.affineType[i] = AFFINEMODEL_6PARAM; gpmAffMrgCtx.mergeType[i] = MRG_TYPE_DEFAULT_N; gpmAffMrgCtx.bcwIdx[i] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + gpmAffMrgCtx.altLMFlag[i] = false; + gpmAffMrgCtx.altLMParaNeighbours[i].resetAltLinearModel(); +#endif #if INTER_LIC gpmAffMrgCtx.licFlags[i] = false; #endif @@ -26794,10 +28695,25 @@ void PU::getGeoAffMergeCandidates(PredictionUnit& pu, AffineMergeCtx& gpmAffMrgC #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS AffineMergeCtx affineRMVFCtx; AffineMergeCtx affineRMVFOriCtx; + +#if JVET_AG0276_NLIC + AltLMAffineMergeCtx altAffineRMVFCtx; + altAffineRMVFCtx.init(); +#if JVET_AG0276_LIC_FLAG_SIGNALING + AltLMAffineMergeCtx altBRAffineRMVFCtx; + altBRAffineRMVFCtx.init(); +#endif +#endif uint16_t addNumRMVF = 0; - PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, pcInterPred, addNumRMVF); + PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, pcInterPred, addNumRMVF +#if JVET_AG0276_NLIC + , altAffineRMVFCtx +#if JVET_AG0276_LIC_FLAG_SIGNALING + , altBRAffineRMVFCtx +#endif +#endif + ); #endif - PU::getAffineMergeCand(pu, tmpMergeCtx #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION , mrgCtxAll @@ -27163,7 +29079,8 @@ bool getAllowedEipMerge(const CodingUnit& cu, const ComponentID compId) return false; } -int getAllowedCurEip(const CodingUnit &cu, const ComponentID compId, static_vector<EIPInfo, NUM_DERIVED_EIP>& eipInfoList) { +int getAllowedCurEip(const CodingUnit &cu, const ComponentID compId, static_vector<EIPInfo, NUM_DERIVED_EIP>& eipInfoList) +{ const int numOfCombEIP[4][4] = { { 3, 3, 3, 2 }, diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 3ff91519c..739b85154 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -64,6 +64,12 @@ namespace CS // CU tools namespace CU { +#if JVET_AG0276_NLIC + bool isSecLicParaNeeded (const CodingUnit &cu); + bool isPredRefined (const CodingUnit &cu); + bool isAllowSecLicPara (const CodingUnit &cu); + bool isTLCond (const CodingUnit &cu); +#endif bool isIntra (const CodingUnit &cu); bool isInter (const CodingUnit &cu); bool isIBC (const CodingUnit &cu); @@ -118,6 +124,10 @@ namespace CU #endif #if INTER_LIC bool isLICFlagPresent (const CodingUnit& cu); +#if JVET_AG0276_LIC_SLOPE_ADJUST + bool isLicSlopeAllowed (const CodingUnit& cu); + bool licSlopeSizeTlCond (const int bw, const int bh, const int layerId); +#endif #endif #if JVET_AC0130_NSPT bool isNSPTAllowed ( const TransformUnit& tu, const ComponentID compID, int width, int height, bool isIntra ); @@ -304,6 +314,16 @@ namespace PU , bool enableTh4Gpm = false #endif ); +#if JVET_AG0276_NLIC + void getAltMergeCandidates (const PredictionUnit &pu, AltLMMergeCtx& cMrgCtx); +#if JVET_AG0276_LIC_FLAG_SIGNALING + void getAltBRMergeCandidates (const PredictionUnit &pu, AltLMMergeCtx& cMrgCtx); + bool isValidAltMergeCandidate (const PredictionUnit &pu, bool isBRCand = false); +#else + bool isValidAltMergeCandidate (const PredictionUnit &pu); +#endif + uint32_t getAltMergeMvdThreshold (const PredictionUnit &pu); +#endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION void getNonAdjacentMergeCandSubTMVP(const PredictionUnit &pu, MergeCtx& mvpMrgCtx, int col); @@ -428,7 +448,14 @@ namespace PU , const MvpDir &eDir #endif ); - void getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit &abovePU, AffineMergeCtx &affMrgCtx, std::vector<RMVFInfo> mvp[NUM_REF_PIC_LIST_01][MAX_NUM_REF], int mrgCandIdx = -1); + void getRMVFAffineGuideCand(const PredictionUnit &pu, const PredictionUnit &abovePU, AffineMergeCtx &affMrgCtx, std::vector<RMVFInfo> mvp[NUM_REF_PIC_LIST_01][MAX_NUM_REF], int mrgCandIdx = -1 +#if JVET_AG0276_NLIC + , AltLMAffineMergeCtx* altAffineMergeCtx = NULL +#if JVET_AG0276_LIC_FLAG_SIGNALING + , AltLMAffineMergeCtx* altBRAffineMergeCtx = NULL +#endif +#endif + ); Position convertNonAdjAffineBlkPos(const Position &pos, int curCtuX, int curCtuY); void collectNeiMotionInfo(std::vector<RMVFInfo> mvpInfoVec[NUM_REF_PIC_LIST_01][MAX_NUM_REF], const PredictionUnit &pu); #endif @@ -603,9 +630,23 @@ namespace PU , bool noSbTMVP = false #endif ); +#if JVET_AG0276_NLIC + void getAltLMAffineMergeCand(const PredictionUnit &pu, AltLMAffineMergeCtx& altLMAffMrgCtx); +#if JVET_AG0276_LIC_FLAG_SIGNALING + void getAltLMBRAffineMergeCand(const PredictionUnit &pu, AltLMAffineMergeCtx& altLMAffMrgCtx); +#endif +#endif #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS bool isAffBMMergeFlagCoded(const PredictionUnit& pu); - void getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMergeRMVFCtx, AffineMergeCtx& affineMergeRMVFOriCtx, InterPrediction* m_pcInterSearch, uint16_t &numCand); + void getRMVFAffineCand(const PredictionUnit &pu, AffineMergeCtx& affineMergeRMVFCtx, AffineMergeCtx& affineMergeRMVFOriCtx, InterPrediction* m_pcInterSearch + , uint16_t &numCand +#if JVET_AG0276_NLIC + , AltLMAffineMergeCtx& altAffineMergeRMVFCtx +#if JVET_AG0276_LIC_FLAG_SIGNALING + , AltLMAffineMergeCtx& altBRAffineMergeRMVFCtx +#endif +#endif + ); void getBMAffineMergeCand(const PredictionUnit &pu, AffineMergeCtx& affineBMMergeCtx, AffineMergeCtx affineMergeRMVFCtx, int mrgCandIdx = -1); bool getBMNonAdjCstMergeCand(const PredictionUnit &pu, AffineMergeCtx &affMrgCtx, const int mrgCandIdx = -1); #endif @@ -773,6 +814,9 @@ namespace PU #else bool checkBDMVRCondition(const PredictionUnit& pu); #endif +#if JVET_AG0276_LIC_BDOF_BDMVR + bool checkBDMVRCondition4Aff(const PredictionUnit& pu); +#endif #endif #if INTER_LIC && RPR_ENABLE bool checkRprLicCondition(const PredictionUnit& pu); @@ -889,6 +933,10 @@ namespace PU bool isBvgCccmCand(const PredictionUnit &pu, Mv &chromaBv, int& rrIbcType, int candIdx = 0); bool checkIsChromaBvCandidateValid(const PredictionUnit &pu, const Mv chromaBv, int &iWidth, int &iHeight, bool isRefTemplate = false, bool isRefAbove = false); #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool isOppositeLIC(const PredictionUnit &pu); + bool hasOppositeLICFlag(const PredictionUnit &pu); +#endif } // TU tools diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 26d78f18c..ec2cbd343 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -5155,6 +5155,13 @@ void CABACReader::merge_data( PredictionUnit& pu ) { affBmFlag(pu); } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.affineOppositeLic = false; + if (PU::hasOppositeLICFlag(pu) && !pu.afMmvdFlag && !pu.affBMMergeFlag && pu.cs->sps->getUseAffMergeOppositeLic()) + { + pu.affineOppositeLic = m_BinDecoder.decodeBin(Ctx::AffineFlagOppositeLic(0)); + } #endif merge_idx(pu); cu.firstPU->regularMergeFlag = false; @@ -5334,6 +5341,21 @@ void CABACReader::merge_data( PredictionUnit& pu ) } else { +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.mergeOppositeLic = false; + pu.tmMergeFlagOppositeLic = false; + if (pu.regularMergeFlag && PU::hasOppositeLICFlag(pu) && !pu.bmMergeFlag) + { + if (pu.tmMergeFlag && pu.cs->sps->getUseTMMergeOppositeLic()) + { + pu.tmMergeFlagOppositeLic = m_BinDecoder.decodeBin(Ctx::TmMergeFlagOppositeLic(0)); + } + else if (pu.cs->sps->getUseMergeOppositeLic()) + { + pu.mergeOppositeLic = m_BinDecoder.decodeBin(Ctx::MergeFlagOppositeLic(0)); + } + } +#endif merge_idx(pu); } } @@ -5359,6 +5381,12 @@ void CABACReader::merge_idx( PredictionUnit& pu ) } #endif int numCandminus1 = int( pu.cs->picHeader->getMaxNumAffineMergeCand() ) - 1; +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.affineOppositeLic) + { + numCandminus1 = int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1; + } +#endif pu.mergeIdx = 0; if ( numCandminus1 > 0 ) { @@ -5659,6 +5687,16 @@ void CABACReader::merge_idx( PredictionUnit& pu ) { numCandminus1 = int(pu.cs->sps->getMaxNumBMMergeCand()) - 1; } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { + numCandminus1 = int(pu.cs->sps->getMaxNumOppositeLicMergeCand()) - 1; + } + else if (pu.tmMergeFlagOppositeLic) + { + numCandminus1 = int(pu.cs->sps->getMaxNumTMOppositeLicMergeCand()) - 1; + } #endif if( numCandminus1 > 0 ) { @@ -9596,8 +9634,24 @@ void CABACReader::cu_lic_flag( CodingUnit& cu ) if( CU::isLICFlagPresent( cu ) ) { RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE( STATS__CABAC_BITS__LIC_FLAG, cu.lumaSize() ); +#if JVET_AG0276_LIC_SLOPE_ADJUST + unsigned ctxId = DeriveCtx::CtxLicFlag( cu ); + cu.licFlag = m_BinDecoder.decodeBin( Ctx::LICFlag( ctxId ) ); +#else cu.licFlag = m_BinDecoder.decodeBin( Ctx::LICFlag( 0 ) ); +#endif DTRACE( g_trace_ctx, D_SYNTAX, "cu_lic_flag() lic_flag=%d\n", cu.licFlag ? 1 : 0 ); +#if JVET_AG0276_LIC_SLOPE_ADJUST + if (cu.licFlag && CU::isLicSlopeAllowed(cu) && cu.firstPU->interDir != 3) + { + int delta = m_BinDecoder.decodeBin(Ctx::LicDelta(0)) ? 1 : 0; + if (delta) + { + delta *= m_BinDecoder.decodeBin(Ctx::LicDelta(1)) ? -1 : +1; + } + cu.licDelta = delta; + } +#endif } } #endif diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 92f202d31..fdb821d79 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -1978,9 +1978,57 @@ void DecCu::xReconInter(CodingUnit &cu) } } #endif +#if JVET_AG0276_NLIC + if (!cu.cs->pcv->isEncoder) + { + if (CU::isSecLicParaNeeded(cu)) + { + UnitArea localUnitArea(cu.chromaFormat, Area(0, 0, cu.lumaSize().width, cu.lumaSize().height)); + PelUnitBuf predBeforeMCAdjBuffer = m_pcInterPred->m_acPredBeforeLICBuffer[REF_PIC_LIST_0].getBuf(localUnitArea); + + if (CU::isAllowSecLicPara(cu)) + { + if (CU::isPredRefined(cu)) + { +#if INTER_LIC + bool orgLicFlag = cu.licFlag; + cu.licFlag = false; +#endif + bool orgCiipFlag = cu.firstPU->ciipFlag; + cu.firstPU->ciipFlag = false; + m_pcInterPred->xPredWoRefinement(*cu.firstPU, predBeforeMCAdjBuffer); +#if INTER_LIC + cu.licFlag = orgLicFlag; +#endif + cu.firstPU->ciipFlag = orgCiipFlag; + } + else + { + predBeforeMCAdjBuffer.copyFrom(cu.cs->getPredBuf(*cu.firstPU)); + } + } + else + { + if (cu.affine && cu.firstPU->mergeFlag && cu.cs->sps->getUseOBMC() && cu.obmcFlag && (cu.cs->sps->getUseAltLM() || cu.cs->sps->getUseAffAltLM())) + { + if (cu.obmcFlag && m_pcInterPred->isSCC(*cu.firstPU) && !CU::isTLCond(cu)) + { + cu.obmcFlag = false; + } + } + } + } + } +#endif #if MULTI_PASS_DMVR if (cu.firstPU->bdmvrRefine) { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (cu.licFlag == true) + { + memset((void*)m_pcInterPred->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv)); + } +#endif PU::spanMotionInfo(*cu.firstPU, MergeCtx(), #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION cu.firstPU->colIdx, @@ -2177,6 +2225,43 @@ void DecCu::xReconInter(CodingUnit &cu) #endif #endif +#if JVET_AG0276_NLIC + if (!cu.cs->pcv->isEncoder) + { + if (cu.altLMFlag) + { + cu.secAltLMParaUnit = cu.altLMParaUnit; + } + else + { + cu.secAltLMParaUnit = cu.altLMParaUnit; + } + if (CU::isSecLicParaNeeded(cu) && CU::isAllowSecLicPara(cu)) + { + UnitArea localUnitArea(cu.chromaFormat, Area(0, 0, cu.lumaSize().width, cu.lumaSize().height)); + PelUnitBuf predBeforeMCAdjBuffer = m_pcInterPred->m_acPredBeforeLICBuffer[REF_PIC_LIST_0].getBuf(localUnitArea); + PelUnitBuf recBuf = m_pcInterPred->m_acPredBeforeLICBuffer[REF_PIC_LIST_1].getBuf(localUnitArea); + recBuf.copyFrom(cu.cs->getRecoBuf(*cu.firstPU)); + if (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) + { + recBuf.Y().rspSignal(m_pcInterPred->m_pcReshape->getInvLUT()); + } +#if JVET_AG0276_LIC_FLAG_SIGNALING + m_pcInterPred->xDevSecLicPara<false>(cu, predBeforeMCAdjBuffer, recBuf); +#else + m_pcInterPred->xDevSecLicPara(cu, predBeforeMCAdjBuffer, recBuf); +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + m_pcInterPred->xDevSecLicPara<true>(cu, predBeforeMCAdjBuffer, recBuf); + if ((cu.altLMBRParaUnit.scale[COMPONENT_Y] == cu.altLMParaUnit.scale[COMPONENT_Y]) && (cu.altLMBRParaUnit.offset[COMPONENT_Y] == cu.altLMParaUnit.offset[COMPONENT_Y])) + { + cu.altLMBRParaUnit.resetAltLinearModel(); + } +#endif + } + } +#endif + DTRACE ( g_trace_ctx, D_TMP, "reco " ); DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getRecoBuf( cu ), &cu.Y() ); @@ -2682,6 +2767,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) m_geoTmMrgCtx0.numValidMergeCand = m_geoMrgCtx.numValidMergeCand; m_geoTmMrgCtx0.bcwIdx[pu.geoMergeIdx0] = BCW_DEFAULT; m_geoTmMrgCtx0.useAltHpelIf[pu.geoMergeIdx0] = false; +#if JVET_AG0276_NLIC + m_geoTmMrgCtx0.altLMFlag[pu.geoMergeIdx0] = m_geoMrgCtx.altLMFlag[pu.geoMergeIdx0]; + m_geoTmMrgCtx0.altLMParaNeighbours[pu.geoMergeIdx0] = m_geoMrgCtx.altLMParaNeighbours[pu.geoMergeIdx0]; +#endif #if INTER_LIC m_geoTmMrgCtx0.licFlags[pu.geoMergeIdx0] = false; #endif @@ -2694,8 +2783,12 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].refIdx; m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].refIdx; #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING +#if JVET_AG0276_NLIC + m_geoTmMrgCtx[GEO_TM_SHAPE_A] = m_geoTmMrgCtx0; +#else memcpy(&m_geoTmMrgCtx[GEO_TM_SHAPE_A], &m_geoTmMrgCtx0, sizeof(m_geoTmMrgCtx0)); #endif +#endif #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING for (uint8_t tmType = GEO_TM_SHAPE_AL; tmType < GEO_NUM_TM_MV_CAND; ++tmType) @@ -2732,6 +2825,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) m_geoTmMrgCtx1.numValidMergeCand = m_geoMrgCtx.numValidMergeCand; m_geoTmMrgCtx1.bcwIdx[pu.geoMergeIdx1] = BCW_DEFAULT; m_geoTmMrgCtx1.useAltHpelIf[pu.geoMergeIdx1] = false; +#if JVET_AG0276_NLIC + m_geoTmMrgCtx1.altLMFlag[pu.geoMergeIdx1] = m_geoMrgCtx.altLMFlag[pu.geoMergeIdx1]; + m_geoTmMrgCtx1.altLMParaNeighbours[pu.geoMergeIdx1] = m_geoMrgCtx.altLMParaNeighbours[pu.geoMergeIdx1]; +#endif #if INTER_LIC m_geoTmMrgCtx1.licFlags[pu.geoMergeIdx1] = false; #endif @@ -2744,8 +2841,12 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].refIdx; m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].refIdx; #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING +#if JVET_AG0276_NLIC + m_geoTmMrgCtx[GEO_TM_SHAPE_L] = m_geoTmMrgCtx1; +#else memcpy(&m_geoTmMrgCtx[GEO_TM_SHAPE_L], &m_geoTmMrgCtx1, sizeof(m_geoTmMrgCtx1)); #endif +#endif #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING for (uint8_t tmType = GEO_TM_SHAPE_AL; tmType < GEO_NUM_TM_MV_CAND; ++tmType) @@ -2824,6 +2925,17 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS AffineMergeCtx affineRMVFCtx; AffineMergeCtx affineRMVFOriCtx; +#endif +#if JVET_AG0276_NLIC + AltLMAffineMergeCtx altAffineRMVFCtx; + altAffineRMVFCtx.init(); +#if JVET_AG0276_LIC_FLAG_SIGNALING + AltLMAffineMergeCtx altBRAffineRMVFCtx; + altBRAffineRMVFCtx.init(); +#endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + AffineMergeCtx affineRMVFCtxOppositeLic; #endif if (pu.cs->sps->getSbTMVPEnabledFlag()) { @@ -2859,7 +2971,14 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #endif #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS uint16_t addNumRMVF = 0; - PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, m_pcInterPred, addNumRMVF); + PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, m_pcInterPred, addNumRMVF +#if JVET_AG0276_NLIC + , altAffineRMVFCtx +#if JVET_AG0276_LIC_FLAG_SIGNALING + , altBRAffineRMVFCtx +#endif +#endif + ); if (pu.affBMMergeFlag) { PU::getBMAffineMergeCand(pu, affineMergeCtx, affineRMVFOriCtx, -1); @@ -2888,11 +3007,59 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #else , (pu.mergeIdx == 0 && !pu.affBMMergeFlag) #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + && !pu.affineOppositeLic +#endif #else , pu.mergeIdx == 0 #endif #endif ); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.affineOppositeLic && !pu.afMmvdFlag) + { + int cnt = 0; + affineRMVFCtxOppositeLic = affineMergeCtx; + affineMergeCtx.numValidMergeCand = 0; + for (int i = 0; i < affineRMVFCtxOppositeLic.numValidMergeCand; i++) + { + if (affineRMVFCtxOppositeLic.mergeType[i] == MRG_TYPE_DEFAULT_N) + { + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affineMergeCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum] = affineRMVFCtxOppositeLic.mvFieldNeighbours[(i << 1) + 0][mvNum]; + affineMergeCtx.mvFieldNeighbours[(cnt << 1) + 1][mvNum] = affineRMVFCtxOppositeLic.mvFieldNeighbours[(i << 1) + 1][mvNum]; + } + affineMergeCtx.interDirNeighbours[cnt] = affineRMVFCtxOppositeLic.interDirNeighbours[i]; + affineMergeCtx.affineType[cnt] = affineRMVFCtxOppositeLic.affineType[i]; + affineMergeCtx.mergeType[cnt] = affineRMVFCtxOppositeLic.mergeType[i]; + affineMergeCtx.bcwIdx[cnt] = affineRMVFCtxOppositeLic.bcwIdx[i]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affineMergeCtx.colIdx[cnt] = affineRMVFCtxOppositeLic.colIdx[i]; +#endif +#if JVET_AG0276_NLIC + affineMergeCtx.altLMFlag[cnt] = affineRMVFCtxOppositeLic.altLMFlag[i]; + affineMergeCtx.altLMParaNeighbours[cnt] = affineRMVFCtxOppositeLic.altLMParaNeighbours[i]; +#endif +#if INTER_LIC + affineMergeCtx.licFlags[cnt] = !affineRMVFCtxOppositeLic.licFlags[i]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affineMergeCtx.obmcFlags[cnt] = affineRMVFCtxOppositeLic.obmcFlags[i]; +#endif + affineMergeCtx.candCost[cnt] = affineRMVFCtxOppositeLic.candCost[i]; + cnt++; + affineMergeCtx.numValidMergeCand++; + } + else + { + continue; + } + } + affineMergeCtx.numAffCandToTestEnc = std::min(affineMergeCtx.numValidMergeCand, affineRMVFCtxOppositeLic.numAffCandToTestEnc); + affineMergeCtx.maxNumMergeCand = affineMergeCtx.numValidMergeCand; + } +#endif #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS } #endif @@ -2908,6 +3075,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) pu.interDir = affineMergeCtx.interDirNeighbours[pu.mergeIdx]; pu.cu->affineType = affineMergeCtx.affineType[pu.mergeIdx]; pu.cu->bcwIdx = affineMergeCtx.bcwIdx[pu.mergeIdx]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affineMergeCtx.altLMFlag[pu.mergeFlag]; + pu.cu->altLMParaUnit = affineMergeCtx.altLMParaNeighbours[pu.mergeFlag]; +#endif #if INTER_LIC pu.cu->licFlag = affineMergeCtx.licFlags[pu.mergeIdx]; #endif @@ -2934,7 +3105,11 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) } } } +#if JVET_AG0276_LIC_BDOF_BDMVR + if (PU::checkBDMVRCondition4Aff(pu)) +#else if (PU::checkBDMVRCondition(pu)) +#endif { if (PU::checkBDMVR4Affine(pu)) { @@ -2974,6 +3149,50 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #if JVET_W0090_ARMC_TM else { +#if JVET_AG0276_NLIC + if (pu.cs->sps->getUseAML() +#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL + && pu.cs->sps->getTMToolsEnableFlag() +#endif + ) + { + if (pu.affBMMergeFlag) + { + m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, pu.mergeIdx); + } + else + { + if (affineMergeCtx.numValidMergeCand > 1) + { + if (pu.cs->sps->getUseAffAltLM() && !CU::isTLCond(*pu.cu)) + { +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (!pu.affineOppositeLic) + { +#endif + AltLMAffineMergeCtx altLMAffMrgCtx; + PU::getAltLMAffineMergeCand(pu, altLMAffMrgCtx); + m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, altLMAffMrgCtx, altAffineRMVFCtx); +#if JVET_AG0276_LIC_FLAG_SIGNALING + } + else + { + AltLMAffineMergeCtx altLMBRAffMrgCtx; + PU::getAltLMBRAffineMergeCand(pu, altLMBRAffMrgCtx); + m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, altLMBRAffMrgCtx, altBRAffineRMVFCtx); + } +#endif + } + else + { + m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, pu.mergeIdx); + } + affineMergeCtx.numValidMergeCand = pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand(); + affineMergeCtx.maxNumMergeCand = pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand(); + } + } + } +#else if (pu.cs->sps->getUseAML() #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL && pu.cs->sps->getTMToolsEnableFlag() @@ -2985,6 +3204,7 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) { m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, pu.mergeIdx); } +#endif #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS if (pu.affBMMergeFlag) { @@ -3031,9 +3251,14 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL && pu.cs->sps->getTMToolsEnableFlag() #endif - && PU::checkAffineTMCondition(pu)) + && PU::checkAffineTMCondition(pu) + ) { +#if JVET_AG0276_LIC_FLAG_SIGNALING + for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < (pu.affineOppositeLic ? int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) : affineMergeCtx.numValidMergeCand); uiAffMergeCand++) +#else for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtx.numValidMergeCand; uiAffMergeCand++) +#endif { if (affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv == Mv(0, 0) && affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv == Mv(0, 0) && affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv == Mv(0, 0) && affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv == Mv(0, 0) && @@ -3043,10 +3268,17 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) validNum = uiAffMergeCand; break; } +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (uiAffMergeCand == (pu.affineOppositeLic ? (int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1) : pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() - 1)) + { + validNum = pu.affineOppositeLic ? int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) : pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand(); + } +#else if (uiAffMergeCand == pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand() - 1) { validNum = pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand(); } +#endif } if (!pu.afMmvdFlag) { @@ -3056,7 +3288,11 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) int value = pu.mergeIdx - validNum; for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < validNum; uiAffMergeCand++) { +#if JVET_AG0276_NLIC + if (!affineMergeCtx.altLMFlag[uiAffMergeCand] && affineMergeCtx.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtx.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP) +#else if (affineMergeCtx.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtx.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP) +#endif { value--; if (value == -1) @@ -3077,6 +3313,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) pu.interDir = affineMergeCtx.interDirNeighbours[pu.mergeIdx]; pu.cu->affineType = affineMergeCtx.affineType[pu.mergeIdx]; pu.cu->bcwIdx = affineMergeCtx.bcwIdx[pu.mergeIdx]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affineMergeCtx.altLMFlag[pu.mergeIdx]; + pu.cu->altLMParaUnit = affineMergeCtx.altLMParaNeighbours[pu.mergeIdx]; +#endif #if INTER_LIC pu.cu->licFlag = affineMergeCtx.licFlags[pu.mergeIdx]; #endif @@ -3111,9 +3351,17 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) } #if JVET_AB0112_AFFINE_DMVR #if JVET_AG0135_AFFINE_CIIP +#if JVET_AG0276_LIC_BDOF_BDMVR + if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && (pu.ciipAffine ? PU::checkBDMVRConditionCIIPAffine(pu) : PU::checkBDMVRCondition4Aff(pu))) +#else if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && (pu.ciipAffine ? PU::checkBDMVRConditionCIIPAffine(pu) : PU::checkBDMVRCondition(pu))) +#endif +#else +#if JVET_AG0276_LIC_BDOF_BDMVR + if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && PU::checkBDMVRCondition4Aff(pu)) #else if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && PU::checkBDMVRCondition(pu)) +#endif #endif { #if !JVET_AC0144_AFFINE_DMVR_REGRESSION @@ -3161,7 +3409,11 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL && pu.cs->sps->getTMToolsEnableFlag() #endif - && !pu.afMmvdFlag && pu.mergeType != MRG_TYPE_SUBPU_ATMVP && pu.interDir != 3 && !((pu.mergeIdx > validNum - 1) && !isAdditional) && PU::checkAffineTMCondition(pu)) +#if JVET_AG0276_NLIC + && (pu.cs->sps->getUseAffAltLMTM() || !pu.cu->altLMFlag) +#endif + && !pu.afMmvdFlag && pu.mergeType != MRG_TYPE_SUBPU_ATMVP && pu.interDir != 3 && !((pu.mergeIdx > validNum - 1) && !isAdditional) && PU::checkAffineTMCondition(pu) + ) { for (int i = 0; i < 3; i++) { @@ -3171,7 +3423,12 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); pu.bdmvrRefine = false; +#if JVET_AG0276_NLIC + if ((!pu.cu->altLMFlag && !affineMergeCtx.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), false)) || + (pu.cu->altLMFlag && !affineMergeCtx.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), true))) +#else if (!affineMergeCtx.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu))) +#endif { m_pcInterPred->processTM4Affine(pu, affineMergeCtx, isAdditional ? 0 : -1, false); pu.mvAffi[0][0] += m_mvBufBDMVR[0][0]; @@ -3765,6 +4022,15 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : #endif pu.cs->sps->getMaxNumMergeCand(); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if ((pu.mergeOppositeLic || pu.tmMergeFlagOppositeLic) && !pu.bmMergeFlag) + { + for (int i = 0; i < mrgCtx.numValidMergeCand; i++) + { + mrgCtx.licFlags[i] = !mrgCtx.licFlags[i]; + } + } +#endif } else #endif @@ -3786,6 +4052,15 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC if (pu.tmMergeFlag && tmMergeRefinedMotion) { +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.tmMergeFlagOppositeLic) + { + for (int i = 0; i < mrgCtx.numValidMergeCand; i++) + { + mrgCtx.licFlags[i] = !mrgCtx.licFlags[i]; + } + } +#endif #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumTMMergeCand()); #else @@ -3793,11 +4068,27 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #endif int tmpPuMrgIdx = pu.mergeIdx; pu.reduceTplSize = true; +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.tmMergeFlagOppositeLic) + { + if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMOppositeLicMergeCand()) + { + mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMOppositeLicMergeCand(); + } + } + else + { + if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) + { + mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); + } + } +#else if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) { mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); } - +#endif if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) { mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; @@ -3806,6 +4097,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -3869,6 +4164,19 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #if JVET_AB0079_TM_BCW_MRG { #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic || pu.tmMergeFlagOppositeLic) + { + for (int i = 0; i < mrgCtx.numValidMergeCand; i++) + { + mrgCtx.licFlags[i] = !mrgCtx.licFlags[i]; + } + } +#endif +#if JVET_AG0276_NLIC + if (pu.tmMergeFlag || pu.ciipFlag) + { +#endif #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, #if TM_MRG @@ -3878,6 +4186,43 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #else m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx); #endif +#if JVET_AG0276_NLIC + } + else + { + if (pu.cs->sps->getUseAltLM() && !CU::isTLCond(*pu.cu)) + { +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (!pu.mergeOppositeLic) + { +#endif + AltLMMergeCtx altLMMrgCtx; + PU::getAltMergeCandidates(pu, altLMMrgCtx); + m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, altLMMrgCtx, pu.cs->sps->getMaxNumMergeCand()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + } + else + { + AltLMMergeCtx altLMBRMrgCtx; + PU::getAltBRMergeCandidates(pu, altLMBRMrgCtx); + m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, altLMBRMrgCtx, pu.cs->sps->getMaxNumMergeCand()); + } +#endif + } + else + { +#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND + m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, +#if TM_MRG + pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : +#endif + pu.cs->sps->getMaxNumMergeCand()); +#else + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx); +#endif + } + } +#endif #if JVET_AB0079_TM_BCW_MRG m_pcInterPred->adjustMergeCandidatesBcwIdx(pu, mrgCtx, pu.mergeIdx); } @@ -3917,6 +4262,15 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #endif if (pu.tmMergeFlag && tmMergeRefinedMotion) { +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.tmMergeFlagOppositeLic) + { + for (int i = 0; i < mrgCtx.numValidMergeCand; i++) + { + mrgCtx.licFlags[i] = !mrgCtx.licFlags[i]; + } + } +#endif int tmpPuMrgIdx = pu.mergeIdx; pu.reduceTplSize = true; if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) @@ -3932,6 +4286,10 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) { mrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mrgCtx.altLMFlag[ui] = false; + mrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mrgCtx.licFlags[ui] = false; #endif @@ -3994,6 +4352,15 @@ void DecCu::xDeriveCUMV(CodingUnit &cu) #endif #if JVET_AB0079_TM_BCW_MRG { +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { + for (int i = 0; i < mrgCtx.numValidMergeCand; i++) + { + mrgCtx.licFlags[i] = !mrgCtx.licFlags[i]; + } + } #endif m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, pu.mergeIdx); #if JVET_AB0079_TM_BCW_MRG diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 8eafb4297..9ec3b3e74 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2243,6 +2243,12 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) #endif #if INTER_LIC READ_FLAG( uiCode, "sps_lic_enabled_flag" ); pcSPS->setLicEnabledFlag( uiCode ); +#if JVET_AG0276_LIC_SLOPE_ADJUST + if (pcSPS->getLicEnabledFlag()) + { + READ_FLAG( uiCode, "sps_lic_slope_adjust_enabled_flag" ); pcSPS->setLicSlopeAdjustEnabledFlag( uiCode ); + } +#endif #endif READ_FLAG(uiCode, "sps_ref_wraparound_enabled_flag"); pcSPS->setWrapAroundEnabledFlag( uiCode ? true : false ); @@ -2391,6 +2397,12 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) { pcSPS->setFpelMmvdEnabledFlag( false ); } +#if JVET_AG0276_LIC_FLAG_SIGNALING + pcSPS->setUseMergeOppositeLic( false ); + pcSPS->setUseTMMergeOppositeLic( false ); + READ_FLAG(uiCode, "sps_oppositelic_merge_enabled_flag"); pcSPS->setUseMergeOppositeLic(uiCode != 0); + READ_FLAG(uiCode, "sps_TM_oppositelic_merge_enabled_flag"); pcSPS->setUseTMMergeOppositeLic(uiCode != 0); +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION #if JVET_AA0132_CONFIGURABLE_TM_TOOLS uiCode = 0; @@ -2402,6 +2414,13 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_UVLC(uiCode, "six_minus_max_num_merge_cand"); CHECK(MRG_MAX_NUM_CANDS <= uiCode, "Incorrrect max number of merge candidates!"); pcSPS->setMaxNumMergeCand(MRG_MAX_NUM_CANDS - uiCode); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pcSPS->getUseMergeOppositeLic()) + { + READ_UVLC(uiCode, "five_max_num_oppolic_merge_cand"); + pcSPS->setMaxNumOppositeLicMergeCand(REG_MRG_MAX_NUM_CANDS_OPPOSITELIC - uiCode); + } +#endif READ_FLAG(uiCode, "sps_sbt_enabled_flag"); pcSPS->setUseSBT ( uiCode != 0 ); #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR READ_FLAG( uiCode, "sps_dmvd_enabled_flag" ); pcSPS->setUseDMVDMode( uiCode != 0 ); @@ -2437,6 +2456,29 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) pcSPS->setMaxNumBMMergeCand(BM_MRG_MAX_NUM_CANDS - uiCode); #endif READ_FLAG( uiCode, "sps_affine_enabled_flag" ); pcSPS->setUseAffine ( uiCode != 0 ); +#if JVET_AG0276_NLIC + pcSPS->setUseAltLM(false); + pcSPS->setUseAffAltLM(false); + if (pcSPS->getUseAML() +#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL + && pcSPS->getTMToolsEnableFlag() +#endif + ) + { + READ_FLAG( uiCode, "sps_alt_lm_enabled_flag" ); pcSPS->setUseAltLM( uiCode != 0 ); + if (pcSPS->getUseAffine()) + { + READ_FLAG( uiCode, "sps_affine_alt_lm_enabled_flag" ); pcSPS->setUseAffAltLM( uiCode != 0 ); + } + } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + pcSPS->setUseAffMergeOppositeLic(false); + if (pcSPS->getUseAffine()) + { + READ_FLAG(uiCode, "sps_affine_oppolic_merge_enabled_flag"); pcSPS->setUseAffMergeOppositeLic(uiCode != 0); + } +#endif if ( pcSPS->getUseAffine() ) { READ_UVLC(uiCode, "five_minus_max_num_subblock_merge_cand"); @@ -2454,6 +2496,13 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) READ_FLAG( uiCode, "sps_affine_type_flag" ); pcSPS->setUseAffineType ( uiCode != 0 ); #if AFFINE_MMVD READ_FLAG( uiCode, "sps_affine_mmvd_enabled_flag" ); pcSPS->setUseAffineMmvdMode ( uiCode != 0 ); +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pcSPS->getUseAffMergeOppositeLic()) + { + READ_UVLC(uiCode, "eight_minus_max_num_aff_oppolic_merge_cand"); + pcSPS->setMaxNumAffineOppositeLicMergeCand(AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC - uiCode); + } #endif if( pcSPS->getAMVREnabledFlag()) { @@ -2483,6 +2532,16 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) pcSPS->setUseAffineTM( false ); } #endif +#if JVET_AG0276_NLIC + if (pcSPS->getUseAffineTM() && pcSPS->getUseAffAltLM()) + { + READ_FLAG(uiCode, "sps_affine_alt_lm_tm_flag"); pcSPS->setUseAffAltLMTM(uiCode != 0); + } + else + { + pcSPS->setUseAffAltLMTM(false); + } +#endif #endif } #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED @@ -4103,10 +4162,16 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag if ( sps->getUseAffine() ) { picHeader->setMaxNumAffineMergeCand(sps->getMaxNumAffineMergeCand()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + picHeader->setMaxNumAffineOppositeLicMergeCand(sps->getMaxNumAffineOppositeLicMergeCand()); +#endif } else { picHeader->setMaxNumAffineMergeCand(sps->getSbTMVPEnabledFlag() && picHeader->getEnableTMVPFlag()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + picHeader->setMaxNumAffineOppositeLicMergeCand(0); +#endif } // full-pel MMVD flag diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index f1b19ce89..161e092da 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -4521,6 +4521,12 @@ void CABACWriter::merge_data(const PredictionUnit& pu) { affBmFlag(pu); } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (PU::hasOppositeLICFlag(pu) && !pu.afMmvdFlag && !pu.affBMMergeFlag && pu.cs->sps->getUseAffMergeOppositeLic()) + { + m_BinEncoder.encodeBin(pu.affineOppositeLic, Ctx::AffineFlagOppositeLic(0)); + } #endif merge_idx(pu); return; @@ -4602,6 +4608,19 @@ void CABACWriter::merge_data(const PredictionUnit& pu) } else { +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.regularMergeFlag && PU::hasOppositeLICFlag(pu) && !pu.bmMergeFlag) + { + if (pu.tmMergeFlag && pu.cs->sps->getUseTMMergeOppositeLic()) + { + m_BinEncoder.encodeBin(pu.tmMergeFlagOppositeLic, Ctx::TmMergeFlagOppositeLic(0)); + } + else if (pu.cs->sps->getUseMergeOppositeLic()) + { + m_BinEncoder.encodeBin(pu.mergeOppositeLic, Ctx::MergeFlagOppositeLic(0)); + } + } +#endif merge_idx(pu); } } @@ -4826,6 +4845,12 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) } #endif int numCandminus1 = int( pu.cs->picHeader->getMaxNumAffineMergeCand() ) - 1; +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.affineOppositeLic) + { + numCandminus1 = int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1; + } +#endif if ( numCandminus1 > 0 ) { #if JVET_AA0128_AFFINE_MERGE_CTX_INC @@ -5142,6 +5167,17 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) #endif else numCandminus1 = int(pu.cs->sps->getMaxNumMergeCand()) - 1; + +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { + numCandminus1 = int(pu.cs->sps->getMaxNumOppositeLicMergeCand()) - 1; + } + else if (pu.tmMergeFlagOppositeLic) + { + numCandminus1 = int(pu.cs->sps->getMaxNumTMOppositeLicMergeCand()) - 1; + } +#endif if( numCandminus1 > 0 ) { #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) @@ -9427,8 +9463,24 @@ void CABACWriter::cu_lic_flag(const CodingUnit& cu) { if (CU::isLICFlagPresent(cu)) { +#if JVET_AG0276_LIC_SLOPE_ADJUST + unsigned ctxId = DeriveCtx::CtxLicFlag( cu ); + m_BinEncoder.encodeBin(cu.licFlag ? 1 : 0, Ctx::LICFlag(ctxId)); +#else m_BinEncoder.encodeBin(cu.licFlag ? 1 : 0, Ctx::LICFlag(0)); +#endif DTRACE(g_trace_ctx, D_SYNTAX, "cu_lic_flag() lic_flag=%d\n", cu.licFlag ? 1 : 0); +#if JVET_AG0276_LIC_SLOPE_ADJUST + if (cu.licFlag && CU::isLicSlopeAllowed(cu) && cu.firstPU->interDir != 3) + { + int delta = cu.licDelta; + m_BinEncoder.encodeBin( delta != 0 ? 1 : 0, Ctx::LicDelta(0) ); + if ( delta ) + { + m_BinEncoder.encodeBin( delta < 0 ? 1 : 0, Ctx::LicDelta(1) ); + } + } +#endif } } #endif diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 53dafb6bc..178b89130 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -414,6 +414,9 @@ protected: bool m_AffineType; #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT bool m_useAffineTM; +#if JVET_AG0276_NLIC + bool m_useAffAltLMTM; +#endif #endif #if JVET_AG0135_AFFINE_CIIP bool m_useCiipAffine; @@ -455,6 +458,15 @@ protected: bool m_BIO; #if JVET_W0090_ARMC_TM bool m_AML; +#if JVET_AG0276_NLIC + bool m_altLM; + bool m_affAltLM; +#endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool m_mergeOppositeLic; + bool m_mergeTMOppositeLic; + bool m_mergeAffOppositeLic; #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC bool m_armcRefinedMotion; @@ -905,10 +917,16 @@ protected: WeightedPredictionMethod m_weightedPredictionMethod; uint32_t m_log2ParallelMergeLevelMinus2; ///< Parallel merge estimation region uint32_t m_maxNumMergeCand; ///< Maximum number of merge candidates +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t m_maxNumOppositeLicMergeCand; ///< Maximum number of merge candidates with opposite LIC flag +#endif #if JVET_X0049_ADAPT_DMVR uint32_t m_maxNumBMMergeCand; ///< Maximum number of BM merge candidates #endif uint32_t m_maxNumAffineMergeCand; ///< Maximum number of affine merge candidates +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t m_maxNumAffineOppositeLicMergeCand; ///< Maximum number of affine merge candidates with opposite LIC flag +#endif uint32_t m_maxNumGeoCand; #if JVET_AG0164_AFFINE_GPM uint32_t m_maxNumGpmAffCand; @@ -1052,6 +1070,9 @@ protected: bool m_fastLICAffine; bool m_fastLICBcw; #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + bool m_licSlopeAdjust; +#endif #endif #if JVET_O0756_CALCULATE_HDRMETRICS @@ -1521,6 +1542,10 @@ public: #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT void setUseAffineTM( bool b ) { m_useAffineTM = b; } bool getUseAffineTM() const { return m_useAffineTM; } +#if JVET_AG0276_NLIC + void setUseAffAltLMTM( bool b ) { m_useAffAltLMTM = b; } + bool getUseAffAltLMTM() const { return m_useAffAltLMTM; } +#endif #endif #if JVET_AG0135_AFFINE_CIIP void setUseCIIPAffine(bool b) { m_useCiipAffine = b; } @@ -1626,6 +1651,20 @@ public: #if JVET_W0090_ARMC_TM void setAML(bool b) { m_AML = b; } bool getAML() const { return m_AML; } +#if JVET_AG0276_NLIC + void setAltLM(bool b) { m_altLM = b; } + bool getAltLM() const { return m_altLM; } + void setAffAltLM(bool b) { m_affAltLM = b; } + bool getAffAltLM() const { return m_affAltLM; } +#endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + void setMergeOppositeLic( bool b ) { m_mergeOppositeLic = b; } + bool setMergeOppositeLic() const { return m_mergeOppositeLic; } + void setMergeTMOppositeLic( bool b ) { m_mergeTMOppositeLic = b; } + bool setMergeTMOppositeLic() const { return m_mergeTMOppositeLic; } + void setMergeAffOppositeLic( bool b ) { m_mergeAffOppositeLic = b; } + bool setMergeAffOppositeLic() const { return m_mergeAffOppositeLic; } #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC void setArmcRefinedMotion(bool b) { m_armcRefinedMotion = b; } @@ -2503,12 +2542,20 @@ public: uint32_t getLog2ParallelMergeLevelMinus2() { return m_log2ParallelMergeLevelMinus2; } void setMaxNumMergeCand ( uint32_t u ) { m_maxNumMergeCand = u; } uint32_t getMaxNumMergeCand () { return m_maxNumMergeCand; } +#if JVET_AG0276_LIC_FLAG_SIGNALING + void setMaxNumOppositeLicMergeCand( uint32_t u ) { m_maxNumOppositeLicMergeCand = u; } + uint32_t getMaxNumOppositeLicMergeCand() { return m_maxNumOppositeLicMergeCand; } +#endif #if JVET_X0049_ADAPT_DMVR void setMaxNumBMMergeCand ( uint32_t u ) { m_maxNumBMMergeCand = u; } uint32_t getMaxNumBMMergeCand () { return m_maxNumBMMergeCand; } #endif void setMaxNumAffineMergeCand ( uint32_t u ) { m_maxNumAffineMergeCand = u; } uint32_t getMaxNumAffineMergeCand () { return m_maxNumAffineMergeCand; } +#if JVET_AG0276_LIC_FLAG_SIGNALING + void setMaxNumAffineOppositeLicMergeCand( uint32_t u ) { m_maxNumAffineOppositeLicMergeCand = u; } + uint32_t getMaxNumAffineOppositeLicMergeCand() { return m_maxNumAffineOppositeLicMergeCand; } +#endif void setMaxNumGeoCand ( uint32_t u ) { m_maxNumGeoCand = u; } uint32_t getMaxNumGeoCand () { return m_maxNumGeoCand; } #if JVET_AG0164_AFFINE_GPM @@ -2739,6 +2786,10 @@ public: void setFastLicBcw( bool b ) { m_fastLICBcw = b; } bool getFastLicBcw() const { return m_fastLICBcw; } #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + void setUseLicSlopeAdjust( bool u ) { m_licSlopeAdjust = u; } + bool getUseLicSlopeAdjust() const { return m_licSlopeAdjust; } +#endif #endif #if JVET_O0756_CALCULATE_HDRMETRICS diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 3c6117c6f..9587edc24 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -3805,6 +3805,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& MergeCtx mergeCtxCIIPtmp; #endif #endif +#if JVET_AG0276_NLIC + MergeCtx mergeOrgCtx; +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + MergeCtx mergeCtxOppositeLic; + mergeCtxOppositeLic.numValidMergeCand = 0; +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED uint32_t mmvdLUT[MMVD_ADD_NUM]; #endif @@ -3844,12 +3851,20 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& AffineMergeCtx affineRMVFCtx; AffineMergeCtx affineRMVFOriCtx; #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + AffineMergeCtx affineMergeCtxOppositeLic; + affineMergeCtxOppositeLic.numValidMergeCand = 0; +#endif #if JVET_W0090_ARMC_TM AffineMergeCtx affineMergeCtxTmp; #endif MergeCtx mrgCtx; #if TM_MRG MergeCtx tmMrgCtx; +#if JVET_AG0276_LIC_FLAG_SIGNALING + MergeCtx tmMrgCtxOppositeLic; + tmMrgCtxOppositeLic.numValidMergeCand = 0; +#endif #if JVET_X0141_CIIP_TIMD_TM MergeCtx ciipTmMrgCtx; #endif @@ -3876,7 +3891,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& for (int i = 0; i < SUB_TMVP_NUM; i++) { mergeCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize); +#if JVET_AG0276_NLIC + mergeOrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize); +#endif mrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize); +#if JVET_AG0276_LIC_FLAG_SIGNALING + mergeCtxOppositeLic.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize); +#endif } #else mergeCtx.subPuMvpMiBuf = MotionBuf(m_subPuMiBuf, bufSize); @@ -3888,6 +3909,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& for (int i = 0; i < SUB_TMVP_NUM; i++) { tmMrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize); +#if JVET_AG0276_LIC_FLAG_SIGNALING + tmMrgCtxOppositeLic.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize); +#endif #if JVET_X0141_CIIP_TIMD_TM ciipTmMrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_subPuMiBuf[i], bufSize); #endif @@ -3910,12 +3934,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if MULTI_PASS_DMVR bool applyBDMVR[MRG_MAX_NUM_CANDS] = { false }; +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool applyBDMVROppositeLic[MRG_MAX_NUM_CANDS] = { false }; +#endif #if JVET_AF0057 bool dmvrImpreciseMv[MRG_MAX_NUM_CANDS] = { false }; #endif #if TM_MRG && MERGE_ENC_OPT #if JVET_AA0093_REFINED_MOTION_FOR_ARMC bool applyBDMVR4TM[TM_MRG_MAX_NUM_INIT_CANDS] = { false }; +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool applyBDMVR4TMOppositeLic[TM_MRG_MAX_NUM_INIT_CANDS] = { false }; +#endif #else bool applyBDMVR4TM[TM_MRG_MAX_NUM_CANDS] = { false }; #endif @@ -3937,6 +3967,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif setMergeBestSATDCost( MAX_DOUBLE ); +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool hasOppositelicMrg = false; + bool hasOppositelicAff = false; +#endif { // first get merge candidates CodingUnit cu( tempCS->area ); @@ -3951,6 +3985,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& PredictionUnit pu( tempCS->area ); pu.cu = &cu; pu.cs = tempCS; +#if JVET_AG0276_LIC_FLAG_SIGNALING + hasOppositelicMrg = PU::hasOppositeLICFlag(pu); + pu.cu->affine = true; + hasOppositelicAff = PU::hasOppositeLICFlag(pu); + pu.cu->affine = false; +#endif #if JVET_AF0057 bool enableVisualCheck = false; if (((m_pcEncCfg->getFrameRate() <= DMVR_ENC_SELECT_FRAME_RATE_THR) || !(m_pcEncCfg->getDMVREncMvSelectDisableHighestTemporalLayer() && (pu.cu->slice->getTLayer() == (pu.cu->slice->getSPS()->getMaxTLayers() - 1)))) @@ -4066,6 +4106,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_pcInterSearch->adjustMergeCandidatesLicFlag(pu, mergeCtx); } #endif +#if JVET_AG0276_NLIC + mergeOrgCtx = mergeCtx; +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic()) + { + mergeCtxOppositeLic = mergeCtx; + for (int i = 0; i < mergeCtx.numValidMergeCand; i++) + { + mergeCtxOppositeLic.licFlags[i] = !mergeCtx.licFlags[i]; + } + } +#endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM if (sps.getUseAML() #if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL @@ -4077,6 +4130,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& if (!sps.getUseTmvpNmvpReordering()) { m_pcInterSearch->adjustInterMergeCandidates(pu, mergeCtx); +#if JVET_AG0276_NLIC + mergeOrgCtx = mergeCtx; +#endif } else #endif @@ -4086,6 +4142,37 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_pcInterSearch->adjustMergeCandidates(pu, mergeCtx, pu.cs->sps->getMaxNumMergeCand()); #else m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mergeCtx, pu.cs->sps->getMaxNumMergeCand()); +#endif +#if JVET_AG0276_NLIC + if (pu.cs->sps->getUseAltLM() && !CU::isTLCond(*pu.cu)) + { + AltLMMergeCtx altLMMrgCtx; + PU::getAltMergeCandidates(pu, altLMMrgCtx); + m_pcInterSearch->adjustMergeCandidates(pu, mergeOrgCtx, altLMMrgCtx, pu.cs->sps->getMaxNumMergeCand()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic()) + { + AltLMMergeCtx altLMBRMrgCtx; + PU::getAltBRMergeCandidates(pu, altLMBRMrgCtx); + m_pcInterSearch->adjustMergeCandidates(pu, mergeCtxOppositeLic, altLMBRMrgCtx, pu.cs->sps->getMaxNumMergeCand()); + } +#endif + } + else + { + mergeOrgCtx = mergeCtx; +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic()) + { + m_pcInterSearch->adjustMergeCandidates(pu, mergeCtxOppositeLic, pu.cs->sps->getMaxNumMergeCand()); + } +#endif + } +#elif JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic()) + { + m_pcInterSearch->adjustMergeCandidates(pu, mergeCtxOppositeLic, pu.cs->sps->getMaxNumMergeCand()); + } #endif } } @@ -4094,9 +4181,22 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { mergeCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand(); } +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic()) + { + if (mergeCtxOppositeLic.numValidMergeCand > pu.cs->sps->getMaxNumOppositeLicMergeCand()) + { + mergeCtxOppositeLic.numValidMergeCand = pu.cs->sps->getMaxNumOppositeLicMergeCand(); + } + } +#endif for (uint32_t ui = mergeCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) { mergeCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mergeCtx.altLMFlag[ui] = false; + mergeCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC mergeCtx.licFlags[ui] = false; #endif @@ -4108,6 +4208,48 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& mergeCtx.addHypNeighbours[ui].clear(); #endif mergeCtx.candCost[ui] = MAX_UINT64; +#if JVET_AG0276_LIC_FLAG_SIGNALING + mergeCtxOppositeLic.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + mergeCtxOppositeLic.altLMFlag[ui] = false; + mergeCtxOppositeLic.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif +#if INTER_LIC + mergeCtxOppositeLic.licFlags[ui] = false; +#endif + mergeCtxOppositeLic.interDirNeighbours[ui] = 0; + mergeCtxOppositeLic.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; + mergeCtxOppositeLic.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; + mergeCtxOppositeLic.useAltHpelIf[ui] = false; +#if MULTI_HYP_PRED + mergeCtxOppositeLic.addHypNeighbours[ui].clear(); +#endif + mergeCtxOppositeLic.candCost[ui] = MAX_UINT64; +#endif + } +#endif + +#if JVET_AG0276_NLIC + if (mergeOrgCtx.numValidMergeCand != pu.cs->sps->getMaxNumMergeCand()) + { + mergeOrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand(); + } + for (uint32_t ui = mergeOrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) + { + mergeOrgCtx.bcwIdx[ui] = BCW_DEFAULT; + mergeOrgCtx.altLMFlag[ui] = false; + mergeOrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#if INTER_LIC + mergeOrgCtx.licFlags[ui] = false; +#endif + mergeOrgCtx.interDirNeighbours[ui] = 0; + mergeOrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; + mergeOrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; + mergeOrgCtx.useAltHpelIf[ui] = false; +#if MULTI_HYP_PRED + mergeOrgCtx.addHypNeighbours[ui].clear(); +#endif + mergeOrgCtx.candCost[ui] = MAX_UINT64; } #endif @@ -4123,6 +4265,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& mrgCtxCiip.mvFieldNeighbours[(uiMergeCand << 1)] = mergeCtx.mvFieldNeighbours[(uiMergeCand << 1)]; mrgCtxCiip.mvFieldNeighbours[(uiMergeCand << 1) + 1] = mergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1]; mrgCtxCiip.useAltHpelIf[uiMergeCand] = mergeCtx.useAltHpelIf[uiMergeCand]; +#if JVET_AG0276_NLIC + mrgCtxCiip.altLMFlag[uiMergeCand] = mergeCtx.altLMFlag[uiMergeCand]; + mrgCtxCiip.altLMParaNeighbours[uiMergeCand] = mergeCtx.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC mrgCtxCiip.licFlags[uiMergeCand] = mergeCtx.licFlags[uiMergeCand]; #endif @@ -4139,6 +4285,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& ) { m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mergeCtx); +#if JVET_AG0276_NLIC + m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mergeOrgCtx); + MergeCtx mergeCtxTemp; + mergeCtxTemp = mergeCtx; + mergeCtx = mergeOrgCtx; + mergeOrgCtx = mergeCtxTemp; +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic()) + { + m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, mergeCtxOppositeLic); + } +#endif } #endif PU::getInterMergeCandidates(pu, mergeCtxtmp, 0); @@ -4198,6 +4357,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if JVET_AG0135_AFFINE_CIIP ciipTmMrgCtx = mergeCtxCIIPtmp; ciipTmMrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand()); +#if !(JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR || JVET_AG0276_NLIC) memcpy(ciipTmMrgCtx.bcwIdx, mergeCtxCIIPtmp.bcwIdx, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(uint8_t)); memcpy(ciipTmMrgCtx.interDirNeighbours, mergeCtxCIIPtmp.interDirNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(unsigned char)); memcpy(ciipTmMrgCtx.mvFieldNeighbours, mergeCtxCIIPtmp.mvFieldNeighbours, (CIIP_TM_MRG_MAX_NUM_CANDS << 1) * sizeof(MvField)); @@ -4208,13 +4368,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if MULTI_HYP_PRED memcpy(ciipTmMrgCtx.addHypNeighbours, mergeCtxCIIPtmp.addHypNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(MultiHypVec)); #endif +#endif #else ciipTmMrgCtx = mergeCtxtmp; ciipTmMrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand()); +#if !(JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR || JVET_AG0276_NLIC) memcpy(ciipTmMrgCtx.bcwIdx, mergeCtxtmp.bcwIdx, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(uint8_t)); memcpy(ciipTmMrgCtx.interDirNeighbours, mergeCtxtmp.interDirNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(unsigned char)); memcpy(ciipTmMrgCtx.mvFieldNeighbours, mergeCtxtmp.mvFieldNeighbours, (CIIP_TM_MRG_MAX_NUM_CANDS << 1) * sizeof(MvField)); memcpy(ciipTmMrgCtx.useAltHpelIf, mergeCtxtmp.useAltHpelIf, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool)); +#if JVET_AG0276_NLIC + memcpy(ciipTmMrgCtx.altLMFlag, mergeCtxtmp.altLMFlag, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool)); + memcpy(ciipTmMrgCtx.altLMParaNeighbours, mergeCtxtmp.altLMParaNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(AltLMInterUnit)); +#endif #if INTER_LIC memcpy(ciipTmMrgCtx.licFlags, mergeCtxtmp.licFlags, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool)); #endif @@ -4222,9 +4388,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& memcpy(ciipTmMrgCtx.addHypNeighbours, mergeCtxtmp.addHypNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(MultiHypVec)); #endif #endif +#endif #else ciipTmMrgCtx = mergeCtx; ciipTmMrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand()); +#if !(JVET_AG0276_LIC_FLAG_SIGNALING || JVET_AG0276_LIC_BDOF_BDMVR || JVET_AG0276_NLIC) memcpy(ciipTmMrgCtx.bcwIdx, mergeCtx.bcwIdx, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(uint8_t)); memcpy(ciipTmMrgCtx.interDirNeighbours, mergeCtx.interDirNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(unsigned char)); memcpy(ciipTmMrgCtx.mvFieldNeighbours, mergeCtx.mvFieldNeighbours, (CIIP_TM_MRG_MAX_NUM_CANDS << 1) * sizeof(MvField)); @@ -4235,6 +4403,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if MULTI_HYP_PRED memcpy(ciipTmMrgCtx.addHypNeighbours, mergeCtx.addHypNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(MultiHypVec)); #endif +#endif #endif for (uint32_t uiMergeCand = 0; uiMergeCand < ciipTmMrgCtx.numValidMergeCand; uiMergeCand++) @@ -4423,6 +4592,16 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_pcInterSearch->adjustMergeCandidatesLicFlag(pu, tmMrgCtx); } #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic()) + { + tmMrgCtxOppositeLic = tmMrgCtx; + for (int i = 0; i < tmMrgCtxOppositeLic.numValidMergeCand; i++) + { + tmMrgCtxOppositeLic.licFlags[i] = !tmMrgCtx.licFlags[i]; + } + } +#endif #if JVET_W0090_ARMC_TM #if JVET_AA0093_REFINED_MOTION_FOR_ARMC bool tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2); @@ -4444,6 +4623,20 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtx); #if JVET_AB0079_TM_BCW_MRG m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtx); +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic()) + { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (!tmMergeRefinedMotion) +#endif + { + m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtxOppositeLic); + } +#if JVET_AB0079_TM_BCW_MRG + m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtxOppositeLic); +#endif + } #endif } else @@ -4466,12 +4659,43 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtx); } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic()) + { +#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND + m_pcInterSearch->adjustMergeCandidates(pu, tmMrgCtxOppositeLic, pu.cs->sps->getMaxNumTMMergeCand()); +#else + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmMrgCtx, pu.cs->sps->getMaxNumTMMergeCand()); +#endif +#if JVET_AB0079_TM_BCW_MRG +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (!tmMergeRefinedMotion) +#endif + { + if (tmMrgCtxOppositeLic.numValidMergeCand > pu.cs->sps->getMaxNumTMOppositeLicMergeCand()) + { + tmMrgCtxOppositeLic.numValidMergeCand = pu.cs->sps->getMaxNumTMOppositeLicMergeCand(); + } + m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtxOppositeLic); + } +#endif + } #endif } if (tmMrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) { tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); } +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic()) + { + if (tmMrgCtxOppositeLic.numValidMergeCand > pu.cs->sps->getMaxNumTMOppositeLicMergeCand()) + { + tmMrgCtxOppositeLic.numValidMergeCand = pu.cs->sps->getMaxNumTMOppositeLicMergeCand(); + } + } +#endif #else #if JVET_AA0093_REFINED_MOTION_FOR_ARMC if (!tmMergeRefinedMotion) @@ -4486,6 +4710,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& for (uint32_t ui = tmMrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) { tmMrgCtx.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + tmMrgCtx.altLMFlag[ui] = false; + tmMrgCtx.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif #if INTER_LIC tmMrgCtx.licFlags[ui] = false; #endif @@ -4498,6 +4726,33 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif tmMrgCtx.candCost[ui] = MAX_UINT64; } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (tmMrgCtxOppositeLic.numCandToTestEnc > tmMrgCtxOppositeLic.numValidMergeCand) + { + tmMrgCtxOppositeLic.numCandToTestEnc = tmMrgCtxOppositeLic.numValidMergeCand; + } + for (uint32_t ui = tmMrgCtxOppositeLic.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) + { + tmMrgCtxOppositeLic.bcwIdx[ui] = BCW_DEFAULT; +#if JVET_AG0276_NLIC + tmMrgCtxOppositeLic.altLMFlag[ui] = false; + tmMrgCtxOppositeLic.altLMParaNeighbours[ui].resetAltLinearModel(); +#endif +#if INTER_LIC + tmMrgCtxOppositeLic.licFlags[ui] = false; +#endif + tmMrgCtxOppositeLic.interDirNeighbours[ui] = 0; + tmMrgCtxOppositeLic.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; + tmMrgCtxOppositeLic.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; + tmMrgCtxOppositeLic.useAltHpelIf[ui] = false; +#if MULTI_HYP_PRED + tmMrgCtxOppositeLic.addHypNeighbours[ui].clear(); +#endif + tmMrgCtxOppositeLic.candCost[ui] = MAX_UINT64; + } +#endif #endif } #endif @@ -4567,6 +4822,56 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand ].setMvField( Mv(), NOT_VALID ); } } +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.tmMergeFlagOppositeLic = true; + for (uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtxOppositeLic.numValidMergeCand; uiMergeCand++) + { + tmMrgCtxOppositeLic.setMergeInfo(pu, uiMergeCand); +#if MULTI_PASS_DMVR + applyBDMVR4TMOppositeLic[uiMergeCand] = PU::checkBDMVRCondition(pu); + if (applyBDMVR4TMOppositeLic[uiMergeCand]) + { + pu.bdmvrRefine = true; + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1]); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (tmMergeRefinedMotion) + { + applyBDMVR4TMOppositeLic[uiMergeCand] = m_pcInterSearch->processBDMVR(pu, 1, tempCost); + } + else +#endif + applyBDMVR4TMOppositeLic[uiMergeCand] = m_pcInterSearch->processBDMVR(pu); + } + else + { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + m_pcInterSearch->deriveTMMv(pu, tempCost); +#else + m_pcInterSearch->deriveTMMv(pu); +#endif + } +#else + m_pcInterSearch->deriveTMMv(pu); +#endif + +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + tmMrgCtxOppositeLic.candCost[uiMergeCand] = tempCost[0]; +#endif + tmMrgCtxOppositeLic.interDirNeighbours[uiMergeCand] = pu.interDir; + tmMrgCtxOppositeLic.bcwIdx[uiMergeCand] = pu.cu->bcwIdx; + tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].setMvField(pu.mv[0], pu.refIdx[0]); + tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(pu.mv[1], pu.refIdx[1]); + if (pu.interDir == 1) + { + tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(Mv(), NOT_VALID); + } + if (pu.interDir == 2) + { + tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].setMvField(Mv(), NOT_VALID); + } + } + pu.tmMergeFlagOppositeLic = false; +#endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC pu.reduceTplSize = false; #endif @@ -4620,6 +4925,50 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif } } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (tmMergeRefinedMotion) + { + pu.tmMergeFlagOppositeLic = true; + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmMrgCtxOppositeLic, applyBDMVR4TMOppositeLic, NULL, NULL, pu.cs->sps->getMaxNumTMMergeCand()); +#if JVET_AB0079_TM_BCW_MRG + m_pcInterSearch->adjustMergeCandidatesBcwIdx(pu, tmMrgCtxOppositeLic); +#endif + pu.tmMergeFlag = true; + for (uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtxOppositeLic.numValidMergeCand; uiMergeCand++) + { + tmMrgCtxOppositeLic.setMergeInfo(pu, uiMergeCand); +#if MULTI_PASS_DMVR + applyBDMVR4TMOppositeLic[uiMergeCand] = PU::checkBDMVRCondition(pu); + if (applyBDMVR4TMOppositeLic[uiMergeCand]) + { + pu.bdmvrRefine = true; + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1]); + applyBDMVR4TMOppositeLic[uiMergeCand] = m_pcInterSearch->processBDMVR(pu); + } + else + { + m_pcInterSearch->deriveTMMv(pu); + } + + tmMrgCtxOppositeLic.interDirNeighbours[uiMergeCand] = pu.interDir; + tmMrgCtxOppositeLic.bcwIdx[uiMergeCand] = pu.cu->bcwIdx; // BCW may change, because bi may be reduced to uni by deriveTMMv(pu) + tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].setMvField(pu.mv[0], pu.refIdx[0]); + tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(pu.mv[1], pu.refIdx[1]); + if (pu.interDir == 1) + { + tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(Mv(), NOT_VALID); + } + if (pu.interDir == 2) + { + tmMrgCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].setMvField(Mv(), NOT_VALID); + } +#endif + } + } +#endif + pu.tmMergeFlagOppositeLic = false; #endif pu.tmMergeFlag = false; #if MULTI_PASS_DMVR @@ -4632,10 +4981,25 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { pu.regularMergeFlag = false; cu.affine = true; +#if JVET_AG0276_NLIC + AltLMAffineMergeCtx altAffineRMVFCtx; + altAffineRMVFCtx.init(); +#if JVET_AG0276_LIC_FLAG_SIGNALING + AltLMAffineMergeCtx altBRAffineRMVFCtx; + altBRAffineRMVFCtx.init(); +#endif +#endif #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS checkaffBmMrg = PU::isAffBMMergeFlagCoded(pu); uint16_t addNumRMVF = 0; - PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, m_pcInterSearch, addNumRMVF); + PU::getRMVFAffineCand(pu, affineRMVFCtx, affineRMVFOriCtx, m_pcInterSearch, addNumRMVF +#if JVET_AG0276_NLIC + , altAffineRMVFCtx +#if JVET_AG0276_LIC_FLAG_SIGNALING + , altBRAffineRMVFCtx +#endif +#endif + ); #endif PU::getAffineMergeCand(pu, affineMergeCtx #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION @@ -4650,6 +5014,51 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& , addNumRMVF #endif ); +#if JVET_AG0276_LIC_FLAG_SIGNALING + int cntAffOppositeLic = 0; + affineMergeCtxOppositeLic.numAffCandToTestEnc = 0; + affineMergeCtxOppositeLic.numValidMergeCand = 0; + if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic()) + { + for (int i = 0; i < affineMergeCtx.numValidMergeCand; i++) + { + if (affineMergeCtx.mergeType[i] == MRG_TYPE_DEFAULT_N) + { + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affineMergeCtxOppositeLic.mvFieldNeighbours[(cntAffOppositeLic << 1) + 0][mvNum] = affineMergeCtx.mvFieldNeighbours[(i << 1) + 0][mvNum]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(cntAffOppositeLic << 1) + 1][mvNum] = affineMergeCtx.mvFieldNeighbours[(i << 1) + 1][mvNum]; + } + affineMergeCtxOppositeLic.interDirNeighbours[cntAffOppositeLic] = affineMergeCtx.interDirNeighbours[i]; + affineMergeCtxOppositeLic.affineType[cntAffOppositeLic] = affineMergeCtx.affineType[i]; + affineMergeCtxOppositeLic.mergeType[cntAffOppositeLic] = affineMergeCtx.mergeType[i]; + affineMergeCtxOppositeLic.bcwIdx[cntAffOppositeLic] = affineMergeCtx.bcwIdx[i]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affineMergeCtxOppositeLic.colIdx[cntAffOppositeLic] = affineMergeCtx.colIdx[i]; +#endif +#if JVET_AG0276_NLIC + affineMergeCtxOppositeLic.altLMFlag[cntAffOppositeLic] = affineMergeCtx.altLMFlag[i]; + affineMergeCtxOppositeLic.altLMParaNeighbours[cntAffOppositeLic] = affineMergeCtx.altLMParaNeighbours[i]; +#endif +#if INTER_LIC + affineMergeCtxOppositeLic.licFlags[cntAffOppositeLic] = !affineMergeCtx.licFlags[i]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affineMergeCtxOppositeLic.obmcFlags[cntAffOppositeLic] = affineMergeCtx.obmcFlags[i]; +#endif + affineMergeCtxOppositeLic.candCost[cntAffOppositeLic] = affineMergeCtx.candCost[i]; + cntAffOppositeLic++; + affineMergeCtxOppositeLic.numValidMergeCand++; + } + else + { + continue; + } + } + affineMergeCtxOppositeLic.numAffCandToTestEnc = std::min(affineMergeCtxOppositeLic.numValidMergeCand, affineMergeCtx.numAffCandToTestEnc); + affineMergeCtxOppositeLic.maxNumMergeCand = affineMergeCtxOppositeLic.numValidMergeCand; + } +#endif #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS if (checkaffBmMrg) { @@ -4699,6 +5108,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.affineType = affineMergeCtxTmp.affineType[uiAffMergeCand]; cu.bcwIdx = affineMergeCtxTmp.bcwIdx[uiAffMergeCand]; pu.mmvdEncOptMode = 0; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtxTmp.altLMFlag[uiAffMergeCand]; + cu.altLMParaUnit = affineMergeCtxTmp.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineMergeCtxTmp.licFlags[uiAffMergeCand]; #endif @@ -4713,7 +5126,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.mvAffi[REF_PIC_LIST_1][0] = affineMergeCtxTmp.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv; pu.mvAffi[REF_PIC_LIST_1][1] = affineMergeCtxTmp.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv; pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtxTmp.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv; +#if JVET_AG0276_LIC_BDOF_BDMVR + if (PU::checkBDMVRCondition4Aff(pu)) +#else if (PU::checkBDMVRCondition(pu)) +#endif { if (PU::checkBDMVR4Affine(pu)) { @@ -4778,7 +5195,40 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif ) { +#if JVET_AG0276_NLIC + if (sps.getUseAffAltLM() && !CU::isTLCond(*pu.cu)) + { + AltLMAffineMergeCtx altLMAffMrgCtx; + PU::getAltLMAffineMergeCand(pu, altLMAffMrgCtx); + m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtx, altLMAffMrgCtx, altAffineRMVFCtx); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic()) + { + AltLMAffineMergeCtx altLMBRAffMrgCtx; + PU::getAltLMBRAffineMergeCand(pu, altLMBRAffMrgCtx); + m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtxOppositeLic, altLMBRAffMrgCtx, altBRAffineRMVFCtx); + } +#endif + } + else + { + m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtx); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic()) + { + m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtxOppositeLic); + } +#endif + } +#else m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtx); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppolicAff && pu.cs->sps->getUseAffMergeOppositeLic()) + { + m_pcInterSearch->adjustAffineMergeCandidates(pu, affineMergeCtxOppositeLic); + } +#endif +#endif #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION affineMergeCtx.numValidMergeCand = slice.getPicHeader()->getMaxNumAffineMergeCand(); affineMergeCtx.maxNumMergeCand = slice.getPicHeader()->getMaxNumAffineMergeCand(); @@ -4788,6 +5238,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { m_pcInterSearch->adjustAffineMergeCandidates(pu, affineBMMergeCtx); } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic()) + { + affineMergeCtxOppositeLic.numValidMergeCand = slice.getPicHeader()->getMaxNumAffineOppositeLicMergeCand(); + affineMergeCtxOppositeLic.maxNumMergeCand = slice.getPicHeader()->getMaxNumAffineOppositeLicMergeCand(); + } #endif } #endif @@ -4844,6 +5301,41 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } } +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic()) + { + pu.mergeOppositeLic = true; + cu.firstPU = &pu; + for (uint32_t uiMergeCand = 0; uiMergeCand < mergeCtxOppositeLic.numValidMergeCand; uiMergeCand++) + { + if (mergeCtxOppositeLic.interDirNeighbours[uiMergeCand] == 3) + { + mergeCtxOppositeLic.setMergeInfo(pu, uiMergeCand); + applyBDMVROppositeLic[uiMergeCand] = PU::checkBDMVRCondition(pu); + + if (applyBDMVROppositeLic[uiMergeCand]) + { + pu.bdmvrRefine = true; + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1]); + + if (mergeCtxOppositeLic.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu))) + { + for (int subPuIdx = 0; subPuIdx < MAX_NUM_SUBCU_DMVR; subPuIdx++) + { + m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1][subPuIdx] = pu.mv[0]; + m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1][subPuIdx] = pu.mv[1]; + } + } + else + { + m_pcInterSearch->processBDMVR(pu); + } + } + } + } + pu.mergeOppositeLic = false; + } +#endif #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT int cnt = 0; int validNum = 0; @@ -4871,6 +5363,35 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if JVET_AF0163_TM_SUBBLOCK_REFINEMENT + int cntOppositeLic = 0; + int validNumOppositeLic = 0; + if (cu.cs->sps->getUseAffineTM() +#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL + && sps.getTMToolsEnableFlag() +#endif + && PU::checkAffineTMCondition(pu) + ) + { + for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtxOppositeLic.numValidMergeCand; uiAffMergeCand++) + { + if (affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv == Mv(0, 0) && affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv == Mv(0, 0) && + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv == Mv(0, 0) && affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv == Mv(0, 0) && + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv == Mv(0, 0) && affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv == Mv(0, 0) + && affineMergeCtxOppositeLic.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP) + { + validNumOppositeLic = uiAffMergeCand; + break; + } + if (uiAffMergeCand == int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()) - 1) + { + validNumOppositeLic = int(pu.cs->picHeader->getMaxNumAffineOppositeLicMergeCand()); + } + } + } +#endif +#endif #if JVET_AB0112_AFFINE_DMVR if (affineMrgAvail #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS @@ -4905,6 +5426,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.affineType = affineMergeCtx.affineType[uiAffMergeCand]; cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand]; pu.mmvdEncOptMode = 0; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand]; + cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand]; #endif @@ -4919,7 +5444,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.mvAffi[REF_PIC_LIST_1][0] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv; pu.mvAffi[REF_PIC_LIST_1][1] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv; pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv; +#if JVET_AG0276_LIC_BDOF_BDMVR + if (PU::checkBDMVRCondition4Aff(pu)) +#else if(PU::checkBDMVRCondition(pu)) +#endif { #if !JVET_AC0144_AFFINE_DMVR_REGRESSION // set merge information @@ -4996,6 +5525,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.mergeIdx = uiAffMergeCand; cu.affineType = affineBMMergeCtx.affineType[uiAffMergeCand]; cu.bcwIdx = affineBMMergeCtx.bcwIdx[uiAffMergeCand]; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineBMMergeCtx.altLMFlag[uiAffMergeCand]; + cu.altLMParaUnit = affineBMMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineBMMergeCtx.licFlags[uiAffMergeCand]; #endif @@ -5011,7 +5544,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.mvAffi[REF_PIC_LIST_1][1] = affineBMMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv; pu.mvAffi[REF_PIC_LIST_1][2] = affineBMMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv; +#if JVET_AG0276_LIC_BDOF_BDMVR + if (PU::checkBDMVRCondition4Aff(pu)) +#else if (PU::checkBDMVRCondition(pu)) +#endif { m_pcInterSearch->processBDMVR4AdaptiveAffine(pu, refinedMvL0, refinedMvL1, affTypeL0, affTypeL1); @@ -5063,6 +5600,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& affineBMMergeL0.mergeType[uiAffMergeCand] = affineBMMergeCtx.mergeType[uiAffMergeCand]; affineBMMergeL0.bcwIdx[uiAffMergeCand] = affineBMMergeCtx.bcwIdx[uiAffMergeCand]; +#if JVET_AG0276_NLIC + affineBMMergeL0.altLMFlag[uiAffMergeCand] = affineBMMergeCtx.altLMFlag[uiAffMergeCand]; + affineBMMergeL0.altLMParaNeighbours[uiAffMergeCand] = affineBMMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC affineBMMergeL0.licFlags[uiAffMergeCand] = affineBMMergeCtx.licFlags[uiAffMergeCand]; #endif @@ -5082,6 +5623,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& affineBMMergeL1.mergeType[uiAffMergeCand] = affineBMMergeCtx.mergeType[uiAffMergeCand]; affineBMMergeL1.bcwIdx[uiAffMergeCand] = affineBMMergeCtx.bcwIdx[uiAffMergeCand]; +#if JVET_AG0276_NLIC + affineBMMergeL1.altLMFlag[uiAffMergeCand] = affineBMMergeCtx.altLMFlag[uiAffMergeCand]; + affineBMMergeL1.altLMParaNeighbours[uiAffMergeCand] = affineBMMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC affineBMMergeL1.licFlags[uiAffMergeCand] = affineBMMergeCtx.licFlags[uiAffMergeCand]; #endif @@ -5092,6 +5637,114 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if JVET_AB0112_AFFINE_DMVR + pu.affineOppositeLic = true; + if (affineMrgAvail +#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS + && PU::checkBDMVR4Affine(pu) +#endif + ) + { +#if JVET_AC0144_AFFINE_DMVR_REGRESSION + EAffineModel affType[AFFINE_MRG_MAX_NUM_CANDS]; + Mv refinedAffineMv[AFFINE_MRG_MAX_NUM_CANDS << 1][3]; + bool applyBDMVR4Affine[AFFINE_MRG_MAX_NUM_CANDS] = { false }; +#endif + for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtxOppositeLic.numValidMergeCand; uiAffMergeCand++) + { +#if !JVET_AC0144_AFFINE_DMVR_REGRESSION + m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1][0].setZero(); + m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0].setZero(); +#endif + pu.bdmvrRefine = false; + if (affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand] == 3 && affineMergeCtxOppositeLic.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP) + { + pu.regularMergeFlag = false; + pu.mergeFlag = true; + pu.mmvdMergeFlag = false; + pu.cu->affine = true; + pu.interDir = affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand]; + pu.cu->imv = 0; + pu.mergeType = affineMergeCtxOppositeLic.mergeType[uiAffMergeCand]; + pu.mv[0].setZero(); + pu.mv[1].setZero(); + pu.mergeIdx = uiAffMergeCand; + cu.affineType = affineMergeCtxOppositeLic.affineType[uiAffMergeCand]; + cu.bcwIdx = affineMergeCtxOppositeLic.bcwIdx[uiAffMergeCand]; + pu.mmvdEncOptMode = 0; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand]; + cu.altLMParaUnit = affineMergeCtxOppositeLic.altLMParaNeighbours[uiAffMergeCand]; +#endif +#if INTER_LIC + cu.licFlag = affineMergeCtxOppositeLic.licFlags[uiAffMergeCand]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + cu.obmcFlag = affineMergeCtxOppositeLic.obmcFlags[uiAffMergeCand]; +#endif + pu.refIdx[0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].refIdx; + pu.refIdx[1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].refIdx; + pu.mvAffi[REF_PIC_LIST_0][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv; + pu.mvAffi[REF_PIC_LIST_0][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv; + pu.mvAffi[REF_PIC_LIST_0][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv; + pu.mvAffi[REF_PIC_LIST_1][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv; + pu.mvAffi[REF_PIC_LIST_1][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv; + pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv; +#if JVET_AG0276_LIC_BDOF_BDMVR + if (PU::checkBDMVRCondition4Aff(pu)) +#else + if (PU::checkBDMVRCondition(pu)) +#endif + { +#if !JVET_AC0144_AFFINE_DMVR_REGRESSION + // set merge information + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1], m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1]); +#endif + if (!affineMergeCtxOppositeLic.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu))) + { + m_pcInterSearch->processBDMVR4Affine(pu); +#if JVET_AC0144_AFFINE_DMVR_REGRESSION + refinedAffineMv[(uiAffMergeCand << 1) + 0][0] = pu.mvAffi[REF_PIC_LIST_0][0]; + refinedAffineMv[(uiAffMergeCand << 1) + 0][1] = pu.mvAffi[REF_PIC_LIST_0][1]; + refinedAffineMv[(uiAffMergeCand << 1) + 0][2] = pu.mvAffi[REF_PIC_LIST_0][2]; + refinedAffineMv[(uiAffMergeCand << 1) + 1][0] = pu.mvAffi[REF_PIC_LIST_1][0]; + refinedAffineMv[(uiAffMergeCand << 1) + 1][1] = pu.mvAffi[REF_PIC_LIST_1][1]; + refinedAffineMv[(uiAffMergeCand << 1) + 1][2] = pu.mvAffi[REF_PIC_LIST_1][2]; + affType[uiAffMergeCand] = (EAffineModel)pu.cu->affineType; + applyBDMVR4Affine[uiAffMergeCand] = true; +#endif + } + } + } + } + for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtxOppositeLic.numValidMergeCand; uiAffMergeCand++) + { +#if JVET_AC0144_AFFINE_DMVR_REGRESSION + if (!applyBDMVR4Affine[uiAffMergeCand]) + { + continue; + } + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv = refinedAffineMv[(uiAffMergeCand << 1) + 0][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv = refinedAffineMv[(uiAffMergeCand << 1) + 0][1]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv = refinedAffineMv[(uiAffMergeCand << 1) + 0][2]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv = refinedAffineMv[(uiAffMergeCand << 1) + 1][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv = refinedAffineMv[(uiAffMergeCand << 1) + 1][1]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv = refinedAffineMv[(uiAffMergeCand << 1) + 1][2]; + affineMergeCtxOppositeLic.affineType[uiAffMergeCand] = affType[uiAffMergeCand]; +#else + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0]; +#endif + } + } + pu.affineOppositeLic = false; +#endif +#endif #endif #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT if (cu.cs->sps->getUseAffineTM() && affineMrgAvail @@ -5109,16 +5762,28 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][i].setZero(); } pu.bdmvrRefine = false; +#if JVET_AG0276_NLIC + if ((sps.getUseAffAltLMTM() || !affineMergeCtx.altLMFlag[uiAffMergeCand]) && affineMergeCtx.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtx.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP) +#else if (affineMergeCtx.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtx.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP) +#endif { int index = -1; +#if JVET_AG0276_NLIC + if ((validNum + cnt) < affineMergeCtx.maxNumMergeCand && !affineMergeCtx.altLMFlag[uiAffMergeCand]) +#else if ((validNum + cnt) < affineMergeCtx.maxNumMergeCand) +#endif { index = validNum + cnt; affineMergeCtx.interDirNeighbours[index] = affineMergeCtx.interDirNeighbours[uiAffMergeCand]; affineMergeCtx.mergeType[index] = affineMergeCtx.mergeType[uiAffMergeCand]; affineMergeCtx.affineType[index] = affineMergeCtx.affineType[uiAffMergeCand]; affineMergeCtx.bcwIdx[index] = affineMergeCtx.bcwIdx[uiAffMergeCand]; +#if JVET_AG0276_NLIC + affineMergeCtx.altLMFlag[index] = affineMergeCtx.altLMFlag[uiAffMergeCand]; + affineMergeCtx.altLMParaNeighbours[index] = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC affineMergeCtx.licFlags[index] = affineMergeCtx.licFlags[uiAffMergeCand]; #endif @@ -5148,6 +5813,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.affineType = affineMergeCtx.affineType[uiAffMergeCand]; cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand]; pu.mmvdEncOptMode = 0; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand]; + pu.cu->altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand]; #endif @@ -5164,7 +5833,13 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv; m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1], m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1]); +#if JVET_AG0276_NLIC + if ((!affineMergeCtx.altLMFlag[uiAffMergeCand] && !affineMergeCtx.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), false)) || + ( affineMergeCtx.altLMFlag[uiAffMergeCand] && !affineMergeCtx.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), true) ) + ) +#else if (!affineMergeCtx.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu))) +#endif { m_pcInterSearch->processTM4Affine(pu, affineMergeCtx, index, true); } @@ -5181,6 +5856,118 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if JVET_AF0163_TM_SUBBLOCK_REFINEMENT + if (cu.cs->sps->getUseAffineTM() && affineMrgAvail +#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL + && sps.getTMToolsEnableFlag() +#endif + && PU::checkAffineTMCondition(pu) + ) + { + for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < validNumOppositeLic; uiAffMergeCand++) + { + for (int i = 0; i < 3; i++) + { + m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1][i].setZero(); + m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][i].setZero(); + } + pu.bdmvrRefine = false; +#if JVET_AG0276_NLIC + if ((sps.getUseAffAltLMTM() || !affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand]) && affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtxOppositeLic.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP) +#else + if (affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand] != 3 && affineMergeCtxOppositeLic.mergeType[uiAffMergeCand] != MRG_TYPE_SUBPU_ATMVP) +#endif + { + int index = -1; +#if JVET_AG0276_NLIC + if ((validNumOppositeLic + cntOppositeLic) < affineMergeCtxOppositeLic.maxNumMergeCand && !affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand]) +#else + if ((validNumOppoLic + cntOppoLic) < affineMergeCtxOppoLic.maxNumMergeCand) +#endif + { + index = validNumOppositeLic + cntOppositeLic; + affineMergeCtxOppositeLic.interDirNeighbours[index] = affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand]; + affineMergeCtxOppositeLic.mergeType[index] = affineMergeCtxOppositeLic.mergeType[uiAffMergeCand]; + affineMergeCtxOppositeLic.affineType[index] = affineMergeCtxOppositeLic.affineType[uiAffMergeCand]; + affineMergeCtxOppositeLic.bcwIdx[index] = affineMergeCtxOppositeLic.bcwIdx[uiAffMergeCand]; +#if JVET_AG0276_NLIC + affineMergeCtxOppositeLic.altLMFlag[index] = affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand]; + affineMergeCtxOppositeLic.altLMParaNeighbours[index] = affineMergeCtxOppositeLic.altLMParaNeighbours[uiAffMergeCand]; +#endif +#if INTER_LIC + affineMergeCtxOppositeLic.licFlags[index] = affineMergeCtxOppositeLic.licFlags[uiAffMergeCand]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + affineMergeCtxOppositeLic.obmcFlags[index] = affineMergeCtxOppositeLic.obmcFlags[uiAffMergeCand]; +#endif + for (int i = 0; i < 2; i++) + { + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affineMergeCtxOppositeLic.mvFieldNeighbours[(index << 1) + i][mvNum].refIdx = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + i][mvNum].refIdx; + affineMergeCtxOppositeLic.mvFieldNeighbours[(index << 1) + i][mvNum].mv = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + i][mvNum].mv; + } + } + cntOppositeLic++; + } + pu.regularMergeFlag = false; + pu.mergeFlag = true; + pu.mmvdMergeFlag = false; + pu.cu->affine = true; + pu.interDir = affineMergeCtxOppositeLic.interDirNeighbours[uiAffMergeCand]; + pu.cu->imv = 0; + pu.mergeType = affineMergeCtxOppositeLic.mergeType[uiAffMergeCand]; + pu.mv[0].setZero(); + pu.mv[1].setZero(); + pu.mergeIdx = uiAffMergeCand; + cu.affineType = affineMergeCtxOppositeLic.affineType[uiAffMergeCand]; + cu.bcwIdx = affineMergeCtxOppositeLic.bcwIdx[uiAffMergeCand]; + pu.mmvdEncOptMode = 0; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand]; + pu.cu->altLMParaUnit = affineMergeCtxOppositeLic.altLMParaNeighbours[uiAffMergeCand]; +#endif +#if INTER_LIC + cu.licFlag = affineMergeCtxOppositeLic.licFlags[uiAffMergeCand]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + cu.obmcFlag = affineMergeCtxOppositeLic.obmcFlags[uiAffMergeCand]; +#endif + pu.refIdx[0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].refIdx; + pu.refIdx[1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].refIdx; + pu.mvAffi[REF_PIC_LIST_0][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv; + pu.mvAffi[REF_PIC_LIST_0][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv; + pu.mvAffi[REF_PIC_LIST_0][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv; + pu.mvAffi[REF_PIC_LIST_1][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv; + pu.mvAffi[REF_PIC_LIST_1][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv; + pu.mvAffi[REF_PIC_LIST_1][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv; + + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4AFFINE[uiAffMergeCand << 1], m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1]); +#if JVET_AG0276_NLIC + if ((!affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand] && !affineMergeCtxOppositeLic.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), false)) || + ( affineMergeCtxOppositeLic.altLMFlag[uiAffMergeCand] && !affineMergeCtxOppositeLic.xCheckSimilarMotion1(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu), true) ) + ) +#else + if (!affineMergeCtxOppositeLic.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu))) +#endif + { + m_pcInterSearch->processTM4Affine(pu, affineMergeCtxOppositeLic, index, true); + } + } + } + for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < validNumOppositeLic; uiAffMergeCand++) + { + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][1].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][2].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 0][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][1].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0]; + affineMergeCtxOppositeLic.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][2].mv += m_mvBufBDMVR4AFFINE[(uiAffMergeCand << 1) + 1][0]; + } + } +#endif +#endif #if JVET_X0049_ADAPT_DMVR checkBmMrg = PU::isBMMergeFlagCoded(pu); if (checkBmMrg) @@ -5592,6 +6379,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& partitioner.setCUData( cu ); cu.slice = tempCS->slice; cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() ); +#if JVET_AG0276_NLIC + cu.altLMFlag = false; + cu.altLMParaUnit.resetAltLinearModel(); +#endif #if INTER_LIC cu.licFlag = false; #endif @@ -5628,6 +6419,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if MULTI_PASS_DMVR pu.bdmvrRefine = false; #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.mergeOppositeLic = false; + pu.affineOppositeLic = false; + pu.tmMergeFlagOppositeLic = false; +#endif #endif DistParam distParam; const bool bUseHadamard = !tempCS->slice->getDisableSATDForRD(); @@ -5793,7 +6589,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { #if MERGE_ENC_OPT #if JVET_AB0079_TM_BCW_MRG +#if JVET_AG0276_NLIC + xCheckSATDCostCiipMerge(tempCS, cu, pu, mrgCtxCiip, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart, mergeOrgCtx); +#else xCheckSATDCostCiipMerge(tempCS, cu, pu, mrgCtxCiip, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart); +#endif #else xCheckSATDCostCiipMerge(tempCS, cu, pu, mergeCtx, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart); #endif @@ -6081,7 +6881,45 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& break; } } - +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (hasOppositelicMrg && pu.cs->sps->getUseMergeOppositeLic()) + { + xCheckSATDCostRegularMergeOppositeLic(tempCS, cu, pu, mergeCtxOppositeLic, acMergeTempBuffer, singleMergeTempBuffer, acMergeTmpBuffer +#if !MULTI_PASS_DMVR + , refinedMvdL0 +#endif + , uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart +#if MULTI_PASS_DMVR + , applyBDMVROppositeLic +#endif + ); + } +#if TM_MRG +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + if (sps.getUseTMMrgMode()) +#else + if (sps.getUseDMVDMode()) +#endif + { + if (hasOppositelicMrg && pu.cs->sps->getUseTMMergeOppositeLic()) + { + xCheckSATDCostTMMergeOppositeLic(tempCS, cu, pu, tmMrgCtxOppositeLic, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart +#if MULTI_PASS_DMVR + , applyBDMVR4TMOppositeLic +#endif + ); + } +#endif + } + if (affineMrgAvail) + { + if (hasOppositelicAff && pu.cs->sps->getUseAffMergeOppositeLic()) + { + xCheckSATDCostAffineMergeOppositeLic(tempCS, cu, pu, affineMergeCtxOppositeLic, mrgCtx, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, rdModeList, candCostList, distParam, ctxStart + ); + } + } +#endif setMergeBestSATDCost( candCostList[0] ); if (isIntrainterEnabled && isChromaEnabled(pu.cs->pcv->chrFormat)) @@ -6222,6 +7060,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() ); cu.skip = false; cu.mmvdSkip = false; +#if JVET_AG0276_NLIC + cu.altLMFlag = false; + cu.altLMParaUnit.resetAltLinearModel(); +#endif #if INTER_LIC cu.licFlag = false; #if JVET_AD0213_LIC_IMP @@ -6303,6 +7145,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if INTER_LIC cu.licFlag = affineMergeCtx.licFlags[uiMergeCand]; #endif +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtx.altLMFlag[uiMergeCand]; + cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiMergeCand]; +#endif #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL cu.obmcFlag = affineMergeCtx.obmcFlags[uiMergeCand]; #endif @@ -6426,6 +7272,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.mmvdSkip = false; pu.regularMergeFlag = false; pu.mmvdMergeFlag = false; +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.affineOppositeLic = false; +#endif pu.mergeFlag = true; pu.afMmvdFlag = true; @@ -6438,6 +7287,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif #if JVET_W0090_ARMC_TM pu.mergeType = affineMergeCtxTmp.mergeType[pu.mergeIdx]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affineMergeCtxTmp.altLMFlag[pu.mergeIdx]; + pu.cu->altLMParaUnit = affineMergeCtxTmp.altLMParaNeighbours[pu.mergeIdx]; +#endif #if INTER_LIC pu.cu->licFlag = affineMergeCtxTmp.licFlags[pu.mergeIdx]; #endif @@ -6492,6 +7345,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& CHECK(uiMergeCand >= affineBMMergeL0.numValidMergeCand, ""); cu.mmvdSkip = false; cu.affine = true; +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.affineOppositeLic = false; +#endif cu.imv = 0; pu.afMmvdFlag = false; pu.regularMergeFlag = false; @@ -6501,6 +7357,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.interDir = affineBMMergeL0.interDirNeighbours[uiMergeCand]; cu.affineType = affineBMMergeL0.affineType[uiMergeCand]; cu.bcwIdx = affineBMMergeL0.bcwIdx[uiMergeCand]; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineBMMergeL0.altLMFlag[uiMergeCand]; + cu.altLMParaUnit = affineBMMergeL0.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineBMMergeL0.licFlags[uiMergeCand]; #endif @@ -6533,6 +7393,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& CHECK(uiMergeCand >= affineBMMergeL1.numValidMergeCand, ""); cu.mmvdSkip = false; cu.affine = true; +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.affineOppositeLic = false; +#endif cu.imv = 0; pu.afMmvdFlag = false; pu.regularMergeFlag = false; @@ -6542,6 +7405,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.interDir = affineBMMergeL1.interDirNeighbours[uiMergeCand]; cu.affineType = affineBMMergeL1.affineType[uiMergeCand]; cu.bcwIdx = affineBMMergeL1.bcwIdx[uiMergeCand]; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineBMMergeL1.altLMFlag[uiMergeCand]; + cu.altLMParaUnit = affineBMMergeL1.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineBMMergeL1.licFlags[uiMergeCand]; #endif @@ -6574,12 +7441,65 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& CHECK(true, "wrong affine BM dir!"); } } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + else if (rdModeList[uiMrgHADIdx].isAffOppositeLic) + { + cu.mmvdSkip = false; + cu.affine = true; + pu.affineOppositeLic = true; + cu.imv = 0; + pu.regularMergeFlag = false; + pu.mergeFlag = true; + pu.mergeIdx = uiMergeCand; + pu.mmvdMergeFlag = false; + pu.interDir = affineMergeCtxOppositeLic.interDirNeighbours[uiMergeCand]; + cu.affineType = affineMergeCtxOppositeLic.affineType[uiMergeCand]; + cu.bcwIdx = affineMergeCtxOppositeLic.bcwIdx[uiMergeCand]; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtxOppositeLic.altLMFlag[uiMergeCand]; + cu.altLMParaUnit = affineMergeCtxOppositeLic.altLMParaNeighbours[uiMergeCand]; +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affineMergeCtxOppositeLic.colIdx[uiMergeCand]; +#endif +#if INTER_LIC + cu.licFlag = affineMergeCtxOppositeLic.licFlags[uiMergeCand]; +#endif +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + cu.obmcFlag = affineMergeCtxOppositeLic.obmcFlags[uiMergeCand]; +#endif + pu.mv[0].setZero(); + pu.mv[1].setZero(); + pu.mvd[REF_PIC_LIST_0] = Mv(); + pu.mvd[REF_PIC_LIST_1] = Mv(); + pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID; + pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID; + pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; + pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; + pu.mergeType = affineMergeCtxOppositeLic.mergeType[uiMergeCand]; +#if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS + pu.affBMMergeFlag = false; +#endif + + for (int i = 0; i < 2; i++) + { + pu.refIdx[i] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiMergeCand << 1) + i][0].refIdx; + pu.mvAffi[i][0] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiMergeCand << 1) + i][0].mv; + pu.mvAffi[i][1] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiMergeCand << 1) + i][1].mv; + pu.mvAffi[i][2] = affineMergeCtxOppositeLic.mvFieldNeighbours[(uiMergeCand << 1) + i][2].mv; + } + PU::spanMotionInfo(pu); + } #endif else if (rdModeList[uiMrgHADIdx].isAffine) { CHECK(uiMergeCand >= affineMergeCtx.numValidMergeCand, ""); cu.mmvdSkip = false; cu.affine = true; +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.affineOppositeLic = false; +#endif cu.imv = 0; pu.regularMergeFlag = false; pu.mergeFlag = true; @@ -6591,6 +7511,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION pu.colIdx = affineMergeCtx.colIdx[uiMergeCand]; #endif +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtx.altLMFlag[uiMergeCand]; + cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineMergeCtx.licFlags[uiMergeCand]; #endif @@ -6632,6 +7556,33 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& PU::spanMotionInfo(pu); } } +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG && MERGE_ENC_OPT +#if JVET_X0141_CIIP_TIMD_TM + else if (rdModeList[uiMrgHADIdx].isTMMrg && rdModeList[uiMrgHADIdx].isTMMrgOppositeLic && !rdModeList[uiMrgHADIdx].isCIIP) +#else + else if (rdModeList[uiMrgHADIdx].isTMMrg) +#endif + { + cu.mmvdSkip = false; + pu.regularMergeFlag = true; + pu.tmMergeFlag = true; + pu.tmMergeFlagOppositeLic = true; +#if JVET_X0141_CIIP_TIMD_TM + pu.ciipFlag = false; +#endif + tmMrgCtxOppositeLic.setMergeInfo(pu, uiMergeCand); +#if MULTI_PASS_DMVR + if (applyBDMVR4TMOppositeLic[uiMergeCand]) + { + isDMVR = true; + pu.bdmvrRefine = true; + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1]); + } +#endif + } +#endif +#endif #if TM_MRG && MERGE_ENC_OPT #if JVET_X0141_CIIP_TIMD_TM else if (rdModeList[uiMrgHADIdx].isTMMrg && !rdModeList[uiMrgHADIdx].isCIIP) @@ -6642,6 +7593,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& cu.mmvdSkip = false; pu.regularMergeFlag = true; pu.tmMergeFlag = true; +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.tmMergeFlagOppositeLic = false; +#endif #if JVET_X0141_CIIP_TIMD_TM pu.ciipFlag = false; #endif @@ -6683,9 +7637,36 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } #endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + else if (rdModeList[uiMrgHADIdx].isOppositeLic) + { + pu.mergeOppositeLic = true; + cu.mmvdSkip = false; + pu.regularMergeFlag = true; + pu.bmMergeFlag = false; + pu.affBMMergeFlag = false; + pu.cu->geoFlag = false; + mergeCtxOppositeLic.setMergeInfo(pu, uiMergeCand); +#if JVET_X0141_CIIP_TIMD_TM && TM_MRG + pu.ciipFlag = false; + pu.tmMergeFlag = false; +#endif +#if MULTI_PASS_DMVR + if (applyBDMVROppositeLic[uiMergeCand]) + { + isDMVR = true; + pu.bdmvrRefine = true; + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1]); + } +#endif + } #endif else { +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.mergeOppositeLic = false; +#endif cu.mmvdSkip = false; pu.regularMergeFlag = true; mergeCtx.setMergeInfo(pu, uiMergeCand); @@ -6735,7 +7716,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } #if MERGE_ENC_OPT +#if JVET_AG0276_LIC_BDOF_BDMVR + if (mrgTempBufSet && uiMrgHADIdx < MMVD_MRG_MAX_RD_NUM && !(pu.bdmvrRefine == true && pu.cu->licFlag == true)) +#else if (mrgTempBufSet && uiMrgHADIdx < MMVD_MRG_MAX_RD_NUM) +#endif #else if( mrgTempBufSet ) #endif @@ -6954,6 +7939,23 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if MULTI_PASS_DMVR if (!rdModeList[uiMrgHADIdx].isAffine && !rdModeList[uiMrgHADIdx].isGeo && pu.bdmvrRefine) { +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG +#if JVET_X0141_CIIP_TIMD_TM + if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic && !rdModeList[uiMrgHADIdx].isCIIP) +#else + if (pu.tmMergeFlag) +#endif + { + PU::spanMotionInfo(pu, mergeCtx, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); + } + else +#endif +#endif #if TM_MRG #if JVET_X0141_CIIP_TIMD_TM if (pu.tmMergeFlag && !rdModeList[uiMrgHADIdx].isCIIP) @@ -6979,6 +7981,25 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } else +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag == true) + { + memset((void*)m_pcInterSearch->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv)); + } +#endif + + PU::spanMotionInfo(pu, mergeCtxOppositeLic, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); + + } + else #endif PU::spanMotionInfo(pu, mergeCtx, #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION @@ -7014,14 +8035,29 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tempCS->getPredBuf().copyFrom(*acMergeTempBuffer[uiMrgHADIdx]); PU::setAffineBdofRefinedMotion(pu, m_mvBufEncAffineBmBDOF[(uiMergeCand << 1) + rdModeList[uiMrgHADIdx].affBMDir - 1]); } +#if JVET_AG0276_LIC_FLAG_SIGNALING + else if (rdModeList[uiMrgHADIdx].isAffine == true && rdModeList[uiMrgHADIdx].isAffBMMrg == false && ((!pu.affineOppositeLic && m_doEncAffineBDOF[uiMergeCand] == true) || (pu.affineOppositeLic && m_doEncAffineBDOFOppositeLic[uiMergeCand] == true))) +#else else if (rdModeList[uiMrgHADIdx].isAffine == true && rdModeList[uiMrgHADIdx].isAffBMMrg == false && m_doEncAffineBDOF[uiMergeCand] == true) +#endif { #if JVET_AG0135_AFFINE_CIIP tempCS->getPredBuf().copyFrom(acMergeAffineBuffer[uiMergeCand]); #else tempCS->getPredBuf().copyFrom(*acMergeTempBuffer[uiMrgHADIdx]); #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.affineOppositeLic) + { + PU::setAffineBdofRefinedMotion(pu, m_mvBufEncAffineBDOFOppositeLic[uiMergeCand]); + } + else + { + PU::setAffineBdofRefinedMotion(pu, m_mvBufEncAffineBDOF[uiMergeCand]); + } +#else PU::setAffineBdofRefinedMotion(pu, m_mvBufEncAffineBDOF[uiMergeCand]); +#endif } #endif else if (rdModeList[uiMrgHADIdx].isAffine) @@ -7096,6 +8132,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& if(pu.bdmvrRefine) #endif { +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG + if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic) + { + PU::spanMotionInfo(pu, mergeCtx, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4TMOPPOSITELIC[uiMergeCand]); + } + else +#endif +#endif #if TM_MRG if( pu.tmMergeFlag ) { @@ -7117,6 +8166,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4BM[uiMergeCand]); } else +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { + PU::spanMotionInfo(pu, mergeCtxOppositeLic, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4OPPOSITELIC[uiMergeCand]); + + } + else #endif PU::spanMotionInfo(pu, mergeCtx, #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION @@ -7160,6 +8221,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if MULTI_PASS_DMVR if (pu.bdmvrRefine) { +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG + if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic) + { + PU::spanMotionInfo(pu, mergeCtx, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); + } + else +#endif +#endif #if TM_MRG if( pu.tmMergeFlag ) { @@ -7181,12 +8255,34 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4BM[uiMergeCand]); } else +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { + PU::spanMotionInfo(pu, mergeCtxOppositeLic, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4OPPOSITELIC[uiMergeCand]); + + } + else +#endif +#if JVET_AG0276_LIC_BDOF_BDMVR + { + if (pu.cu->licFlag == true) + { + memset((void*)m_pcInterSearch->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv)); + } #endif PU::spanMotionInfo(pu, mergeCtx, #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION pu.colIdx, #endif m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); +#if JVET_AG0276_LIC_BDOF_BDMVR + } +#endif } #endif } @@ -7199,6 +8295,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif #if AFFINE_MMVD && MERGE_ENC_OPT && !pu.afMmvdFlag +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + && !pu.mergeOppositeLic + && !pu.tmMergeFlagOppositeLic #endif ) { @@ -9658,6 +10758,10 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct } mergeCtx[i].bcwIdx[idx] = BCW_DEFAULT; mergeCtx[i].useAltHpelIf[idx] = false; +#if JVET_AG0276_NLIC + mergeCtx[i].altLMFlag[idx] = false; + mergeCtx[i].altLMParaNeighbours[idx].resetAltLinearModel(); +#endif #if INTER_LIC mergeCtx[i].licFlags[idx] = false; #endif @@ -12017,8 +13121,15 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu, ) { +#if JVET_AG0276_NLIC + cu.altLMFlag = false; + cu.altLMParaUnit.resetAltLinearModel(); +#endif #if INTER_LIC cu.licFlag = false; +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.mergeOppositeLic = false; #endif cu.mmvdSkip = false; cu.geoFlag = false; @@ -12053,11 +13164,17 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu, pu.mvRefine = true; distParam.cur = singleMergeTempBuffer->Y(); acMergeTmpBuffer[uiMergeCand] = m_acMergeTmpBuffer[uiMergeCand].getBuf(localUnitArea); +#if JVET_AG0276_NLIC + m_pcInterSearch->m_storeBeforeLIC = false; +#else #if INTER_LIC #if JVET_AD0213_LIC_IMP m_pcInterSearch->m_storeBeforeLIC = mergeCtx.licFlags[uiMergeCand] ? true : false; #else m_pcInterSearch->m_storeBeforeLIC = mergeCtx.interDirNeighbours[uiMergeCand] == 3 ? false : true; +#endif +#if JVET_AG0276_LIC_BDOF_BDMVR + m_pcInterSearch->m_storeBeforeLIC &= (applyBDMVR[uiMergeCand] == false); #endif if (m_pcInterSearch->m_storeBeforeLIC) { @@ -12066,9 +13183,11 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu, } else #endif +#endif #if MULTI_PASS_DMVR if (applyBDMVR[uiMergeCand]) { +#if !JVET_AG0276_NLIC if (pu.cu->cs->sps->getUseCiip()) { #if MULTI_HYP_PRED @@ -12083,6 +13202,7 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu, mergeCtx.setMergeInfo(pu, uiMergeCand); #endif } +#endif pu.bdmvrRefine = true; m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1]); @@ -12091,6 +13211,16 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu, if( pu.bdmvrRefine ) { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag == true) + { + Mv* bdofMvBuf = m_pcInterSearch->getBdofSubPuMvOffset(); + for (int z = 0; z < BDOF_SUBPU_MAX_NUM; z++) + { + bdofMvBuf[z].setZero(); + } + } +#endif ::memcpy( m_mvBufEncBDOF[uiMergeCand], m_pcInterSearch->getBdofSubPuMvOffset(), sizeof( Mv ) * BDOF_SUBPU_MAX_NUM ); } @@ -12099,7 +13229,11 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu, else #endif { +#if JVET_AG0276_NLIC + m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer); +#else m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, true, &(acMergeTmpBuffer[uiMergeCand])); +#endif } #if INTER_LIC m_pcInterSearch->m_storeBeforeLIC = false; @@ -12147,7 +13281,11 @@ void EncCu::xCheckSATDCostRegularMerge(CodingStructure *&tempCS, CodingUnit &cu, #if MULTI_PASS_DMVR CHECK(pu.bdmvrRefine && !applyBDMVR[uiMergeCand], ""); #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + uint32_t uiBitsCand = uiMergeCand + 1 + 1 + 1 + 1; // one bit for merge flag, one bit for subblock_merge_flag, and one bit for regualr_merge_flag, one bit for mergeOppoLic flag +#else uint32_t uiBitsCand = uiMergeCand + 1 + 1 + 1; // one bit for merge flag, one bit for subblock_merge_flag, and one bit for regualr_merge_flag +#endif MEResult mergeResult; mergeResult.cu = cu; mergeResult.pu = pu; @@ -12191,6 +13329,9 @@ void EncCu::xCheckSATDCostCiipAffineMerge(CodingStructure *&tempCS, CodingUnit & { #if INTER_LIC cu.licFlag = false; +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.affineOppositeLic = false; #endif cu.mmvdSkip = false; cu.geoFlag = false; @@ -12232,6 +13373,10 @@ void EncCu::xCheckSATDCostCiipAffineMerge(CodingStructure *&tempCS, CodingUnit & cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand]; #if INTER_LIC cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand]; +#endif +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand]; + cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand]; #endif pu.mv[0].setZero(); pu.mv[1].setZero(); @@ -12335,9 +13480,151 @@ void EncCu::xCheckSATDCostCiipAffineMerge(CodingStructure *&tempCS, CodingUnit & pu.ciipAffine = false; } #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +void EncCu::xCheckSATDCostRegularMergeOppositeLic(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtxOppositeLic, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acMergeTmpBuffer[MRG_MAX_NUM_CANDS] +#if !MULTI_PASS_DMVR + , Mv refinedMvdL0[MAX_NUM_PARTS_IN_CTU][MRG_MAX_NUM_CANDS] +#endif + , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart +#if MULTI_PASS_DMVR + , bool* applyBDMVR +#endif +) +{ +#if JVET_AG0276_NLIC + cu.altLMFlag = false; + cu.altLMParaUnit.resetAltLinearModel(); +#endif +#if INTER_LIC + cu.licFlag = false; +#endif + pu.mergeOppositeLic = true; + cu.mmvdSkip = false; + cu.geoFlag = false; + cu.affine = false; + cu.imv = 0; + + pu.ciipFlag = false; +#if CIIP_PDPC + pu.ciipPDPC = false; +#endif + pu.mmvdMergeFlag = false; + pu.regularMergeFlag = true; + + const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE; + const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height)); +#if MULTI_HYP_PRED + const bool testMHP = tempCS->sps->getUseInterMultiHyp() + && (tempCS->area.lumaSize().area() > MULTI_HYP_PRED_RESTRICT_BLOCK_SIZE + && std::min(tempCS->area.lwidth(), tempCS->area.lheight()) >= MULTI_HYP_PRED_RESTRICT_MIN_WH); +#endif + + int insertPos = -1; + for (uint32_t uiMergeCand = 0; uiMergeCand < mergeCtxOppositeLic.numValidMergeCand; uiMergeCand++) + { + mergeCtxOppositeLic.setMergeInfo(pu, uiMergeCand); +#if MULTI_PASS_DMVR + pu.bdmvrRefine = false; // init as false +#endif + pu.mvRefine = true; + distParam.cur = singleMergeTempBuffer->Y(); +#if MULTI_PASS_DMVR + if (applyBDMVR[uiMergeCand]) + { + pu.bdmvrRefine = true; + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4OPPOSITELIC[(uiMergeCand << 1) + 1]); + + pu.mvRefine = true; + m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer); + + if (pu.bdmvrRefine) + { + ::memcpy(m_mvBufEncBDOF4OPPOSITELIC[uiMergeCand], m_pcInterSearch->getBdofSubPuMvOffset(), sizeof(Mv) * BDOF_SUBPU_MAX_NUM); + } + + pu.mvRefine = false; + } + else +#endif + { + m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer); + } + pu.mvRefine = false; +#if !MULTI_PASS_DMVR + if (mergeCtxOppositeLic.interDirNeighbours[uiMergeCand] == 3) + { + mergeCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand].mv = pu.mv[0]; + mergeCtxOppositeLic.mvFieldNeighbours[2 * uiMergeCand + 1].mv = pu.mv[1]; + { + int dx, dy, i, j, num = 0; + dy = std::min<int>(pu.lumaSize().height, DMVR_SUBCU_HEIGHT); + dx = std::min<int>(pu.lumaSize().width, DMVR_SUBCU_WIDTH); + if (PU::checkDMVRCondition(pu)) + { + for (i = 0; i < (pu.lumaSize().height); i += dy) + { + for (j = 0; j < (pu.lumaSize().width); j += dx) + { + refinedMvdL0[num][uiMergeCand] = pu.mvdL0SubPu[num]; + num++; + } + } + } + } + } +#endif + + Distortion uiSad = distParam.distFunc(distParam); + m_CABACEstimator->getCtx() = ctxStart; + uint64_t fracBits = m_pcInterSearch->xCalcPuMeBits(pu); + double cost = (double)uiSad + (double)fracBits * sqrtLambdaForFirstPassIntra; +#if MULTI_HYP_PRED + if (testMHP && pu.addHypData.size() < tempCS->sps->getMaxNumAddHyps()) + { + uint32_t uiBitsCand = uiMergeCand + 1 + 1 + 1 + 1; // one bit for merge flag, one bit for subblock_merge_flag, and one bit for regualr_merge_flag, one bit for mergeOppoLic flag + MEResult mergeResult; + mergeResult.cu = cu; + mergeResult.pu = pu; + mergeResult.bits = uiBitsCand; + mergeResult.cost = uiSad + m_pcRdCost->getCost(uiBitsCand); + m_baseResultsForMH.push_back(mergeResult); + } +#endif + insertPos = -1; + updateCandList(ModeInfo(cu, pu), cost, rdModeList, candCostList, uiNumMrgSATDCand, &insertPos); + if (insertPos != -1 && insertPos < MMVD_MRG_MAX_RD_NUM) + { + if (insertPos == rdModeList.size() - 1) + { + swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]); + } + else + { + for (uint32_t i = uint32_t(rdModeList.size()) - 1; i > insertPos; i--) + { + swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]); + } + swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]); + } + } + } +#if MULTI_PASS_DMVR + pu.bdmvrRefine = false; +#endif + pu.mergeOppositeLic = false; +} +#endif void EncCu::xCheckSATDCostCiipMerge(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acMergeTmpBuffer[MRG_MAX_NUM_CANDS] +#if JVET_AG0276_NLIC + , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart, MergeCtx mergeCtx1) +#else , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart) +#endif { +#if JVET_AG0276_NLIC + cu.altLMFlag = false; + cu.altLMParaUnit.resetAltLinearModel(); +#endif #if INTER_LIC cu.licFlag = false; #endif @@ -12381,7 +13668,27 @@ void EncCu::xCheckSATDCostCiipMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr //acMergeTmpBuffer[mergeCand] = m_acMergeTmpBuffer[mergeCand].getBuf(localUnitArea); // estimate merge bits +#if JVET_AG0276_NLIC + // lic flag is used to generate luma prediction samples for SATD RD to ensure the identical results as anchor; however, the correct solution is to remove such condition on lic flag + if (mergeCtx1.licFlags[mergeCand]) + { + pu.ciipFlag = false; + mergeCtx1.setMergeInfo(pu, mergeCand); + m_pcInterSearch->m_storeBeforeLIC = true; + m_pcInterSearch->m_predictionBeforeLIC = acMergeTmpBuffer[mergeCand]; + m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false); + m_pcInterSearch->m_storeBeforeLIC = false; + pu.ciipFlag = true; + mergeCtx.setMergeInfo(pu, mergeCand); + } + else + { +#endif mergeCtx.setMergeInfo(pu, mergeCand); +#if JVET_AG0276_NLIC + m_pcInterSearch->motionCompensation(pu, acMergeTmpBuffer[mergeCand], REF_PIC_LIST_X, true, false); + } +#endif // first round pu.intraDir[0] = PLANAR_IDX; @@ -12458,6 +13765,10 @@ pu.ciipAffine = false; void EncCu::xCheckSATDCostCiipTmMerge(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acTmMergeTmpBuffer[MRG_MAX_NUM_CANDS] , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart) { +#if JVET_AG0276_NLIC + cu.altLMFlag = false; + cu.altLMParaUnit.resetAltLinearModel(); +#endif #if INTER_LIC cu.licFlag = false; #endif @@ -12508,7 +13819,11 @@ void EncCu::xCheckSATDCostCiipTmMerge(CodingStructure *&tempCS, CodingUnit &cu, pu.numMergedAddHyps = 0; #endif acTmMergeTmpBuffer[mergeCand] = m_acTmMergeTmpBuffer[mergeCand].getBuf(localUnitArea); +#if JVET_AG0276_NLIC + m_pcInterSearch->motionCompensation(pu, acTmMergeTmpBuffer[mergeCand], REF_PIC_LIST_X, true, false); +#else m_pcInterSearch->motionCompensation(pu, acTmMergeTmpBuffer[mergeCand]); +#endif // first round pu.intraDir[0] = PLANAR_IDX; @@ -12589,6 +13904,10 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr #endif ) { +#if JVET_AG0276_NLIC + cu.altLMFlag = false; + cu.altLMParaUnit.resetAltLinearModel(); +#endif #if INTER_LIC cu.licFlag = false; #endif @@ -12665,33 +13984,157 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED && !pu.cs->sps->getUseTMMMVD() #endif - ) - { - continue; - } + ) + { + continue; + } +#endif + +#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED + mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCandtemp, mmvdMergeCand); +#else + mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand); +#endif + pu.mvRefine = true; + distParam.cur = singleMergeTempBuffer->Y(); +#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED + pu.mmvdEncOptMode = (refineStep > 1 +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + + (pu.cs->sps->getUseTMMMVD() ? 0 : 1) +#endif + ? 2 : 1); +#else + pu.mmvdEncOptMode = (refineStep > 2 ? 2 : 1); +#endif + CHECK(!pu.mmvdMergeFlag, "MMVD merge should be set"); + // Don't do chroma MC here + m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false); + pu.mmvdEncOptMode = 0; + pu.mvRefine = false; + Distortion uiSad = distParam.distFunc(distParam); + + m_CABACEstimator->getCtx() = ctxStart; + uint64_t fracBits = m_pcInterSearch->xCalcPuMeBits(pu); + double cost = (double)uiSad + (double)fracBits * sqrtLambdaForFirstPassIntra; +#if MULTI_HYP_PRED + if (testMHP && pu.addHypData.size() < tempCS->sps->getMaxNumAddHyps()) + { + uint32_t uiBitsCand = baseIdx + refineStep + 2 + 1 + 1 + 1; // one bit for merge flag, one bit for subblock_merge_flag, and one bit for regualr_merge_flag + MEResult mergeResult; + mergeResult.cu = cu; + mergeResult.pu = pu; + mergeResult.bits = uiBitsCand; + mergeResult.cost = uiSad + m_pcRdCost->getCost(uiBitsCand); + + m_baseResultsForMH.push_back(mergeResult); + } +#endif + insertPos = -1; + updateCandList(ModeInfo(cu, pu), cost, rdModeList, candCostList, uiNumMrgSATDCand, &insertPos); + if (insertPos != -1 && insertPos < MMVD_MRG_MAX_RD_NUM) + { + for (int i = int(rdModeList.size()) - 1; i > insertPos; i--) + { + swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]); + } + swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]); + } + } +} +#if JVET_AG0276_LIC_FLAG_SIGNALING +void EncCu::xCheckSATDCostAffineMergeOppositeLic(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer + , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart +) +{ + cu.mmvdSkip = false; + cu.geoFlag = false; + cu.affine = true; +#if INTER_LIC + cu.licFlag = false; +#endif + pu.affineOppositeLic = true; + pu.afMmvdFlag = false; + pu.affBMMergeFlag = false; + pu.mergeFlag = true; + pu.ciipFlag = false; +#if CIIP_PDPC + pu.ciipPDPC = false; +#endif + pu.mmvdMergeFlag = false; + pu.regularMergeFlag = false; +#if MULTI_HYP_PRED + pu.addHypData.clear(); + pu.numMergedAddHyps = 0; + const bool testMHP = tempCS->sps->getUseInterMultiHyp() + && (tempCS->area.lumaSize().area() > MULTI_HYP_PRED_RESTRICT_BLOCK_SIZE + && std::min(tempCS->area.lwidth(), tempCS->area.lheight()) >= MULTI_HYP_PRED_RESTRICT_MIN_WH); +#endif + + const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE; + int insertPos = -1; + for (uint32_t uiAffMergeCand = 0; uiAffMergeCand < affineMergeCtx.numValidMergeCand; uiAffMergeCand++) + { + // set merge information + pu.interDir = affineMergeCtx.interDirNeighbours[uiAffMergeCand]; + pu.mergeIdx = uiAffMergeCand; + cu.affineType = affineMergeCtx.affineType[uiAffMergeCand]; + cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand]; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand]; + cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif +#if INTER_LIC + cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand]; +#endif + pu.mv[0].setZero(); + pu.mv[1].setZero(); + cu.imv = 0; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affineMergeCtx.colIdx[uiAffMergeCand]; #endif - -#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED - mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCandtemp, mmvdMergeCand); -#else - mergeCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand); + pu.mergeType = affineMergeCtx.mergeType[uiAffMergeCand]; +#if JVET_AD0193_ADAPTIVE_OBMC_CONTROL + cu.obmcFlag = affineMergeCtx.obmcFlags[uiAffMergeCand]; #endif - pu.mvRefine = true; + PU::setAllAffineMvField(pu, affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 0], REF_PIC_LIST_0); + PU::setAllAffineMvField(pu, affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1], REF_PIC_LIST_1); + distParam.cur = singleMergeTempBuffer->Y(); -#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED - pu.mmvdEncOptMode = (refineStep > 1 -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS - + (pu.cs->sps->getUseTMMMVD() ? 0 : 1) -#endif - ? 2 : 1); +#if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT + if (PU::checkDoAffineBdofRefine(pu, m_pcInterSearch)) + { + pu.availableBdofRefinedMv = AFFINE_SUBPU_BDOF_APPLY_AND_STORE_MV; + m_pcInterSearch->setDoAffineSubPuBdof(false); + m_pcInterSearch->setBdofSubPuMvBuf(m_mvBufEncAffineBDOFOppositeLic[uiAffMergeCand]); + if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) + { + int bioSubPuIdx = 0; + const int bioSubPuStrideIncr = BDOF_SUBPU_STRIDE - (int)(pu.lumaSize().width >> BDOF_SUBPU_DIM_LOG2); + for (int y = 0; y < pu.lumaSize().height; y += 4) + { + for (int x = 0; x < pu.lumaSize().width; x += 4) + { + m_mvBufEncAffineBDOF[uiAffMergeCand][bioSubPuIdx].setZero(); + bioSubPuIdx++; + } + bioSubPuIdx += bioSubPuStrideIncr; + } + } + else + { + PU::spanMotionInfo(pu); + } + m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X); + } + else + { + m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false); + } + pu.availableBdofRefinedMv = AFFINE_SUBPU_BDOF_NOT_APPLY; + m_doEncAffineBDOFOppositeLic[uiAffMergeCand] = false; #else - pu.mmvdEncOptMode = (refineStep > 2 ? 2 : 1); -#endif - CHECK(!pu.mmvdMergeFlag, "MMVD merge should be set"); - // Don't do chroma MC here m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer, REF_PIC_LIST_X, true, false); - pu.mmvdEncOptMode = 0; - pu.mvRefine = false; +#endif Distortion uiSad = distParam.distFunc(distParam); m_CABACEstimator->getCtx() = ctxStart; @@ -12700,19 +14143,30 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr #if MULTI_HYP_PRED if (testMHP && pu.addHypData.size() < tempCS->sps->getMaxNumAddHyps()) { - uint32_t uiBitsCand = baseIdx + refineStep + 2 + 1 + 1 + 1; // one bit for merge flag, one bit for subblock_merge_flag, and one bit for regualr_merge_flag + uint32_t uiBitsCand = uiAffMergeCand + 1; + if (uiAffMergeCand == tempCS->picHeader->getMaxNumAffineMergeCand() - 1) + { + uiBitsCand--; + } + uiBitsCand = uiBitsCand + 1 + 1 + 1; // one bit for merge flag, and one bit for subblock_merge_flag, one for affineOppoLic MEResult mergeResult; mergeResult.cu = cu; mergeResult.pu = pu; mergeResult.bits = uiBitsCand; mergeResult.cost = uiSad + m_pcRdCost->getCost(uiBitsCand); - m_baseResultsForMH.push_back(mergeResult); } +#endif +#if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT + m_pcInterSearch->setDoAffineSubPuBdof(false); #endif insertPos = -1; updateCandList(ModeInfo(cu, pu), cost, rdModeList, candCostList, uiNumMrgSATDCand, &insertPos); +#if MERGE_ENC_OPT if (insertPos != -1 && insertPos < MMVD_MRG_MAX_RD_NUM) +#else + if (insertPos != -1) +#endif { for (int i = int(rdModeList.size()) - 1; i > insertPos; i--) { @@ -12721,7 +14175,11 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]); } } + pu.regularMergeFlag = true; + cu.affine = false; + pu.affineOppositeLic = false; } +#endif #if JVET_AG0135_AFFINE_CIIP void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acMergeAffineBuffer[AFFINE_MRG_MAX_NUM_CANDS] , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart) @@ -12736,6 +14194,9 @@ void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu, #if INTER_LIC cu.licFlag = false; #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.affineOppositeLic = false; +#endif pu.mergeFlag = true; pu.ciipFlag = false; @@ -12766,6 +14227,10 @@ void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu, pu.mergeIdx = uiAffMergeCand; cu.affineType = affineMergeCtx.affineType[uiAffMergeCand]; cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand]; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand]; + cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand]; #endif @@ -12854,7 +14319,11 @@ void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu, { uiBitsCand--; } +#if JVET_AG0276_LIC_FLAG_SIGNALING + uiBitsCand = uiBitsCand + 1 + 1 + 1; // one bit for merge flag, and one bit for subblock_merge_flag +#else uiBitsCand = uiBitsCand + 1 + 1; // one bit for merge flag, and one bit for subblock_merge_flag +#endif MEResult mergeResult; mergeResult.cu = cu; mergeResult.pu = pu; @@ -12928,6 +14397,10 @@ void EncCu::xCheckSATDCostBMAffineMerge(CodingStructure *&tempCS, CodingUnit &cu pu.mergeIdx = uiAffMergeCand; cu.affineType = affineMergeCtx.affineType[uiAffMergeCand]; cu.bcwIdx = affineMergeCtx.bcwIdx[uiAffMergeCand]; +#if JVET_AG0276_NLIC + cu.altLMFlag = affineMergeCtx.altLMFlag[uiAffMergeCand]; + cu.altLMParaUnit = affineMergeCtx.altLMParaNeighbours[uiAffMergeCand]; +#endif #if INTER_LIC cu.licFlag = affineMergeCtx.licFlags[uiAffMergeCand]; #endif @@ -13048,6 +14521,9 @@ void EncCu::xCheckSATDCostTMMerge( CodingStructure*& tempCS, pu.mmvdMergeFlag = false; pu.regularMergeFlag = false; pu.tmMergeFlag = true; +#if JVET_AG0276_LIC_FLAG_SIGNALING + pu.tmMergeFlagOppositeLic = false; +#endif const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE; int insertPos = -1; @@ -13115,6 +14591,100 @@ void EncCu::xCheckSATDCostTMMerge( CodingStructure*& tempCS, pu.bdmvrRefine = false; #endif } +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG && MERGE_ENC_OPT +void EncCu::xCheckSATDCostTMMergeOppositeLic( CodingStructure*& tempCS, + CodingUnit& cu, + PredictionUnit& pu, + MergeCtx& mrgCtx, + PelUnitBuf* acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], + PelUnitBuf*& singleMergeTempBuffer, + unsigned& uiNumMrgSATDCand, + static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, + static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, + DistParam distParam, + const TempCtx& ctxStart, +#if MULTI_PASS_DMVR + bool* applyBDMVR +#endif +) +{ + pu.mergeFlag = true; + cu.mmvdSkip = false; + cu.geoFlag = false; + cu.affine = false; + cu.imv = IMV_OFF; + pu.ciipFlag = false; +#if CIIP_PDPC + pu.ciipPDPC = false; +#endif + pu.mmvdMergeFlag = false; + pu.regularMergeFlag = false; + pu.tmMergeFlag = true; + pu.tmMergeFlagOppositeLic = true; + const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE; + int insertPos = -1; + for (uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++) + { + mrgCtx.setMergeInfo(pu, uiMergeCand); +#if MULTI_PASS_DMVR + if (applyBDMVR[uiMergeCand]) + { + pu.bdmvrRefine = true; + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[uiMergeCand << 1], m_mvBufBDMVR4TMOPPOSITELIC[(uiMergeCand << 1) + 1]); + } +#if !BDOF_RM_CONSTRAINTS + else +#endif +#endif +#if !BDOF_RM_CONSTRAINTS + { + PU::spanMotionInfo(pu, mrgCtx); + } +#endif + + pu.mvRefine = false; +#if INTER_LIC + m_pcInterSearch->m_storeBeforeLIC = false; +#endif + m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer); +#if MULTI_PASS_DMVR + if (pu.bdmvrRefine) + { + ::memcpy(m_mvBufEncBDOF4TMOPPOSITELIC[uiMergeCand], m_pcInterSearch->getBdofSubPuMvOffset(), sizeof(Mv) * BDOF_SUBPU_MAX_NUM); + } +#endif + distParam.cur = singleMergeTempBuffer->Y(); + Distortion uiSad = distParam.distFunc(distParam); + + m_CABACEstimator->getCtx() = ctxStart; + uint64_t fracBits = m_pcInterSearch->xCalcPuMeBits(pu); + double cost = (double)uiSad + (double)fracBits * sqrtLambdaForFirstPassIntra; + insertPos = -1; + updateCandList(ModeInfo(cu, pu), cost, rdModeList, candCostList, uiNumMrgSATDCand, &insertPos); + + if (insertPos != -1 && insertPos < MMVD_MRG_MAX_RD_NUM) + { + for (int i = int(rdModeList.size()) - 1; i > insertPos; i--) + { + swap(acMergeTempBuffer[i - 1], acMergeTempBuffer[i]); + } + swap(singleMergeTempBuffer, acMergeTempBuffer[insertPos]); + } + } + pu.regularMergeFlag = true; + cu.affine = false; +#if AFFINE_MMVD + pu.afMmvdFlag = false; +#endif + pu.tmMergeFlag = false; + pu.tmMergeFlagOppositeLic = false; +#if MULTI_PASS_DMVR + pu.bdmvrRefine = false; +#endif +} +#endif +#endif #endif #if AFFINE_MMVD && MERGE_ENC_OPT @@ -13251,6 +14821,10 @@ void EncCu::xCheckSATDCostAffineMmvdMerge( CodingStructure*& tempCS, pu.mergeType = affineMergeCtx.mergeType [pu.mergeIdx]; pu.interDir = affineMergeCtx.interDirNeighbours[pu.mergeIdx]; pu.cu->affineType = affineMergeCtx.affineType [pu.mergeIdx]; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = affineMergeCtx.altLMFlag[pu.mergeIdx]; + pu.cu->altLMParaUnit = affineMergeCtx.altLMParaNeighbours[pu.mergeIdx]; +#endif #if INTER_LIC pu.cu->licFlag = affineMergeCtx.licFlags [pu.mergeIdx]; #endif @@ -17997,6 +19571,25 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false; +#if JVET_AG0276_LIC_SLOPE_ADJUST + bool testLicSlopeAdjust = tempCS->sps->getLicSlopeAdjustEnabledFlag() && lic && bdmvrAmSearchLoop == 0; + testLicSlopeAdjust &= (tempCS->area.Y().x || tempCS->area.Y().y); + testLicSlopeAdjust &= CU::licSlopeSizeTlCond(tempCS->area.Y().width, tempCS->area.Y().height, tempCS->slice->getTLayer()); + int licDeltaE = testLicSlopeAdjust ? LIC_SLOPE_MAX_NUM_DELTA : 0; + for (int licDeltaIdx = 0; licDeltaIdx <= licDeltaE; licDeltaIdx++) + { + int licDelta = g_licSlopeDeltaSet[licDeltaIdx]; + bcwLoopNum = licDelta == 0 ? bcwLoopNum : 1; + if (licDelta != 0) + { + ComprCUCtx cuECtx = m_modeCtrl->getComprCUCtx(); + double licCost = cuECtx.get<double>(BEST_LIC_COST); + if (licCost != MAX_DOUBLE * .5 && m_pcEncCfg->getFastLicAffine() && ((licCost > bestCS->cost * 1.5 && m_pcEncCfg->getIntraPeriod() > 1) || (licCost > bestCS->cost * 1.4 && m_pcEncCfg->getIntraPeriod() < 0))) + { + continue; + } + } +#endif for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ ) { if( m_pcEncCfg->getUseBcwFast() ) @@ -18039,6 +19632,9 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC cu.predMode = MODE_INTER; #if INTER_LIC cu.licFlag = lic; +#if JVET_AG0276_LIC_SLOPE_ADJUST + cu.licDelta = licDelta; +#endif #endif cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; @@ -18079,6 +19675,12 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC { m_pcInterSearch->setDoAffineLic(bestCS->cus.front()->affine || bestCS->cus.front()->licFlag); } +#if JVET_AG0276_LIC_SLOPE_ADJUST + else if (licDelta != 0) + { + m_pcInterSearch->setDoAffineLic(bestCS->cus.front()->affine || bestCS->cus.front()->licFlag); + } +#endif #endif if (cu.firstPU->amvpMergeModeFlag[0] || cu.firstPU->amvpMergeModeFlag[1]) { @@ -18125,6 +19727,14 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC } CHECK(!(testBcw || (!testBcw && bcwIdx == BCW_DEFAULT)), " !( bTestBcw || (!bTestBcw && bcwIdx == BCW_DEFAULT ) )"); +#if JVET_AG0276_LIC_SLOPE_ADJUST + if (licDelta != 0 && cu.firstPU->interDir == 3) + { + tempCS->initStructData(encTestMode.qp); + continue; + } +#endif + bool isEqualUni = false; if( m_pcEncCfg->getUseBcwFast() ) { @@ -18382,6 +19992,9 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC break; } } // for( UChar bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ ) +#if JVET_AG0276_LIC_SLOPE_ADJUST + } +#endif if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE ) { xCalDebCost( *bestCS, partitioner ); @@ -18451,7 +20064,32 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes #endif double curBestCost = bestCS->cost; double equBcwCost = MAX_DOUBLE; - +#if JVET_AG0276_LIC_SLOPE_ADJUST + bool testLicSlopeAdjust = tempCS->sps->getLicSlopeAdjustEnabledFlag() && lic; + testLicSlopeAdjust &= (tempCS->area.Y().x || tempCS->area.Y().y); + testLicSlopeAdjust &= CU::licSlopeSizeTlCond(tempCS->area.Y().width, tempCS->area.Y().height, tempCS->slice->getTLayer()); + int licDeltaE = testLicSlopeAdjust ? LIC_SLOPE_MAX_NUM_DELTA : 0; + for (int licDeltaIdx = 0; licDeltaIdx <= licDeltaE; licDeltaIdx++) + { + int licDelta = g_licSlopeDeltaSet[licDeltaIdx]; + bcwLoopNum = licDelta == 0 ? bcwLoopNum : 1; + if (licDelta != 0 && iIMV > 1) + { + if (!bestCS->cus.front()->licFlag) + { + continue; + } + } + if (licDelta != 0) + { + ComprCUCtx cuECtx = m_modeCtrl->getComprCUCtx(); + double licCost = cuECtx.get<double>(BEST_LIC_COST); + if (licCost != MAX_DOUBLE * .5 && m_pcEncCfg->getFastLicAffine() && ((licCost > bestCS->cost * 1.5 && m_pcEncCfg->getIntraPeriod() > 1) || (licCost > bestCS->cost * 1.4 && m_pcEncCfg->getIntraPeriod() < 0))) + { + continue; + } + } +#endif for( int bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ ) { if( m_pcEncCfg->getUseBcwFast() ) @@ -18507,6 +20145,9 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes cu.predMode = MODE_INTER; #if INTER_LIC cu.licFlag = lic; +#if JVET_AG0276_LIC_SLOPE_ADJUST + cu.licDelta = licDelta; +#endif #endif cu.chromaQpAdj = m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; @@ -18551,7 +20192,13 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes { m_pcInterSearch->setDoAffineLic(bestCS->cus.front()->affine || bestCS->cus.front()->licFlag); } -#endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + else if (licDelta != 0) + { + m_pcInterSearch->setDoAffineLic(bestCS->cus.front()->affine || bestCS->cus.front()->licFlag); + } +#endif +#endif #endif #if JVET_AF0159_AFFINE_SUBPU_BDOF_REFINEMENT m_pcInterSearch->setBdofSubPuMvBuf(m_mvBufEncMhpAffineBDOF); @@ -18587,6 +20234,14 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes } CHECK(!(testBcw || (!testBcw && bcwIdx == BCW_DEFAULT)), " !( bTestBcw || (!bTestBcw && bcwIdx == BCW_DEFAULT ) )"); +#if JVET_AG0276_LIC_SLOPE_ADJUST + if (licDelta != 0 && cu.firstPU->interDir == 3) + { + tempCS->initStructData(encTestMode.qp); + continue; + } +#endif + bool isEqualUni = false; if( m_pcEncCfg->getUseBcwFast() ) { @@ -18864,6 +20519,9 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes } validMode = true; } // for( UChar bcwLoopIdx = 0; bcwLoopIdx < bcwLoopNum; bcwLoopIdx++ ) +#if JVET_AG0276_LIC_SLOPE_ADJUST + } +#endif if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE ) { @@ -20273,12 +21931,28 @@ void EncCu::predInterSearchAdditionalHypothesisMulti(const MEResultVec& in, MERe #if MULTI_PASS_DMVR else if( pu.bdmvrRefine ) { +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG + if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic) + { + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4TMOPPOSITELIC[(pu.mergeIdx << 1) + 1]); + } + else +#endif +#endif #if TM_MRG if( pu.tmMergeFlag ) { m_pcInterSearch->setBdmvrSubPuMvBuf( m_mvBufBDMVR4TM[pu.mergeIdx << 1], m_mvBufBDMVR4TM[( pu.mergeIdx << 1 ) + 1] ); } else +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4OPPOSITELIC[(pu.mergeIdx << 1) + 1]); + } + else #endif { m_pcInterSearch->setBdmvrSubPuMvBuf( m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[( pu.mergeIdx << 1 ) + 1] ); @@ -20392,6 +22066,15 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc #if MULTI_PASS_DMVR if (pu.bdmvrRefine) { +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG + if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic) + { + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TMOPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4TMOPPOSITELIC[(pu.mergeIdx << 1) + 1]); + } + else +#endif +#endif #if TM_MRG if( pu.tmMergeFlag ) { @@ -20406,7 +22089,18 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc } else #endif - m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[(pu.mergeIdx << 1) + 1]); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4OPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4OPPOSITELIC[(pu.mergeIdx << 1) + 1]); + } + else + { +#endif + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[(pu.mergeIdx << 1) + 1]); +#if JVET_AG0276_LIC_FLAG_SIGNALING + } +#endif } else { @@ -20479,6 +22173,19 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc #if MULTI_PASS_DMVR if (pu.bdmvrRefine) { +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG + if (pu.tmMergeFlag && pu.tmMergeFlagOppositeLic) + { + PU::spanMotionInfo(pu, mrgCtx, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4TMOPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4TMOPPOSITELIC[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); + } + else +#endif +#endif #if TM_MRG if( pu.tmMergeFlag ) { @@ -20501,11 +22208,38 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc } else #endif - PU::spanMotionInfo(pu, mrgCtx, +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pu.mergeOppositeLic) + { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (pu.cu->licFlag == true) + { + memset((void*)m_pcInterSearch->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv)); + } +#endif + PU::spanMotionInfo(pu, mrgCtx, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4OPPOSITELIC[pu.mergeIdx << 1], m_mvBufBDMVR4OPPOSITELIC[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); + } + else +#endif +#if JVET_AG0276_LIC_BDOF_BDMVR + { + if (pu.cu->licFlag == true) + { + memset((void*)m_pcInterSearch->getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv)); + } +#endif + PU::spanMotionInfo(pu, mrgCtx, #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION pu.colIdx, #endif m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); +#if JVET_AG0276_LIC_BDOF_BDMVR + } +#endif } #endif pu.mvRefine = false; diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index afe0df047..64bdcf4bc 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -392,6 +392,12 @@ private: Mv m_mvBufEncBDOF4BM[BM_MRG_MAX_NUM_CANDS<<1][BDOF_SUBPU_MAX_NUM]; #endif #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + Mv m_mvBufBDMVR4OPPOSITELIC[MRG_MAX_NUM_CANDS << 1][MAX_NUM_SUBCU_DMVR]; + Mv m_mvBufEncBDOF4OPPOSITELIC[MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM]; + Mv m_mvBufBDMVR4TMOPPOSITELIC[(TM_MRG_MAX_NUM_INIT_CANDS << 1)][MAX_NUM_SUBCU_DMVR]; + Mv m_mvBufEncBDOF4TMOPPOSITELIC[MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM]; +#endif #if JVET_AE0046_BI_GPM Mv* m_mvBufBDMVR4GPM[2]; Mv* m_mvBufEncBDOF4GPM[GEO_NUM_TM_MV_CAND][MRG_MAX_NUM_CANDS]; @@ -406,6 +412,11 @@ private: bool m_doEncAffineBDOF[AFFINE_MRG_MAX_NUM_CANDS]; bool m_doEncAffineBmBDOF[AFFINE_ADAPTIVE_DMVR_INIT_SIZE << 1]; Mv m_mvBufEncMhpAffineBDOF[BDOF_SUBPU_MAX_NUM]; +#if JVET_AG0276_LIC_FLAG_SIGNALING + Mv m_mvBufEncAffineBDOFOppositeLic[AFFINE_MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM]; + bool m_doEncAffineBDOFOppositeLic[AFFINE_MRG_MAX_NUM_CANDS]; + Mv m_mvBufEncMhpAffineBDOFOppositeLic[BDOF_SUBPU_MAX_NUM]; +#endif #endif #if JVET_X0083_BM_AMVP_MERGE_MODE || JVET_AE0046_BI_GPM Mv m_mvBufEncAmBDMVR[2][MAX_NUM_SUBCU_DMVR]; @@ -532,6 +543,18 @@ protected: #endif ); +#if JVET_AG0276_LIC_FLAG_SIGNALING + void xCheckSATDCostRegularMergeOppositeLic + (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtxOppositeLic, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acMergeTmpBuffer[MRG_MAX_NUM_CANDS] +#if !MULTI_PASS_DMVR + , Mv refinedMvdL0[MAX_NUM_PARTS_IN_CTU][MRG_MAX_NUM_CANDS] +#endif + , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart +#if MULTI_PASS_DMVR + , bool* applyBDMVR +#endif + ); +#endif #if JVET_X0049_ADAPT_DMVR #if JVET_AA0093_REFINED_MOTION_FOR_ARMC void xCheckSATDCostBMMerge @@ -556,9 +579,14 @@ protected: (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acMergeAffineBuffer[AFFINE_MRG_MAX_NUM_CANDS] , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart); #endif +#if JVET_AG0276_NLIC + void xCheckSATDCostCiipMerge(CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acMergeTmpBuffer[MRG_MAX_NUM_CANDS], + unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart, MergeCtx mergeCtx1); +#else void xCheckSATDCostCiipMerge ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acMergeTmpBuffer[MRG_MAX_NUM_CANDS] , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart); +#endif #if JVET_X0141_CIIP_TIMD_TM && TM_MRG void xCheckSATDCostCiipTmMerge (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx mergeCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer, PelUnitBuf acTmMergeTmpBuffer[MRG_MAX_NUM_CANDS] @@ -580,6 +608,12 @@ protected: ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart); #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + void xCheckSATDCostAffineMergeOppositeLic + (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtx, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer + , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart + ); +#endif #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS void xCheckSATDCostBMAffineMerge (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, AffineMergeCtx affineMergeCtxL0, RefPicList reflist, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer @@ -598,6 +632,17 @@ protected: #endif ); #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING +#if TM_MRG + void xCheckSATDCostTMMergeOppositeLic + (CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer + , unsigned& uiNumMrgSATDCand, static_vector<ModeInfo, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &rdModeList, static_vector<double, MRG_MAX_NUM_CANDS + MMVD_ADD_NUM> &candCostList, DistParam distParam, const TempCtx &ctxStart +#if MULTI_PASS_DMVR + , bool* applyBDMVR +#endif + ); +#endif +#endif #if TM_MRG void xCheckSATDCostTMMerge ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx& mrgCtx, PelUnitBuf *acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf *&singleMergeTempBuffer diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 8e4b5044d..f1ee20cc4 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1812,6 +1812,15 @@ void EncLib::xInitSPS( SPS& sps ) sps.setBDOFEnabledFlag ( m_BIO ); #if JVET_W0090_ARMC_TM sps.setUseAML ( m_AML ); +#if JVET_AG0276_NLIC + sps.setUseAltLM ( m_altLM ); + sps.setUseAffAltLM ( m_affAltLM ); +#endif +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + sps.setUseMergeOppositeLic ( m_mergeOppositeLic ); + sps.setUseTMMergeOppositeLic ( m_mergeTMOppositeLic ); + sps.setUseAffMergeOppositeLic ( m_mergeAffOppositeLic ); #endif #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION sps.setUseFastSubTmvp ((m_sourceWidth * m_sourceHeight) > (m_intraPeriod == -1 ? 0 : 832 * 480)); @@ -1820,10 +1829,22 @@ void EncLib::xInitSPS( SPS& sps ) sps.setUseArmcRefinedMotion ( m_armcRefinedMotion ); #endif sps.setMaxNumMergeCand(getMaxNumMergeCand()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + sps.setMaxNumOppositeLicMergeCand( getMaxNumOppositeLicMergeCand() ); +#endif #if JVET_X0049_ADAPT_DMVR sps.setMaxNumBMMergeCand(getMaxNumBMMergeCand()); #endif sps.setMaxNumAffineMergeCand(getMaxNumAffineMergeCand()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + sps.setMaxNumAffineOppositeLicMergeCand( getMaxNumAffineOppositeLicMergeCand() ); + if (getIntraPeriod() < 0 && getBaseQP() > 32 ) + { + sps.setUseMergeOppositeLic(false); + sps.setUseTMMergeOppositeLic(false); + sps.setUseAffMergeOppositeLic(false); + } +#endif sps.setMaxNumIBCMergeCand(getMaxNumIBCMergeCand()); sps.setMaxNumGeoCand(getMaxNumGeoCand()); #if JVET_AG0164_AFFINE_GPM @@ -1836,6 +1857,37 @@ void EncLib::xInitSPS( SPS& sps ) sps.setUseAffineType ( m_AffineType ); #if JVET_AF0163_TM_SUBBLOCK_REFINEMENT sps.setUseAffineTM ( m_useAffineTM ); +#if JVET_AG0276_NLIC + sps.setUseAffAltLMTM ( m_useAffAltLMTM ); + if (getIntraPeriod() > 0) + { + if ((getSourceWidth() * getSourceHeight()) > (832 * 480) && ((getSourceWidth() * getSourceHeight()) < (3840 * 2160))) + { + sps.setUseAffAltLMTM(false); + } + if (getBaseQP() > 32) + { + sps.setUseAltLM(false); + sps.setUseAffAltLM(false); + sps.setUseAffAltLMTM(false); + } + else if (getBaseQP() < 27) + { + sps.setUseAltLM(false); + sps.setUseAffAltLM(true); + sps.setUseAffAltLMTM(true); + } + } + else + { + sps.setUseAffAltLM(false); + sps.setUseAffAltLMTM(false); + if (getBaseQP() < 27) + { + sps.setUseAltLM(false); + } + } +#endif #endif #if JVET_AG0135_AFFINE_CIIP sps.setUseCiipAffine (((m_sourceWidth * m_sourceHeight) > (m_intraPeriod == -1 ? 832 * 480 : 0)) ? m_useCiipAffine : false); @@ -1882,6 +1934,9 @@ void EncLib::xInitSPS( SPS& sps ) sps.setUseBcw ( m_bcw ); #if INTER_LIC sps.setLicEnabledFlag ( m_lic ); +#if JVET_AG0276_LIC_SLOPE_ADJUST + sps.setLicSlopeAdjustEnabledFlag( m_licSlopeAdjust ); +#endif #endif #if LUMA_ADAPTIVE_DEBLOCKING_FILTER_QP_OFFSET sps.setLadfEnabled ( m_LadfEnabled ); @@ -2709,6 +2764,9 @@ void EncLib::xInitPicHeader(PicHeader &picHeader, const SPS &sps, const PPS &pps // merge list sizes picHeader.setMaxNumAffineMergeCand(getMaxNumAffineMergeCand()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + picHeader.setMaxNumAffineOppositeLicMergeCand( getMaxNumAffineOppositeLicMergeCand() ); +#endif // copy partitioning constraints from SPS picHeader.setSplitConsOverrideFlag(false); picHeader.setMinQTSizes( sps.getMinQTSizes() ); diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 98b86025c..5cd6407fc 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1733,6 +1733,9 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt ) #endif { +#if JVET_AG0276_NLIC + if (encTestmode.type != ETM_POST_DONT_SPLIT) +#endif return false; } @@ -1776,7 +1779,11 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt const uint32_t numComp = getNumberValidComponents( slice.getSPS()->getChromaFormatIdc() ); const uint32_t width = partitioner.currArea().lumaSize().width; const CodingStructure *bestCS = cuECtx.bestCS; +#if JVET_AG0276_NLIC + CodingUnit *bestCU = cuECtx.bestCU; +#else const CodingUnit *bestCU = cuECtx.bestCU; +#endif const EncTestMode bestMode = bestCS ? getCSEncMode( *bestCS ) : EncTestMode(); CodedCUInfo &relatedCU = getBlkInfo( partitioner.currArea() ); @@ -2498,6 +2505,99 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt CacheBlkInfoCtrl::touch(partitioner.currArea()); #endif cuECtx.set( IS_BEST_NOSPLIT_SKIP, bestCU->skip ); +#if JVET_AG0276_NLIC + if (cuECtx.bestCU->altLMFlag) + { + cuECtx.bestCU->secAltLMParaUnit = cuECtx.bestCU->altLMParaUnit; + } + else + { + cuECtx.bestCU->secAltLMParaUnit = cuECtx.bestCU->altLMParaUnit; + } + cuECtx.bestCU->altLMParaUnit.resetAltLinearModel(); +#if JVET_AG0276_LIC_FLAG_SIGNALING + cuECtx.bestCU->altLMBRParaUnit.resetAltLinearModel(); +#endif + if (CU::isSecLicParaNeeded(*bestCU)) + { + UnitArea localUnitArea(bestCU->chromaFormat, Area(0, 0, bestCU->lumaSize().width, bestCU->lumaSize().height)); + PelUnitBuf predBeforeMCAdjBuffer = m_pcInterSearch->m_acPredBeforeLICBuffer[REF_PIC_LIST_0].getBuf(localUnitArea); + + bool isPredSampleRefined = CU::isPredRefined(*bestCU); + if (!isPredSampleRefined) + { + bool obmcApplied = true; + if (bestCU->cs->sps->getUseOBMC() == false || bestCU->obmcFlag == false || bestCU->lwidth() * bestCU->lheight() < 32) + { + obmcApplied = false; + } + if (obmcApplied && bestCU->firstPU->mergeFlag) + { + if (m_pcInterSearch->isSCC(*bestCU->firstPU)) + { + obmcApplied = false; + } + } + if (obmcApplied) + { + isPredSampleRefined = true; + } + } + if (CU::isAllowSecLicPara(*bestCU)) + { + if (isPredSampleRefined) + { +#if INTER_LIC + bool orgLicFlag = bestCU->licFlag; + bestCU->licFlag = false; +#endif + bool orgCiipFlag = bestCU->firstPU->ciipFlag; + bestCU->firstPU->ciipFlag = false; + m_pcInterSearch->xPredWoRefinement(*bestCU->firstPU, predBeforeMCAdjBuffer); +#if INTER_LIC + bestCU->licFlag = orgLicFlag; +#endif + bestCU->firstPU->ciipFlag = orgCiipFlag; + } + else + { + m_pcInterSearch->motionCompensation(*cuECtx.bestCU); + predBeforeMCAdjBuffer.copyFrom(cuECtx.bestCU->cs->getPredBuf(*cuECtx.bestCU->firstPU)); + } + } + else + { + if (cuECtx.bestCU->affine && cuECtx.bestCU->firstPU->mergeFlag && cuECtx.bestCU->cs->sps->getUseOBMC() && cuECtx.bestCU->obmcFlag && (cuECtx.bestCU->cs->sps->getUseAltLM() || cuECtx.bestCU->cs->sps->getUseAffAltLM())) + { + if (cuECtx.bestCU->obmcFlag && m_pcInterSearch->isSCC(*cuECtx.bestCU->firstPU) && !CU::isTLCond(*cuECtx.bestCU)) + { + cuECtx.bestCU->obmcFlag = false; + } + } + } + if (CU::isAllowSecLicPara(*bestCU)) + { + PelUnitBuf recBuf = m_pcInterSearch->m_acPredBeforeLICBuffer[REF_PIC_LIST_1].getBuf(localUnitArea); + recBuf.copyFrom(cuECtx.bestCU->cs->getRecoBuf(*cuECtx.bestCU->firstPU)); + if (bestCS->slice->getLmcsEnabledFlag() && m_pcInterSearch->m_pcReshape->getCTUFlag()) + { + recBuf.Y().rspSignal(m_pcInterSearch->m_pcReshape->getInvLUT()); + } +#if JVET_AG0276_LIC_FLAG_SIGNALING + m_pcInterSearch->xDevSecLicPara<false>(*cuECtx.bestCU, predBeforeMCAdjBuffer, recBuf); +#else + m_pcInterSearch->xDevSecLicPara(*cuECtx.bestCU, predBeforeMCAdjBuffer, recBuf); +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + m_pcInterSearch->xDevSecLicPara<true>(*cuECtx.bestCU, predBeforeMCAdjBuffer, recBuf); + if ((cuECtx.bestCU->altLMBRParaUnit.scale[COMPONENT_Y] == cuECtx.bestCU->altLMParaUnit.scale[COMPONENT_Y]) && (cuECtx.bestCU->altLMBRParaUnit.offset[COMPONENT_Y] == cuECtx.bestCU->altLMParaUnit.offset[COMPONENT_Y])) + { + cuECtx.bestCU->altLMBRParaUnit.resetAltLinearModel(); + } +#endif + } + } +#endif } } diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index ed3698952..b3b0e8e65 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -5936,6 +5936,9 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) pu.cu->imv <= (pu.cu->slice->getSPS()->getAMVREnabledFlag() ? IMV_4PEL : 0)); CodingUnit *bestCU = pu.cu->cs->bestCS != nullptr ? pu.cu->cs->bestCS->getCU( CHANNEL_TYPE_LUMA ) : nullptr; bool trySmvd = ( bestCU != nullptr && pu.cu->imv == 2 && checkAffine ) ? ( !bestCU->firstPU->mergeFlag && !bestCU->affine ) : true; +#if JVET_AG0276_LIC_SLOPE_ADJUST + trySmvd &= pu.cu->licDelta == 0; +#endif #if JVET_AG0098_AMVP_WITH_SBTMVP bool bestSubTmvp = (bestCU != NULL && (bestCU->firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP || bestCU->firstPU->amvpSbTmvpFlag)) ? true : false; bool tryAmvpSbTmvp = cs.sps->getSbTMVPEnabledFlag() && cs.slice->getAmvpSbTmvpEnabledFlag() && !cu.licFlag && checkNonAffine && bcwIdx == BCW_DEFAULT ? true : false; @@ -6222,6 +6225,9 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) // Bi-predictive Motion estimation #if JVET_AD0213_LIC_IMP bool condOn = cu.slice->getCheckLDC() || bcwIdx == BCW_DEFAULT || !m_affineModeSelected || !m_pcEncCfg->getUseBcwFast() || (cu.licFlag && bcwIdx != BCW_DEFAULT); +#endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + condOn &= cu.licDelta == 0; #endif if( ( cs.slice->isInterB() ) && ( PU::isBipredRestriction( pu ) == false ) #if JVET_AD0213_LIC_IMP @@ -7500,6 +7506,12 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) #if JVET_X0083_BM_AMVP_MERGE_MODE if (pu.bdmvrRefine) { +#if JVET_AG0276_LIC_BDOF_BDMVR + if (cu.licFlag == true) + { + memset((void*)getBdofSubPuMvOffset(), 0, BDOF_SUBPU_MAX_NUM * sizeof(Mv)); + } +#endif PU::spanMotionInfo(*cu.firstPU, MergeCtx(), #if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION pu.colIdx, @@ -7896,6 +7908,10 @@ void InterSearch::predInterSearchAdditionalHypothesis(PredictionUnit& pu, const const int numWeights = sps.getNumAddHypWeights(); unsigned idx1, idx2, idx3, idx4; getAreaIdx(pu.Y(), *pu.cs->slice->getPPS()->pcv, idx1, idx2, idx3, idx4); +#if JVET_AG0276_NLIC + bool savedAltLMFlag = pu.cu->altLMFlag; + AltLMInterUnit savedAltLMParaUnit = pu.cu->altLMParaUnit; +#endif #if INTER_LIC auto savedLICFlag = pu.cu->licFlag; #endif @@ -7953,6 +7969,10 @@ void InterSearch::predInterSearchAdditionalHypothesis(PredictionUnit& pu, const fakePredData.refIdx[1 - refList] = -1; fakePredData.cu->affine = false; fakePredData.cu->imv = m_geoMrgCtx.useAltHpelIf[i] ? IMV_HPEL : 0; +#if JVET_AG0276_NLIC + fakePredData.cu->altLMFlag = m_geoMrgCtx.altLMFlag[i]; + fakePredData.cu->altLMParaUnit = m_geoMrgCtx.altLMParaNeighbours[i]; +#endif fakePredData.mvRefine = true; if (savedLICFlag) { @@ -7964,6 +7984,10 @@ void InterSearch::predInterSearchAdditionalHypothesis(PredictionUnit& pu, const } fakePredData.mvRefine = false; // the restore of affine flag and imv flag has to be here +#if JVET_AG0276_NLIC + fakePredData.cu->altLMFlag = savedAltLMFlag; + fakePredData.cu->altLMParaUnit = savedAltLMParaUnit; +#endif fakePredData.cu->imv = savedIMV; fakePredData.cu->affine = savedAffine; } @@ -8128,11 +8152,19 @@ void InterSearch::predInterSearchAdditionalHypothesis(PredictionUnit& pu, const cMv = cMvPred; } Distortion uiCostTemp = 0; +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = false; + pu.cu->altLMParaUnit.resetAltLinearModel(); +#endif #if INTER_LIC pu.cu->licFlag = tempMHPredData.licFlag; #endif xMotionEstimation(pu, tempOrigBuf, eRefPicList, cMvPred, iRefIdxPred, cMv, tempMHPredData.mvpIdx, uiBits, uiCostTemp, amvpInfo, false, g_addHypWeight[tempMHPredData.weightIdx]); xCheckBestMVP(eRefPicList, cMv, cMvPred, tempMHPredData.mvpIdx, amvpInfo, uiBits, uiCostTemp, pu.cu->imv); +#if JVET_AG0276_NLIC + pu.cu->altLMFlag = savedAltLMFlag; + pu.cu->altLMParaUnit = savedAltLMParaUnit; +#endif #if INTER_LIC pu.cu->licFlag = savedLICFlag; #endif @@ -11024,6 +11056,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, // Therefore, the undefined bits would be stored in MHP candidates. && !(pu.cu->affineType == AFFINEMODEL_6PARAM && (refIdx4Para[0] == NOT_VALID || refIdx4Para[1] == NOT_VALID)) #endif +#if JVET_AG0276_LIC_SLOPE_ADJUST + && pu.cu->licDelta == 0 +#endif #if INTER_LIC && !JVET_AD0213_LIC_IMP && !pu.cu->licFlag #endif diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h index cfc1d3cea..0574ce27e 100644 --- a/source/Lib/EncoderLib/InterSearch.h +++ b/source/Lib/EncoderLib/InterSearch.h @@ -121,6 +121,11 @@ struct ModeInfo #if TM_MRG bool isTMMrg; #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + bool isTMMrgOppositeLic; + bool isOppositeLic; + bool isAffOppositeLic; +#endif #if JVET_X0049_ADAPT_DMVR bool isBMMrg; uint8_t bmDir; @@ -157,6 +162,11 @@ struct ModeInfo #if TM_MRG , isTMMrg(false) #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + , isTMMrgOppositeLic(false) + , isOppositeLic(false) + , isAffOppositeLic(false) +#endif #if JVET_X0049_ADAPT_DMVR , isBMMrg(false) , bmDir(0) @@ -192,6 +202,11 @@ struct ModeInfo #endif #if TM_MRG , const bool isTMMrg = false +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + , const bool isTMMrgOppositeLic = false + , const bool isOppositeLic = false + , const bool isAffOppositeLic = false #endif ) : mergeCand(mergeCand), isRegularMerge(isRegularMerge), isMMVD(isMMVD), isCIIP(isCIIP) @@ -211,6 +226,11 @@ struct ModeInfo #if TM_MRG , isTMMrg(isTMMrg) #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + , isTMMrgOppositeLic(isTMMrgOppositeLic) + , isOppositeLic(isOppositeLic) + , isAffOppositeLic(isAffOppositeLic) +#endif #if JVET_X0049_ADAPT_DMVR , isBMMrg( false ) , bmDir( 0 ) @@ -257,6 +277,11 @@ struct ModeInfo #if TM_MRG isTMMrg = pu.tmMergeFlag; #endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + isTMMrgOppositeLic = pu.tmMergeFlagOppositeLic; + isOppositeLic = pu.mergeOppositeLic; + isAffOppositeLic = pu.affineOppositeLic; +#endif #if JVET_X0049_ADAPT_DMVR isBMMrg = pu.bmMergeFlag; bmDir = pu.bmDir; @@ -806,7 +831,13 @@ protected: BilateralFilter* m_bilateralFilter; #endif TrQuant* m_pcTrQuant; +#if JVET_AG0276_NLIC +public: EncReshape* m_pcReshape; +protected: +#else + EncReshape* m_pcReshape; +#endif // ME parameters int m_iSearchRange; diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index b9f5d30e8..66e1915e4 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1380,6 +1380,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) #endif #if INTER_LIC WRITE_FLAG(pcSPS->getLicEnabledFlag() ? 1 : 0, "sps_lic_enabled_flag"); +#if JVET_AG0276_LIC_SLOPE_ADJUST + if (pcSPS->getLicEnabledFlag()) + { + WRITE_FLAG(pcSPS->getLicSlopeAdjustEnabledFlag() ? 1 : 0, "sps_lic_slope_adjust_enabled_flag"); + } +#endif #endif WRITE_FLAG( pcSPS->getWrapAroundEnabledFlag() ? 1 : 0, "sps_ref_wraparound_enabled_flag" ); @@ -1485,6 +1491,10 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) { WRITE_FLAG(pcSPS->getFpelMmvdEnabledFlag() ? 1 : 0, "sps_mmvd_fullpel_only_flag"); } +#if JVET_AG0276_LIC_FLAG_SIGNALING + WRITE_FLAG(pcSPS->getUseMergeOppositeLic() ? 1 : 0, "sps_oppositelic_merge_enabled_flag"); + WRITE_FLAG(pcSPS->getUseTMMergeOppositeLic() ? 1 : 0, "sps_TM_oppositelic_merge_enabled_flag"); +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED || JVET_AD0140_MVD_PREDICTION #if JVET_AA0132_CONFIGURABLE_TM_TOOLS if (pcSPS->getTMToolsEnableFlag()) @@ -1492,6 +1502,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_FLAG(pcSPS->getUseMvdPred() ? 1 : 0, "sps_mvd_pred_enabled_flag"); #endif WRITE_UVLC(MRG_MAX_NUM_CANDS - pcSPS->getMaxNumMergeCand(), "six_minus_max_num_merge_cand"); +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pcSPS->getUseMergeOppositeLic()) + { + WRITE_UVLC(REG_MRG_MAX_NUM_CANDS_OPPOSITELIC - pcSPS->getMaxNumOppositeLicMergeCand(), "five_minus_max_num_oppositelic_merge_cand"); + } +#endif WRITE_FLAG( pcSPS->getUseSBT() ? 1 : 0, "sps_sbt_enabled_flag"); #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR WRITE_FLAG( pcSPS->getUseDMVDMode() ? 1 : 0, "sps_dmvd_enabled_flag" ); @@ -1516,12 +1532,38 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) WRITE_UVLC(BM_MRG_MAX_NUM_CANDS - pcSPS->getMaxNumBMMergeCand(), "six_minus_max_num_bm_merge_cand"); #endif WRITE_FLAG( pcSPS->getUseAffine() ? 1 : 0, "sps_affine_enabled_flag" ); +#if JVET_AG0276_NLIC + if (pcSPS->getUseAML() +#if JVET_AE0174_NONINTER_TM_TOOLS_CONTROL + && pcSPS->getTMToolsEnableFlag() +#endif + ) + { + WRITE_FLAG(pcSPS->getUseAltLM() ? 1 : 0, "sps_alt_lm_enabled_flag"); + if (pcSPS->getUseAffine()) + { + WRITE_FLAG(pcSPS->getUseAffAltLM() ? 1 : 0, "sps_affine_alt_lm_enabled_flag"); + } + } +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pcSPS->getUseAffine()) + { + WRITE_FLAG(pcSPS->getUseAffMergeOppositeLic() ? 1 : 0, "sps_affine_oppositelic_merge_enabled_flag"); + } +#endif if ( pcSPS->getUseAffine() ) { WRITE_UVLC(AFFINE_MRG_MAX_NUM_CANDS - pcSPS->getMaxNumAffineMergeCand(), "five_minus_max_num_subblock_merge_cand"); WRITE_FLAG( pcSPS->getUseAffineType() ? 1 : 0, "sps_affine_type_flag" ); #if AFFINE_MMVD WRITE_FLAG( pcSPS->getUseAffineMmvdMode() ? 1 : 0, "sps_affine_mmvd_enabled_flag" ); +#endif +#if JVET_AG0276_LIC_FLAG_SIGNALING + if (pcSPS->getUseAffMergeOppositeLic()) + { + WRITE_UVLC(AFF_MRG_MAX_NUM_CANDS_OPPOSITELIC - pcSPS->getMaxNumAffineOppositeLicMergeCand(), "eight_minus_max_num_oppositelic_subblock_merge_cand"); + } #endif if (pcSPS->getAMVREnabledFlag()) { @@ -1541,6 +1583,12 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) { #endif WRITE_FLAG(pcSPS->getUseAffineTM() ? 1 : 0, "sps_tm_affine_flag"); +#if JVET_AG0276_NLIC + if (pcSPS->getUseAffineTM() && pcSPS->getUseAffAltLM()) + { + WRITE_FLAG(pcSPS->getUseAffAltLMTM() ? 1 : 0, "sps_affine_alt_lm_tm_flag"); + } +#endif #if JVET_AA0132_CONFIGURABLE_TM_TOOLS } #endif @@ -2680,10 +2728,16 @@ void HLSWriter::codePictureHeader( PicHeader* picHeader, bool writeRbspTrailingB if ( sps->getUseAffine() ) { picHeader->setMaxNumAffineMergeCand(sps->getMaxNumAffineMergeCand()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + picHeader->setMaxNumAffineOppositeLicMergeCand(sps->getMaxNumAffineOppositeLicMergeCand()); +#endif } else { picHeader->setMaxNumAffineMergeCand(sps->getSbTMVPEnabledFlag() && picHeader->getEnableTMVPFlag()); +#if JVET_AG0276_LIC_FLAG_SIGNALING + picHeader->setMaxNumAffineOppositeLicMergeCand(0); +#endif } // full-pel MMVD flag -- GitLab