diff --git a/cfg/encoder_lowdelay_ecm.cfg b/cfg/encoder_lowdelay_ecm.cfg index 6ba267eb682ccf1b42ff451f01cfb40e55601928..c82ae77afcfd935a3496762c90dd20e392a45ae0 100644 --- a/cfg/encoder_lowdelay_ecm.cfg +++ b/cfg/encoder_lowdelay_ecm.cfg @@ -121,6 +121,7 @@ Geo : 1 IBC : 0 # turned off in CTC AllowDisFracMMVD : 1 AffineAmvr : 0 +ArmcRefinedMotion : 0 LMCSEnable : 1 # LMCS: 0: disable, 1:enable LMCSSignalType : 0 # Input signal type: 0:SDR, 1:HDR-PQ, 2:HDR-HLG LMCSUpdateCtrl : 2 # LMCS model update control: 0:RA, 1:AI, 2:LDB/LDP diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 7f8151fddc6521cb75f609ee0616c590579b45e4..a815a0cc86168613c83a93758251f6540328104a 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -607,6 +607,12 @@ void EncApp::xInitLibCfg() m_cEncLib.setRPLList1 ( m_RPLList1); m_cEncLib.setIDRRefParamListPresent ( m_idrRefParamList ); m_cEncLib.setGopList ( m_GOPList ); + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + m_cEncLib.setIsRA ( m_isRA ); + m_cEncLib.setNumQPOffset ( m_numQPOffset ); + m_cEncLib.setQPOffsetList ( m_qpOffsetList ); +#endif for(int i = 0; i < MAX_TLAYER; i++) { @@ -775,6 +781,9 @@ void EncApp::xInitLibCfg() m_cEncLib.setBIO (m_BIO); #if JVET_W0090_ARMC_TM m_cEncLib.setAML ( m_AML ); +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + m_cEncLib.setArmcRefinedMotion ( m_iQP < 25 ? false : m_armcRefinedMotion ); #endif m_cEncLib.setUseLMChroma ( m_LMChroma ); m_cEncLib.setHorCollocatedChromaFlag ( m_horCollocatedChromaFlag ); diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 7ea5f1c7e1cbc5a68f2849d3970f975701599fd1..bb33a5d92bc9ebf6e793c8815086fefae8ee09f3 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1014,6 +1014,9 @@ 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") +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + ("ArmcRefinedMotion", m_armcRefinedMotion, true, "Enable adaptive re-ordering of merge candidates with refined motion") #endif ("IMV", m_ImvMode, 1, "Adaptive MV precision Mode (IMV)\n" "\t0: disabled\n" @@ -1880,6 +1883,76 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) } } } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int numQPOffset[MAX_GOP][2]; + int numQPOffsetadded = 0; + + for (int i = 0; i < m_iGOPSize; i++) + { + numQPOffset[i][0] = MAX_INT; + numQPOffset[i][1] = 0; + } + for (int i = 0; i < m_iGOPSize; i++) + { + if (!(m_GOPList[i].m_numRefPicsActive0 > 0 || m_GOPList[i].m_numRefPicsActive1 > 0)) + { + continue; + } + + int qp = m_iQP + m_GOPList[i].m_QPOffset; + + // adjust QP according to QPOffsetModel for the GOP entry. + double dqpOffset = qp * m_GOPList[i].m_QPOffsetModelScale + m_GOPList[i].m_QPOffsetModelOffset + 0.5; + int qpOffset = (int) floor(Clip3<double>(0.0, 3.0, dqpOffset)); + qp += qpOffset; + + bool isQpOffsetAllreadyIdentified = false; + for (int j = 0; j < numQPOffsetadded; j++) + { + if (numQPOffset[j][0] == qp - m_iQP && m_GOPList[i].m_sliceType != 0) + { + isQpOffsetAllreadyIdentified = true; + numQPOffset[j][1]++; + break; + } + } + if (!isQpOffsetAllreadyIdentified) + { + numQPOffset[numQPOffsetadded][0] = qp - m_iQP; + numQPOffset[numQPOffsetadded][1]++; + numQPOffsetadded++; + } + } + + m_numQPOffset = numQPOffsetadded; + if (m_GOPList[0].m_deltaRefPics0[0] > 1) + { + m_isRA = true; + } + else + { + m_isRA = false; + } + + for (int j = 0; j < m_numQPOffset; j++) + { + int max = MAX_INT; + int pos = -1; + for (int i = 0; i < numQPOffsetadded; i++) + { + if ((numQPOffset[i][1]>0) && (max > numQPOffset[i][0])) + { + max = numQPOffset[i][0]; + pos = i; + } + } + if (pos != -1) + { + m_qpOffsetList[j] = numQPOffset[pos][0]; + } + numQPOffset[pos][1] = -1; + } +#endif for (list<const char*>::const_iterator it = argv_unhandled.begin(); it != argv_unhandled.end(); it++) { @@ -4778,6 +4851,9 @@ void EncAppCfg::xPrintParameter() msg( VERBOSE, "DualITree:%d ", m_dualTree ); msg( VERBOSE, "IMV:%d ", m_ImvMode ); msg( VERBOSE, "BIO:%d ", m_BIO ); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + msg( VERBOSE, "ArmcRefinedMotion:%d ", m_armcRefinedMotion ); +#endif msg( VERBOSE, "LMChroma:%d ", m_LMChroma ); msg( VERBOSE, "HorCollocatedChroma:%d ", m_horCollocatedChromaFlag ); msg( VERBOSE, "VerCollocatedChroma:%d ", m_verCollocatedChromaFlag ); diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index a940c531f07cf84e81bb8be33ed77a1b99c38bfc..7b0d539e19974f16303466bb4a5a53f2dc52d600 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -297,6 +297,11 @@ protected: bool m_cabacBypassAlignmentEnabledFlag; bool m_ISP; bool m_useFastISP; ///< flag for enabling fast methods for ISP +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + bool m_isRA; + int m_numQPOffset; + int m_qpOffsetList[MAX_GOP]; +#endif // coding quality #if QP_SWITCHING_FOR_PARALLEL @@ -396,6 +401,9 @@ protected: bool m_BIO; #if JVET_W0090_ARMC_TM bool m_AML; +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool m_armcRefinedMotion; #endif int m_LMChroma; bool m_horCollocatedChromaFlag; diff --git a/source/Lib/CommonLib/Buffer.cpp b/source/Lib/CommonLib/Buffer.cpp index 111680b57a04f3d21066a3605b562e550aa79261..2f73ff97c8d6730293a9aebee430ac701632c6c8 100644 --- a/source/Lib/CommonLib/Buffer.cpp +++ b/source/Lib/CommonLib/Buffer.cpp @@ -960,6 +960,10 @@ PelBufferOps::PelBufferOps() removeHighFreq8 = removeHighFreq; removeHighFreq4 = removeHighFreq; #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + removeWeightHighFreq1 = removeWeightHighFreq; + removeHighFreq1 = removeHighFreq; +#endif profGradFilter = gradFilterCore <false>; applyPROF = applyPROFCore; diff --git a/source/Lib/CommonLib/Buffer.h b/source/Lib/CommonLib/Buffer.h index 6adde3275b44b4e01c5d8087f69e4cdf87c56f16..5a67cf41dabac313632da090d30b6ff6b7ff265a 100644 --- a/source/Lib/CommonLib/Buffer.h +++ b/source/Lib/CommonLib/Buffer.h @@ -95,6 +95,10 @@ struct PelBufferOps void(*calcBlkGradient)(int sx, int sy, int *arraysGx2, int *arraysGxGy, int *arraysGxdI, int *arraysGy2, int *arraysGydI, int &sGx2, int &sGy2, int &sGxGy, int &sGxdI, int &sGydI, int width, int height, int unitSize); void(*copyBuffer)(Pel *src, int srcStride, Pel *dst, int dstStride, int width, int height); void(*padding)(Pel *dst, int stride, int width, int height, int padSize); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + void ( *removeWeightHighFreq1) ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int bcwWeight); + void ( *removeHighFreq1) ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height); +#endif #if ENABLE_SIMD_OPT_BCW && defined(TARGET_SIMD_X86) void ( *removeWeightHighFreq8) ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int bcwWeight); void ( *removeWeightHighFreq4) ( Pel* src0, int src0Stride, const Pel* src1, int src1Stride, int width, int height, int shift, int bcwWeight); @@ -550,7 +554,11 @@ void AreaBuf<T>::removeWeightHighFreq(const AreaBuf<T>& other, const bool bClip, else if(!(width & 3)) g_pelBufOP.removeWeightHighFreq4(dst, dstStride, src, srcStride, width, height, 16, bcwWeight); else +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + g_pelBufOP.removeWeightHighFreq1(dst, dstStride, src, srcStride, width, height, 16, bcwWeight); +#else CHECK(true, "Not supported"); +#endif } else { @@ -613,7 +621,11 @@ void AreaBuf<T>::removeHighFreq( const AreaBuf<T>& other, const bool bClip, cons else if (!(width & 3)) g_pelBufOP.removeHighFreq4(dst, dstStride, src, srcStride, width, height); else +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + g_pelBufOP.removeHighFreq1(dst, dstStride, src, srcStride, width, height); +#else CHECK(true, "Not supported"); +#endif } else { diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 7fb8e912451565566a46ba98e4ebc1a00826bef4..4fc14c8f0b7e57918322be03798a95a413287b92 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -162,16 +162,26 @@ static const int AMVP_DECIMATION_FACTOR = 1; static const int AMVP_DECIMATION_FACTOR = 2; #endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC +static const int NUM_MERGE_CANDS = 28; ///< for maximum buffer of merging candidates +static const int NUM_TMVP_CANDS = 8; ///< TMVP +static const int MAX_PAIR_CANDS = 4; ///< MAX Pairiwse candidates for Regular TM and BM merge modes +#else static const int NUM_MERGE_CANDS = 30; ///< for maximum buffer of merging candidates static const int NUM_TMVP_CANDS = 9; ///< TMVP +#endif #elif JVET_Z0075_IBC_HMVP_ENLARGE static const int NUM_MERGE_CANDS = 20; #endif #if NON_ADJACENT_MRG_CAND static const int MRG_MAX_NUM_CANDS = 15; ///< MERGE #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC +static const int NUM_NON_ADJ_CANDS = 16; ///< Non-Adj +#else static const int NUM_NON_ADJ_CANDS = 18; ///< Non-Adj #endif +#endif static const int LAST_MERGE_IDX_CABAC = 5; #else static const int MRG_MAX_NUM_CANDS = 6; ///< MERGE @@ -205,6 +215,20 @@ static const int AMVP_MERGE_MODE_MERGE_LIST_MAX_CANDS = 6; static const int AMVP_MERGE_MODE_REDUCED_MV_REFINE_SEARCH_ROUND = 8; #endif +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC +static const double LAMBDA_DEC_SIDE[MAX_QP] = { + 0.777106, 0.872272, 0.979092, 1.098994, 1.233579, 1.384646, 1.554212, + 1.744544, 1.958185, 2.197988, 2.467158, 2.769291, 3.108425, 3.489089, + 3.916370, 4.395976, 4.934316, 5.538583, 6.216849, 6.978177, 7.832739, + 8.791952, 9.868633, 11.077166, 12.433698, 13.956355, 15.665478, 17.583905, + 19.737266, 22.154332, 24.867397, 27.912709, 31.330957, 35.167810, 39.474532, + 44.308664, 49.734793, 55.825418, 62.661913, 70.335619, 78.949063, 88.617327, + 99.469587, 111.650836, 125.323826, 140.671239, 157.898127, 177.234655, 198.939174, + 223.301672, 250.647653, 281.342477, 315.796254, 354.469310, 397.878347, 446.603345, + 501.295305, 562.684955, 631.592507, 708.938619, 795.756695, 893.206689, 1002.590610 +}; +#endif + static const int MAX_TLAYER = 7; ///< Explicit temporal layer QP offset - max number of temporal layer static const int ADAPT_SR_SCALE = 1; ///< division factor for adaptive search range @@ -577,15 +601,25 @@ static const int LAST_SIGNIFICANT_GROUPS = 14; #endif static const int AFFINE_MIN_BLOCK_SIZE = 4; ///< Minimum affine MC block size - +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +static const int MMVD_BI_DIR = 3; +static const int AFFINE_BI_DIR = 3; +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED static const int MMVD_REFINE_STEP = 6; ///< max number of distance step #else static const int MMVD_REFINE_STEP = 8; ///< max number of distance step #endif +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +static const int MMVD_MAX_DIR_UNI = 16; +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +static const int MMVD_MAX_DIR = MMVD_MAX_DIR_UNI * MMVD_BI_DIR; +#else static const int MMVD_MAX_DIR = 16; #endif +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED static const int MMVD_SIZE_SHIFT = 3; @@ -596,7 +630,11 @@ static const int MMVD_MAX_REFINE_NUM = (MMVD_REFINE static const int MMVD_MAX_REFINE_NUM = (MMVD_REFINE_STEP * 4); ///< max number of candidate from a base candidate #endif +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +static const int MMVD_BASE_MV_NUM = 3; ///< max number of base candidate +#else static const int MMVD_BASE_MV_NUM = 2; ///< max number of base candidate +#endif static const int MMVD_ADD_NUM = (MMVD_MAX_REFINE_NUM * MMVD_BASE_MV_NUM);///< total number of mmvd candidate #if MERGE_ENC_OPT static const int MMVD_MRG_MAX_RD_NUM = 20; @@ -701,10 +739,22 @@ static const int NUM_MRG_SATD_CAND = 4; static const double MRG_FAST_RATIO = 1.25; static const int NUM_AFF_MRG_SATD_CAND = 2; #if AFFINE_MMVD +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +static const int AF_MMVD_BASE_NUM = 3; +#else static const int AF_MMVD_BASE_NUM = 1; +#endif +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +static const int AF_MMVD_STEP_NUM = 4; // number of distance offset +#else static const int AF_MMVD_STEP_NUM = 5; // number of distance offset +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +static const int AF_MMVD_OFFSET_DIR = 8 * AFFINE_BI_DIR; +#else static const int AF_MMVD_OFFSET_DIR = 8; +#endif #else static const int AF_MMVD_OFFSET_DIR = 4; // 00: (+, 0); 01: (-, 0); 10: (0, +); 11 (0, -); #endif @@ -730,7 +780,7 @@ static const int TM_LOG2_BASE_WEIGHT = 5; ///< base static const int TM_DISTANCE_WEIGHTS[][4] = { { 0, 1, 2, 3 }, { 1, 2, 3, 3 } }; ///< far to near static const int TM_SPATIAL_WEIGHTS [][4] = { { 2, 2, 2, 2 }, { 0, 1, 1, 2 } }; ///< "left to right for above template" or "top to bottom for left template" #if TM_MRG -#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +#if (JVET_Y0134_TMVP_NAMVP_CAND_REORDERING || JVET_AA0093_REFINED_MOTION_FOR_ARMC) && JVET_W0090_ARMC_TM static const int TM_MRG_MAX_NUM_INIT_CANDS = 10; ///< maximum number of TM merge candidates for ARMC (note: should be at most equal to MRG_MAX_NUM_CANDS) #endif static const int TM_MRG_MAX_NUM_CANDS = 4; ///< maximum number of TM merge candidates (note: should be at most equal to MRG_MAX_NUM_CANDS) @@ -744,7 +794,7 @@ static const int TM_MAX_NUM_SATD_CAND = std::min((int)4, TM_MRG_MAX_NUM_CANDS #endif #endif #endif -#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +#if (JVET_Y0134_TMVP_NAMVP_CAND_REORDERING || JVET_AA0093_REFINED_MOTION_FOR_ARMC) && JVET_W0090_ARMC_TM static const int BM_MRG_MAX_NUM_INIT_CANDS = 10; ///< maximum number of BM merge candidates (note: should be at most equal to MRG_MAX_NUM_CANDS) #endif #if MULTI_PASS_DMVR @@ -801,8 +851,12 @@ static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD = MMVD_MAX_REFINE_NUM; #endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF = AF_MMVD_MAX_REFINE_NUM >> 1; +#else static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF = AF_MMVD_MAX_REFINE_NUM; #endif +#endif #if JVET_AA0057_CCCM static const int CCCM_WINDOW_SIZE = 6; diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 105399327aace3b58a6bc217e18607eb5f82201e..4258d75e88064aae67af583182063ec4247d0f8a 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -649,6 +649,96 @@ bool MergeCtx::xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThr return false; } #endif +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC +bool MergeCtx::xCheckSimilarMotion2Lists(int mergeCandIndex, MergeCtx *mrgCtx, uint32_t mvdSimilarityThresh ) const +{ + if (mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx < 0 && mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx < 0) + { + return true; + } + + if (mvdSimilarityThresh > 1) + { + for (uint32_t ui = 0; ui < numValidMergeCand; ui++) + { + if (interDirNeighbours[ui] == mrgCtx->interDirNeighbours[mergeCandIndex]) + { + if (interDirNeighbours[ui] == 3) + { + if (mvFieldNeighbours[(ui << 1)].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx && + mvFieldNeighbours[(ui << 1) + 1].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx) + { + Mv mvDiffL0 = mvFieldNeighbours[(ui << 1)].mv - mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].mv; + Mv mvDiffL1 = mvFieldNeighbours[(ui << 1) + 1].mv - mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv; + + if (mvDiffL0.getAbsHor() < mvdSimilarityThresh && mvDiffL0.getAbsVer() < mvdSimilarityThresh + && mvDiffL1.getAbsHor() < mvdSimilarityThresh && mvDiffL1.getAbsVer() < mvdSimilarityThresh) + { + return true; + } + } + } + else if (interDirNeighbours[ui] == 1) + { + if (mvFieldNeighbours[(ui << 1)].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx) + { + Mv mvDiff = mvFieldNeighbours[(ui << 1)].mv - mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].mv; + if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh) + { + return true; + } + } + } + else if (interDirNeighbours[ui] == 2) + { + if (mvFieldNeighbours[(ui << 1) + 1].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx) + { + Mv mvDiff = mvFieldNeighbours[(ui << 1) + 1].mv - mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv; + if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh) + { + return true; + } + } + } + } + } + return false; + } + for (uint32_t ui = 0; ui < numValidMergeCand; ui++) + { + if (interDirNeighbours[ui] == mrgCtx->interDirNeighbours[mergeCandIndex]) + { + if (interDirNeighbours[ui] == 3) + { + if (mvFieldNeighbours[(ui << 1)].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx && + mvFieldNeighbours[(ui << 1) + 1].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx && + mvFieldNeighbours[(ui << 1)].mv == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].mv && + mvFieldNeighbours[(ui << 1) + 1].mv == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv) + { + return true; + } + } + else if (interDirNeighbours[ui] == 1) + { + if (mvFieldNeighbours[(ui << 1)].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].refIdx && + mvFieldNeighbours[(ui << 1)].mv == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1)].mv) + { + return true; + } + } + else if (interDirNeighbours[ui] == 2) + { + if (mvFieldNeighbours[(ui << 1) + 1].refIdx == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx && + mvFieldNeighbours[(ui << 1) + 1].mv == mrgCtx->mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv) + { + return true; + } + } + } + } + return false; +} +#endif #if JVET_Z0084_IBC_TM #if JVET_Z0075_IBC_HMVP_ENLARGE bool MergeCtx::xCheckSimilarIBCMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh, int compareNum) const @@ -855,10 +945,55 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx) const int refList1 = mmvdBaseMv[fPosBaseIdx][1].refIdx; #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + //0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 + const int xDir[] = {1, -1, 0, 0, 1, -1, 1, -1, 2, -2, -2, 2, 1, -1, -1, 1}; + const int yDir[] = {0, 0, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 2, -2, 2, -2}; +#else const int xDir[] = {1, -1, 0, 0, 1, -1, 1, -1, 2, -2, 2, -2, 1, 1, -1, -1}; const int yDir[] = {0, 0, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 2, -2, 2, -2}; #endif - +#endif + +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if ((refList0 != -1) && (refList1 != -1)) + { + tempMv[0] = Mv(0,0); + tempMv[1] = Mv(0,0); + int cutOff1 = 2 * MMVD_MAX_DIR_UNI; + int cutOff2 = MMVD_MAX_DIR_UNI; + if (fPosPosition >= cutOff1) + { + fPosPosition -= cutOff1; + const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0); + const int poc1 = slice.getRefPOC(REF_PIC_LIST_1, refList1); + const int currPoc = slice.getPOC(); + tempMv[0] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset); + if ((poc1 - currPoc)*(poc0 - currPoc) > 0) + { + tempMv[1] = tempMv[0]; + } + else + { + tempMv[1].set(-1 * tempMv[0].getHor(), -1 * tempMv[0].getVer()); + } + } + else if (fPosPosition >= cutOff2) + { + fPosPosition -= cutOff2; + tempMv[1] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset); + } + else + { + tempMv[0] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset); + } + pu.interDir = 3; + pu.mv[REF_PIC_LIST_0] = mmvdBaseMv[fPosBaseIdx][0].mv + tempMv[0]; + pu.refIdx[REF_PIC_LIST_0] = refList0; + pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1]; + pu.refIdx[REF_PIC_LIST_1] = refList1; + } +#else if ((refList0 != -1) && (refList1 != -1)) { const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0); @@ -934,6 +1069,7 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx) pu.mv[REF_PIC_LIST_1] = mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1]; pu.refIdx[REF_PIC_LIST_1] = refList1; } +#endif else if (refList0 != -1) { #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index f11db5fe40a9c2acc2bef2e36f5ce84ba91cc63f..446f3ad05a1a3f6eff54a2789c968d84640ec599 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -607,6 +607,9 @@ public: #else bool xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1) const; #endif +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + bool xCheckSimilarMotion2Lists(int mergeCandIndex, MergeCtx *mrgCtx, uint32_t mvdSimilarityThresh = 1) const; +#endif #endif #if JVET_Z0084_IBC_TM #if JVET_Z0075_IBC_HMVP_ENLARGE diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index 705198c0beea465dadf9cad4e114382a6930fa63..4f3fe5204148286c11513893582eac836562d02c 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -912,6 +912,19 @@ const CtxSet ContextSetCfg::GPMIntraFlag = ContextSetCfg::addCtxSet const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet ({ +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + { 18, 18, 18, 18}, + { 18, 18, 18, 18}, + { CNU, CNU, CNU, CNU }, + { 6, 6, 6, 6 }, + { 5, 5, 5, 5}, + { DWS, DWS, DWS, DWS}, + { 18, 18, 18, 18}, + { 18, 18, 18, 18}, + { DWE, DWE, DWE, DWE}, + { 117, 117, 117, 117}, + { 117, 117, 117, 117}, +#else { 18, }, { 18, }, { CNU, }, @@ -923,10 +936,24 @@ const CtxSet ContextSetCfg::MmvdFlag = ContextSetCfg::addCtxSet { DWE, }, { 117, }, { 117, }, +#endif }); const CtxSet ContextSetCfg::MmvdMergeIdx = ContextSetCfg::addCtxSet ({ +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + { 58, 58, 58, 58}, + { 43, 43, 43, 43}, + { CNU, CNU, CNU, CNU }, + { 9, 9, 9, 9}, + { 10, 10, 10, 10}, + { DWS, DWS,DWS,DWS}, + { 18, 18,18,18}, + { 11, 11,11,11}, + { DWE, DWE,DWE,DWE}, + { 116, 116,116,116}, + { 118, 118,118,118}, +#else { 58, }, { 43, }, { CNU, }, @@ -938,6 +965,7 @@ const CtxSet ContextSetCfg::MmvdMergeIdx = ContextSetCfg::addCtxSet { DWE, }, { 116, }, { 118, }, +#endif }); const CtxSet ContextSetCfg::MmvdStepMvpIdx = ContextSetCfg::addCtxSet @@ -1053,6 +1081,19 @@ const CtxSet ContextSetCfg::AfMmvdFlag = ContextSetCfg::addCtxSet const CtxSet ContextSetCfg::AfMmvdIdx = ContextSetCfg::addCtxSet ({ +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + { CNU, CNU,CNU,CNU}, + { CNU, CNU,CNU,CNU}, + { CNU, CNU,CNU,CNU}, + { DWS, DWS,DWS,DWS}, + { DWS, DWS,DWS,DWS}, + { DWS, DWS,DWS,DWS}, + { DWE, DWE,DWE,DWE}, + { DWE, DWE,DWE,DWE}, + { DWE, DWE,DWE,DWE}, + { 119, 119,119,119}, + { 119, 119,119,119}, +#else { CNU, }, { CNU, }, { CNU, }, @@ -1064,11 +1105,25 @@ const CtxSet ContextSetCfg::AfMmvdIdx = ContextSetCfg::addCtxSet { DWE, }, { 119, }, { 119, }, +#endif }); const CtxSet ContextSetCfg::AfMmvdOffsetStep = ContextSetCfg::addCtxSet ({ #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + { 21, 29, 29, 29, 44, CNU}, + { 13, 21, 36, 29, 44, CNU}, + { CNU, CNU, CNU, CNU, CNU, CNU}, + { 5, 5, 5, 4, 5, DWS}, + { 5, 5, 4, 5, 9, DWS}, + { DWS, DWS, DWS, DWS, DWS, DWS}, + { 18, 18, 18, 11, 11, DWE}, + { 18, 18, 11, 18, 25, DWE}, + { DWE, DWE, DWE, DWE, DWE, DWE}, + { 126, 141, 187, 219, 238, DWO}, + { 117, 102, 100, 100, 87, DWO}, +#else { 21, 29, 29, 29, 44, }, { 13, 21, 36, 29, 44, }, { CNU, CNU, CNU, CNU, CNU, }, @@ -1080,6 +1135,7 @@ const CtxSet ContextSetCfg::AfMmvdOffsetStep = ContextSetCfg::addCtxSet { DWE, DWE, DWE, DWE, DWE, }, { 126, 141, 187, 219, 238, }, { 117, 102, 100, 100, 87, }, +#endif #else { 21 }, { 13 }, diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 59e852616b9b0dc0ceae4c6fcaec55af4b33c657..c07fc2104e3907d62f86c7c92dd1a1854ac00664 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -1956,7 +1956,11 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio { #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + int filterIdx = isAML && (pu.mmvdMergeFlag || (pu.tmMergeFlag && !pu.ciipFlag && !pu.cu->geoFlag)) ? 1 : 0; +#else int filterIdx = isAML && pu.mmvdMergeFlag ? 1 : 0; +#endif #else int filterIdx = 0; #endif @@ -5882,9 +5886,9 @@ void InterPrediction::cacheAssign( CacheModel *cache ) #endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED -void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, uint32_t * mmvdLUT, uint32_t MMVDIdx) +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, uint32_t * mmvdLUT, int16_t MMVDIdx) { - const int tempNum = (const int) (std::min<int>(MMVD_BASE_MV_NUM, mrgCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM); const int groupSize = std::min<int>(tempNum, ADAPTIVE_SUB_GROUP_SIZE_MMVD); #if _WINDOWS @@ -5892,7 +5896,7 @@ void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx #else Distortion candCostList[tempNum] ; #endif - + for (uint32_t i = 0; i < tempNum; i++) { mmvdLUT[i] = i; @@ -5907,7 +5911,13 @@ void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx { return; } - + + // Store + int8_t posList0 = 0; + int8_t posList1 = 0; + bool load0 = false; + bool load1 = false; + int startMMVDIdx = 0; int endMMVDIdx = tempNum; if(MMVDIdx != -1) @@ -5916,9 +5926,338 @@ void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx startMMVDIdx = gpId * groupSize; endMMVDIdx = (gpId+1) * groupSize; } - + + int shiftEnc = MMVD_SIZE_SHIFT; + int encGrpSize = groupSize >> shiftEnc; + + encGrpSize /= MMVD_BI_DIR; +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + uint8_t curIdx = 0; + double threshold = 1.02; +#endif + encGrpSize <<= MMVD_SIZE_SHIFT; + + // Joint for all + const Slice &slice = *pu.cs->slice; + const int mvShift = MV_FRACTIONAL_BITS_DIFF; + const int refMvdCands[] = { 1 << mvShift , 2 << mvShift , 4 << mvShift , 8 << mvShift , 16 << mvShift , 32 << mvShift }; + const int xDir[] = {1, -1, 0, 0, 1, -1, 1, -1, 2, -2, -2, 2, 1, -1, -1, 1}; + const int yDir[] = {0, 0, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, 2, -2, 2, -2}; + pu.mmvdMergeFlag = true; + pu.mergeFlag = true; + pu.regularMergeFlag = true; + pu.mergeType = MRG_TYPE_DEFAULT_N; + pu.bdmvrRefine = false; + 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; +#if MULTI_HYP_PRED + pu.addHypData.clear(); + pu.numMergedAddHyps = 0; +#endif + // Joint for all ends + for (int fPosBaseIdx = startMMVDIdx/MMVD_MAX_REFINE_NUM; fPosBaseIdx < endMMVDIdx/MMVD_MAX_REFINE_NUM; fPosBaseIdx++) + { + // joint for each base + 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 INTER_LIC + pu.cu->LICFlag = mrgCtx.LICFlags[fPosBaseIdx]; +#endif + pu.cu->BcwIdx = (mrgCtx.interDirNeighbours[fPosBaseIdx] == 3) ? mrgCtx.BcwIdx[fPosBaseIdx] : BCW_DEFAULT; + pu.refIdx[REF_PIC_LIST_0] = refList0; + pu.refIdx[REF_PIC_LIST_1] = refList1; + // joint for each base ends + + //Store + posList0 = 0; + posList1 = 0; + load0 = false; + load1 = false; + + for (int tempIdx = 0; tempIdx < MMVD_MAX_REFINE_NUM; tempIdx++) + { + // special for each case + int fPosStep = 0; + int fPosPosition = 0; + Mv tempMv[2]; + fPosStep = tempIdx / MMVD_MAX_DIR; + fPosPosition = tempIdx - fPosStep * MMVD_MAX_DIR; + // special for each case + + /* Skipping dir 16 to 47 for uni */ + if ((fPosPosition >= MMVD_MAX_DIR_UNI) && ((refList0 == -1) || (refList1 == -1))) + { + continue; + } + int candIdx = fPosBaseIdx * MMVD_MAX_REFINE_NUM + tempIdx; + pu.mmvdMergeIdx = candIdx; + pu.mergeIdx = candIdx; + int offset = refMvdCands[fPosStep]; + if ( pu.cu->slice->getPicHeader()->getDisFracMMVD() ) + { + offset <<= 2; + } + + if ((refList0 != -1) && (refList1 != -1)) + { + tempMv[0] = Mv(0,0); + tempMv[1] = Mv(0,0); + + int fPosPosition1 = fPosPosition % MMVD_MAX_DIR_UNI; + int fPosPosition2 = fPosPosition / MMVD_MAX_DIR_UNI; + if (fPosPosition2 == 0) + { + tempMv[0] = Mv(xDir[fPosPosition1] * offset, yDir[fPosPosition1] * offset); + //Store + posList0 = fPosPosition1 + 1; + posList1 = 0; + load0 = false; + load1 = (fPosPosition1 != 0) || (fPosStep != 0); + } + else if (fPosPosition2 == 1) + { + tempMv[1] = Mv(xDir[fPosPosition1] * offset, yDir[fPosPosition1] * offset); + //Store + posList0 = 0; + posList1 = fPosPosition1 + 1; + load0 = (fPosPosition1 != 0) || (fPosStep != 0); + load1 = false; + } + else + { + const int poc0 = slice.getRefPOC(REF_PIC_LIST_0, refList0); + const int poc1 = slice.getRefPOC(REF_PIC_LIST_1, refList1); + const int currPoc = slice.getPOC(); + tempMv[0] = Mv(xDir[fPosPosition1] * offset, yDir[fPosPosition1] * offset); + if ((poc1 - currPoc)*(poc0 - currPoc) > 0) + { + tempMv[1] = tempMv[0]; + //Store + posList0 = fPosPosition1 + 1; + posList1 = fPosPosition1 + 1; + load0 = true; + load1 = true; + } + else + { + tempMv[1].set(-1 * tempMv[0].getHor(), -1 * tempMv[0].getVer()); + //Store + posList0 = fPosPosition1 + 1; + posList1 = (fPosPosition1 ^ 1) + 1; + load0 = true; + load1 = true; + } + } + pu.interDir = 3; + pu.mv[REF_PIC_LIST_0] = mrgCtx.mmvdBaseMv[fPosBaseIdx][0].mv + tempMv[0]; + pu.mv[REF_PIC_LIST_1] = mrgCtx.mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1]; + pu.mv[0].clipToStorageBitDepth(); + pu.mv[1].clipToStorageBitDepth(); + } + else if (refList0 != -1) + { + tempMv[0] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset); + pu.interDir = 1; + pu.mv[REF_PIC_LIST_0] = mrgCtx.mmvdBaseMv[fPosBaseIdx][0].mv + tempMv[0]; + pu.mv[REF_PIC_LIST_1] = Mv(0, 0); + pu.mv[0].clipToStorageBitDepth(); + } + else + { + tempMv[1] = Mv(xDir[fPosPosition] * offset, yDir[fPosPosition] * offset); + pu.interDir = 2; + pu.mv[REF_PIC_LIST_0] = Mv(0, 0); + pu.mv[REF_PIC_LIST_1] = mrgCtx.mmvdBaseMv[fPosBaseIdx][1].mv + tempMv[1]; + pu.mv[1].clipToStorageBitDepth(); + } + // Derive prediction + for (int refList = 0; refList < 2; refList++) + { + if (pu.refIdx[refList] >= 0) + { + pu.mv[refList].roundToPrecision(MV_PRECISION_QUARTER, MV_PRECISION_INT); + } + } + uiCost = 0; + + 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))); + //Store + if ((refList0 != -1) && (refList1 != -1)) + { + getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft, posList0, posList1, load0, load1); + } + else + { + 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_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 + // update part + uint32_t i; + uint32_t shift = 0; + uint32_t gpIdx = candIdx/groupSize; + uint32_t endIdx = gpIdx * groupSize + encGrpSize; + while (shift < encGrpSize && uiCost < candCostList[endIdx - 1 - shift]) + { + shift++; + } + if (shift != 0) + { + for (i = 1; i < shift; i++) + { + mmvdLUT[endIdx - i] = mmvdLUT[endIdx - 1 - i]; + candCostList[endIdx - i] = candCostList[endIdx - 1 - i]; + } + mmvdLUT[endIdx - shift] = candIdx; + candCostList[endIdx - shift] = uiCost; + } + } +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int startPoint = fPosBaseIdx * MMVD_MAX_REFINE_NUM; + for (int i = 1; i < encGrpSize; i++) + { + if(((double)candCostList[startPoint+i]/(double)candCostList[startPoint+curIdx]) > threshold) + { + mmvdLUT[startPoint+curIdx+1] = mmvdLUT[startPoint+i]; + candCostList[startPoint+curIdx+1] = candCostList[startPoint+i]; + curIdx++; + if (curIdx >= (encGrpSize >> MMVD_SIZE_SHIFT) -1) + { + break; + } + } + } + curIdx = 0; +#endif + + } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + Distortion lambdaTh = pu.cs->slice->getCostForARMC(); + startMMVDIdx = 0; + endMMVDIdx = MMVD_BASE_MV_NUM; + if (MMVDIdx != -1) + { + uint32_t gpId = MMVDIdx / groupSize; + startMMVDIdx = gpId; + endMMVDIdx = (gpId + 1); + } + for (int mmvdBaseIdx = startMMVDIdx; mmvdBaseIdx < endMMVDIdx; mmvdBaseIdx++) + { + uint32_t startIdx = ( mmvdBaseIdx ) * groupSize; + int maxCand = (MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT)/MMVD_BI_DIR; + bool enoughDiverse = false; + uint32_t diverseCand = 0; + uint32_t posToBeInserted = 0; + for (uint32_t uiCand = startIdx; uiCand < startIdx + maxCand - 1; ++uiCand) + { + for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < startIdx + groupSize - 2; ++uiMergeCand) + { + if (lambdaTh <= abs((int)(candCostList[uiMergeCand] - candCostList[uiCand]))) + { + enoughDiverse = true; + for (uint32_t uiMergeCand3 = startIdx; uiMergeCand3 < uiCand; ++uiMergeCand3) + { + if (lambdaTh > abs((int)(candCostList[uiMergeCand] - candCostList[uiMergeCand3]))) + { + enoughDiverse = false; + break; + } + } + if (enoughDiverse) + { + diverseCand = uiMergeCand; + posToBeInserted = uiCand + 1; + break; + } + } + } + if (enoughDiverse) + { + Distortion saveCandCost = candCostList[diverseCand]; + uint32_t mmvdLUTSave = mmvdLUT[diverseCand]; + for (int i = diverseCand; i > posToBeInserted - 1; i--) + { + candCostList[i] = candCostList[i - 1]; + mmvdLUT[i] = mmvdLUT[i - 1]; + } + candCostList[posToBeInserted] = saveCandCost; + mmvdLUT[posToBeInserted] = mmvdLUTSave; + } + } + } +#endif +} +#else +void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit& pu, MergeCtx& mrgCtx, uint32_t* mmvdLUT, uint32_t MMVDIdx) +{ + + const int tempNum = (const int)(std::min<int>(MMVD_BASE_MV_NUM, mrgCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM); + const int groupSize = std::min<int>(tempNum, ADAPTIVE_SUB_GROUP_SIZE_MMVD); +#if _WINDOWS + Distortion candCostList[MMVD_BASE_MV_NUM * MMVD_MAX_REFINE_NUM]; +#else + Distortion candCostList[tempNum]; +#endif + + for (uint32_t i = 0; i < tempNum; i++) + { + mmvdLUT[i] = i; + candCostList[i] = 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; + } + + int startMMVDIdx = 0; + int endMMVDIdx = tempNum; + if (MMVDIdx != -1) + { + uint32_t gpId = MMVDIdx / groupSize; + startMMVDIdx = gpId * groupSize; + endMMVDIdx = (gpId + 1) * groupSize; + } + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int encGrpSize = groupSize; +#else int shiftEnc = MMVD_SIZE_SHIFT; int encGrpSize = groupSize >> shiftEnc; +#endif for (int mmvdMergeCand = startMMVDIdx; mmvdMergeCand < endMMVDIdx; mmvdMergeCand++) { mrgCtx.setMmvdMergeCandiInfo(pu, mmvdMergeCand, mmvdMergeCand); @@ -5930,29 +6269,39 @@ void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx pu.mv[refList].roundToPrecision(MV_PRECISION_QUARTER, MV_PRECISION_INT); } } - + uiCost = 0; - + 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))); - + 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_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 // update part uint32_t i; uint32_t shift = 0; @@ -5974,98 +6323,397 @@ void InterPrediction::sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx } } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + Distortion lambdaTh = pu.cs->slice->getCostForARMC(); + startMMVDIdx = 0; + endMMVDIdx = MMVD_BASE_MV_NUM; + if (MMVDIdx != -1) + { + uint32_t gpId = MMVDIdx / groupSize; + startMMVDIdx = gpId; + endMMVDIdx = (gpId + 1); + } + + for (int mmvdBaseIdx = startMMVDIdx; mmvdBaseIdx < endMMVDIdx; mmvdBaseIdx++) + { + uint32_t startIdx = (mmvdBaseIdx)*groupSize; + int maxCand = (MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT); + bool enoughDiverse = false; + uint32_t diverseCand = 0; + uint32_t posToBeInserted = 0; + for (uint32_t uiCand = startIdx; uiCand < startIdx + maxCand - 1; ++uiCand) + { + for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < startIdx + groupSize - 2; ++uiMergeCand) + { + if (lambdaTh <= abs((int)(candCostList[uiMergeCand] - candCostList[uiCand]))) + { + enoughDiverse = true; + for (uint32_t uiMergeCand3 = startIdx; uiMergeCand3 < uiCand; ++uiMergeCand3) + { + if (lambdaTh > abs((int)(candCostList[uiMergeCand] - candCostList[uiMergeCand3]))) + { + enoughDiverse = false; + break; + } + } + + if (enoughDiverse) + { + diverseCand = uiMergeCand; + posToBeInserted = uiCand + 1; + break; + } + } + } + if (enoughDiverse) + { + Distortion saveCandCost = candCostList[diverseCand]; + uint32_t mmvdLUTSave = mmvdLUT[diverseCand]; + + for (int i = diverseCand; i > posToBeInserted - 1; i--) + { + candCostList[i] = candCostList[i - 1]; + mmvdLUT[i] = mmvdLUT[i - 1]; + } + candCostList[posToBeInserted] = saveCandCost; + mmvdLUT[posToBeInserted] = mmvdLUTSave; + } + } + } +#endif } #endif +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED -void InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, uint32_t afMMVDIdx) +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +void InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, int16_t afMMVDIdx, bool fromStart) { - const int tempNum = AF_MMVD_NUM; int baseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affMrgCtx, 0); int baseCount = std::min<int>((int)AF_MMVD_BASE_NUM, affMrgCtx.numValidMergeCand - baseIdxToMergeIdxOffset); + const int tempNum = baseCount * AF_MMVD_MAX_REFINE_NUM; const int groupSize = std::min<int>(tempNum, ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF); +#if _WINDOWS + Distortion candCostList[AF_MMVD_BASE_NUM * AF_MMVD_MAX_REFINE_NUM]; +#else Distortion candCostList[tempNum]; +#endif for (uint32_t i = 0; i < tempNum; i++) { affMmvdLUT[i] = i; candCostList[i] = MAX_UINT; } - + if (baseCount < 1) { return; } Distortion uiCost; - + DistParam cDistParam; cDistParam.applyWeight = false; - + int nWidth = pu.lumaSize().width; int nHeight = pu.lumaSize().height; - + if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)) { return; } - + int startMMVDIdx = 0; int endMMVDIdx = tempNum; + int8_t gpId = -1; + int stepCutoff = AF_MMVD_STEP_NUM >> 1; if(afMMVDIdx != -1) { - uint32_t gpId = afMMVDIdx/groupSize; - startMMVDIdx = gpId * groupSize; - endMMVDIdx = (gpId+1) * groupSize; + gpId = afMMVDIdx/groupSize; + startMMVDIdx = fromStart ? 0 : gpId * groupSize; + endMMVDIdx = (gpId + 2) * groupSize; + gpId += (afMMVDIdx % 2); } int shiftEnc = AFFINE_MMVD_SIZE_SHIFT; int encGrpSize = groupSize >> shiftEnc; - for (int mmvdMergeCand = startMMVDIdx; mmvdMergeCand < endMMVDIdx; mmvdMergeCand++) - { - pu.afMmvdMergeIdx = (uint8_t)mmvdMergeCand; - - int baseIdx = (int)mmvdMergeCand / AF_MMVD_MAX_REFINE_NUM; - int stepIdx = (int)mmvdMergeCand - baseIdx * AF_MMVD_MAX_REFINE_NUM; - int dirIdx = stepIdx % AF_MMVD_OFFSET_DIR; - stepIdx = stepIdx / AF_MMVD_OFFSET_DIR; - - pu.cu->affine = true; - pu.cu->imv = IMV_OFF; - pu.cu->mmvdSkip = false; - pu.regularMergeFlag = false; - pu.mmvdMergeFlag = false; - pu.mergeFlag = true; - pu.afMmvdFlag = true; + encGrpSize /= AFFINE_BI_DIR; //changed + pu.cu->affine = true; + pu.cu->imv = IMV_OFF; + pu.cu->mmvdSkip = false; + pu.regularMergeFlag = false; + pu.mmvdMergeFlag = false; + pu.mergeFlag = true; + pu.afMmvdFlag = true; + pu.cu->LICFlag = false; + pu.ciipFlag = false; + //Store + int8_t posList0 = 0; + int8_t posList1 = 0; + bool load0 = false; + bool load1 = false; + + for (int fPosBaseIdx = startMMVDIdx/AF_MMVD_MAX_REFINE_NUM; fPosBaseIdx < endMMVDIdx/AF_MMVD_MAX_REFINE_NUM; fPosBaseIdx++) + { + int baseIdx = fPosBaseIdx; pu.afMmvdBaseIdx = (uint8_t)baseIdx; - pu.afMmvdDir = (uint8_t)dirIdx; - pu.afMmvdStep = (uint8_t)stepIdx; pu.mergeIdx = (uint8_t)(baseIdxToMergeIdxOffset + baseIdx); pu.mergeType = affMrgCtx.mergeType[pu.mergeIdx]; -#if INTER_LIC - pu.cu->LICFlag = affMrgCtx.LICFlags[pu.mergeIdx]; - pu.cu->LICFlag = false; -#endif pu.interDir = affMrgCtx.interDirNeighbours[pu.mergeIdx]; pu.cu->affineType = affMrgCtx.affineType[pu.mergeIdx]; pu.cu->BcwIdx = affMrgCtx.BcwIdx[pu.mergeIdx]; - pu.ciipFlag = false; - MvField mvfMmvd[2][3]; - PU::getAfMmvdMvf(pu, affMrgCtx, mvfMmvd, pu.mergeIdx, pu.afMmvdStep, pu.afMmvdDir); -#if JVET_Z0067_RPR_ENABLE - bool bIsRefScaled = false; -#endif - for (int i = 0; i < 2; i++) + //Store + posList0 = 0; + posList1 = 0; + load0 = false; + load1 = false; + int startSub = 0; + int endSub = AF_MMVD_MAX_REFINE_NUM; + if (!fromStart) { - if( pu.cs->slice->getNumRefIdx( RefPicList( i ) ) > 0 ) + if (gpId % 2) { - pu.mvpIdx[i] = 0; - pu.mvpNum[i] = 0; - pu.mvd[i] = Mv(); - pu.refIdx[i] = mvfMmvd[i][0].refIdx; - pu.mvAffi[i][0] = mvfMmvd[i][0].mv; - pu.mvAffi[i][1] = mvfMmvd[i][1].mv; - pu.mvAffi[i][2] = mvfMmvd[i][2].mv; + startSub = groupSize; } -#if JVET_Z0067_RPR_ENABLE - if ( !bIsRefScaled && pu.refIdx[i]>=0 && pu.cu->slice->getRefPic(i ? REF_PIC_LIST_1 : REF_PIC_LIST_0, pu.refIdx[i])->isRefScaled(pu.cs->pps) ) + else + { + endSub = groupSize; + } + } + for (int tempIdx = startSub; tempIdx < endSub; tempIdx++) + { + uint16_t mmvdMergeCand = fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + tempIdx; + pu.afMmvdMergeIdx = (uint16_t)mmvdMergeCand; + int stepIdx = tempIdx; + int dirIdx = stepIdx % AF_MMVD_OFFSET_DIR; + int fPosPosition1 = dirIdx % 8; + stepIdx = stepIdx / AF_MMVD_OFFSET_DIR; + pu.afMmvdDir = (uint8_t)dirIdx; + pu.afMmvdStep = (uint8_t)stepIdx; + //changed + if ((pu.afMmvdDir >= 8) && (pu.interDir < 3)) + { + continue; + } + MvField mvfMmvd[2][3]; + PU::getAfMmvdMvf(pu, affMrgCtx, mvfMmvd, pu.mergeIdx, pu.afMmvdStep, pu.afMmvdDir); +#if JVET_Z0067_RPR_ENABLE + bool bIsRefScaled = false; +#endif + for (int i = 0; i < 2; i++) + { + if( pu.cs->slice->getNumRefIdx( RefPicList( i ) ) > 0 ) + { + pu.mvpIdx[i] = 0; + pu.mvpNum[i] = 0; + pu.mvd[i] = Mv(); + pu.refIdx[i] = mvfMmvd[i][0].refIdx; + pu.mvAffi[i][0] = mvfMmvd[i][0].mv; + pu.mvAffi[i][1] = mvfMmvd[i][1].mv; + pu.mvAffi[i][2] = mvfMmvd[i][2].mv; + } +#if JVET_Z0067_RPR_ENABLE + if ( !bIsRefScaled && pu.refIdx[i]>=0 && pu.cu->slice->getRefPic(i ? REF_PIC_LIST_1 : REF_PIC_LIST_0, pu.refIdx[i])->isRefScaled(pu.cs->pps) ) + { + bIsRefScaled = true; + } +#endif + } + //Store + if (pu.interDir == 3) + { + if (dirIdx < 8) + { + posList0 = fPosPosition1 + 1; + posList1 = 0; + load0 = false; + load1 = (fPosPosition1 != 0) || (stepIdx != 0 && stepIdx != stepCutoff ); + } + else if (dirIdx < 16) + { + posList0 = 0; + posList1 = fPosPosition1 + 1; + load0 = (fPosPosition1 != 0) || (stepIdx != 0 && stepIdx != stepCutoff ); + load1 = false; + } + else + { + const int poc0 = pu.cu->slice->getRefPOC(REF_PIC_LIST_0, mvfMmvd[0][0].refIdx); + const int poc1 = pu.cu->slice->getRefPOC(REF_PIC_LIST_1, mvfMmvd[0][0].refIdx); + const int currPoc = pu.cu->slice->getPOC(); + if ((poc1 - currPoc)*(poc0 - currPoc) > 0) + { + posList0 = fPosPosition1 + 1; + posList1 = fPosPosition1 + 1; + load0 = true; + load1 = true; + } + else + { + posList0 = fPosPosition1 + 1; + posList1 = (fPosPosition1 ^ 1) + 1; + load0 = true; + load1 = true; + } + } + } + + uiCost = 0; +#if JVET_Z0067_RPR_ENABLE + if ( bIsRefScaled ) + { + uiCost = std::numeric_limits<Distortion>::max(); + } + else + { +#endif + 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))); + //Store + if (pu.interDir == 3) + { + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft, posList0, posList1, load0, load1); + } + else + { + getAffAMLRefTemplate(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 + + // update part + uint32_t i; + uint32_t shift = 0; + uint32_t gpIdx = mmvdMergeCand/groupSize; + uint32_t endIdx = gpIdx * groupSize + encGrpSize; + while (shift < encGrpSize && uiCost < candCostList[endIdx - 1 - shift]) + { + shift++; + } + + if (shift != 0) + { + for (i = 1; i < shift; i++) + { + affMmvdLUT[endIdx - i] = affMmvdLUT[endIdx - 1 - i]; + candCostList[endIdx - i] = candCostList[endIdx - 1 - i]; + } + affMmvdLUT[endIdx - shift] = mmvdMergeCand; + candCostList[endIdx - shift] = uiCost; + } + } + for (int j = encGrpSize - 1; j >= 0 ; j--) + { + affMmvdLUT[fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + 2*j] = affMmvdLUT[fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + j]; + } + for (int j = 0; j < encGrpSize ; j++) + { + affMmvdLUT[fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + 2*j + 1] = affMmvdLUT[fPosBaseIdx * AF_MMVD_MAX_REFINE_NUM + groupSize + j]; + } + } +} +#else +void InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, uint32_t afMMVDIdx) +{ + const int tempNum = AF_MMVD_NUM; + int baseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affMrgCtx, 0); + int baseCount = std::min<int>((int)AF_MMVD_BASE_NUM, affMrgCtx.numValidMergeCand - baseIdxToMergeIdxOffset); + const int groupSize = std::min<int>(tempNum, ADAPTIVE_SUB_GROUP_SIZE_MMVD_AFF); + Distortion candCostList[tempNum]; + for (uint32_t i = 0; i < tempNum; i++) + { + affMmvdLUT[i] = i; + candCostList[i] = MAX_UINT; + } + + if (baseCount < 1) + { + return; + } + Distortion uiCost; + + DistParam cDistParam; + cDistParam.applyWeight = false; + + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + + if (!xAMLGetCurBlkTemplate(pu, nWidth, nHeight)) + { + return; + } + + int startMMVDIdx = 0; + int endMMVDIdx = tempNum; + if(afMMVDIdx != -1) + { + uint32_t gpId = afMMVDIdx/groupSize; + startMMVDIdx = gpId * groupSize; + endMMVDIdx = (gpId+1) * groupSize; + } + int shiftEnc = AFFINE_MMVD_SIZE_SHIFT; + int encGrpSize = groupSize >> shiftEnc; + for (int mmvdMergeCand = startMMVDIdx; mmvdMergeCand < endMMVDIdx; mmvdMergeCand++) + { + pu.afMmvdMergeIdx = (uint8_t)mmvdMergeCand; + + int baseIdx = (int)mmvdMergeCand / AF_MMVD_MAX_REFINE_NUM; + int stepIdx = (int)mmvdMergeCand - baseIdx * AF_MMVD_MAX_REFINE_NUM; + int dirIdx = stepIdx % AF_MMVD_OFFSET_DIR; + stepIdx = stepIdx / AF_MMVD_OFFSET_DIR; + + pu.cu->affine = true; + pu.cu->imv = IMV_OFF; + pu.cu->mmvdSkip = false; + pu.regularMergeFlag = false; + pu.mmvdMergeFlag = false; + pu.mergeFlag = true; + pu.afMmvdFlag = true; + pu.afMmvdBaseIdx = (uint8_t)baseIdx; + pu.afMmvdDir = (uint8_t)dirIdx; + pu.afMmvdStep = (uint8_t)stepIdx; + pu.mergeIdx = (uint8_t)(baseIdxToMergeIdxOffset + baseIdx); + pu.mergeType = affMrgCtx.mergeType[pu.mergeIdx]; +#if INTER_LIC + pu.cu->LICFlag = affMrgCtx.LICFlags[pu.mergeIdx]; + pu.cu->LICFlag = false; +#endif + pu.interDir = affMrgCtx.interDirNeighbours[pu.mergeIdx]; + pu.cu->affineType = affMrgCtx.affineType[pu.mergeIdx]; + pu.cu->BcwIdx = affMrgCtx.BcwIdx[pu.mergeIdx]; + pu.ciipFlag = false; + MvField mvfMmvd[2][3]; + PU::getAfMmvdMvf(pu, affMrgCtx, mvfMmvd, pu.mergeIdx, pu.afMmvdStep, pu.afMmvdDir); +#if JVET_Z0067_RPR_ENABLE + bool bIsRefScaled = false; +#endif + for (int i = 0; i < 2; i++) + { + if( pu.cs->slice->getNumRefIdx( RefPicList( i ) ) > 0 ) + { + pu.mvpIdx[i] = 0; + pu.mvpNum[i] = 0; + pu.mvd[i] = Mv(); + pu.refIdx[i] = mvfMmvd[i][0].refIdx; + pu.mvAffi[i][0] = mvfMmvd[i][0].mv; + pu.mvAffi[i][1] = mvfMmvd[i][1].mv; + pu.mvAffi[i][2] = mvfMmvd[i][2].mv; + } +#if JVET_Z0067_RPR_ENABLE + if ( !bIsRefScaled && pu.refIdx[i]>=0 && pu.cu->slice->getRefPic(i ? REF_PIC_LIST_1 : REF_PIC_LIST_0, pu.refIdx[i])->isRefScaled(pu.cs->pps) ) { bIsRefScaled = true; } @@ -6127,6 +6775,7 @@ void InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC } } #endif +#endif #if JVET_W0090_ARMC_TM #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING @@ -6215,12 +6864,19 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer const int numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand); - uint32_t RdCandList[MRG_MAX_NUM_CANDS]; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + uint32_t rdCandList[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS]; + Distortion candCostList[NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS]; + + for (uint32_t j = 0; j < NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS; j++) +#else + uint32_t rdCandList[MRG_MAX_NUM_CANDS]; Distortion candCostList[MRG_MAX_NUM_CANDS]; for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++) +#endif { - RdCandList[j] = j; + rdCandList[j] = j; candCostList[j] = MAX_UINT64; } @@ -6258,6 +6914,21 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer PelUnitBuf pcBufPredRefLeft = (PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAMLTemplate[1][0], AML_MERGE_TEMPLATE_SIZE, nHeight))); +#if JVET_Z0067_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; + 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 + getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); if (m_bAMLTemplateAvailabe[0]) @@ -6275,160 +6946,593 @@ void InterPrediction::adjustMergeCandidates(PredictionUnit& pu, MergeCtx& mvpMer uiCost += cDistParam.distFunc(cDistParam); } +#if JVET_Z0067_RPR_ENABLE + } +#endif + +#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 } else { uiCost = mvpMergeCandCtx.candCost[uiMergeCand]; } - updateCandList(uiMergeCand, uiCost, mvpMergeCandCtx.numValidMergeCand, RdCandList, candCostList); + updateCandList(uiMergeCand, uiCost, mvpMergeCandCtx.numValidMergeCand, rdCandList, candCostList); } pu.mergeIdx = origMergeIdx; - updateCandInOneCandidateGroup(mvpMergeCandCtx, RdCandList, mvpMergeCandCtx.numValidMergeCand); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + MergeCtx pairMergeCand; + pairMergeCand.numValidMergeCand = 0; + pairMergeCand.numCandToTestEnc = 0; - for (int idx = 0; idx < mvpMergeCandCtx.numValidMergeCand; idx++) - { - mvpMergeCandCtx.candCost[idx] = candCostList[idx]; - } + bool pairAdded = false; - mvpMergeCandCtx.numValidMergeCand = numCandInCategory; + if (mvpMergeCandCtx.numCandToTestEnc > 1 ) + { + int cnt = 0; + int maxPairToBeAdded = std::min(mvpMergeCandCtx.numCandToTestEnc, numCandInCategory); + if (pu.tmMergeFlag) + { + maxPairToBeAdded = std::min(mvpMergeCandCtx.numCandToTestEnc, TM_MRG_MAX_NUM_INIT_CANDS); + } - for (int idx = 0; idx < numCandInCategory; idx++) - { - mvpMergeCandCtx.candCost[idx] = candCostList[idx]; - } -} -#endif + int cand1 = 0; + cnt = 0; + for (int cand2 = 1; cand2 < std::min(maxPairToBeAdded, MRG_MAX_NUM_CANDS); cand2++) + { + if (cand1 == cand2) + { + continue; + } -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]; + pairMergeCand.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID); + pairMergeCand.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID); + +#if INTER_LIC + 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 - mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; + pairMergeCand.addHypNeighbours[cnt].clear(); #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]]; + + // calculate average MV for L0 and L1 seperately + unsigned char interDir = 0; + for (int refListId = 0; refListId < (pu.cu->slice->isInterB() ? 2 : 1); refListId++) + { + const short refIdxI = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand1] * 2 + refListId].refIdx; + const short refIdxJ = mvpMergeCandCtx.mvFieldNeighbours[rdCandList[cand2] * 2 + refListId].refIdx; + + // both MVs are invalid, skip + if ((refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID)) + { + continue; + } + + 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; + + // average two MVs + Mv avgMv = mvI; + avgMv += mvJ; + roundAffineMv(avgMv.hor, avgMv.ver, 1); + + pairMergeCand.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI); + } + // only one MV is valid, take the only one MV + else if (refIdxI != NOT_VALID) + { + 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); + } + } + + pairMergeCand.interDirNeighbours[cnt] = interDir; + + if (interDir > 0) + { #if INTER_LIC - mrgCtx.LICFlags[uiMergeCand] = mrgCtxTmp.LICFlags[RdCandList[uiMergeCand]]; -#endif -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[RdCandList[uiMergeCand]]; + if (interDir == 3) + { + pairMergeCand.LICFlags[cnt] = false; + } #endif + if (!pairMergeCand.xCheckSimilarMotion(cnt, pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1)) + { + if (!mvpMergeCandCtx.xCheckSimilarMotion2Lists(cnt, &pairMergeCand, pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1)) + { + pairAdded = true; + cnt++; + pairMergeCand.numValidMergeCand++; + pairMergeCand.numCandToTestEnc++; + if (pairMergeCand.numValidMergeCand == MAX_PAIR_CANDS) + { + break; + } + } + } + } + } + + if (pairAdded) + { + for (uint32_t uiMergeCand = 0; uiMergeCand < pairMergeCand.numValidMergeCand; uiMergeCand++) + { + 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+ mvpMergeCandCtx.numValidMergeCand), uiCost, (mvpMergeCandCtx.numValidMergeCand + pairMergeCand.numValidMergeCand), rdCandList, candCostList); + } + pu.mergeIdx = origMergeIdx; + } + + Distortion cost = pu.cs->slice->getCostForARMC(); + uint32_t candToBeRemoved = NUM_MERGE_CANDS + MRG_MAX_NUM_CANDS; + Distortion min = MAX_UINT64; + + for (int sizeCandList = mvpMergeCandCtx.numCandToTestEnc+ pairMergeCand.numValidMergeCand; sizeCandList > 1; sizeCandList--) + { + min = MAX_UINT64; + if(pu.tmMergeFlag) + { + candToBeRemoved = 0; + min = candCostList[0]; + } + 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]; + 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)]; + } + candCostList[candToBeReplaced] = candCost; + rdCandList[candToBeReplaced] = rdCand; + } + else + { + break; + } + } + } + + updateCandInTwoCandidateGroups(mvpMergeCandCtx, rdCandList, mvpMergeCandCtx.numValidMergeCand, pairMergeCand); +#else + updateCandInOneCandidateGroup(mvpMergeCandCtx, rdCandList, mvpMergeCandCtx.numValidMergeCand); +#endif + + for (int idx = 0; idx < mvpMergeCandCtx.numValidMergeCand; idx++) + { + mvpMergeCandCtx.candCost[idx] = candCostList[idx]; + } + + mvpMergeCandCtx.numValidMergeCand = numCandInCategory; + +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + for (int idx = 0; idx < numCandInCategory; idx++) + { + mvpMergeCandCtx.candCost[idx] = candCostList[idx]; } +#endif } #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 j = 0; j < MRG_MAX_NUM_CANDS; j++) + +#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 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 + } + } +} +#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 + +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 j = 0; j < MRG_MAX_NUM_CANDS; j++) + { + RdCandList[i][j] = j; + candCostList[i][j] = MAX_UINT; + } + } + + Distortion uiCost; + + 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; + } + +#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) + { + 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; + + 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], AML_MERGE_TEMPLATE_SIZE, nHeight))); + +#if JVET_Y0128_NON_CTC + 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 + 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_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 (pu.tmMergeFlag || (mvpMergeCandCtx.numCandToTestEnc != mvpMergeCandCtx.numValidMergeCand && uiMergeCand > mvpMergeCandCtx.numCandToTestEnc )) + { + 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], AML_MERGE_TEMPLATE_SIZE, pu.lheight()))); +#if JVET_Z0067_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; + 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 + + 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 + + } + 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 INTER_LIC + mrgCtxTmp.LICFlags[uiMergeCand] = mrgCtx.LICFlags[uiMergeCand]; +#endif +#if MULTI_HYP_PRED + mrgCtxTmp.addHypNeighbours[uiMergeCand] = mrgCtx.addHypNeighbours[uiMergeCand]; +#endif + if (applyBDMVR) { - RdCandList[i][j] = j; - candCostList[i][j] = MAX_UINT; + applyBDMVRTmp[uiMergeCand] = applyBDMVR[uiMergeCand]; } } - - Distortion uiCost; - - 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)) + //update + for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) { - return; - } - -#if JVET_X0049_ADAPT_DMVR - uint8_t origMergeIdx = pu.mergeIdx; + 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 - 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) +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[uiMergeCand] = mrgCtxTmp.addHypNeighbours[rdCandList[uiMergeCand]]; +#endif + if (applyBDMVR) { - break; + applyBDMVR[uiMergeCand] = applyBDMVRTmp[rdCandList[uiMergeCand]]; } - 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], AML_MERGE_TEMPLATE_SIZE, nHeight))); - -#if JVET_Y0128_NON_CTC - bool bRefIsRescaled = false; - for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + if (mvBufBDMVR && mvBufBDMVRTmp) { - 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; + mvBufBDMVRTmp[(uiMergeCand << 1)] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1)]; + mvBufBDMVRTmp[(uiMergeCand << 1) + 1] = mvBufBDMVR[(rdCandList[uiMergeCand] << 1) + 1]; } - if ( !bRefIsRescaled ) - { -#endif - getBlkAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); - - if (m_bAMLTemplateAvailabe[0]) + if (subRefineList && subRefineListTmp) { - m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); - - uiCost += cDistParam.distFunc(cDistParam); + subRefineList[uiMergeCand][0] = subRefineListTmp[rdCandList[uiMergeCand]][0]; + subRefineList[uiMergeCand][1] = subRefineListTmp[rdCandList[uiMergeCand]][1]; } - - if (m_bAMLTemplateAvailabe[1]) + } + if (mvBufBDMVR && mvBufBDMVRTmp) + { + for (uint32_t uiMergeCand = 0; uiMergeCand < numCandInCategory; uiMergeCand++) { - 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 + mvBufBDMVR[(uiMergeCand << 1)] = mvBufBDMVRTmp[(uiMergeCand << 1)]; + mvBufBDMVR[(uiMergeCand << 1) + 1] = mvBufBDMVRTmp[(uiMergeCand << 1) + 1]; } -#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 +#endif #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC bool InterPrediction::xAMLGetCurBlkTemplate(PredictionUnit& pu, int nCurBlkWidth, int nCurBlkHeight) @@ -6609,226 +7713,276 @@ void InterPrediction::updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MR #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 (xCheckIdenticalMotion(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]) +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (!bLoadSave && xCheckIdenticalMotion(pu)) +#else + if (xCheckIdenticalMotion(pu)) +#endif { - Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); - mvTop += subPelMv; + 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); + 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]); + 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 ); + 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 ); + 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 ); + 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 ); + 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; + } + 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); + 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]); + 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 ); + 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 ); + 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 ); + 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 ); + 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++) + else { - if (pu.refIdx[refList] < 0) - { - 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]; - /*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]) + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) { - 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.refIdx[0] >= 0 && pu.refIdx[1] >= 0) + 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]); + 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 ); + 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 ); + 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 ); + 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 ); + 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 - { + } + 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]); + 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 ); + 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 ); + 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 ); + 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 ); + 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.refIdx[0] >= 0 && pu.refIdx[1] >= 0) + 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] ); + 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 ); + 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 ); + 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 +#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 - } - else - { +#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]); + 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 ); + 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 ); + 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 ); + 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 ); + 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_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]) + { + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeft.Y())); // changed + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeft.Y())); // changed + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); + } + +#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], pcBufPredRefLeft.Y())); + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y())); + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); + } +#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]) - { - CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeft.Y())); - CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y())); - xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); - } - } } #endif @@ -6975,6 +8129,17 @@ void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer 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 } @@ -6994,6 +8159,63 @@ void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer #endif } 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]))) + { + 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 ); @@ -7146,62 +8368,34 @@ void InterPrediction::xGetSublkAMLTemplate(const CodingUnit& cu, } } } +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION +void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0, int8_t posList1, bool load0, bool load1) +#else void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft) +#endif { +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + bool bLoadSave = (posList0 != -1); +#endif #if INTER_LIC int LICshift[2] = { 0 }; int scale[2] = { 0 }; int offset[2] = { 0 }; #endif const int bitDepth = pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA); - if (xCheckIdenticalMotion(pu)) - { - Pel * refLeftTemplate = m_acYuvRefAMLTemplate[1][0]; - Pel * refAboveTemplate = m_acYuvRefAMLTemplate[0][0]; - int numTemplate[2] = { 0, 0 }; // 0:Above, 1:Left - const RefPicList eRefPicList = REF_PIC_LIST_0; -#if JVET_Z0067_RPR_ENABLE - CHECK(pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[eRefPicList])->isRefScaled(pu.cs->pps), "getAffAMLRefTemplate not supported with ref scaled."); -#endif - xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate); -#if INTER_LIC - if (pu.cu->LICFlag) - { - Pel *recLeftTemplate = m_acYuvCurAMLTemplate[1][0]; - Pel *recAboveTemplate = m_acYuvCurAMLTemplate[0][0]; - xGetLICParamGeneral(*pu.cu, COMPONENT_Y, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, - recAboveTemplate, LICshift[0], scale[0], offset[0]); - if (m_bAMLTemplateAvailabe[0]) - { - PelBuf & dstBuf = pcBufPredRefTop.bufs[0]; - const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); - dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng); - } - if (m_bAMLTemplateAvailabe[1]) - { - PelBuf & dstBuf = pcBufPredRefLeft.bufs[0]; - const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); - dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng); - } - } +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (!bLoadSave && xCheckIdenticalMotion(pu)) +#else + if (xCheckIdenticalMotion(pu)) #endif - } - else - { - 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); - CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); + Pel * refLeftTemplate = m_acYuvRefAMLTemplate[1][0]; + Pel * refAboveTemplate = m_acYuvRefAMLTemplate[0][0]; + int numTemplate[2] = { 0, 0 }; // 0:Above, 1:Left + const RefPicList eRefPicList = REF_PIC_LIST_0; #if JVET_Z0067_RPR_ENABLE CHECK(pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[eRefPicList])->isRefScaled(pu.cs->pps), "getAffAMLRefTemplate not supported with ref scaled."); #endif - Pel *refLeftTemplate = m_acYuvRefLeftTemplate[refList][0]; - Pel *refAboveTemplate = m_acYuvRefAboveTemplate[refList][0]; - int numTemplate[2] = { 0, 0 }; // 0:Above, 1:Left xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate); #if INTER_LIC if (pu.cu->LICFlag) @@ -7209,81 +8403,167 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf Pel *recLeftTemplate = m_acYuvCurAMLTemplate[1][0]; Pel *recAboveTemplate = m_acYuvCurAMLTemplate[0][0]; xGetLICParamGeneral(*pu.cu, COMPONENT_Y, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, - recAboveTemplate, LICshift[refList], scale[refList], offset[refList]); + recAboveTemplate, LICshift[0], scale[0], offset[0]); + if (m_bAMLTemplateAvailabe[0]) + { + PelBuf & dstBuf = pcBufPredRefTop.bufs[0]; + const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); + dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng); + } + if (m_bAMLTemplateAvailabe[1]) + { + PelBuf & dstBuf = pcBufPredRefLeft.bufs[0]; + const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); + dstBuf.linearTransform(scale[0], LICshift[0], offset[0], true, clpRng); + } } #endif } - if (m_bAMLTemplateAvailabe[0]) + else { - PelUnitBuf srcPred[2]; - srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y())); - srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y())); -#if INTER_LIC - if (pu.cu->LICFlag) + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) { - for (int i = 0; i < 2; i++) + if (pu.refIdx[refList] < 0) { - if (pu.refIdx[i] >= 0) - { - PelBuf & dstBuf = srcPred[i].bufs[0]; - const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); - dstBuf.linearTransform(scale[i], LICshift[i], offset[i], true, clpRng); - } + continue; + } +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (bLoadSave && (((refList == 0) && load0) || ((refList == 1) && load1)) )// changed + { + continue; } - } #endif - const int iRefIdx0 = pu.refIdx[0]; - const int iRefIdx1 = pu.refIdx[1]; - if (iRefIdx0 >= 0 && iRefIdx1 >= 0) - { - for (int i = 0; i < 2; i++) + RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); +#if JVET_Z0067_RPR_ENABLE + CHECK(pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[eRefPicList])->isRefScaled(pu.cs->pps), "getAffAMLRefTemplate not supported with ref scaled."); +#endif + Pel *refLeftTemplate = m_acYuvRefLeftTemplate[refList][0]; + Pel *refAboveTemplate = m_acYuvRefAboveTemplate[refList][0]; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (bLoadSave) { - PelBuf & dstBuf = srcPred[i].bufs[0]; - const int biShift = IF_INTERNAL_PREC - bitDepth; - const Pel biOffset = -IF_INTERNAL_OFFS; - ClpRng clpRngDummy; - dstBuf.linearTransform(1, -biShift, biOffset, false, clpRngDummy); + refLeftTemplate += (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE; + refAboveTemplate += (refList == 0 ? posList0 : posList1) * MAX_CU_SIZE;// changed } - } - xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); - } - if (m_bAMLTemplateAvailabe[1]) - { - PelUnitBuf srcPred[2]; - srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeft.Y())); - srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y())); +#endif + int numTemplate[2] = { 0, 0 }; // 0:Above, 1:Left + xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate); #if INTER_LIC - if (pu.cu->LICFlag) + if (pu.cu->LICFlag) + { + Pel *recLeftTemplate = m_acYuvCurAMLTemplate[1][0]; + Pel *recAboveTemplate = m_acYuvCurAMLTemplate[0][0]; + xGetLICParamGeneral(*pu.cu, COMPONENT_Y, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, + recAboveTemplate, LICshift[refList], scale[refList], offset[refList]); + } +#endif + } + if (m_bAMLTemplateAvailabe[0]) { - for (int i = 0; i < 2; i++) + PelUnitBuf srcPred[2]; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int offset0 = bLoadSave ? posList0 * MAX_CU_SIZE : 0; + int offset1 = bLoadSave ? posList1 * MAX_CU_SIZE : 0; + srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0] + offset0, pcBufPredRefTop.Y())); //changed + srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0] + offset1, pcBufPredRefTop.Y())); //changed +#else + srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y())); + srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y())); +#endif +#if INTER_LIC +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (!bLoadSave && pu.cu->LICFlag) +#else + if (pu.cu->LICFlag) +#endif + { + for (int i = 0; i < 2; i++) + { + if (pu.refIdx[i] >= 0) + { + PelBuf & dstBuf = srcPred[i].bufs[0]; + const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); + dstBuf.linearTransform(scale[i], LICshift[i], offset[i], true, clpRng); + } + } + } +#endif + const int iRefIdx0 = pu.refIdx[0]; + const int iRefIdx1 = pu.refIdx[1]; + if (iRefIdx0 >= 0 && iRefIdx1 >= 0) { - if (pu.refIdx[i] >= 0) + for (int i = 0; i < 2; i++) { - PelBuf & dstBuf = srcPred[i].bufs[0]; - const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); - dstBuf.linearTransform(scale[i], LICshift[i], offset[i], true, clpRng); +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (bLoadSave && (((i == 0) && load0) || ((i == 1) && load1)))// changed + { + continue; + } +#endif + PelBuf & dstBuf = srcPred[i].bufs[0]; + const int biShift = IF_INTERNAL_PREC - bitDepth; + const Pel biOffset = -IF_INTERNAL_OFFS; + ClpRng clpRngDummy; + dstBuf.linearTransform(1, -biShift, biOffset, false, clpRngDummy); } } + xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); } -#endif - const int iRefIdx0 = pu.refIdx[0]; - const int iRefIdx1 = pu.refIdx[1]; - if (iRefIdx0 >= 0 && iRefIdx1 >= 0) + if (m_bAMLTemplateAvailabe[1]) { - for (int i = 0; i < 2; i++) + PelUnitBuf srcPred[2]; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int offset0 = bLoadSave ? posList0 * MAX_CU_SIZE : 0; + int offset1 = bLoadSave ? posList1 * MAX_CU_SIZE : 0; + srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0] + offset0, pcBufPredRefLeft.Y())); //changed + srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0] + offset1, pcBufPredRefLeft.Y())); //changed +#else + srcPred[0] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[0][0], pcBufPredRefLeft.Y())); + srcPred[1] = PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[1][0], pcBufPredRefLeft.Y())); +#endif +#if INTER_LIC +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (!bLoadSave && pu.cu->LICFlag) +#else + if (pu.cu->LICFlag) +#endif + { + for (int i = 0; i < 2; i++) + { + if (pu.refIdx[i] >= 0) + { + PelBuf & dstBuf = srcPred[i].bufs[0]; + const ClpRng &clpRng = pu.cu->cs->slice->clpRng(COMPONENT_Y); + dstBuf.linearTransform(scale[i], LICshift[i], offset[i], true, clpRng); + } + } + } +#endif + const int iRefIdx0 = pu.refIdx[0]; + const int iRefIdx1 = pu.refIdx[1]; + if (iRefIdx0 >= 0 && iRefIdx1 >= 0) { - PelBuf & dstBuf = srcPred[i].bufs[0]; - const int biShift = IF_INTERNAL_PREC - bitDepth; - const Pel biOffset = -IF_INTERNAL_OFFS; - ClpRng clpRngDummy; - dstBuf.linearTransform(1, -biShift, biOffset, false, clpRngDummy); + for (int i = 0; i < 2; i++) + { +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (bLoadSave && (((i == 0) && load0) || ((i == 1) && load1)))// changed + { + continue; + } +#endif + PelBuf & dstBuf = srcPred[i].bufs[0]; + const int biShift = IF_INTERNAL_PREC - bitDepth; + const Pel biOffset = -IF_INTERNAL_OFFS; + ClpRng clpRngDummy; + dstBuf.linearTransform(1, -biShift, biOffset, false, clpRngDummy); + } } + xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); } - xWeightedAverageY(pu, srcPred[0], srcPred[1], pcBufPredRefLeft, pu.cu->slice->getSPS()->getBitDepths(), - pu.cu->slice->clpRngs()); } - } } #if JVET_Y0058_IBC_LIST_MODIFY void InterPrediction::adjustIBCMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx) @@ -9349,7 +10629,18 @@ Distortion InterPrediction::deriveTMMv(const PredictionUnit& pu, bool fillCurTpl if (otherMvf == nullptr) // uni prediction { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.reduceTplSize && pu.tmMergeFlag) + { + tplCtrl.deriveMvUni<1>(); + } + else + { +#endif tplCtrl.deriveMvUni<TM_TPL_SIZE>(); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + } +#endif mv = tplCtrl.getFinalMv(); return tplCtrl.getMinCost(); } @@ -9362,8 +10653,20 @@ Distortion InterPrediction::deriveTMMv(const PredictionUnit& pu, bool fillCurTpl } #endif const Picture& otherRefPic = *cu.slice->getRefPic((RefPicList)(1-eRefList), otherMvf->refIdx)->unscaledPic; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.reduceTplSize && pu.tmMergeFlag) + { + tplCtrl.removeHighFreq<1>(otherRefPic, otherMvf->mv, getBcwWeight(cu.BcwIdx, eRefList)); + tplCtrl.deriveMvUni<1>(); + } + else + { +#endif tplCtrl.removeHighFreq<TM_TPL_SIZE>(otherRefPic, otherMvf->mv, getBcwWeight(cu.BcwIdx, eRefList)); tplCtrl.deriveMvUni<TM_TPL_SIZE>(); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + } +#endif mv = tplCtrl.getFinalMv(); int8_t intWeight = getBcwWeight(cu.BcwIdx, eRefList); @@ -9372,7 +10675,11 @@ Distortion InterPrediction::deriveTMMv(const PredictionUnit& pu, bool fillCurTpl } #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC +void InterPrediction::deriveTMMv(PredictionUnit& pu, Distortion* tmCost) +#else void InterPrediction::deriveTMMv(PredictionUnit& pu) +#endif { if( !pu.tmMergeFlag ) { @@ -9388,6 +10695,12 @@ void InterPrediction::deriveTMMv(PredictionUnit& pu) minCostUni[iRefList] = deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), (RefPicList)iRefList, pu.refIdx[iRefList], TM_MAX_NUM_OF_ITERATIONS, pu.mv[iRefList]); } } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (tmCost) + { + *tmCost = minCostUni[0] <= minCostUni[1] ? minCostUni[0] : minCostUni[1]; + } +#endif if (pu.cu->slice->isInterB() && pu.interDir == 3 #if MULTI_PASS_DMVR @@ -9410,6 +10723,12 @@ void InterPrediction::deriveTMMv(PredictionUnit& pu) pu.mv [eTargetPicList] = Mv(); pu.refIdx[eTargetPicList] = NOT_VALID; } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + else if (tmCost) + { + *tmCost = minCostBi; + } +#endif } } #endif // TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) @@ -9450,8 +10769,58 @@ TplMatchingCtrl::TplMatchingCtrl( const PredictionUnit& pu, } #endif // Initialization +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (m_pu.reduceTplSize && pu.tmMergeFlag) + { + bool tplAvalableAbove = xFillCurTemplate<1, true >((fillCurTpl ? curTplAbove : nullptr)); + bool tplAvalableLeft = xFillCurTemplate<1, false>((fillCurTpl ? curTplLeft : nullptr)); + tplAvalableAbove &= !(tplAvalableLeft && pu.lwidth()*2 < pu.lheight()); + tplAvalableLeft &= !(tplAvalableAbove && pu.lheight()*2 < pu.lwidth()); + + m_curTplAbove = tplAvalableAbove ? PelBuf(curTplAbove, pu.lwidth(), 1 ) : PelBuf(); + m_curTplLeft = tplAvalableLeft ? PelBuf(curTplLeft , 1, pu.lheight()) : PelBuf(); + m_refTplAbove = tplAvalableAbove ? PelBuf(refTplAbove, m_curTplAbove ) : PelBuf(); + m_refTplLeft = tplAvalableLeft ? PelBuf(refTplLeft , m_curTplLeft ) : PelBuf(); +#if JVET_X0056_DMVD_EARLY_TERMINATION + m_earlyTerminateTh = ((tplAvalableAbove ? m_pu.lwidth() : 0) + (tplAvalableLeft ? m_pu.lheight() : 0)); +#endif + + // Pre-interpolate samples on search area +#if JVET_Z0084_IBC_TM + m_refSrAbove = tplAvalableAbove && maxSearchRounds > 0 && !CU::isIBC(m_cu) ? PelBuf(interRes.m_preFillBufA, m_curTplAbove.width + 2 * TM_SEARCH_RANGE, m_curTplAbove.height + 2 * TM_SEARCH_RANGE) : PelBuf(); +#else + m_refSrAbove = tplAvalableAbove && maxSearchRounds > 0 ? PelBuf(interRes.m_preFillBufA, m_curTplAbove.width + 2 * TM_SEARCH_RANGE, m_curTplAbove.height + 2 * TM_SEARCH_RANGE) : PelBuf(); +#endif + if (m_refSrAbove.buf != nullptr) + { + m_refSrAbove = xGetRefTemplate<1, true, TM_SEARCH_RANGE>(m_pu, m_refPic, mvStart, m_refSrAbove); + m_refSrAbove = m_refSrAbove.subBuf(Position(TM_SEARCH_RANGE, TM_SEARCH_RANGE), m_curTplAbove); + } + +#if JVET_Z0084_IBC_TM + m_refSrLeft = tplAvalableLeft && maxSearchRounds > 0 && !CU::isIBC(m_cu) ? PelBuf(interRes.m_preFillBufL, m_curTplLeft .width + 2 * TM_SEARCH_RANGE, m_curTplLeft .height + 2 * TM_SEARCH_RANGE) : PelBuf(); +#else + m_refSrLeft = tplAvalableLeft && maxSearchRounds > 0 ? PelBuf(interRes.m_preFillBufL, m_curTplLeft .width + 2 * TM_SEARCH_RANGE, m_curTplLeft .height + 2 * TM_SEARCH_RANGE) : PelBuf(); +#endif + if (m_refSrLeft.buf != nullptr) + { + m_refSrLeft = xGetRefTemplate<1, false, TM_SEARCH_RANGE>(m_pu, m_refPic, mvStart, m_refSrLeft); + m_refSrLeft = m_refSrLeft.subBuf(Position(TM_SEARCH_RANGE, TM_SEARCH_RANGE), m_curTplLeft); + } + } + else + { + bool tplAvalableAbove = xFillCurTemplate<TM_TPL_SIZE, true >((fillCurTpl ? curTplAbove : nullptr)); + bool tplAvalableLeft = xFillCurTemplate<TM_TPL_SIZE, false>((fillCurTpl ? curTplLeft : nullptr)); + if (pu.reduceTplSize) + { + tplAvalableAbove &= !(tplAvalableLeft && pu.lwidth()*2 < pu.lheight()); + tplAvalableLeft &= !(tplAvalableAbove && pu.lheight()*2 < pu.lwidth()); + } +#else const bool tplAvalableAbove = xFillCurTemplate<TM_TPL_SIZE, true >((fillCurTpl ? curTplAbove : nullptr)); const bool tplAvalableLeft = xFillCurTemplate<TM_TPL_SIZE, false>((fillCurTpl ? curTplLeft : nullptr)); +#endif m_curTplAbove = tplAvalableAbove ? PelBuf(curTplAbove, pu.lwidth(), TM_TPL_SIZE ) : PelBuf(); m_curTplLeft = tplAvalableLeft ? PelBuf(curTplLeft , TM_TPL_SIZE, pu.lheight()) : PelBuf(); m_refTplAbove = tplAvalableAbove ? PelBuf(refTplAbove, m_curTplAbove ) : PelBuf(); @@ -9482,6 +10851,9 @@ TplMatchingCtrl::TplMatchingCtrl( const PredictionUnit& pu, m_refSrLeft = xGetRefTemplate<TM_TPL_SIZE, false, TM_SEARCH_RANGE>(m_pu, m_refPic, mvStart, m_refSrLeft); m_refSrLeft = m_refSrLeft.subBuf(Position(TM_SEARCH_RANGE, TM_SEARCH_RANGE), m_curTplLeft); } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + } +#endif } int TplMatchingCtrl::getDeltaMean(const PelBuf& bufCur, const PelBuf& bufRef, const int rowSubShift, const int bd) @@ -9513,6 +10885,9 @@ void TplMatchingCtrl::deriveMvUni() #endif xRefineMvSearch<tplSize, TplMatchingCtrl::TMSEARCH_CROSS >( 1, searchStepShift - 2); xRefineMvSearch<tplSize, TplMatchingCtrl::TMSEARCH_CROSS >( 1, searchStepShift - 3); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + xRefineMvSearch<tplSize, TplMatchingCtrl::TMSEARCH_CROSS >( 1, searchStepShift - 4); +#endif #if MULTI_PASS_DMVR } else @@ -10050,7 +11425,9 @@ Distortion TplMatchingCtrl::xGetTempMatchError(const Mv& mv) #endif int tmWeightIdx = (m_pu.lwidth() >= TM_MIN_CU_SIZE_FOR_ALT_WEIGHTED_COST && m_pu.lheight() >= TM_MIN_CU_SIZE_FOR_ALT_WEIGHTED_COST ? 1 : 0); m_interRes.m_pcRdCost->setDistParam( cDistParam, curTplBuf, refTplBuf, bitDepth, trueAfalseL, tmWeightIdx, rowSubShift, m_compID ); +#if !JVET_AA0093_REFINED_MOTION_FOR_ARMC CHECK(TM_TPL_SIZE != 4, "The distortion function of template matching is implemetned currently only for size=4."); +#endif partSum = cDistParam.distFunc( cDistParam ); } else @@ -10189,15 +11566,29 @@ bool InterPrediction::processBDMVRPU2Dir(PredictionUnit& pu, bool subPURefine[2] return false; } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.cu->cs->pcv->isEncoder || (!pu.cu->cs->pcv->isEncoder && pu.bmDir == 1)) + { +#endif minCost = xBDMVRMvOneTemplateHPelSquareSearch<1>(mvFinal, initCost, pu, mvInitial_PU, 2, MV_FRACTIONAL_BITS_INTERNAL - 1, bUseMR, false); subPURefine[0] = minCost >= lumaArea; finalMvDir[0] = mvFinal[0]; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + } +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.cu->cs->pcv->isEncoder || (!pu.cu->cs->pcv->isEncoder && pu.bmDir == 2)) + { +#endif mvFinal[0] = mvInitial_PU[0]; mvFinal[1] = mvInitial_PU[1]; minCost = xBDMVRMvOneTemplateHPelSquareSearch<2>(mvFinal, initCost, pu, mvInitial_PU, 2, MV_FRACTIONAL_BITS_INTERNAL - 1, bUseMR, false); subPURefine[1] = minCost >= lumaArea; finalMvDir[1] = mvFinal[1]; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + } +#endif return true; } @@ -10340,7 +11731,11 @@ void InterPrediction::processBDMVRSubPU(PredictionUnit& pu, bool subPURefine) #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC +bool InterPrediction::processBDMVR(PredictionUnit& pu, int step, Distortion* tmCost) +#else bool InterPrediction::processBDMVR(PredictionUnit& pu) +#endif { if( !pu.cs->slice->getSPS()->getUseDMVDMode() || !pu.cs->slice->isInterB() ) { @@ -10352,6 +11747,9 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu) const int lumaArea = pu.lumaSize().area(); bool subPURefine = true; Mv puOrgMv[2] = { pu.mv[0], pu.mv[1] }; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (step != 2) +#endif { Distortion minCost = std::numeric_limits<Distortion>::max(); bool bUseMR = lumaArea > 64; @@ -10399,9 +11797,17 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu) } #if TM_MRG +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.tmMergeFlag && step != 2) +#else if (pu.tmMergeFlag) +#endif { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + deriveTMMv(pu, tmCost); +#else deriveTMMv(pu); +#endif if (pu.interDir != 3) { return false; @@ -10409,6 +11815,27 @@ bool InterPrediction::processBDMVR(PredictionUnit& pu) } #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (step == 2 && pu.interDir != 3) + { + return false; + } + else if (step == 1) + { + return true; + } + else if (step == 2) + { + bool bUseMR = lumaArea > 64; +#if JVET_Y0089_DMVR_BCW + bUseMR |= (pu.cu->BcwIdx != BCW_DEFAULT); +#endif + Mv mvInitial_PU[2] = { pu.mv[0], pu.mv[1] }; + Distortion initCost = xBDMVRGetMatchingError(pu, mvInitial_PU, bUseMR, false); + subPURefine = initCost >= lumaArea; + } +#endif + if (!subPURefine) { // span motion to subPU @@ -13074,6 +14501,55 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<Mv, Distortion> & l, const std::pair<Mv, Distortion> & r) {return l.second < r.second; }); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int sizeCandList = (int) distance(aMvCostVec.begin(), aMvCostVec.end()); + + if (sizeCandList > 2) + { + Distortion lambdaTh = pu.cs->slice->getCostForARMC(); + bool enoughDiverse = false; + uint32_t diverseCand = 0; + uint32_t posToBeInserted = 0; + for (uint32_t uiCand = 0; uiCand < sizeCandList - 1; ++uiCand) + { + for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < sizeCandList; ++uiMergeCand) + { + if (lambdaTh <= abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiCand].second))) + { + enoughDiverse = true; + for (uint32_t uiMergeCand3 = 0; uiMergeCand3 < uiCand; ++uiMergeCand3) + { + if (lambdaTh > abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiMergeCand3].second))) + { + enoughDiverse = false; + break; + } + } + + if (enoughDiverse) + { + diverseCand = uiMergeCand; + posToBeInserted = uiCand + 1; + break; + } + } + } + if (enoughDiverse) + { + Distortion saveCandCost = aMvCostVec[diverseCand].second; + Mv mvSave = aMvCostVec[diverseCand].first; + + for (int i = diverseCand; i > posToBeInserted - 1; i--) + { + aMvCostVec[i].second = aMvCostVec[i - 1].second; + aMvCostVec[i].first = aMvCostVec[i - 1].first; + } + aMvCostVec[posToBeInserted].second = saveCandCost; + aMvCostVec[posToBeInserted].first = mvSave; + } + } + } +#endif for (int n = 0; n < patternsNum; ++n) { cMvdDerived[n] = aMvCostVec[n].first; @@ -13139,6 +14615,55 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e aMvCostVec.push_back(std::pair<Mv, Distortion>(*it, uiCost)); } std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<Mv, Distortion> & l, const std::pair<Mv, Distortion> & r) {return l.second < r.second; }); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + + int sizeCandList = (int) distance( aMvCostVec.begin(), aMvCostVec.end()); + if (sizeCandList > 2) + { + Distortion lambdaTh = pu.cs->slice->getCostForARMC(); + bool enoughDiverse = false; + uint32_t diverseCand = 0; + uint32_t posToBeInserted = 0; + for (uint32_t uiCand = 0; uiCand < sizeCandList - 1; ++uiCand) + { + for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < sizeCandList; ++uiMergeCand) + { + if (lambdaTh <= abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiCand].second))) + { + enoughDiverse = true; + for (uint32_t uiMergeCand3 = 0; uiMergeCand3 < uiCand; ++uiMergeCand3) + { + if (lambdaTh > abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiMergeCand3].second))) + { + enoughDiverse = false; + break; + } + } + + if (enoughDiverse) + { + diverseCand = uiMergeCand; + posToBeInserted = uiCand + 1; + break; + } + } + } + if (enoughDiverse) + { + Distortion saveCandCost = aMvCostVec[diverseCand].second; + Mv mvSave = aMvCostVec[diverseCand].first; + + for (int i = diverseCand; i > posToBeInserted - 1; i--) + { + aMvCostVec[i].second = aMvCostVec[i - 1].second; + aMvCostVec[i].first = aMvCostVec[i - 1].first; + } + aMvCostVec[posToBeInserted].second = saveCandCost; + aMvCostVec[posToBeInserted].first = mvSave; + } + } + } +#endif for (size_t n = 0; n < cMvdDerived.size(); ++n) { cMvdDerived[n] = aMvCostVec[n].first; @@ -13228,6 +14753,54 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<Mv, Distortion> & l, const std::pair<Mv, Distortion> & r) {return l.second < r.second; }); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int sizeCandList = (int) distance(aMvCostVec.begin(), aMvCostVec.end()); + if (sizeCandList > 2) + { + Distortion lambdaTh = pu.cs->slice->getCostForARMC(); + bool enoughDiverse = false; + uint32_t diverseCand = 0; + uint32_t posToBeInserted = 0; + for (uint32_t uiCand = 0; uiCand < sizeCandList - 1; ++uiCand) + { + for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < sizeCandList; ++uiMergeCand) + { + if (lambdaTh <= abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiCand].second))) + { + enoughDiverse = true; + for (uint32_t uiMergeCand3 = 0; uiMergeCand3 < uiCand; ++uiMergeCand3) + { + if (lambdaTh > abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiMergeCand3].second))) + { + enoughDiverse = false; + break; + } + } + + if (enoughDiverse) + { + diverseCand = uiMergeCand; + posToBeInserted = uiCand + 1; + break; + } + } + } + if (enoughDiverse) + { + Distortion saveCandCost = aMvCostVec[diverseCand].second; + Mv mvSave = aMvCostVec[diverseCand].first; + + for (int i = diverseCand; i > posToBeInserted - 1; i--) + { + aMvCostVec[i].second = aMvCostVec[i - 1].second; + aMvCostVec[i].first = aMvCostVec[i - 1].first; + } + aMvCostVec[posToBeInserted].second = saveCandCost; + aMvCostVec[posToBeInserted].first = mvSave; + } + } + } +#endif for (int n = 0; n < patternsNum; ++n) { cMvdDerived[n] = aMvCostVec[n].first; @@ -13726,6 +15299,53 @@ void InterPrediction::deriveMVDcandAffine(const PredictionUnit& pu, RefPicList e //--------------------------------------------------------------------------------// ///////////////////////////////////////////////////////////////// std::stable_sort(aMvCostVec.begin(), aMvCostVec.end(), [](const std::pair<int, Distortion> & l, const std::pair<int, Distortion> & r) {return l.second < r.second; }); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int sizeCandList = (int) distance(aMvCostVec.begin(), aMvCostVec.end()); + if (sizeCandList > 2) + { + Distortion lambdaTh = pu.cs->slice->getCostForARMC(); + bool enoughDiverse = false; + uint32_t diverseCand = 0; + uint32_t posToBeInserted = 0; + for (uint32_t uiCand = 0; uiCand < sizeCandList - 1; ++uiCand) + { + for (uint32_t uiMergeCand = uiCand + 1; uiMergeCand < sizeCandList; ++uiMergeCand) + { + if (lambdaTh <= abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiCand].second))) + { + enoughDiverse = true; + for (uint32_t uiMergeCand3 = 0; uiMergeCand3 < uiCand; ++uiMergeCand3) + { + if (lambdaTh > abs((int)(aMvCostVec[uiMergeCand].second - aMvCostVec[uiMergeCand3].second))) + { + enoughDiverse = false; + break; + } + } + if (enoughDiverse) + { + diverseCand = uiMergeCand; + posToBeInserted = uiCand + 1; + break; + } + } + } + if (enoughDiverse) + { + Distortion saveCandCost = aMvCostVec[diverseCand].second; + int mvSave = aMvCostVec[diverseCand].first; + + for (int i = diverseCand; i > posToBeInserted - 1; i--) + { + aMvCostVec[i].second = aMvCostVec[i - 1].second; + aMvCostVec[i].first = aMvCostVec[i - 1].first; + } + aMvCostVec[posToBeInserted].second = saveCandCost; + aMvCostVec[posToBeInserted].first = mvSave; + } + } + } +#endif for (int n = 0; n < patternsNum; ++n) { int index = aMvCostVec[n].first; diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index 0d0f0659d35a774c8c67255709a9e123f770fc9d..96199f6fbbdf8392d43bdd5bca40373abe715489 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -542,12 +542,20 @@ public: static bool isSubblockVectorSpreadOverLimit( int a, int b, int c, int d, int predType ); #endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + void sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, uint32_t * mmvdLUT, int16_t MMVDIdx = -1); +#else void sortInterMergeMMVDCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, uint32_t * mmvdLUT, uint32_t MMVDIdx = -1); #endif +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + void sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, int16_t afMMVDIdx = -1, bool fromStart = false); +#else void sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, uint32_t afMMVDIdx = -1); #endif +#endif #if JVET_W0090_ARMC_TM void adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx = -1); @@ -575,8 +583,12 @@ public: void updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MRG_MAX_NUM_CANDS], int mrgCandIdx = -1); #endif #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + void getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0 = -1, int8_t posList1 = -1, bool load0 = false, bool load1 = false); +#else void getBlkAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft); #endif +#endif #if JVET_W0090_ARMC_TM void adjustAffineMergeCandidates(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, int mrgCandIdx = -1 #if JVET_Z0139_NA_AFF @@ -598,13 +610,24 @@ public: , bool wrapRef = false #endif ); +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + void getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, int8_t posList0 = -1, int8_t posList1 = -1, bool loadSave0 = false, bool loadSave1 = false); +#else void getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft); +#endif #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND void adjustMergeCandidates(PredictionUnit& pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand); #endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING void adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand, int mrgCandIdx = -1); void updateCandInOneCandidateGroup(MergeCtx& mrgCtx, uint32_t* RdCandList, int numCandInCategory = -1); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + void updateCandInTwoCandidateGroups(MergeCtx& mrgCtx, uint32_t* rdCandList, int numCandInCategory, MergeCtx mrgCtx2); +#endif +#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); #endif #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION void adjustAffineMergeCandidatesOneGroup(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, int listsize, int mrgCandIdx = -1); @@ -678,7 +701,11 @@ public: #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + void deriveTMMv (PredictionUnit& pu, Distortion* tmCost = NULL); +#else void deriveTMMv (PredictionUnit& pu); +#endif #endif Distortion deriveTMMv (const PredictionUnit& pu, bool fillCurTpl, Distortion curBestCost, RefPicList eRefList, int refIdx, int maxSearchRounds, Mv& mv, const MvField* otherMvf = nullptr); #endif // TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM @@ -745,7 +772,11 @@ public: public: Mv* getBdofSubPuMvOffset() {return m_bdofSubPuMvOffset;} void setBdmvrSubPuMvBuf(Mv* mvBuf0, Mv* mvBuf1) { m_bdmvrSubPuMvBuf[0] = mvBuf0; m_bdmvrSubPuMvBuf[1] = mvBuf1; } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool processBDMVR (PredictionUnit& pu, int step = 0, Distortion* tmCost = NULL); +#else bool processBDMVR (PredictionUnit& pu); +#endif #if JVET_X0049_ADAPT_DMVR bool processBDMVRPU2Dir (PredictionUnit& pu, bool subPURefine[2], Mv(&finalMvDir)[2]); void processBDMVRSubPU (PredictionUnit& pu, bool subPURefine); diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 4999ea7855074bf6265c166ef7d105025912f851..ab0b8a20f9a8cff488b6c2d06cf70fec8a326ce9 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1533,6 +1533,9 @@ void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll) m_pcPicHeader = pSrc->m_pcPicHeader; m_colFromL0Flag = pSrc->m_colFromL0Flag; m_colRefIdx = pSrc->m_colRefIdx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + m_costForARMC = pSrc->m_costForARMC; +#endif if( cpyAlmostAll ) setLambdas(pSrc->getLambdas()); @@ -3517,6 +3520,9 @@ SPS::SPS() , m_uiMaxCUHeight ( 32) , m_numRPL0 ( 0 ) , m_numRPL1 ( 0 ) +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + , m_numLambda ( 0 ) +#endif , m_rpl1CopyFromRpl0Flag ( false ) , m_rpl1IdxPresentFlag ( false ) , m_allRplEntriesHasSameSignFlag ( true ) @@ -3610,6 +3616,9 @@ SPS::SPS() #if JVET_W0090_ARMC_TM , m_AML ( false ) #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC +, m_armcRefinedMotion ( false ) +#endif , m_GDREnabledFlag ( true ) , m_SubLayerCbpParametersPresentFlag ( true ) , m_rprEnabledFlag ( false ) @@ -3670,7 +3679,29 @@ void SPS::createRPLList1(int numRPL) m_rpl1IdxPresentFlag = (m_numRPL0 != m_numRPL1) ? true : false; } - +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC +int SPS::getIdx(uint32_t val) const { + for (int i = 0; i < m_numLambda; i++) + { + if (m_lambdaVal[i] == val) + { + return i; + } + } + return -1; +} +int SPS::getQPOffsetsIdx(int val) const +{ + for (int i = 0; i < m_numLambda; i++) + { + if (m_qpOffsets[i] == val) + { + return i; + } + } + return -1; +} +#endif const int SPS::m_winUnitX[]={1,2,2,1}; const int SPS::m_winUnitY[]={1,2,1,1}; diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 008a2e36d0c9820ce0f862e4fafb2fce350b802a..477d3b69177c3c85c77e039009c9dc2cfd4bc31d 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1581,6 +1581,13 @@ private: RPLList m_RPLList1; uint32_t m_numRPL0; uint32_t m_numRPL1; + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + uint32_t m_numLambda; + uint32_t m_lambdaVal[MAX_GOP]; + int m_qpOffsets[MAX_GOP]; + int m_maxbitsLambdaVal; +#endif bool m_rpl1CopyFromRpl0Flag; bool m_rpl1IdxPresentFlag; @@ -1719,6 +1726,9 @@ private: bool m_MIP; #if JVET_W0090_ARMC_TM || JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0075_IBC_HMVP_ENLARGE bool m_AML; +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool m_armcRefinedMotion; #endif ChromaQpMappingTable m_chromaQpMappingTable; bool m_GDREnabledFlag; @@ -1935,6 +1945,18 @@ public: RPLList* getRPLList1() { return &m_RPLList1; } uint32_t getNumRPL0() const { return m_numRPL0; } uint32_t getNumRPL1() const { return m_numRPL1; } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + uint32_t getNumLambda() const { return m_numLambda; } + int getIdx(uint32_t val) const; + uint32_t getLambdaVal(int idx) const { return m_lambdaVal[idx]; } + void setNumLambda(uint32_t numL) { m_numLambda = numL; } + void setLambdaVal(int idx, uint32_t val) { m_lambdaVal[idx] = val; } + uint32_t getMaxbitsLambdaVal() const { return m_maxbitsLambdaVal; } + void setMaxbitsLambdaVal(int numL) { m_maxbitsLambdaVal = numL; } + void setQPOffsets(int idx, int val) { m_qpOffsets[idx] = val; } + int getQPOffsets(int idx) const { return m_qpOffsets[idx]; } + int getQPOffsetsIdx(int val) const; +#endif void setRPL1CopyFromRPL0Flag(bool isCopy) { m_rpl1CopyFromRpl0Flag = isCopy; } bool getRPL1CopyFromRPL0Flag() const { return m_rpl1CopyFromRpl0Flag; } bool getRPL1IdxPresentFlag() const { return m_rpl1IdxPresentFlag; } @@ -2199,6 +2221,10 @@ void setCCALFEnabledFlag( bool b ) #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; } +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + void setUseArmcRefinedMotion ( bool b ) { m_armcRefinedMotion = b; } + bool getUseArmcRefinedMotion () const { return m_armcRefinedMotion; } #endif bool getUseWP () const { return m_useWeightPred; } bool getUseWPBiPred () const { return m_useWeightedBiPred; } @@ -2759,6 +2785,9 @@ private: bool m_enableTMVPFlag; //!< enable temporal motion vector prediction bool m_picColFromL0Flag; //!< syntax element collocated_from_l0_flag uint32_t m_colRefIdx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + uint32_t m_costForARMC; //!< Cost for diversity criterion +#endif bool m_mvdL1ZeroFlag; //!< L1 MVD set to zero flag uint32_t m_maxNumAffineMergeCand; //!< max number of sub-block merge candidates bool m_disFracMMVD; //!< fractional MMVD offsets disabled flag @@ -2896,6 +2925,10 @@ public: bool getPicColFromL0Flag() const { return m_picColFromL0Flag; } void setColRefIdx( uint32_t refIdx) { m_colRefIdx = refIdx; } uint32_t getColRefIdx() { return m_colRefIdx; } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + void setCostForARMC(uint32_t cost) { m_costForARMC = cost; } + uint32_t getCostForARMC() { return m_costForARMC; } +#endif void setMvdL1ZeroFlag( bool b ) { m_mvdL1ZeroFlag = b; } bool getMvdL1ZeroFlag() const { return m_mvdL1ZeroFlag; } void setMaxNumAffineMergeCand( uint32_t val ) { m_maxNumAffineMergeCand = val; } @@ -3136,6 +3169,9 @@ private: uint32_t m_colRefIdx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + uint32_t m_costForARMC; +#endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING std::vector<int> m_implicitRefIdx[NUM_REF_PIC_LIST_01][NUM_REF_PIC_LIST_01][MAX_NUM_REF + 1]; #endif @@ -3295,6 +3331,9 @@ public: bool getColFromL0Flag() const { return m_colFromL0Flag; } uint32_t getColRefIdx() const { return m_colRefIdx; } void checkColRefIdx(uint32_t curSliceSegmentIdx, const Picture* pic); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + uint32_t getCostForARMC() const { return m_costForARMC; } +#endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING void resizeImBuf(int numSlices) { @@ -3392,6 +3431,9 @@ public: void setColRefIdx( uint32_t refIdx) { m_colRefIdx = refIdx; } void setCheckLDC( bool b ) { m_bCheckLDC = b; } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + void setCostForARMC(uint32_t cost) { m_costForARMC = cost; } +#endif void setBiDirPred( bool b, int refIdx0, int refIdx1 ) { m_biDirPred = b; m_symRefIdx[0] = refIdx0; m_symRefIdx[1] = refIdx1; } bool getBiDirPred() const { return m_biDirPred; } int getSymRefIdx( int refList ) const { return m_symRefIdx[refList]; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 67201d86365cf5d7001b502058153ac20ee4303e..f24394be67d5ba8d1ba7edccbd593b5ed8350181 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -201,8 +201,13 @@ #define JVET_Y0134_TMVP_NAMVP_CAND_REORDERING 1 // JVET-Y0134: MV candidate reordering for TMVP and NAMVP types (controlled by JVET_W0090_ARMC_TM), and reference picture selection for TMVP #if JVET_W0090_ARMC_TM #define JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED 1 // JVET-Y0067: TM based reordering for MMVD and affine MMVD and MVD sign prediction +#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#define JVET_AA0093_ENHANCED_MMVD_EXTENSION 1 // JVET-AA0093: Test 2.3 part: Extension on TM based reordering for MMVD and affine MMVD +#endif #define JVET_Z0102_NO_ARMC_FOR_ZERO_CAND 1 // JVET-Z0102: No ARMC for the zero candidates of regular, TM and BM merge modes #define JVET_Z0054_BLK_REF_PIC_REORDER 1 // JVET-Z0054: Block level TM based reordering of reference pictures +#define JVET_AA0093_REFINED_MOTION_FOR_ARMC 1 // JVET-AA0093: Refined motion for ARMC +#define JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC 1 // JVET-AA0093: Diversity criterion for ARMC reordering #endif // Transform and coefficient coding diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 4b17a450b2f8462a2e1d0f4fc699455670f71cfa..1fefd8c815b3536b6f9ed68a04ab7f47182f59b7 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -705,6 +705,9 @@ void PredictionUnit::initData() #else ::memset(mvdL0SubPu, 0, sizeof(mvdL0SubPu)); #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + reduceTplSize = false; +#endif #if JVET_Z0054_BLK_REF_PIC_REORDER refIdxLC = -1; @@ -830,6 +833,9 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData) #else ::memcpy(mvdL0SubPu, predData.mvdL0SubPu, sizeof(mvdL0SubPu)); #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + reduceTplSize = predData.reduceTplSize; +#endif for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++) { @@ -951,6 +957,9 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other ) #else ::memcpy(mvdL0SubPu, other.mvdL0SubPu, sizeof(mvdL0SubPu)); #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + reduceTplSize = other.reduceTplSize; +#endif for (uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++) { diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 72b66531d4fa420513d258aa052281d180bea337..39de95978dd388fa8b5db80f3d312076f4fe0000 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -439,7 +439,11 @@ struct InterPredictionData { bool mergeFlag; bool regularMergeFlag; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t mergeIdx; +#else uint8_t mergeIdx; +#endif uint8_t geoSplitDir; #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING uint8_t geoSyntaxMode; @@ -464,16 +468,24 @@ struct InterPredictionData uint8_t geoBldIdx; #endif bool mmvdMergeFlag; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t mmvdMergeIdx; +#else uint8_t mmvdMergeIdx; +#endif #if AFFINE_MMVD bool afMmvdFlag; uint8_t afMmvdBaseIdx; // base vector's merge index at the affine merge list, excluding sbTmvp uint8_t afMmvdStep; uint8_t afMmvdDir; #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t afMmvdMergeIdx; +#else uint8_t afMmvdMergeIdx; #endif #endif +#endif #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) bool tmMergeFlag; #endif @@ -491,6 +503,9 @@ struct InterPredictionData #else Mv mvdL0SubPu[MAX_NUM_SUBCU_DMVR]; #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool reduceTplSize; +#endif #if JVET_X0083_BM_AMVP_MERGE_MODE bool amvpMergeModeFlag[NUM_REF_PIC_LIST_01]; #endif diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 96efd102c1e39b3696602fe30d87b61f0597feb7..515b0fdacfe37c5fac12eed83e732d370304a11c 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -2799,11 +2799,25 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, const Slice &slice = *pu.cs->slice; #if TM_MRG const uint32_t mvdSimilarityThresh = pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + uint32_t additionalMRGCand = 0; + if (tmvpMrgCtx != NULL) + { + additionalMRGCand = tmvpMrgCtx->numValidMergeCand; + } + if (namvpMrgCtx != NULL) + { + additionalMRGCand += namvpMrgCtx->numValidMergeCand; + } + const uint32_t maxNumMergeCand = pu.tmMergeFlag ? std::min((int)(TM_MRG_MAX_NUM_INIT_CANDS + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3))) + : std::min((int) (pu.cs->sps->getMaxNumMergeCand() + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3))); +#else #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM const uint32_t maxNumMergeCand = pu.tmMergeFlag ? (pu.cs->sps->getUseAML()) ? TM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand(); #else const uint32_t maxNumMergeCand = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand(); #endif +#endif #else const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumMergeCand(); #endif @@ -3428,6 +3442,84 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, } else if (tmvpMrgCtx->numValidMergeCand > 0) { +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (!pu.tmMergeFlag) + { + for (uint32_t ui = 0; ui < tmvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand - 1; ++ui) + { + mrgCtx.BcwIdx[cnt] = tmvpMrgCtx->BcwIdx[ui]; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = tmvpMrgCtx->LICFlags[ui]; +#endif + mrgCtx.interDirNeighbours[cnt] = tmvpMrgCtx->interDirNeighbours[ui]; + mrgCtx.mvFieldNeighbours[cnt << 1] = tmvpMrgCtx->mvFieldNeighbours[ui << 1]; + mrgCtx.useAltHpelIf[cnt] = tmvpMrgCtx->useAltHpelIf[ui]; + if (slice.isInterB()) + { + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = tmvpMrgCtx->mvFieldNeighbours[(ui << 1) + 1]; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = tmvpMrgCtx->addHypNeighbours[ui]; +#endif + } + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) + { +#endif + mrgCtx.candCost[cnt] = tmvpMrgCtx->candCost[ui]; + if (mrgCandIdx == cnt) + { + return; + } + + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } + else + { + mrgCtx.BcwIdx[cnt] = tmvpMrgCtx->BcwIdx[0]; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = tmvpMrgCtx->LICFlags[0]; +#endif + mrgCtx.interDirNeighbours[cnt] = tmvpMrgCtx->interDirNeighbours[0]; + mrgCtx.mvFieldNeighbours[cnt << 1] = tmvpMrgCtx->mvFieldNeighbours[0]; + mrgCtx.useAltHpelIf[cnt] = tmvpMrgCtx->useAltHpelIf[0]; + if (slice.isInterB()) + { + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = tmvpMrgCtx->mvFieldNeighbours[1]; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = tmvpMrgCtx->addHypNeighbours[0]; +#endif + } + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + ,mvdSimilarityThresh +#endif + )) + { +#endif + mrgCtx.candCost[cnt] = tmvpMrgCtx->candCost[0]; + if (mrgCandIdx == cnt) + { + return; + } + + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } +#else mrgCtx.BcwIdx[cnt] = tmvpMrgCtx->BcwIdx[0]; #if INTER_LIC mrgCtx.LICFlags[cnt] = tmvpMrgCtx->LICFlags[0]; @@ -3462,6 +3554,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, } #endif } +#endif #endif } @@ -3482,12 +3575,20 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, const int iNACANDIDATE_NUM[4] = { 3, 5, 5, 5 }; const int idxMap[4][5] = { { 0, 1, 4 },{ 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4 } }; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCand; iDistanceIndex++) +#else for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCand - 1; iDistanceIndex++) +#endif { const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++) +#else for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand - 1; NASPIdx++) +#endif { switch (idxMap[iDistanceIndex][NASPIdx]) { @@ -3571,7 +3672,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, } else { +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + for (uint32_t ui = 0; ui < namvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand; ++ui) +#else for (uint32_t ui = 0; ui < namvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand - 1; ++ui) +#endif { mrgCtx.BcwIdx[cnt] = namvpMrgCtx->BcwIdx[ui]; #if INTER_LIC @@ -3611,7 +3716,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #endif #endif +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int maxNumMergeCandMin1 = maxNumMergeCand; +#else int maxNumMergeCandMin1 = maxNumMergeCand - 1; +#endif if (cnt != maxNumMergeCandMin1) { #if !JVET_Z0075_IBC_HMVP_ENLARGE @@ -3643,6 +3752,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, } } +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC // pairwise-average candidates { if (cnt > 1 && cnt < maxNumMergeCand) @@ -3742,6 +3852,13 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, return; } } +#else + // early termination + if (cnt == maxNumMergeCand) + { + return; + } +#endif #if JVET_Z0139_HIST_AFF if (addMergeHMVPCandFromAffModel(pu, mrgCtx, mrgCandIdx, cnt @@ -4685,7 +4802,21 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const CodingStructure &cs = *pu.cs; const Slice &slice = *pu.cs->slice; #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + uint32_t additionalMRGCand = 0; + if (mvpMrgCtx1 != NULL) + { + additionalMRGCand = mvpMrgCtx1->numValidMergeCand; + } + if (mvpMrgCtx2 != NULL) + { + additionalMRGCand += mvpMrgCtx2->numValidMergeCand; + } + const uint32_t maxNumMergeCand = (pu.cs->sps->getUseAML()) ? std::min((int)(BM_MRG_MAX_NUM_INIT_CANDS + additionalMRGCand), ((int)NUM_MERGE_CANDS - (3))) + : pu.cs->sps->getMaxNumBMMergeCand(); +#else const uint32_t maxNumMergeCand = (pu.cs->sps->getUseAML()) ? BM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumBMMergeCand(); +#endif #else const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumBMMergeCand(); #endif @@ -5060,6 +5191,33 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, } #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + else if (mvpMrgCtx1->numValidMergeCand > 0) + { + for (int uiNumCand = 0; uiNumCand < mvpMrgCtx1->numValidMergeCand && cnt < maxNumMergeCand; uiNumCand++) + { + mrgCtx.interDirNeighbours[cnt] = mvpMrgCtx1->interDirNeighbours[uiNumCand]; + mrgCtx.mvFieldNeighbours[cnt << 1] = mvpMrgCtx1->mvFieldNeighbours[uiNumCand << 1]; + mrgCtx.useAltHpelIf[cnt] = mvpMrgCtx1->useAltHpelIf[uiNumCand]; + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = mvpMrgCtx1->mvFieldNeighbours[(uiNumCand << 1) + 1]; +#if JVET_Y0089_DMVR_BCW + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? mvpMrgCtx1->BcwIdx[uiNumCand] : BCW_DEFAULT; +#endif +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) +#endif + { + mrgCtx.candCost[cnt] = mvpMrgCtx1->candCost[uiNumCand]; + if (mrgCandIdx == cnt) + { + mrgCtx.numValidMergeCand = cnt + 1; + return; + } + cnt++; + } + } + } +#else else if (mvpMrgCtx1->numValidMergeCand > 0) { mrgCtx.interDirNeighbours[cnt] = mvpMrgCtx1->interDirNeighbours[0]; @@ -5085,6 +5243,7 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, cnt++; } } +#endif #endif } @@ -5095,7 +5254,11 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, return; } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int maxNumMergeCandMin1 = maxNumMergeCand; +#else int maxNumMergeCandMin1 = maxNumMergeCand - 1; +#endif #if NON_ADJACENT_MRG_CAND #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM if (mvpMrgCtx2 == NULL) @@ -5217,6 +5380,7 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, } } +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC { if (cnt > 1 && cnt < maxNumMergeCand) { @@ -5244,12 +5408,12 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, } interDir += 1 << refListId; - const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv; - const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv; + const Mv& mvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv; + const Mv& mvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv; // average two MVs - Mv avgMv = MvI; - avgMv += MvJ; + Mv avgMv = mvI; + avgMv += mvJ; roundAffineMv(avgMv.hor, avgMv.ver, 1); mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI); @@ -5272,6 +5436,7 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, return; } } +#endif mrgCtx.numCandToTestEnc = cnt; @@ -5656,7 +5821,11 @@ void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) #if TM_MRG const uint32_t mvdSimilarityThresh = 1; #endif +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + const uint32_t maxNumMergeCand = pu.tmMergeFlag ? 1 :NUM_TMVP_CANDS; +#else const uint32_t maxNumMergeCand = NUM_TMVP_CANDS; +#endif for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.BcwIdx[ui] = BCW_DEFAULT; @@ -5923,7 +6092,11 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) const Slice &slice = *pu.cs->slice; #if TM_MRG +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + const uint32_t mvdSimilarityThresh = pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1; +#else const uint32_t mvdSimilarityThresh = getBDMVRMvdThreshold(pu); +#endif #endif const uint32_t maxNumMergeCand = NUM_NON_ADJ_CANDS; @@ -7040,9 +7213,47 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in tmCost[i] = std::numeric_limits<Distortion>::max(); } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool armcRefinedMotion = isArmcRefinedMotionEnabled(pu, 0); + if (armcRefinedMotion) + { + pu.reduceTplSize = true; + } + if (armcRefinedMotion && pInfo->numCand > 1) + { + for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx) + { + tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]); + temp.AMVPCand = pInfo->mvCand[candIdx]; + temp.cost = tmCost[candIdx]; + input.push_back(temp); + } + stable_sort(input.begin(), input.end(), CostIncSort); + for (int candIdx = 1; candIdx < pInfo->numCand; ++candIdx) + { + if (input.at(candIdx).cost > 5 * input.at(0).cost) + { + pInfo->numCand = candIdx + 1; + break; + } + } + input.clear(); + } +#endif for (int candIdx = 0; candIdx < pInfo->numCand; ++candIdx) { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (armcRefinedMotion) + { + tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, TM_MAX_NUM_OF_ITERATIONS, pInfo->mvCand[candIdx]); + } + else + { + tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]); + } +#else tmCost[candIdx] = interPred->deriveTMMv(pu, true, std::numeric_limits<Distortion>::max(), eRefPicList, refIdx, 0, pInfo->mvCand[candIdx]); +#endif temp.AMVPCand = pInfo->mvCand[candIdx]; temp.cost = tmCost[candIdx]; input.push_back(temp); @@ -7054,9 +7265,19 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in pInfo->mvCand[candIdx] = input.at(candIdx).AMVPCand; tmCost[candIdx] = input.at(candIdx).cost; } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + pu.reduceTplSize = false; +#endif pInfo->numCand = 1; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (!armcRefinedMotion) + { +#endif interPred->deriveTMMv(pu, true, tmCost[0], eRefPicList, refIdx, TM_MAX_NUM_OF_ITERATIONS, pInfo->mvCand[0]); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + } +#endif } while (pInfo->numCand < pInfo->maxStorageSize) @@ -10638,7 +10859,11 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg CHECK(!pu.cu->affine, "Affine flag is not on for Affine MMVD mode!"); CHECK(affineMergeCtx.mergeType[afMmvdBase] != MRG_TYPE_DEFAULT_N, "AFF_MMVD base candidate type is not regular Affine!"); +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + static const int32_t refMvdCands[AF_MMVD_STEP_NUM] = { 1, 2, 4, 8 }; +#else static const int32_t refMvdCands[AF_MMVD_STEP_NUM] = { 1, 2, 4, 8, 16 }; +#endif #if JVET_Y0128_NON_CTC const int32_t iPicSize = pu.cu->slice->getPic()->lumaSize().area(); const int32_t mvShift = iPicSize < 921600 ? 0 : ( iPicSize < 4096000 ? 2 : MV_FRACTIONAL_BITS_INTERNAL - 1); // 921600 = 1280x720, 4096000 = 2560x1600 @@ -10667,8 +10892,13 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED const int xDir[] = {1, -1, 0, 0, 1, -1, 1, -1, 2, -2, 2, -2, 1, 1, -1, -1}; const int yDir[] = {0, 0, 1, -1, 1, -1, -1, 1, 1, 1, -1, -1, 2, -2, 2, -2}; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int offsetX = xDir[offsetDir % 8] * step; + int offsetY = yDir[offsetDir % 8] * step; +#else int offsetX = xDir[offsetDir] * step; int offsetY = yDir[offsetDir] * step; +#endif #else int magY = (offsetDir >> 1) & 0x1; int sign = (offsetDir & 0x1) ? -1 : 1; @@ -10688,6 +10918,31 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg { mvfMmvd[1][cpIdx].mv = baseMv[1][cpIdx] + offsetMv; } +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + else if (interDir == 3) + { + if (offsetDir >= 16) + { + int poc_cur = pu.cu->slice->getPOC(); + int poc_l0 = pu.cu->slice->getRefPOC(REF_PIC_LIST_0, refIdxL0); + int poc_l1 = pu.cu->slice->getRefPOC(REF_PIC_LIST_1, refIdxL1); + int distL0 = poc_l0 - poc_cur; + int distL1 = poc_l1 - poc_cur; + mvfMmvd[0][cpIdx].mv = baseMv[0][cpIdx] + offsetMv; + mvfMmvd[1][cpIdx].mv = distL0 * distL1 < 0 ? baseMv[1][cpIdx] - offsetMv : baseMv[1][cpIdx] + offsetMv; + } + else if (offsetDir >= 8) + { + mvfMmvd[0][cpIdx].mv = baseMv[0][cpIdx] ; + mvfMmvd[1][cpIdx].mv = baseMv[1][cpIdx] + offsetMv; + } + else + { + mvfMmvd[0][cpIdx].mv = baseMv[0][cpIdx] + offsetMv; + mvfMmvd[1][cpIdx].mv = baseMv[1][cpIdx] ; + } + } +#else else if (interDir == 3) { int poc_cur = pu.cu->slice->getPOC(); @@ -10699,6 +10954,7 @@ void PU::getAfMmvdMvf(const PredictionUnit& pu, const AffineMergeCtx& affineMerg mvfMmvd[0][cpIdx].mv = baseMv[0][cpIdx] + offsetMv; mvfMmvd[1][cpIdx].mv = distL0 * distL1 < 0 ? baseMv[1][cpIdx] - offsetMv : baseMv[1][cpIdx] + offsetMv; } +#endif } } @@ -13716,6 +13972,31 @@ bool PU::checkIsValidMergeMvCand(const CodingStructure &cs, const PredictionUnit return true; } #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC +bool PU::isArmcRefinedMotionEnabled(const PredictionUnit &pu, unsigned mode) +{ + if (!pu.cs->sps->getUseAML() || !pu.cs->sps->getUseArmcRefinedMotion()) + { + return false; + } + int blkSize = pu.lwidth() * pu.lheight(); + if (mode == 0) + { + if (pu.cs->slice->getTLayer() < 5 && blkSize > 32 && blkSize <= 1024) + { + return true; + } + } + else + { + if ((blkSize <= (mode == 1 ? 2048 : 4096)) && ( blkSize > 64)) + { + return true; + } + } + return false; +} +#endif #endif #if JVET_Z0135_TEMP_CABAC_WIN_WEIGHT diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 12f2a13350218a528d9433756bcfec9f07025cf9..492c28ab478014209afc12bf8b221aed44a50521 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -400,6 +400,9 @@ namespace PU #endif bool isLMCModeEnabled (const PredictionUnit &pu, unsigned mode); bool isChromaIntraModeCrossCheckMode(const PredictionUnit &pu); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool isArmcRefinedMotionEnabled(const PredictionUnit &pu, unsigned mode); +#endif #if JVET_W0097_GPM_MMVD_TM #if TM_MRG diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 7341fc244d9f1dc9ad49031d5a4e509f1c4cdf07..b903b3ec86f2340d093d30aa8d432369c39e85de 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -3317,42 +3317,68 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu) return; } RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__AFFINE_MMVD, pu.lumaSize()); - + pu.afMmvdFlag = (m_BinDecoder.decodeBin(Ctx::AfMmvdFlag())); DTRACE(g_trace_ctx, D_SYNTAX, "affine_mmvd_flag() af_mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.afMmvdFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height); - + if (!pu.afMmvdFlag) { return; } - + // Base affine merge candidate idx uint8_t afMmvdBaseIdx = 0; - int numCandminus1_base = AF_MMVD_BASE_NUM - 1; - if (numCandminus1_base > 0) + int numCandMinus1Base = AF_MMVD_BASE_NUM - 1; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + unsigned ctxId = 0; + const CodingStructure *cs = pu.cu->cs; + const CodingUnit *cuLeft = cs->getCURestricted( pu.cu->lumaPos().offset( -1, 0 ), *pu.cu, CH_L ); + ctxId = (cuLeft && cuLeft->affine) ? 1 : 0; + const CodingUnit *cuAbove = cs->getCURestricted( pu.cu->lumaPos().offset( 0, -1 ), *pu.cu, CH_L ); + ctxId += (cuAbove && cuAbove->affine) ? 1 : 0; + numCandMinus1Base = (ctxId == 0) ? 0 : ((ctxId == 1) ? 1 : AF_MMVD_BASE_NUM-1); +#endif + if (numCandMinus1Base > 0) { // to support more base candidates - if (m_BinDecoder.decodeBin(Ctx::AfMmvdIdx())) - { - afMmvdBaseIdx++; - for (; afMmvdBaseIdx < numCandminus1_base; afMmvdBaseIdx++) +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int ctx2 = (numCandMinus1Base == 1) ? 1 : 0; + if (m_BinDecoder.decodeBin(Ctx::AfMmvdIdx(ctx2))) +#else + if (m_BinDecoder.decodeBin(Ctx::AfMmvdIdx())) +#endif { - if (!m_BinDecoder.decodeBinEP()) + afMmvdBaseIdx++; + for (; afMmvdBaseIdx < numCandMinus1Base; afMmvdBaseIdx++) { - break; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if (!m_BinDecoder.decodeBin(Ctx::AfMmvdIdx(afMmvdBaseIdx + 1))) +#else + if (!m_BinDecoder.decodeBinEP()) +#endif + { + break; + } } } - } } pu.afMmvdBaseIdx = afMmvdBaseIdx; DTRACE(g_trace_ctx, D_SYNTAX, "afMmvd_base_idx() afMmvd_base_idx=%d\n", afMmvdBaseIdx); - + #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED unsigned int ricePar = 1; - int numCandminus1_step = (AF_MMVD_MAX_REFINE_NUM >> (ricePar + AFFINE_MMVD_SIZE_SHIFT)) - 1; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int numStepCandMinus1 = (AF_MMVD_MAX_REFINE_NUM >> (ricePar+AFFINE_MMVD_SIZE_SHIFT)) / AFFINE_BI_DIR - 1; +#else + int numStepCandMinus1 = (AF_MMVD_MAX_REFINE_NUM >> (ricePar + AFFINE_MMVD_SIZE_SHIFT)) - 1; +#endif +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int temp = m_BinDecoder.decodeBin(Ctx::AfMmvdOffsetStep(5)); +#else int temp = (ricePar == 0) ? 0 : m_BinDecoder.decodeBinsEP(ricePar); +#endif int uiUnaryIdx = 0; - for (; uiUnaryIdx < numCandminus1_step; ++uiUnaryIdx) + for (; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx) { if (!m_BinDecoder.decodeBin(Ctx::AfMmvdOffsetStep((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)))) { @@ -3361,6 +3387,9 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu) } uiUnaryIdx <<= ricePar; uiUnaryIdx += temp; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uiUnaryIdx += afMmvdBaseIdx * AF_MMVD_MAX_REFINE_NUM; +#endif pu.afMmvdMergeIdx = uiUnaryIdx; pu.afMmvdStep = 0; pu.afMmvdDir = 0; @@ -3368,13 +3397,13 @@ void CABACReader::affine_mmvd_data(PredictionUnit& pu) { // Decode Step Value uint8_t stepOffset = 0; - int numCandminus1_step = AF_MMVD_STEP_NUM - 1; - if (numCandminus1_step > 0) + int numStepCandMinus1 = AF_MMVD_STEP_NUM - 1; + if (numStepCandMinus1 > 0) { if (m_BinDecoder.decodeBin(Ctx::AfMmvdOffsetStep())) { stepOffset++; - for (; stepOffset < numCandminus1_step; stepOffset++) + for (; stepOffset < numStepCandMinus1; stepOffset++) { if (!m_BinDecoder.decodeBinEP()) { @@ -3542,8 +3571,13 @@ void CABACReader::merge_data( PredictionUnit& pu ) #endif ) { - RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_FLAG, pu.lumaSize()); + RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_FLAG, pu.lumaSize()); +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + unsigned ctxId = pu.cu->skip ? 0 : 1; + cu.firstPU->mmvdMergeFlag = m_BinDecoder.decodeBin(Ctx::MmvdFlag(ctxId)); +#else cu.firstPU->mmvdMergeFlag = m_BinDecoder.decodeBin(Ctx::MmvdFlag(0)); +#endif DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", cu.firstPU->mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height); } else @@ -3873,12 +3907,12 @@ void CABACReader::merge_idx( PredictionUnit& pu ) void CABACReader::geo_mmvd_idx(PredictionUnit& pu, RefPicList eRefPicList) { bool extMMVD = pu.cs->picHeader->getGPMMMVDTableFlag(); - int numCandminus1_step = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1; + int numStepCandMinus1 = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1; int step = 0; if (m_BinDecoder.decodeBin(Ctx::GeoMmvdStepMvpIdx())) { step++; - for (; step < numCandminus1_step; step++) + for (; step < numStepCandMinus1; step++) { if (!m_BinDecoder.decodeBinEP()) { @@ -4093,18 +4127,41 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu) RExt__DECODER_DEBUG_BIT_STATISTICS_CREATE_SET_SIZE(STATS__CABAC_BITS__MERGE_INDEX, pu.lumaSize()); unsigned int uiUnaryIdx = 0; int var0 = 0; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int numCandMinus1Base = std::min<int>(MMVD_BASE_MV_NUM, pu.cs->sps->getMaxNumMergeCand()) - 1; + if (numCandMinus1Base > 0) + { + // to support more base candidates + if (m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx(0))) + { + var0++; + for (; var0 < numCandMinus1Base; var0++) + { + if (!m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx(var0))) + { + break; + } + } + } + } +#else if (pu.cs->sps->getMaxNumMergeCand() > 1) { static_assert(MMVD_BASE_MV_NUM == 2, ""); var0 = m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx()); } +#endif DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() base_mvp_idx=%d\n", var0); unsigned int ricePar = 1; - int numCandminus1_step = (MMVD_MAX_REFINE_NUM >> (ricePar+MMVD_SIZE_SHIFT)) - 1; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int numStepCandMinus1 = ((MMVD_MAX_REFINE_NUM >> (ricePar+MMVD_SIZE_SHIFT)))/MMVD_BI_DIR - 1; +#else + int numStepCandMinus1 = (MMVD_MAX_REFINE_NUM >> (ricePar+MMVD_SIZE_SHIFT)) - 1; +#endif int temp = 0; temp = m_BinDecoder.decodeBinsEP(ricePar); - for (; uiUnaryIdx < numCandminus1_step; ++uiUnaryIdx) + for (; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx) { if (!m_BinDecoder.decodeBin(Ctx::MmvdStepMvpIdx((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx)))) { @@ -4128,12 +4185,12 @@ void CABACReader::mmvd_merge_idx(PredictionUnit& pu) var0 = m_BinDecoder.decodeBin(Ctx::MmvdMergeIdx()); } DTRACE(g_trace_ctx, D_SYNTAX, "base_mvp_idx() base_mvp_idx=%d\n", var0); - int numCandminus1_step = MMVD_REFINE_STEP - 1; + int numStepCandMinus1 = MMVD_REFINE_STEP - 1; int var1 = 0; if (m_BinDecoder.decodeBin(Ctx::MmvdStepMvpIdx())) { var1++; - for (; var1 < numCandminus1_step; var1++) + for (; var1 < numStepCandMinus1; var1++) { if (!m_BinDecoder.decodeBinEP()) { diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 462995d2e5835a54c32f52c56fb97cd9a3031403..f00b2d95a114868980d389d1d2e1eb63c9db7388 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -1646,7 +1646,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) ); #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED uint32_t mmvdLUT[MMVD_ADD_NUM]; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t mmvdIdx = pu.mmvdMergeIdx; +#else uint8_t mmvdIdx = pu.mmvdMergeIdx; +#endif m_pcInterPred->sortInterMergeMMVDCandidates(pu, mrgCtx, mmvdLUT, mmvdIdx); mrgCtx.setMmvdMergeCandiInfo(pu, mmvdIdx, mmvdLUT[mmvdIdx]); #else @@ -1923,13 +1927,22 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #endif else { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool applyBDMVR4TM[TM_MRG_MAX_NUM_INIT_CANDS] = { false }; + bool tmMergeRefinedMotion = false; + bool admvrRefinedMotion = false; +#endif if (CU::isIBC(*pu.cu)) { #if JVET_Y0058_IBC_LIST_MODIFY && JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { #if JVET_Z0075_IBC_HMVP_ENLARGE +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t mrgCandIdx = pu.mergeIdx; +#else uint8_t mrgCandIdx = pu.mergeIdx; +#endif PU::getIBCMergeCandidates(pu, mrgCtx); m_pcInterPred->adjustIBCMergeCandidates(pu, mrgCtx, 0, IBC_MRG_MAX_NUM_CANDS_MEM); pu.mergeIdx = mrgCandIdx; @@ -1957,8 +1970,16 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) uint8_t bmDir = pu.bmDir; MergeCtx tmvpMergeCandCtx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if ( tplAvail) + { +#endif PU::getTmvpBMCand(pu, tmvpMergeCandCtx); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + } +#endif pu.bmDir = 0; +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1, pu.mergeIdx); @@ -1967,9 +1988,18 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) { tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand); } +#endif MergeCtx namvpMergeCandCtx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if ( tplAvail) + { +#endif PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + } +#endif pu.bmDir = 0; +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 3, pu.mergeIdx); @@ -1978,22 +2008,144 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) { namvpMergeCandCtx.numValidMergeCand = std::min(3, namvpMergeCandCtx.numValidMergeCand); } +#else + if (!tplAvail) + { + PU::getInterBMCandidates(pu, mrgCtx +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , -1 + , NULL + , NULL +#endif + ); + } + else +#endif PU::getInterBMCandidates(pu, mrgCtx, -1, &tmvpMergeCandCtx, &namvpMergeCandCtx); +#else +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + PU::getInterBMCandidates(pu, mrgCtx, -1); #else PU::getInterBMCandidates(pu, mrgCtx, pu.cs->sps->getUseAML() && (((mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumBMMergeCand()) || (mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : mergeIdx); +#endif uint8_t bmDir = pu.bmDir; #endif pu.bmDir = 0; #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + admvrRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 1); + admvrRefinedMotion &= tplAvail; +#endif if (tplAvail) { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumBMMergeCand()); + if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) + { + mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; + } + if (admvrRefinedMotion) + { + bool subPuRefineList[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, }; + bool subPuRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, }; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t orgMergeIdx = pu.mergeIdx; +#else + uint8_t orgMergeIdx = pu.mergeIdx; +#endif + pu.bmDir = 0; + mrgCtx.setMergeInfo( pu, 0 ); + + pu.bmDir = bmDir; + pu.bdmvrRefine = true; + for( uint32_t candIdx = 0; candIdx < mrgCtx.numValidMergeCand; candIdx++ ) + { + pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0; + pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx]; + pu.mv[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].mv; + pu.mv[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv; + pu.refIdx[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].refIdx; + pu.refIdx[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx; + + Mv finalMvDir[2]; + applyBDMVR4BM[candIdx] = m_pcInterPred->processBDMVRPU2Dir(pu, subPuRefineList[candIdx], finalMvDir); + subPuRefineListTmp[candIdx][0] = subPuRefineList[candIdx][0]; + subPuRefineListTmp[candIdx][1] = subPuRefineList[candIdx][1]; + mrgCtx.mvFieldNeighbours[(candIdx << 1) + bmDir - 1].mv = finalMvDir[bmDir - 1]; + } + pu.bmDir = 0; + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, bmDir == 2 ? applyBDMVR4BM : NULL, NULL, NULL, mergeIdx + 1, subPuRefineList, subPuRefineListTmp, mergeIdx); + pu.bmDir = bmDir; + pu.mergeIdx = orgMergeIdx; + mrgCtx.setMergeInfo( pu, pu.mergeIdx); + m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); + m_pcInterPred->processBDMVRSubPU(pu, subPuRefineList[mergeIdx][pu.bmDir - 1]); + } +#if !JVET_AA0093_REFINED_MOTION_FOR_ARMC + else +#endif +#endif #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND +#if !JVET_AA0093_REFINED_MOTION_FOR_ARMC m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumBMMergeCand()); +#endif #else m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, mergeIdx + 1, mergeIdx); #endif } #else +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + admvrRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 1); + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); + admvrRefinedMotion &= tplAvail; + if (admvrRefinedMotion) + { + if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) + { + mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; + } + if (admvrRefinedMotion) + { + bool subPuRefineList[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, }; + bool subPuRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, }; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t orgMergeIdx = pu.mergeIdx; +#else + uint8_t orgMergeIdx = pu.mergeIdx; +#endif + pu.bmDir = 0; + mrgCtx.setMergeInfo( pu, 0 ); + + pu.bmDir = bmDir; + pu.bdmvrRefine = true; + for( uint32_t candIdx = 0; candIdx < mrgCtx.numValidMergeCand; candIdx++ ) + { + pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0; + pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx]; + pu.mv[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].mv; + pu.mv[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv; + pu.refIdx[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].refIdx; + pu.refIdx[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx; + + Mv finalMvDir[2]; + applyBDMVR4BM[candIdx] = m_pcInterPred->processBDMVRPU2Dir(pu, subPuRefineList[candIdx], finalMvDir); + subPuRefineListTmp[candIdx][0] = subPuRefineList[candIdx][0]; + subPuRefineListTmp[candIdx][1] = subPuRefineList[candIdx][1]; + mrgCtx.mvFieldNeighbours[(candIdx << 1) + bmDir - 1].mv = finalMvDir[bmDir - 1]; + } + pu.bmDir = 0; + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, bmDir == 2 ? applyBDMVR4BM : NULL, NULL, NULL, mergeIdx + 1, subPuRefineList, subPuRefineListTmp, mergeIdx); + pu.bmDir = bmDir; + pu.mergeIdx = orgMergeIdx; + mrgCtx.setMergeInfo( pu, pu.mergeIdx); + m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); + m_pcInterPred->processBDMVRSubPU(pu, subPuRefineList[mergeIdx][pu.bmDir - 1]); + } + } + else +#endif m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, mergeIdx); #endif pu.bmDir = bmDir; @@ -2013,7 +2165,15 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); MergeCtx tmvpMergeCandCtx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (tplAvail) + { +#endif PU::getTmvpMergeCand(pu, tmvpMergeCandCtx); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + } +#endif +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1, pu.mergeIdx); @@ -2022,8 +2182,17 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) { tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand); } +#endif MergeCtx namvpMergeCandCtx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (tplAvail) + { +#endif PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + } +#endif +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 9, pu.mergeIdx); @@ -2032,11 +2201,103 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) { namvpMergeCandCtx.numValidMergeCand = std::min(9, namvpMergeCandCtx.numValidMergeCand); } +#else + if (!tplAvail) + { + PU::getInterMergeCandidates(pu, mrgCtx, 0, -1); + mrgCtx.numValidMergeCand = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand(); + } + else +#endif PU::getInterMergeCandidates(pu, mrgCtx, 0, -1, &tmvpMergeCandCtx, &namvpMergeCandCtx); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2); + tmMergeRefinedMotion &= tplAvail; +#endif if (tplAvail) { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.tmMergeFlag && tmMergeRefinedMotion) + { +#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND + m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumTMMergeCand()); +#else + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, mrgCtx.numValidMergeCand, pu.mergeIdx); +#endif + int tmpPuMrgIdx = pu.mergeIdx; + pu.reduceTplSize = true; + if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) + { + mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); + } + + if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) + { + mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; + } + + for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) + { + mrgCtx.BcwIdx[ui] = BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[ui] = false; +#endif + mrgCtx.interDirNeighbours[ui] = 0; + mrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; + mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; + mrgCtx.useAltHpelIf[ui] = false; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[ui].clear(); +#endif + mrgCtx.candCost[ui] = MAX_UINT64; + } + + Distortion tempCost[1]; + for( uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++ ) + { + mrgCtx.setMergeInfo( pu, uiMergeCand ); +#if MULTI_PASS_DMVR + applyBDMVR4TM[uiMergeCand] = PU::checkBDMVRCondition(pu); + if (applyBDMVR4TM[uiMergeCand]) + { + m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1]); + pu.bdmvrRefine = true; + applyBDMVR4TM[uiMergeCand] = m_pcInterPred->processBDMVR( pu, 1, tempCost ); + } + else + { + m_pcInterPred->deriveTMMv(pu, tempCost); + } +#else + m_pcInterPred->deriveTMMv( pu ); +#endif + + mrgCtx.candCost[uiMergeCand] = tempCost[0]; + mrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir; + mrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx; + mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv = pu.mv[0]; + mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = pu.refIdx[0]; + mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv = pu.mv[1]; + mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = pu.refIdx[1]; + if( pu.interDir == 1 ) + { + mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv.setZero(); + mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = NOT_VALID; + } + if( pu.interDir == 2 ) + { + mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv.setZero(); + mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = NOT_VALID; + } + } + pu.reduceTplSize = false; + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, applyBDMVR4TM, NULL, NULL, mrgCtx.numValidMergeCand); + pu.mergeIdx = tmpPuMrgIdx; + } + else +#endif #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, #if TM_MRG @@ -2045,10 +2306,96 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) pu.cs->sps->getMaxNumMergeCand()); #else m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx); +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) + { + mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; + } #endif } #else PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumMergeCand()) || (pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : pu.mergeIdx); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2); + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); + tmMergeRefinedMotion &= tplAvail; + if (pu.tmMergeFlag && tmMergeRefinedMotion) + { + int tmpPuMrgIdx = pu.mergeIdx; + pu.reduceTplSize = true; + if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) + { + mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); + } + + if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) + { + mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; + } + + for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) + { + mrgCtx.BcwIdx[ui] = BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[ui] = false; +#endif + mrgCtx.interDirNeighbours[ui] = 0; + mrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; + mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; + mrgCtx.useAltHpelIf[ui] = false; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[ui].clear(); +#endif + mrgCtx.candCost[ui] = MAX_UINT64; + } + + Distortion tempCost[1]; + for( uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++ ) + { + mrgCtx.setMergeInfo( pu, uiMergeCand ); +#if MULTI_PASS_DMVR + applyBDMVR4TM[uiMergeCand] = PU::checkBDMVRCondition(pu); + if (applyBDMVR4TM[uiMergeCand]) + { + m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1]); + pu.bdmvrRefine = true; + applyBDMVR4TM[uiMergeCand] = m_pcInterPred->processBDMVR( pu, 1, tempCost ); + } + else + { + m_pcInterPred->deriveTMMv(pu, tempCost); + } +#else + m_pcInterPred->deriveTMMv( pu ); +#endif + + mrgCtx.candCost[uiMergeCand] = tempCost[0]; + mrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir; + mrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx; + mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv = pu.mv[0]; + mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = pu.refIdx[0]; + mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv = pu.mv[1]; + mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = pu.refIdx[1]; + if( pu.interDir == 1 ) + { + mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv.setZero(); + mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = NOT_VALID; + } + if( pu.interDir == 2 ) + { + mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv.setZero(); + mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = NOT_VALID; + } + } + pu.reduceTplSize = false; + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, applyBDMVR4TM, NULL, NULL, mrgCtx.numValidMergeCand); + pu.mergeIdx = tmpPuMrgIdx; + } + else +#endif m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, pu.mergeIdx); #endif } @@ -2060,6 +2407,25 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.mergeIdx); #endif mrgCtx.setMergeInfo( pu, pu.mergeIdx ); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.tmMergeFlag && tmMergeRefinedMotion) + { + pu.bdmvrRefine = applyBDMVR4TM[pu.mergeIdx]; + if (pu.bdmvrRefine) + { + m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); + pu.bdmvrRefine = m_pcInterPred->processBDMVR( pu ); + } + else + { + m_pcInterPred->deriveTMMv(pu); + } + } + if (pu.bmMergeFlag) + { + pu.bdmvrRefine = true; + } +#endif #if (TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)) && !MULTI_PASS_DMVR if (pu.tmMergeFlag) { @@ -2074,7 +2440,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) } #endif #if MULTI_PASS_DMVR +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (PU::checkBDMVRCondition(pu) && (!pu.tmMergeFlag || (pu.tmMergeFlag && !tmMergeRefinedMotion)) && (!pu.bmMergeFlag || (pu.bmMergeFlag && !admvrRefinedMotion))) +#else if (PU::checkBDMVRCondition(pu)) +#endif { m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); pu.bdmvrRefine = true; @@ -2110,7 +2480,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) else { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.tmMergeFlag && !tmMergeRefinedMotion) +#else if (pu.tmMergeFlag) +#endif { m_pcInterPred->deriveTMMv(pu); #if JVET_Z0084_IBC_TM && IBC_TM_MRG diff --git a/source/Lib/DecoderLib/DecCu.h b/source/Lib/DecoderLib/DecCu.h index dfc76bab69e33bbe7df7f7935f13ee268d11ceec..25ddddfe96f2fa0cc076ef405fc35576efa47642 100644 --- a/source/Lib/DecoderLib/DecCu.h +++ b/source/Lib/DecoderLib/DecCu.h @@ -100,9 +100,16 @@ private: PelStorage m_ciipBuffer; MotionInfo m_SubPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool applyBDMVR4BM[BM_MRG_MAX_NUM_INIT_CANDS]; +#endif #if MULTI_PASS_DMVR +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + Mv m_mvBufBDMVR[MRG_MAX_NUM_CANDS << 1][MAX_NUM_SUBCU_DMVR]; +#else Mv m_mvBufBDMVR[2][MAX_NUM_SUBCU_DMVR]; #endif +#endif #if JVET_X0083_BM_AMVP_MERGE_MODE MvField m_mvFieldAmListDec[MAX_NUM_AMVP_CANDS_MAX_REF << 1]; #endif diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 708ae2b0607d589c38d9b1712943b3fe19b28c10..b56096083646c2265d658a8039ab02eb89968969 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2193,6 +2193,48 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) #if JVET_W0090_ARMC_TM READ_FLAG( uiCode, "sps_aml_enabled_flag"); pcSPS->setUseAML ( uiCode != 0 ); #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pcSPS->getUseAML()) + { + READ_FLAG( uiCode, "sps_ArmcRefinedMotion_enabled_flag"); pcSPS->setUseArmcRefinedMotion ( uiCode != 0 ); + } +#endif +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (pcSPS->getUseAML()) + { + READ_UVLC(uiCode, "num_Lambda"); + pcSPS->setNumLambda(uiCode); + + READ_CODE(4, uiCode, "MaxBitsLambda"); + pcSPS->setMaxbitsLambdaVal(uiCode); + + for (int i = 0; i < pcSPS->getNumLambda(); i++) + { + int32_t qpOffset = 0; + if (i == 0) + { + READ_SVLC(qpOffset, "QP_Offset"); + pcSPS->setQPOffsets(i, (int)qpOffset); + } + else + { + if (pcSPS->getQPOffsets(i - 1) < 0) + { + READ_SVLC(qpOffset, "QP_Offset"); + pcSPS->setQPOffsets(i, (int)qpOffset + pcSPS->getQPOffsets(i - 1)); + } + else + { + READ_UVLC(uiCode, "QP_Offset"); + pcSPS->setQPOffsets(i, (int)uiCode + pcSPS->getQPOffsets(i - 1)); + } + } + + READ_CODE(pcSPS->getMaxbitsLambdaVal(), uiCode, "Lambda"); + pcSPS->setLambdaVal(i, uiCode); + } + } +#endif #if JVET_Z0054_BLK_REF_PIC_REORDER READ_FLAG( uiCode, "sps_arl_enabled_flag"); pcSPS->setUseARL ( uiCode != 0 ); #endif @@ -4899,6 +4941,23 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, Par pcSlice->setDefaultClpRng( *sps ); } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (!pcSlice->isIntra() && sps->getUseAML()) + { + int index = sps->getQPOffsetsIdx(pcSlice->getSliceQp() - (pps->getPicInitQPMinus26() + 26)); + bool lambdaCanBePredicted = false; + if (index != -1) + { + lambdaCanBePredicted = true; + pcSlice->setCostForARMC(sps->getLambdaVal((int) index)); + } + if (!lambdaCanBePredicted) + { + READ_CODE(9, uiCode, "lambda"); + pcSlice->setCostForARMC((uint32_t)uiCode); + } + } +#endif #if MULTI_HYP_PRED if (sps->getUseInterMultiHyp() && pcSlice->isInterB()) diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index 431aeb02ec198406c54976929fec121fc055fa60..885fd265e41eccdc23ecf507999105491bb4095a 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -2922,17 +2922,35 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu) // Base affine merge candidate idx uint8_t afMmvdBaseIdx = pu.afMmvdBaseIdx; - int numCandminus1_base = AF_MMVD_BASE_NUM - 1; - if (numCandminus1_base > 0) + int numCandMinus1Base = AF_MMVD_BASE_NUM - 1; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + unsigned ctxId = 0; + const CodingStructure *cs = pu.cu->cs; + const CodingUnit *cuLeft = cs->getCURestricted( pu.cu->lumaPos().offset( -1, 0 ), *pu.cu, CH_L ); + ctxId = (cuLeft && cuLeft->affine) ? 1 : 0; + const CodingUnit *cuAbove = cs->getCURestricted( pu.cu->lumaPos().offset( 0, -1 ), *pu.cu, CH_L ); + ctxId += (cuAbove && cuAbove->affine) ? 1 : 0; + numCandMinus1Base = (ctxId == 0) ? 0 : ((ctxId == 1) ? 1 : AF_MMVD_BASE_NUM-1); +#endif + if (numCandMinus1Base > 0) { // to support more base candidates +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int ctx2 = (numCandMinus1Base == 1) ? 1 : 0; + m_BinEncoder.encodeBin((afMmvdBaseIdx == 0 ? 0 : 1), Ctx::AfMmvdIdx(ctx2)); +#else m_BinEncoder.encodeBin((afMmvdBaseIdx == 0 ? 0 : 1), Ctx::AfMmvdIdx()); - +#endif + if (afMmvdBaseIdx > 0) { - for (unsigned idx = 1; idx < numCandminus1_base; idx++) + for (unsigned idx = 1; idx < numCandMinus1Base; idx++) { +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + m_BinEncoder.encodeBin(afMmvdBaseIdx == idx ? 0 : 1, Ctx::AfMmvdIdx(idx + 1)); +#else m_BinEncoder.encodeBinEP(afMmvdBaseIdx == idx ? 0 : 1); +#endif if (afMmvdBaseIdx == idx) { break; @@ -2943,15 +2961,30 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu) DTRACE(g_trace_ctx, D_SYNTAX, "afMmvd_base_idx() afMmvd_base_idx=%d\n", afMmvdBaseIdx); #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t sym = pu.afMmvdMergeIdx; +#else uint8_t sym = pu.afMmvdMergeIdx; +#endif +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + sym -= afMmvdBaseIdx * AF_MMVD_MAX_REFINE_NUM; +#endif unsigned int ricePar = 1; - int numCandminus1_step = ((AF_MMVD_MAX_REFINE_NUM >> ricePar) >> AFFINE_MMVD_SIZE_SHIFT) - 1; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int numStepCandMinus1 = ((AF_MMVD_MAX_REFINE_NUM >> ricePar) >> AFFINE_MMVD_SIZE_SHIFT) / AFFINE_BI_DIR - 1; +#else + int numStepCandMinus1 = ((AF_MMVD_MAX_REFINE_NUM >> ricePar) >> AFFINE_MMVD_SIZE_SHIFT) - 1; +#endif if(ricePar > 0) { +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + m_BinEncoder.encodeBin( sym % (1 << ricePar), Ctx::AfMmvdOffsetStep(5)); +#else m_BinEncoder.encodeBinsEP( sym % (1 << ricePar), ricePar); +#endif } sym >>= ricePar; - for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numCandminus1_step; ++uiUnaryIdx) + for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx) { unsigned int uiSymbol = sym == uiUnaryIdx ? 0 : 1; m_BinEncoder.encodeBin(uiSymbol, Ctx::AfMmvdOffsetStep((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx))); @@ -2964,14 +2997,14 @@ void CABACWriter::affine_mmvd_data(const PredictionUnit& pu) { // Code Step Value uint8_t step = pu.afMmvdStep; - int numCandminus1_base = AF_MMVD_STEP_NUM - 1; - if (numCandminus1_base > 0) + int numCandMinus1Base = AF_MMVD_STEP_NUM - 1; + if (numCandMinus1Base > 0) { m_BinEncoder.encodeBin((step == 0 ? 0 : 1), Ctx::AfMmvdOffsetStep()); if (step > 0) { - for (unsigned idx = 1; idx < numCandminus1_base; idx++) + for (unsigned idx = 1; idx < numCandMinus1Base; idx++) { m_BinEncoder.encodeBinEP(step == idx ? 0 : 1); if (step == idx) @@ -3123,7 +3156,12 @@ void CABACWriter::merge_data(const PredictionUnit& pu) #endif ) { +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + unsigned ctxId = pu.cu->skip ? 0 : 1; + m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(ctxId)); +#else m_BinEncoder.encodeBin(pu.mmvdMergeFlag, Ctx::MmvdFlag(0)); +#endif DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_flag() mmvd_merge=%d pos=(%d,%d) size=%dx%d\n", pu.mmvdMergeFlag ? 1 : 0, pu.lumaPos().x, pu.lumaPos().y, pu.lumaSize().width, pu.lumaSize().height); } if (pu.mmvdMergeFlag || pu.cu->mmvdSkip) @@ -3414,7 +3452,11 @@ void CABACWriter::merge_idx( const PredictionUnit& pu ) } int numCandminus1; #if JVET_X0049_ADAPT_DMVR +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint16_t mergeIdx = pu.mergeIdx; +#else uint8_t mergeIdx = pu.mergeIdx; +#endif #endif if (pu.cu->predMode == MODE_IBC) numCandminus1 = int(pu.cs->sps->getMaxNumIBCMergeCand()) - 1; @@ -3524,21 +3566,45 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu) int var0; var0 = mvpIdx / MMVD_MAX_REFINE_NUM; mvpIdx -= var0 * MMVD_MAX_REFINE_NUM; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int numCandMinus1Base = std::min<int>(MMVD_BASE_MV_NUM, pu.cs->sps->getMaxNumMergeCand()) - 1; + if (numCandMinus1Base > 0) + { + // to support more base candidates + m_BinEncoder.encodeBin((var0 == 0 ? 0 : 1), Ctx::MmvdMergeIdx(0)); + if (var0 > 0) + { + for (unsigned idx = 1; idx < numCandMinus1Base; idx++) + { + m_BinEncoder.encodeBin((var0 == idx ? 0 : 1), Ctx::MmvdMergeIdx(idx)); + if (var0 == idx) + { + break; + } + } + } + } +#else if (pu.cs->sps->getMaxNumMergeCand() > 1) { static_assert(MMVD_BASE_MV_NUM == 2, ""); assert(var0 < 2); m_BinEncoder.encodeBin(var0, Ctx::MmvdMergeIdx()); } +#endif DTRACE(g_trace_ctx, D_SYNTAX, "mmvd_merge_idx() base_mvp_idx=%d\n", var0); unsigned int ricePar = 1; - int numCandminus1_step = ((MMVD_MAX_REFINE_NUM >> ricePar) >> MMVD_SIZE_SHIFT) - 1; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + int numStepCandMinus1 = ((MMVD_MAX_REFINE_NUM >> ricePar) >> MMVD_SIZE_SHIFT)/MMVD_BI_DIR - 1; +#else + int numStepCandMinus1 = ((MMVD_MAX_REFINE_NUM >> ricePar) >> MMVD_SIZE_SHIFT) - 1; +#endif if(ricePar > 0) { m_BinEncoder.encodeBinsEP( mvpIdx % (1 << ricePar), ricePar); } mvpIdx >>= ricePar; - for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numCandminus1_step; ++uiUnaryIdx) + for (unsigned int uiUnaryIdx = 0; uiUnaryIdx < numStepCandMinus1; ++uiUnaryIdx) { unsigned int uiSymbol = mvpIdx == uiUnaryIdx ? 0 : 1; m_BinEncoder.encodeBin(uiSymbol, Ctx::MmvdStepMvpIdx((uiUnaryIdx > LAST_MERGE_MMVD_IDX_CABAC - 1 ? LAST_MERGE_MMVD_IDX_CABAC - 1 : uiUnaryIdx))); @@ -3566,8 +3632,8 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu) } DTRACE(g_trace_ctx, D_SYNTAX, "base_mvp_idx() base_mvp_idx=%d\n", var0); - int numCandminus1_step = MMVD_REFINE_STEP - 1; - if (numCandminus1_step > 0) + int numStepCandMinus1 = MMVD_REFINE_STEP - 1; + if (numStepCandMinus1 > 0) { if (var1 == 0) { @@ -3576,7 +3642,7 @@ void CABACWriter::mmvd_merge_idx(const PredictionUnit& pu) else { m_BinEncoder.encodeBin(1, Ctx::MmvdStepMvpIdx()); - for (unsigned idx = 1; idx < numCandminus1_step; idx++) + for (unsigned idx = 1; idx < numStepCandMinus1; idx++) { m_BinEncoder.encodeBinEP(var1 == idx ? 0 : 1); if (var1 == idx) @@ -3668,8 +3734,8 @@ void CABACWriter::geo_mmvd_idx(const PredictionUnit& pu, RefPicList eRefPicList) int mmvdStepToIdx[GPM_EXT_MMVD_REFINE_STEP] = { 5, 0, 1, 2, 3, 4, 6, 7, 8 }; step = mmvdStepToIdx[step]; - int numCandminus1_step = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1; - if (numCandminus1_step > 0) + int numStepCandMinus1 = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1; + if (numStepCandMinus1 > 0) { if (step == 0) { @@ -3678,7 +3744,7 @@ void CABACWriter::geo_mmvd_idx(const PredictionUnit& pu, RefPicList eRefPicList) else { m_BinEncoder.encodeBin(1, Ctx::GeoMmvdStepMvpIdx()); - for (unsigned idx = 1; idx < numCandminus1_step; idx++) + for (unsigned idx = 1; idx < numStepCandMinus1; idx++) { m_BinEncoder.encodeBinEP(step == idx ? 0 : 1); if (step == idx) @@ -3872,8 +3938,8 @@ uint64_t CABACWriter::geo_mmvdIdx_est(const TempCtx& ctxStart, const int geoMMVD int mmvdStepToIdx[GPM_EXT_MMVD_REFINE_STEP] = { 5, 0, 1, 2, 3, 4, 6, 7, 8 }; step = mmvdStepToIdx[step]; - int numCandminus1_step = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1; - if (numCandminus1_step > 0) + int numStepCandMinus1 = (extMMVD ? GPM_EXT_MMVD_REFINE_STEP : GPM_MMVD_REFINE_STEP) - 1; + if (numStepCandMinus1 > 0) { if (step == 0) { @@ -3882,7 +3948,7 @@ uint64_t CABACWriter::geo_mmvdIdx_est(const TempCtx& ctxStart, const int geoMMVD else { m_BinEncoder.encodeBin(1, Ctx::GeoMmvdStepMvpIdx()); - for (unsigned idx = 1; idx < numCandminus1_step; idx++) + for (unsigned idx = 1; idx < numStepCandMinus1; idx++) { m_BinEncoder.encodeBinEP(step == idx ? 0 : 1); if (step == idx) diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 45b660375a0908b266953192712e14ac7ec62bfd..85726c6e3c62609a12fd825e4dfc0ab22a6c514d 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -322,6 +322,11 @@ protected: int m_maxDecPicBuffering[MAX_TLAYER]; int m_numReorderPics[MAX_TLAYER]; int m_drapPeriod; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + bool m_isRA; + int m_numQPOffset; + int m_qpOffsetList[MAX_GOP]; +#endif int m_iQP; // if (AdaptiveQP == OFF) ChromaQpMappingTableParams m_chromaQpMappingTableParams; @@ -412,6 +417,9 @@ protected: #if JVET_W0090_ARMC_TM bool m_AML; #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool m_armcRefinedMotion; +#endif bool m_SMVD; bool m_compositeRefEnabled; //composite reference @@ -1172,6 +1180,10 @@ public: if (m_RPLList1[i].m_POC != -1) m_numRPLList1++; } } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + void setIsRA (bool b) { m_isRA = b; } + void setNumQPOffset (int num) { m_numQPOffset = num; } +#endif const RPLEntry &getRPLEntry(int L01, int idx) const { return (L01 == 0) ? m_RPLList0[idx] : m_RPLList1[idx]; } int getRPLCandidateSize(int L01) const { return (L01 == 0) ? m_numRPLList0 : m_numRPLList1; } void setEncodedFlag(uint32_t i, bool value) { m_RPLList0[i].m_isEncoded = value; m_RPLList1[i].m_isEncoded = value; m_GOPList[i].m_isEncoded = value; } @@ -1329,6 +1341,10 @@ public: void setAML(bool b) { m_AML = b; } bool getAML() const { return m_AML; } #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + void setArmcRefinedMotion(bool b) { m_armcRefinedMotion = b; } + bool getArmcRefinedMotion() const { return m_armcRefinedMotion; } +#endif #if ENABLE_OBMC void setUseOBMC ( bool n ) { m_OBMC = n; } bool getUseOBMC () const { return m_OBMC; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index d0557810bee374097ccdf271ddb5a05c5f3aaee3..8c705f2c8dcaa00ae73807807100b60424029f4a 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -3144,6 +3144,22 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED uint32_t mmvdLUT[MMVD_ADD_NUM]; #endif +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uint8_t numBaseAffine = AF_MMVD_BASE_NUM; + unsigned ctxId = 0; + { + CodingUnit cu( tempCS->area ); + cu.cs = tempCS; + cu.predMode = MODE_INTER; + cu.slice = tempCS->slice; + cu.tileIdx = tempCS->pps->getTileIdx( tempCS->area.lumaPos() ); + const CodingUnit* cuLeft = tempCS->getCURestricted(cu.lumaPos().offset(-1, 0), cu, partitioner.chType); + ctxId = (cuLeft && cuLeft->affine) ? 1 : 0; + const CodingUnit* cuAbove = tempCS->getCURestricted(cu.lumaPos().offset( 0,-1), cu, partitioner.chType); + ctxId += (cuAbove && cuAbove->affine) ? 1 : 0; + } + numBaseAffine = (ctxId == 0) ? 1 : ((ctxId == 1) ? 2 : AF_MMVD_BASE_NUM); +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED uint32_t affMmvdLUT[AF_MMVD_NUM]; #endif @@ -3169,6 +3185,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if JVET_X0049_ADAPT_DMVR MergeCtx bmMrgCtx; bool checkBmMrg = false; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + MergeCtx bmMrgCtxDir2; +#endif #endif if (sps.getSbTMVPEnabledFlag()) @@ -3189,12 +3208,21 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if MULTI_PASS_DMVR bool applyBDMVR[MRG_MAX_NUM_CANDS] = { false }; #if TM_MRG && MERGE_ENC_OPT +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool admvrRefinedMotion = false; + bool applyBDMVR4TM[TM_MRG_MAX_NUM_INIT_CANDS] = { false }; +#else bool applyBDMVR4TM[TM_MRG_MAX_NUM_CANDS] = { false }; #endif +#endif #if JVET_X0049_ADAPT_DMVR +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool applyBDMVR4BM[(BM_MRG_MAX_NUM_INIT_CANDS << 1)<<1] = { false }; +#else bool applyBDMVR4BM[(BM_MRG_MAX_NUM_CANDS << 1)<<1] = { false }; #endif #endif +#endif #if !MULTI_PASS_DMVR Mv refinedMvdL0[MAX_NUM_PARTS_IN_CTU][MRG_MAX_NUM_CANDS]; #endif @@ -3217,12 +3245,23 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) pu.tmMergeFlag = false; #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC && !JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + bool tplAvail = m_pcInterSearch->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); +#endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM int nWidth = pu.lumaSize().width; int nHeight = pu.lumaSize().height; bool tplAvail = m_pcInterSearch->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); MergeCtx tmvpMergeCandCtx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (sps.getUseAML() && tplAvail) + { + PU::getTmvpMergeCand(pu, tmvpMergeCandCtx); + } +#else if (sps.getUseAML()) { PU::getTmvpMergeCand(pu, tmvpMergeCandCtx); @@ -3235,7 +3274,14 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand); } } +#endif MergeCtx namvpMergeCandCtx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (sps.getUseAML() && tplAvail) + { + PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx); + } +#else if (sps.getUseAML()) { PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx); @@ -3249,6 +3295,16 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } #endif +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (!tplAvail) + { + PU::getInterMergeCandidates(pu, mergeCtx, 0, -1); + tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand(); + } + else +#endif +#endif + PU::getInterMergeCandidates(pu, mergeCtx , 0 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM @@ -3269,6 +3325,27 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif } } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (mergeCtx.numValidMergeCand != pu.cs->sps->getMaxNumMergeCand()) + { + mergeCtx.numValidMergeCand = pu.cs->sps->getMaxNumMergeCand(); + } + for (uint32_t ui = mergeCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) + { + mergeCtx.BcwIdx[ui] = BCW_DEFAULT; +#if INTER_LIC + mergeCtx.LICFlags[ui] = false; +#endif + mergeCtx.interDirNeighbours[ui] = 0; + mergeCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; + mergeCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; + mergeCtx.useAltHpelIf[ui] = false; +#if MULTI_HYP_PRED + mergeCtx.addHypNeighbours[ui].clear(); +#endif + mergeCtx.candCost[ui] = MAX_UINT64; + } +#endif PU::getInterMergeCandidates(pu, mergeCtxtmp, 0); #endif @@ -3365,7 +3442,16 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { cu.firstPU = &pu; #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC || JVET_AA0093_REFINED_MOTION_FOR_ARMC + pu.tmMergeFlag = true; +#endif MergeCtx tmvpTmMergeCandCtx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (sps.getUseAML() && tplAvail) + { + PU::getTmvpMergeCand(pu, tmvpTmMergeCandCtx); + } +#else if (sps.getUseAML()) { PU::getTmvpMergeCand(pu, tmvpTmMergeCandCtx); @@ -3378,7 +3464,14 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tmvpTmMergeCandCtx.numValidMergeCand = std::min(1, tmvpTmMergeCandCtx.numValidMergeCand); } } +#endif MergeCtx namvpTmMergeCandCtx; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (sps.getUseAML() && tplAvail) + { + PU::getNonAdjacentMergeCand(pu, namvpTmMergeCandCtx); + } +#else if (sps.getUseAML()) { PU::getNonAdjacentMergeCand(pu, namvpTmMergeCandCtx); @@ -3391,8 +3484,17 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& namvpTmMergeCandCtx.numValidMergeCand = std::min(9, namvpTmMergeCandCtx.numValidMergeCand); } } +#endif #endif pu.tmMergeFlag = true; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + if (!tplAvail) + { + PU::getInterMergeCandidates(pu, tmMrgCtx, 0, -1); + tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); + } + else +#endif PU::getInterMergeCandidates(pu, tmMrgCtx, 0 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM , -1 @@ -3401,6 +3503,10 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif ); #if JVET_W0090_ARMC_TM +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2); + tmMergeRefinedMotion &= tplAvail; +#endif if (sps.getUseAML()) { #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING @@ -3417,9 +3523,41 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); } #else +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (!tmMergeRefinedMotion) +#endif m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtx); #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (tmMrgCtx.numCandToTestEnc > tmMrgCtx.numValidMergeCand) + { + tmMrgCtx.numCandToTestEnc = tmMrgCtx.numValidMergeCand; + } + for (uint32_t ui = tmMrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) + { + tmMrgCtx.BcwIdx[ui] = BCW_DEFAULT; +#if INTER_LIC + tmMrgCtx.LICFlags[ui] = false; +#endif + tmMrgCtx.interDirNeighbours[ui] = 0; + tmMrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; + tmMrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; + tmMrgCtx.useAltHpelIf[ui] = false; +#if MULTI_HYP_PRED + tmMrgCtx.addHypNeighbours[ui].clear(); +#endif + tmMrgCtx.candCost[ui] = MAX_UINT64; + } +#endif + } +#endif + +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (tmMergeRefinedMotion) + { + pu.reduceTplSize = true; } + Distortion tempCost[1]; #endif for( uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtx.numValidMergeCand; uiMergeCand++ ) @@ -3431,16 +3569,30 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { pu.bdmvrRefine = true; m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[(uiMergeCand << 1) + 1]); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (tmMergeRefinedMotion) + { + applyBDMVR4TM[uiMergeCand] = m_pcInterSearch->processBDMVR(pu, 1, tempCost); + } + else +#endif applyBDMVR4TM[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 + tmMrgCtx.candCost[uiMergeCand] = tempCost[0]; +#endif // Store refined motion back to tmMrgCtx tmMrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir; tmMrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx; // Bcw may change, because bi may be reduced to uni by deriveTMMv(pu) @@ -3455,7 +3607,47 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand ].setMvField( Mv(), NOT_VALID ); } } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + pu.reduceTplSize = false; +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (tmMergeRefinedMotion) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmMrgCtx, applyBDMVR4TM, NULL, NULL, pu.cs->sps->getMaxNumTMMergeCand()); + pu.tmMergeFlag = true; + for( uint32_t uiMergeCand = 0; uiMergeCand < tmMrgCtx.numValidMergeCand; uiMergeCand++ ) + { + tmMrgCtx.setMergeInfo( pu, uiMergeCand ); +#if MULTI_PASS_DMVR + applyBDMVR4TM[uiMergeCand] = PU::checkBDMVRCondition(pu); + if (applyBDMVR4TM[uiMergeCand]) + { + pu.bdmvrRefine = true; + m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[(uiMergeCand << 1) + 1]); + applyBDMVR4TM[uiMergeCand] = m_pcInterSearch->processBDMVR(pu); + } + else + { + m_pcInterSearch->deriveTMMv(pu); + } + + tmMrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir; + tmMrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx; // Bcw may change, because bi may be reduced to uni by deriveTMMv(pu) + tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand ].setMvField( pu.mv[0], pu.refIdx[0] ); + tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField( pu.mv[1], pu.refIdx[1] ); + if( pu.interDir == 1 ) + { + tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField( Mv(), NOT_VALID ); + } + if( pu.interDir == 2 ) + { + tmMrgCtx.mvFieldNeighbours[2 * uiMergeCand ].setMvField( Mv(), NOT_VALID ); + } +#endif + } + } +#endif pu.tmMergeFlag = false; #if MULTI_PASS_DMVR pu.bdmvrRefine = false; @@ -3479,7 +3671,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& affineMergeCtxTmp.maxNumMergeCand = slice.getPicHeader()->getMaxNumAffineMergeCand(); #endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + m_pcInterSearch->sortAffineMergeCandidates(pu, affineMergeCtxTmp, affMmvdLUT, (numBaseAffine - 1 ) * AF_MMVD_MAX_REFINE_NUM, true); +#else m_pcInterSearch->sortAffineMergeCandidates(pu, affineMergeCtxTmp, affMmvdLUT); +#endif #endif if (sps.getUseAML()) { @@ -3532,9 +3728,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& checkBmMrg = PU::isBMMergeFlagCoded(pu); if (checkBmMrg) { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + admvrRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 1); + admvrRefinedMotion &= tplAvail; +#endif pu.bmMergeFlag = true; #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM MergeCtx tmvpMergeCandCtx2; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (sps.getUseAML() && tplAvail) + { + PU::getTmvpBMCand(pu, tmvpMergeCandCtx2); + } +#else if (sps.getUseAML()) { PU::getTmvpBMCand(pu, tmvpMergeCandCtx2); @@ -3548,7 +3754,14 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& tmvpMergeCandCtx2.numValidMergeCand = std::min(1, tmvpMergeCandCtx2.numValidMergeCand); } } +#endif MergeCtx namvpMergeCandCtx2; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (sps.getUseAML() && tplAvail) + { + PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx2); + } +#else if (sps.getUseAML()) { PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx2); @@ -3563,6 +3776,21 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } } #endif +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (!tplAvail) + { + PU::getInterBMCandidates(pu, bmMrgCtx +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , -1 + , NULL + , NULL +#endif + ); + } + else +#endif +#endif + PU::getInterBMCandidates(pu, bmMrgCtx #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM , -1 @@ -3579,6 +3807,12 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND m_pcInterSearch->adjustMergeCandidates(pu, bmMrgCtx, pu.cs->sps->getMaxNumBMMergeCand()); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (bmMrgCtx.numCandToTestEnc > bmMrgCtx.numValidMergeCand) + { + bmMrgCtx.numCandToTestEnc = bmMrgCtx.numValidMergeCand; + } +#endif #else m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, bmMrgCtx, pu.cs->sps->getMaxNumBMMergeCand()); #endif @@ -3588,6 +3822,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& bmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand(); } #else +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (!admvrRefinedMotion) +#endif m_pcInterSearch->adjustInterMergeCandidates(pu, bmMrgCtx); #endif } @@ -3596,6 +3833,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { checkBmMrg = false; } +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bmMrgCtxDir2 = bmMrgCtx; +#endif pu.bmMergeFlag = false; pu.bdmvrRefine = false; @@ -4210,6 +4450,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& xCheckSATDCostAffineMmvdMerge(tempCS, cu, pu, affineMergeCtxTmp, mrgCtx, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, RdModeList, candCostList, distParam, ctxStart #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED , affMmvdLUT +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + , numBaseAffine +#endif #endif ); #else @@ -4225,11 +4468,19 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if JVET_X0049_ADAPT_DMVR if (sps.getUseDMVDMode() && checkBmMrg) { +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + xCheckSATDCostBMMerge(tempCS, cu, pu, bmMrgCtx, bmMrgCtxDir2, admvrRefinedMotion, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, RdModeList, candCostList, distParam, ctxStart +#if MULTI_PASS_DMVR + , applyBDMVR4BM +#endif + ); +#else xCheckSATDCostBMMerge(tempCS, cu, pu, bmMrgCtx, acMergeTempBuffer, singleMergeTempBuffer, uiNumMrgSATDCand, RdModeList, candCostList, distParam, ctxStart #if MULTI_PASS_DMVR , applyBDMVR4BM #endif ); +#endif } #endif // Try to limit number of candidates using SATD-costs @@ -4295,7 +4546,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { if (bestIsMMVDSkip) { +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + uiNumMrgSATDCand = mergeCtx.numValidMergeCand + std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM; +#else uiNumMrgSATDCand = mergeCtx.numValidMergeCand + ((mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1); +#endif } else { @@ -4571,7 +4826,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.regularMergeFlag = true; pu.bmMergeFlag = true; pu.bmDir = RdModeList[uiMrgHADIdx].bmDir; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pu.bmDir == 1) + { + bmMrgCtx.setMergeInfo(pu, uiMergeCand); + } + else + { + bmMrgCtxDir2.setMergeInfo(pu, uiMergeCand); + } +#else bmMrgCtx.setMergeInfo(pu, uiMergeCand); +#endif if (applyBDMVR4BM[uiMergeCand]) { isDMVR = true; @@ -8373,11 +8639,19 @@ void EncCu::xCheckSATDCostMmvdMerge(CodingStructure *&tempCS, CodingUnit &cu, Pr && std::min(tempCS->area.lwidth(), tempCS->area.lheight()) >= MULTI_HYP_PRED_RESTRICT_MIN_WH); #endif +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + const int tempNum = (std::min<int>(MMVD_BASE_MV_NUM, mergeCtx.numValidMergeCand) * MMVD_MAX_REFINE_NUM); +#else const int tempNum = (mergeCtx.numValidMergeCand > 1) ? MMVD_ADD_NUM : MMVD_ADD_NUM >> 1; +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED for (int mmvdMergeCandtemp = 0; mmvdMergeCandtemp < tempNum; mmvdMergeCandtemp++) { +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if(mmvdMergeCandtemp - (mmvdMergeCandtemp/MMVD_MAX_REFINE_NUM )* MMVD_MAX_REFINE_NUM >= ((MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT )/MMVD_BI_DIR)) +#else if(mmvdMergeCandtemp - (mmvdMergeCandtemp/MMVD_MAX_REFINE_NUM )* MMVD_MAX_REFINE_NUM >= (MMVD_MAX_REFINE_NUM >> MMVD_SIZE_SHIFT )) +#endif { continue; } @@ -8656,6 +8930,9 @@ void EncCu::xCheckSATDCostAffineMmvdMerge( CodingStructure*& tempCS, const TempCtx& ctxStart #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED , uint32_t * affMmvdLUT +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + , uint8_t numBaseAffine +#endif #endif ) { @@ -8681,6 +8958,9 @@ void EncCu::xCheckSATDCostAffineMmvdMerge( CodingStructure*& tempCS, int baseIdxToMergeIdxOffset = (int)PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtx, 0); int baseCount = std::min<int>((int)AF_MMVD_BASE_NUM, affineMergeCtx.numValidMergeCand - baseIdxToMergeIdxOffset); +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + baseCount = std::min<int>(baseCount, numBaseAffine); +#endif int afMmvdCandCount = baseCount * AF_MMVD_MAX_REFINE_NUM; if (baseCount < 1) { @@ -8698,7 +8978,11 @@ void EncCu::xCheckSATDCostAffineMmvdMerge( CodingStructure*& tempCS, for (uint32_t uiMergeCandTemp = 0; uiMergeCandTemp < afMmvdCandCount; uiMergeCandTemp++) { uint32_t uiMergeCand = affMmvdLUT[uiMergeCandTemp]; +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + if(uiMergeCandTemp - (uiMergeCandTemp/AF_MMVD_MAX_REFINE_NUM )* AF_MMVD_MAX_REFINE_NUM >= ((AF_MMVD_MAX_REFINE_NUM >> AFFINE_MMVD_SIZE_SHIFT ) / AFFINE_BI_DIR)) +#else if(uiMergeCandTemp - (uiMergeCandTemp/AF_MMVD_MAX_REFINE_NUM )* AF_MMVD_MAX_REFINE_NUM >= (AF_MMVD_MAX_REFINE_NUM >> AFFINE_MMVD_SIZE_SHIFT)) +#endif { continue; } @@ -8719,7 +9003,11 @@ void EncCu::xCheckSATDCostAffineMmvdMerge( CodingStructure*& tempCS, pu.afMmvdStep = (uint8_t)stepIdx; pu.mergeIdx = (uint8_t)(baseIdx + baseIdxToMergeIdxOffset); #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + pu.afMmvdMergeIdx = (uint16_t)uiMergeCandTemp; +#else pu.afMmvdMergeIdx = (uint8_t)uiMergeCandTemp; +#endif #endif pu.mergeType = affineMergeCtx.mergeType [pu.mergeIdx]; pu.interDir = affineMergeCtx.interDirNeighbours[pu.mergeIdx]; @@ -12319,6 +12607,10 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS, CodingUnit& cu, PredictionUnit& pu, MergeCtx& mrgCtx, +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + MergeCtx& mrgCtxDir2, + bool armcRefinedMotion, +#endif PelUnitBuf* acMergeTempBuffer[MMVD_MRG_MAX_RD_NUM], PelUnitBuf*& singleMergeTempBuffer, unsigned& uiNumMrgSATDCand, @@ -12356,12 +12648,108 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS, const double sqrtLambdaForFirstPassIntra = m_pcRdCost->getMotionLambda() * FRAC_BITS_SCALE; int insertPos = -1; #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + uint32_t maxNumCand = armcRefinedMotion ? mrgCtx.numValidMergeCand : ((pu.cs->sps->getUseAML()) ? min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc) : mrgCtx.numCandToTestEnc); +#else const uint32_t maxNumCand = (pu.cs->sps->getUseAML()) ? min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc) : mrgCtx.numCandToTestEnc; +#endif +#else +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + uint32_t maxNumCand = armcRefinedMotion ? mrgCtx.numValidMergeCand : ((pu.cs->sps->getUseAML()) ? min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc) : mrgCtx.numCandToTestEnc); +#else +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + uint32_t maxNumCand = armcRefinedMotion ? mrgCtx.numValidMergeCand : mrgCtx.numCandToTestEnc; #else const uint32_t maxNumCand = mrgCtx.numCandToTestEnc; +#endif +#endif #endif bool subPuRefine[2] = { false, false }; Mv finalMvDir[2]; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool hasAtLeastOne2nd = false; + bool subRefineList[BM_MRG_MAX_NUM_INIT_CANDS << 2][2] = {{false, false}, }; + bool subRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS << 2][2] = {{false, false}, }; + if (armcRefinedMotion) + { + for (uint32_t candIdx = 0; candIdx < maxNumCand; candIdx++) + { + pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0; + pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx]; + pu.mv[REF_PIC_LIST_0] = mrgCtx.mvFieldNeighbours[(candIdx << 1)].mv; + pu.mv[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv; + pu.refIdx[REF_PIC_LIST_0] = mrgCtx.mvFieldNeighbours[(candIdx << 1)].refIdx; + pu.refIdx[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx; + bool test2nd = m_pcInterSearch->processBDMVRPU2Dir(pu, subPuRefine, finalMvDir); + hasAtLeastOne2nd |= test2nd; + for (pu.bmDir = 1; pu.bmDir <= (test2nd ? 2 : 1); pu.bmDir++) + { + uint8_t curDir = pu.bmDir - 1; + uint8_t refDir = 1 - curDir; + uint32_t uiMergeCand = candIdx; + if (pu.bmDir == 2) + { + uiMergeCand = candIdx + BM_MRG_MAX_NUM_INIT_CANDS; + } + applyBDMVR[uiMergeCand] = true; + pu.mergeIdx = uiMergeCand; + pu.mv[curDir] = finalMvDir[curDir]; + if (pu.bmDir == 1) + { + pu.mv[refDir] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + refDir].mv; + } + else + { + pu.mv[refDir] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1) + refDir].mv; + } + if (pu.bmDir == 1) + { + mrgCtx.mvFieldNeighbours[2 * candIdx ].setMvField( pu.mv[0], pu.refIdx[0] ); + mrgCtx.mvFieldNeighbours[2 * candIdx + 1].setMvField( pu.mv[1], pu.refIdx[1] ); + } + else + { + mrgCtxDir2.mvFieldNeighbours[2 * candIdx ].setMvField( pu.mv[0], pu.refIdx[0] ); + mrgCtxDir2.mvFieldNeighbours[2 * candIdx + 1].setMvField( pu.mv[1], pu.refIdx[1] ); + } + subRefineList[uiMergeCand][curDir] = subPuRefine[curDir]; + subRefineListTmp[uiMergeCand][curDir] = subRefineList[uiMergeCand][curDir]; + } + if (!test2nd) + { + uint32_t uiMergeCand = candIdx + BM_MRG_MAX_NUM_INIT_CANDS; + applyBDMVR[uiMergeCand] = false; + pu.mv[0] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1)].mv; + pu.mv[1] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1) + 1].mv; + subRefineList[uiMergeCand][1] = subPuRefine[1]; + subRefineListTmp[uiMergeCand][1] = subRefineList[uiMergeCand][1]; + } + } + pu.bmDir = 0; + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, NULL, NULL, NULL, mrgCtx.numValidMergeCand, subRefineList, subRefineListTmp); + if (hasAtLeastOne2nd) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtxDir2, applyBDMVR + BM_MRG_MAX_NUM_INIT_CANDS, NULL, NULL, mrgCtxDir2.numValidMergeCand, &subRefineList[BM_MRG_MAX_NUM_INIT_CANDS], &subRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS]); + for (uint32_t candIdx = BM_MRG_MAX_NUM_CANDS; candIdx < 2*BM_MRG_MAX_NUM_CANDS; candIdx++) + { + subRefineList[candIdx][1] = subRefineList[candIdx - BM_MRG_MAX_NUM_CANDS + BM_MRG_MAX_NUM_INIT_CANDS][1]; + } + } + for (uint32_t candIdx = BM_MRG_MAX_NUM_CANDS; candIdx < 2*BM_MRG_MAX_NUM_CANDS; candIdx++) + { + applyBDMVR[candIdx] = applyBDMVR[candIdx - BM_MRG_MAX_NUM_CANDS + BM_MRG_MAX_NUM_INIT_CANDS]; + } + if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumBMMergeCand()) + { + mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand(); + } + if (mrgCtxDir2.numValidMergeCand > pu.cs->sps->getMaxNumBMMergeCand()) + { + mrgCtxDir2.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand(); + } + maxNumCand = ::min(mrgCtx.numValidMergeCand, (int)pu.cs->sps->getMaxNumBMMergeCand()); + } +#endif for (uint32_t candIdx = 0; candIdx < maxNumCand; candIdx++) { pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0; @@ -12370,7 +12758,11 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS, pu.mv[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv; pu.refIdx[REF_PIC_LIST_0] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 0].refIdx; pu.refIdx[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + bool test2nd = armcRefinedMotion ? applyBDMVR[candIdx + BM_MRG_MAX_NUM_CANDS] : m_pcInterSearch->processBDMVRPU2Dir(pu, subPuRefine, finalMvDir); +#else bool test2nd = m_pcInterSearch->processBDMVRPU2Dir(pu, subPuRefine, finalMvDir); +#endif for (pu.bmDir = 1; pu.bmDir <= (test2nd ? 2 : 1); pu.bmDir++) { uint8_t curDir = pu.bmDir - 1; @@ -12382,13 +12774,52 @@ void EncCu::xCheckSATDCostBMMerge(CodingStructure*& tempCS, } pu.mergeIdx = uiMergeCand; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (armcRefinedMotion) + { + if (pu.bmDir == 1) + { + pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0; + pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx]; + pu.mv[0] = mrgCtx.mvFieldNeighbours[(candIdx << 1)].mv; + pu.mv[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv; + pu.refIdx[REF_PIC_LIST_0] = mrgCtx.mvFieldNeighbours[(candIdx << 1)].refIdx; + pu.refIdx[REF_PIC_LIST_1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx; + } + else + { + pu.cu->imv = mrgCtxDir2.useAltHpelIf[candIdx] ? IMV_HPEL : 0; + pu.cu->BcwIdx = mrgCtxDir2.BcwIdx[candIdx]; + pu.mv[0] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1)].mv; + pu.mv[1] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1) + 1].mv; + pu.refIdx[REF_PIC_LIST_0] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1)].refIdx; + pu.refIdx[REF_PIC_LIST_1] = mrgCtxDir2.mvFieldNeighbours[(candIdx << 1) + 1].refIdx; + } + } + else + { +#endif pu.mv[curDir] = finalMvDir[curDir]; pu.mv[refDir] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + refDir].mv; applyBDMVR[uiMergeCand] = true; +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + } +#endif pu.bdmvrRefine = true; m_pcInterSearch->setBdmvrSubPuMvBuf(m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1]); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (armcRefinedMotion) + { + m_pcInterSearch->processBDMVRSubPU(pu, subRefineList[uiMergeCand][curDir]); + } + else + { +#endif m_pcInterSearch->processBDMVRSubPU(pu, subPuRefine[curDir]); +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + } +#endif m_pcInterSearch->motionCompensation(pu, *singleMergeTempBuffer); #if MULTI_PASS_DMVR diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index cf62ce5eacb265e5a0bab4ec7588f130c02776a3..8274b2870df27fb0ca42b15c4e169045753e1bd7 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -331,15 +331,24 @@ private: #if MULTI_PASS_DMVR Mv m_mvBufBDMVR[(MRG_MAX_NUM_CANDS << 1)][MAX_NUM_SUBCU_DMVR]; #if TM_MRG +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + Mv m_mvBufBDMVR4TM[(TM_MRG_MAX_NUM_INIT_CANDS << 1)][MAX_NUM_SUBCU_DMVR]; +#else Mv m_mvBufBDMVR4TM[(TM_MRG_MAX_NUM_CANDS << 1)][MAX_NUM_SUBCU_DMVR]; +#endif #endif Mv m_mvBufEncBDOF[MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM]; Mv m_mvBufEncBDOF4TM[MRG_MAX_NUM_CANDS][BDOF_SUBPU_MAX_NUM]; #if JVET_X0049_ADAPT_DMVR +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + Mv m_mvBufBDMVR4BM[(BM_MRG_MAX_NUM_INIT_CANDS << 1)<<1][MAX_NUM_SUBCU_DMVR]; + Mv m_mvBufEncBDOF4BM[BM_MRG_MAX_NUM_INIT_CANDS<<1][BDOF_SUBPU_MAX_NUM]; +#else Mv m_mvBufBDMVR4BM[(BM_MRG_MAX_NUM_CANDS << 1)<<1][MAX_NUM_SUBCU_DMVR]; Mv m_mvBufEncBDOF4BM[BM_MRG_MAX_NUM_CANDS<<1][BDOF_SUBPU_MAX_NUM]; #endif #endif +#endif #if JVET_X0083_BM_AMVP_MERGE_MODE Mv m_mvBufEncAmBDMVR[2][MAX_NUM_SUBCU_DMVR]; MvField m_mvFieldAmListEnc[MAX_NUM_AMVP_CANDS_MAX_REF << 1]; @@ -448,6 +457,15 @@ protected: #endif ); #if JVET_X0049_ADAPT_DMVR +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + void xCheckSATDCostBMMerge + ( CodingStructure *&tempCS, CodingUnit &cu, PredictionUnit &pu, MergeCtx& mrgCtx, MergeCtx& mrgCtxDir2, bool armcRefinedMotion, 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 + ); +#else void xCheckSATDCostBMMerge ( 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 @@ -455,6 +473,7 @@ protected: , bool* applyBDMVR #endif ); +#endif #endif 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] @@ -480,6 +499,9 @@ protected: , 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_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED , uint32_t * affMmvdLUT +#if JVET_AA0093_ENHANCED_MMVD_EXTENSION + , uint8_t numBaseAffine = AF_MMVD_BASE_NUM +#endif #endif ); #endif diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index eb85f040fe723530ccd35cb74446132ec8a0183e..a30e7923647fd8c474dfcddc94e599939587698d 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -2580,6 +2580,53 @@ void EncGOP::compressGOP(int iPOCLast, int iNumPicRcvd, PicList &rcListPic, std: { pcSlice->setCheckLDC(true); } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (!pcSlice->isIntra() && pcSlice->getSPS()->getUseAML()) + { + int index = pcSlice->getSPS()->getQPOffsetsIdx(pcSlice->getSliceQp() - (pcSlice->getPPS()->getPicInitQPMinus26() + 26)); + if (index != -1) + { + const SPS* sps = pcSlice->getSPS(); + pcSlice->setCostForARMC(sps->getLambdaVal(index)); + } + else + { + pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp(), 0), MAX_QP)]); + } + + if (pcSlice->getCheckLDC()) + { + int iCurrPOC = pcSlice->getPOC(); + int iRefIdx = 0; + int mindist = MAX_INT; + for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0); iRefIdx++) + { + if (abs(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() - iCurrPOC) < mindist) + { + mindist = abs(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() - iCurrPOC); + } + } + if (pcSlice->isInterB()) + { + for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1); iRefIdx++) + { + if (abs(pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() - iCurrPOC) < mindist) + { + mindist = abs(pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() - iCurrPOC); + } + } + } + if (mindist != 1 ) + { + pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp() - 4, 0), MAX_QP)]); + } + } + else + { + pcSlice->setCostForARMC((uint32_t) LAMBDA_DEC_SIDE[min(max(pcSlice->getSliceQp() - 4, 0), MAX_QP)]); + } + } +#endif //------------------------------------------------------------- diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 46d0c7ebc4098ff7c07212b15dfa217a1b83d1c7..35376a2d94409f445d531c01e082a5c50e543d87 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -356,6 +356,29 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) xInitPPS(pps0, sps0); // initialize APS xInitRPL(sps0, isFieldCoding); +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (sps0.getUseAML()) + { + sps0.setNumLambda(m_numQPOffset); + int maxBits = 0; + for (int idx = 0; idx < m_numQPOffset; idx++) + { + sps0.setQPOffsets(idx, m_qpOffsetList[idx]); + sps0.setLambdaVal(idx, (uint32_t)LAMBDA_DEC_SIDE[26 + pps0.getPicInitQPMinus26() + m_qpOffsetList[idx] - 4 * ((int)m_isRA)]); + uint32_t lambda = (uint32_t)LAMBDA_DEC_SIDE[26 + pps0.getPicInitQPMinus26() + m_qpOffsetList[idx] - 4 * ((int)m_isRA)]; + for (int shift = 0; shift < 16; shift++) + if (lambda >> shift == 0) + { + if (shift > maxBits) + { + maxBits = shift; + } + break; + } + } + sps0.setMaxbitsLambdaVal(maxBits); + } +#endif if (m_resChangeInClvsEnabled) { @@ -943,6 +966,13 @@ bool EncLib::encode( const InputColourSpaceConversion snrCSC, std::list<PelUnitB return false; } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC +void EncLib::setQPOffsetList(const int QPOffset[MAX_GOP]) +{ + std::memcpy(m_qpOffsetList, QPOffset,(MAX_GOP) * sizeof(int)); +} +#endif + /**------------------------------------------------ Separate interlaced frame into two fields -------------------------------------------------**/ @@ -1504,6 +1534,9 @@ void EncLib::xInitSPS( SPS& sps ) sps.setBDOFEnabledFlag ( m_BIO ); #if JVET_W0090_ARMC_TM sps.setUseAML ( m_AML ); +#endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + sps.setUseArmcRefinedMotion ( m_armcRefinedMotion ); #endif sps.setMaxNumMergeCand(getMaxNumMergeCand()); #if JVET_X0049_ADAPT_DMVR diff --git a/source/Lib/EncoderLib/EncLib.h b/source/Lib/EncoderLib/EncLib.h index a5b40bcb180559602e7455ff17b8eaa31c8d33f9..f02f94a83936c8e7a92c7e9e12ad39ccb71f6f4f 100644 --- a/source/Lib/EncoderLib/EncLib.h +++ b/source/Lib/EncoderLib/EncLib.h @@ -320,6 +320,10 @@ public: #if DUMP_BEFORE_INLOOP std::string m_reconFileName; #endif + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + void setQPOffsetList(const int QPOffset[MAX_GOP]); +#endif }; //! \} diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 6cf009d29f4e0bd2a1972c53b9401ed99d4c4c71..fbc566e219d988dea2b87b5f0501a5ff0bba978c 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1334,6 +1334,41 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) #if JVET_W0090_ARMC_TM WRITE_FLAG( pcSPS->getUseAML() ? 1 : 0, "sps_aml_enabled_flag" ); #endif +#if JVET_AA0093_REFINED_MOTION_FOR_ARMC + if (pcSPS->getUseAML()) + { + WRITE_FLAG( pcSPS->getUseArmcRefinedMotion() ? 1 : 0, "sps_ArmcRefinedMotion_enabled_flag" ); + } +#endif + +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (pcSPS->getUseAML()) + { + WRITE_UVLC(pcSPS->getNumLambda(), "num_Lambda"); + WRITE_CODE(pcSPS->getMaxbitsLambdaVal(), 4, "MaxBitsLambda"); + + for (int i = 0; i < pcSPS->getNumLambda(); i++) + { + int code = pcSPS->getQPOffsets(i); + if (i == 0) + { + WRITE_SVLC(code, "QP_Offset"); + } + else + { + if (pcSPS->getQPOffsets(i - 1) < 0) + { + WRITE_SVLC((code - pcSPS->getQPOffsets(i - 1)), "QP_Offset"); + } + else + { + WRITE_UVLC((code - pcSPS->getQPOffsets(i - 1)), "QP_Offset"); + } + } + WRITE_CODE(pcSPS->getLambdaVal(i), pcSPS->getMaxbitsLambdaVal(), "Lambda"); + } + } +#endif #if JVET_Z0054_BLK_REF_PIC_REORDER WRITE_FLAG( pcSPS->getUseARL() ? 1 : 0, "sps_arl_enabled_flag" ); #endif @@ -2995,6 +3030,25 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) { WRITE_FLAG(pcSlice->getTSResidualCodingDisabledFlag() ? 1 : 0, "slice_ts_residual_coding_disabled_flag"); } +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if ( !pcSlice->isIntra() && pcSlice->getSPS()->getUseAML()) + { + // Prediction of the Lambda value + int index = pcSlice->getSPS()->getQPOffsetsIdx(pcSlice->getSliceQp() - (pcSlice->getPPS()->getPicInitQPMinus26() + 26)); + bool lambdaCanBePredicted = false; + if (index !=-1) + { + if(pcSlice->getSPS()->getLambdaVal(index) == pcSlice->getCostForARMC()) + { + lambdaCanBePredicted = true; + } + } + if (!lambdaCanBePredicted) + { + WRITE_CODE(pcSlice->getCostForARMC(), 9, "Lambda"); + } + } +#endif #if MULTI_HYP_PRED if (pcSlice->getSPS()->getUseInterMultiHyp() && pcSlice->isInterB())