diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index c3eef79afcc3beb3fe5a7dc1c62f35d1dedd514e..11abbddb5fdf9a6e4cb16c6a893d91fa2af44b9f 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -161,8 +161,15 @@ static const int AMVP_DECIMATION_FACTOR = 1; #else static const int AMVP_DECIMATION_FACTOR = 2; #endif +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +static const int NUM_MERGE_CANDS = 30; ///< for maximum buffer of merging candidates +static const int NUM_TMVP_CANDS = 9; ///< TMVP +#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 +static const int NUM_NON_ADJ_CANDS = 18; ///< Non-Adj +#endif static const int LAST_MERGE_IDX_CABAC = 5; #else static const int MRG_MAX_NUM_CANDS = 6; ///< MERGE @@ -615,6 +622,9 @@ 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 +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) #if JVET_X0141_CIIP_TIMD_TM static const int CIIP_TM_MRG_MAX_NUM_CANDS = 2; ///< maximum number of CIIP TM merge candidates (note: should be at most equal to CIIP_TM_MRG_MAX_NUM_CANDS) @@ -626,6 +636,9 @@ 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 +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 static const int BDMVR_INTME_RANGE = 8; ///< Bilateral matching search range (n represents for -n pel to n pel, inclusive) static const int BDMVR_INTME_STRIDE = (BDMVR_INTME_RANGE << 1) + 1; ///< Bilateral matching search stride @@ -793,6 +806,9 @@ static const auto MULTI_HYP_PRED_SEARCH_RANGE = 16; #if NON_ADJACENT_MRG_CAND || TM_AMVP static const auto NADISTANCE_LEVEL = 4; #endif +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +static const auto TMVP_DISTANCE_LEVEL = 5; +#endif #if MULTI_HYP_PRED static const auto MULTI_HYP_PRED_RESTRICT_BLOCK_SIZE = 64; // disable multi-hyp for all blocks <= this number static const auto MULTI_HYP_PRED_RESTRICT_MIN_WH = 8; diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index b2f3aeb1f8c9cecd4d7540a37f12472e1fce10f1..ea06a25967d0a8753c6050e4e9daa4788506f9d7 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -540,7 +540,7 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) #endif } -#if NON_ADJACENT_MRG_CAND || TM_MRG || MULTI_PASS_DMVR || JVET_W0097_GPM_MMVD_TM +#if NON_ADJACENT_MRG_CAND || TM_MRG || MULTI_PASS_DMVR || JVET_W0097_GPM_MMVD_TM || (JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM) bool MergeCtx::xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh) const { if (mvFieldNeighbours[(mergeCandIndex << 1)].refIdx < 0 && mvFieldNeighbours[(mergeCandIndex << 1) + 1].refIdx < 0) diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 3d837eed127f3d74b78175385c3eeaf851eda809..186967179567229b3ca71310fc172765728ee534 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -546,6 +546,18 @@ public: class MergeCtx { public: +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + MvField mvFieldNeighbours[NUM_MERGE_CANDS << 1]; // double length for mv of both lists + uint8_t BcwIdx[NUM_MERGE_CANDS]; +#if INTER_LIC + bool LICFlags[NUM_MERGE_CANDS]; +#endif + unsigned char interDirNeighbours[NUM_MERGE_CANDS]; +#if MULTI_HYP_PRED + MultiHypVec addHypNeighbours[NUM_MERGE_CANDS]; +#endif + Distortion candCost[NUM_MERGE_CANDS]; +#else MergeCtx() : numValidMergeCand( 0 ), hasMergedCandList( false ) { } ~MergeCtx() {} public: @@ -557,6 +569,7 @@ public: unsigned char interDirNeighbours[ MRG_MAX_NUM_CANDS ]; #if MULTI_HYP_PRED MultiHypVec addHypNeighbours[MRG_MAX_NUM_CANDS]; +#endif #endif int numValidMergeCand; #if JVET_X0049_ADAPT_DMVR @@ -569,9 +582,13 @@ public: MvField mmvdBaseMv[MMVD_BASE_MV_NUM][2]; void setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx); bool mmvdUseAltHpelIf [ MMVD_BASE_MV_NUM ]; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + bool useAltHpelIf [ NUM_MERGE_CANDS ]; +#else bool useAltHpelIf [ MRG_MAX_NUM_CANDS ]; +#endif void setMergeInfo( PredictionUnit& pu, int candIdx ); -#if NON_ADJACENT_MRG_CAND || TM_MRG || MULTI_PASS_DMVR || JVET_W0097_GPM_MMVD_TM +#if NON_ADJACENT_MRG_CAND || TM_MRG || MULTI_PASS_DMVR || JVET_W0097_GPM_MMVD_TM || (JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM) bool xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1) const; #endif #if TM_MRG diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 5e374b9c9d454d19168b8378b2c562f39dc049f1..96a2628ba3254bb5369559f147c5a0e78b2e851e 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -4607,6 +4607,117 @@ void InterPrediction::cacheAssign( CacheModel *cache ) #endif #if JVET_W0090_ARMC_TM +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING +void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& mvpMergeCandCtx, int numRetrievedMergeCand, int mrgCandIdx) +{ + if (mvpMergeCandCtx.numValidMergeCand <= 1) + { + return; + } + + const int numCandInCategory = std::min(numRetrievedMergeCand, mvpMergeCandCtx.numValidMergeCand); + + uint32_t RdCandList[MRG_MAX_NUM_CANDS]; + Distortion candCostList[MRG_MAX_NUM_CANDS]; + + for (uint32_t j = 0; j < MRG_MAX_NUM_CANDS; j++) + { + RdCandList[j] = j; + candCostList[j] = MAX_UINT; + } + + Distortion uiCost; + + DistParam cDistParam; + cDistParam.applyWeight = false; + + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + + auto origMergeIdx = pu.mergeIdx; + for (uint32_t uiMergeCand = 0; uiMergeCand < mvpMergeCandCtx.numValidMergeCand; uiMergeCand++) + { + if (mvpMergeCandCtx.candCost[uiMergeCand] == MAX_UINT64) + { + uiCost = 0; + + mvpMergeCandCtx.setMergeInfo(pu, uiMergeCand); + + 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); + } + } + else + { + uiCost = mvpMergeCandCtx.candCost[uiMergeCand]; + } + + updateCandList(uiMergeCand, uiCost, numCandInCategory, RdCandList, candCostList); + } + pu.mergeIdx = origMergeIdx; + + updateCandInOneCandidateGroup(mvpMergeCandCtx, RdCandList, numCandInCategory); + + mvpMergeCandCtx.numValidMergeCand = numCandInCategory; + + for (int idx = 0; idx < numCandInCategory; idx++) + { + mvpMergeCandCtx.candCost[idx] = candCostList[idx]; + } +} + +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]; diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index d665d211733eac68187d25a00cb1bcda1d536433..5b5b1a5e15d2c47986b57e10da70988530ecdd2b 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -345,6 +345,10 @@ public: void updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtx, uint32_t(*RdCandList)[AFFINE_MRG_MAX_NUM_CANDS], int mrgCandIdx = -1); void xGetSublkAMLTemplate(const CodingUnit& cu, const ComponentID compID, const Picture& refPic, const Mv& mv, const int sublkWidth, const int sublkHeight, const int posW, const int posH, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate); void getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft); +#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); +#endif #endif #if INTER_LIC void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset); diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 3db6d8442d66a444ac4045029392cfc5516d510e..9ec83a13f4a1ad9036f458e91afe57a7b16b7bd3 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -3053,6 +3053,9 @@ private: uint32_t m_colRefIdx; +#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 double m_lambdas[MAX_NUM_COMPONENT]; #if INTER_LIC bool m_UseLIC; @@ -3204,6 +3207,28 @@ public: bool getColFromL0Flag() const { return m_colFromL0Flag; } uint32_t getColRefIdx() const { return m_colRefIdx; } void checkColRefIdx(uint32_t curSliceSegmentIdx, const Picture* pic); +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + void resizeImBuf(int numSlices) + { + for (int refIdx = 0; refIdx < MAX_NUM_REF + 1; refIdx++) + { + m_implicitRefIdx[REF_PIC_LIST_0][REF_PIC_LIST_0][refIdx].resize(numSlices); + std::fill(m_implicitRefIdx[REF_PIC_LIST_0][REF_PIC_LIST_0][refIdx].begin(), m_implicitRefIdx[REF_PIC_LIST_0][REF_PIC_LIST_0][refIdx].end(), -1); + + m_implicitRefIdx[REF_PIC_LIST_0][REF_PIC_LIST_1][refIdx].resize(numSlices); + std::fill(m_implicitRefIdx[REF_PIC_LIST_0][REF_PIC_LIST_1][refIdx].begin(), m_implicitRefIdx[REF_PIC_LIST_0][REF_PIC_LIST_1][refIdx].end(), -1); + + m_implicitRefIdx[REF_PIC_LIST_1][REF_PIC_LIST_0][refIdx].resize(numSlices); + std::fill(m_implicitRefIdx[REF_PIC_LIST_1][REF_PIC_LIST_0][refIdx].begin(), m_implicitRefIdx[REF_PIC_LIST_1][REF_PIC_LIST_0][refIdx].end(), -1); + + m_implicitRefIdx[REF_PIC_LIST_1][REF_PIC_LIST_1][refIdx].resize(numSlices); + std::fill(m_implicitRefIdx[REF_PIC_LIST_1][REF_PIC_LIST_1][refIdx].begin(), m_implicitRefIdx[REF_PIC_LIST_1][REF_PIC_LIST_1][refIdx].end(), -1); + } + } + void setImRefIdx(int sliceIdx, RefPicList colRefPicList, RefPicList curRefPicList, int col_refIdx, int cur_refIdx) { m_implicitRefIdx[colRefPicList][curRefPicList][col_refIdx][sliceIdx] = cur_refIdx; } + int getImRefIdx(int sliceIdx, RefPicList colRefPicList, RefPicList curRefPicList, int col_refIdx) { return m_implicitRefIdx[colRefPicList][curRefPicList][col_refIdx][sliceIdx]; } + int getImRefIdx(int sliceIdx, RefPicList colRefPicList, RefPicList curRefPicList, int col_refIdx) const { return m_implicitRefIdx[colRefPicList][curRefPicList][col_refIdx][sliceIdx]; } +#endif bool getIsUsedAsLongTerm(int i, int j) const { return m_bIsUsedAsLongTerm[i][j]; } void setIsUsedAsLongTerm(int i, int j, bool value) { m_bIsUsedAsLongTerm[i][j] = value; } bool getCheckLDC() const { return m_bCheckLDC; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index b8934415c17900d10fbb71b0033c739a00de5f67..9a57fcdd79328ac498ddb307157fb2feb3127a9e 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -1,4 +1,4 @@ -/* The copyright in this software is being made available under the BSD +/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. @@ -154,6 +154,7 @@ #endif #define JVET_W0097_GPM_MMVD_TM 1 // JVET-W0097: GPM-MMVD and GPM-TM, GPM-TM part is controlled by TM_MRG #define JVET_X0141_CIIP_TIMD_TM 1 // JVET-X0141: CIIP with TIMD and TM merge, CIIP-TM part is controlled by TM_MRG, and CIIP-TIMD part is controlled by JVET_W0123_TIMD_FUSION +#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 // Transform and coefficient coding #define TCQ_8STATES 1 diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 38c1df2b51252273de6aa558ba55f89cf9da34aa..3c4e4031e9467fe7822a00d16cfa15a964c10bf8 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -1599,14 +1599,23 @@ int PU::reorderInterMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, int mmvdList, - const int& mrgCandIdx ) + const int& mrgCandIdx +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , MergeCtx* tmvpMrgCtx + , MergeCtx* namvpMrgCtx +#endif +) { const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; const CodingStructure &cs = *pu.cs; const Slice &slice = *pu.cs->slice; #if TM_MRG const uint32_t mvdSimilarityThresh = pu.tmMergeFlag ? PU::getTMMvdThreshold(pu) : 1; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + const uint32_t maxNumMergeCand = pu.tmMergeFlag ? TM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumMergeCand(); +#else const uint32_t maxNumMergeCand = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand(); +#endif #else const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumMergeCand(); #endif @@ -1622,6 +1631,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.useAltHpelIf[ui] = false; #if MULTI_HYP_PRED mrgCtx.addHypNeighbours[ui].clear(); +#endif +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + mrgCtx.candCost[ui] = MAX_UINT64; #endif } @@ -1990,6 +2002,10 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, if (slice.getPicHeader()->getEnableTMVPFlag() && (pu.lumaSize().width + pu.lumaSize().height > 12)) #endif { +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + if (tmvpMrgCtx == NULL) + { +#endif //>> MTK colocated-RightBottom // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to Position posRB = pu.Y().bottomRight().offset( -3, -3 ); @@ -2019,8 +2035,16 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, int iRefIdx = 0; int dir = 0; unsigned uiArrayAddr = cnt; - bool bExistMV = ( C0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv, iRefIdx, false ) ) - || getColocatedMVP( pu, REF_PIC_LIST_0, posC1, cColMv, iRefIdx, false ); + bool bExistMV = ( C0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv, iRefIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , &iRefIdx +#endif + ) ) + || getColocatedMVP( pu, REF_PIC_LIST_0, posC1, cColMv, iRefIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , &iRefIdx +#endif + ); if (bExistMV) { dir |= 1; @@ -2029,8 +2053,16 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, if (slice.isInterB()) { - bExistMV = ( C0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv, iRefIdx, false ) ) - || getColocatedMVP( pu, REF_PIC_LIST_1, posC1, cColMv, iRefIdx, false ); + bExistMV = ( C0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv, iRefIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , &iRefIdx +#endif + ) ) + || getColocatedMVP( pu, REF_PIC_LIST_1, posC1, cColMv, iRefIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , &iRefIdx +#endif + ); if (bExistMV) { dir |= 2; @@ -2077,6 +2109,45 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #endif } } +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + } + else if (tmvpMrgCtx->numValidMergeCand > 0) + { + 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 + } +#endif } // early termination @@ -2086,6 +2157,10 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, } #if NON_ADJACENT_MRG_CAND +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + if (namvpMrgCtx == NULL) + { +#endif MotionInfo miNeighbor; int offsetX = 0; int offsetY = 0; @@ -2162,6 +2237,48 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, } } +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + } + else + { + for (uint32_t ui = 0; ui < namvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand - 1; ++ui) + { + mrgCtx.BcwIdx[cnt] = namvpMrgCtx->BcwIdx[ui]; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = namvpMrgCtx->LICFlags[ui]; +#endif + mrgCtx.interDirNeighbours[cnt] = namvpMrgCtx->interDirNeighbours[ui]; + mrgCtx.mvFieldNeighbours[cnt << 1] = namvpMrgCtx->mvFieldNeighbours[ui << 1]; + mrgCtx.useAltHpelIf[cnt] = namvpMrgCtx->useAltHpelIf[ui]; + if (slice.isInterB()) + { + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = namvpMrgCtx->mvFieldNeighbours[(ui << 1) + 1]; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = namvpMrgCtx->addHypNeighbours[ui]; +#endif + } + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) + { +#endif + mrgCtx.candCost[cnt] = namvpMrgCtx->candCost[ui]; + if (mrgCandIdx == cnt) + { + return; + } + + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } +#endif #endif int maxNumMergeCandMin1 = maxNumMergeCand - 1; @@ -2492,12 +2609,21 @@ bool PU::addBMMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const i } void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, - const int& mrgCandIdx) + const int& mrgCandIdx +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , MergeCtx* mvpMrgCtx1 + , MergeCtx* mvpMrgCtx2 +#endif +) { const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; const CodingStructure &cs = *pu.cs; const Slice &slice = *pu.cs->slice; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + const uint32_t maxNumMergeCand = BM_MRG_MAX_NUM_INIT_CANDS; +#else const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumBMMergeCand(); +#endif for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.BcwIdx[ui] = BCW_DEFAULT; @@ -2510,6 +2636,9 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.useAltHpelIf[ui] = false; #if MULTI_HYP_PRED mrgCtx.addHypNeighbours[ui].clear(); +#endif +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + mrgCtx.candCost[ui] = MAX_UINT64; #endif } @@ -2751,6 +2880,10 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, if (slice.getPicHeader()->getEnableTMVPFlag() && (pu.lumaSize().width + pu.lumaSize().height > 12)) #endif { +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + if (mvpMrgCtx1 == NULL) + { +#endif //>> MTK colocated-RightBottom // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to Position posRB = pu.Y().bottomRight().offset(-3, -3); @@ -2807,55 +2940,900 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.interDirNeighbours[uiArrayAddr] = dir; mrgCtx.useAltHpelIf[uiArrayAddr] = false; #if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[uiArrayAddr].clear(); + mrgCtx.addHypNeighbours[uiArrayAddr].clear(); +#endif +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) + { +#endif + if (mrgCandIdx == cnt) + { + mrgCtx.numValidMergeCand = cnt + 1; + return; + } + + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + } + else if (mvpMrgCtx1->numValidMergeCand > 0) + { + mrgCtx.interDirNeighbours[cnt] = mvpMrgCtx1->interDirNeighbours[0]; + mrgCtx.mvFieldNeighbours[cnt << 1] = mvpMrgCtx1->mvFieldNeighbours[0]; + mrgCtx.useAltHpelIf[cnt] = mvpMrgCtx1->useAltHpelIf[0]; + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = mvpMrgCtx1->mvFieldNeighbours[1]; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = mvpMrgCtx1->addHypNeighbours[0]; +#endif +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) +#endif + { + mrgCtx.candCost[cnt] = mvpMrgCtx1->candCost[0]; + if (mrgCandIdx == cnt) + { + mrgCtx.numValidMergeCand = cnt + 1; + return; + } + cnt++; + } + } +#endif + } + + // early termination + if (cnt == maxNumMergeCand) + { + mrgCtx.numValidMergeCand = cnt; + return; + } + + int maxNumMergeCandMin1 = maxNumMergeCand - 1; +#if NON_ADJACENT_MRG_CAND +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + if (mvpMrgCtx2 == NULL) + { +#endif + MotionInfo miNeighbor; + int offsetX = 0; + int offsetY = 0; + 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 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCandMin1; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCandMin1; NASPIdx++) + { + switch (idxMap[iDistanceIndex][NASPIdx]) + { + case 0:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height + iNADistanceVer - 1; break; + case 1:offsetX = pu.Y().width + iNADistanceHor - 1; offsetY = -iNADistanceVer - 1; break; + case 2:offsetX = pu.Y().width >> 1; offsetY = -iNADistanceVer - 1; break; + case 3:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height >> 1; break; + case 4:offsetX = -iNADistanceHor - 1; offsetY = -iNADistanceVer - 1; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + + if (isAvailableNonAdjacent) + { + miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + + + if (isBiPredFromDifferentDirEqDistPoc(pu, miNeighbor.refIdx[0], miNeighbor.refIdx[1]) + ) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + // get Mv from Above-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) +#endif + { + if (mrgCandIdx == cnt) + { + mrgCtx.numValidMergeCand = cnt + 1; + return; + } + cnt++; + } + } + } + } + } +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + } + else + { + for (int uiNumCand = 0; uiNumCand < mvpMrgCtx2->numValidMergeCand && cnt < maxNumMergeCandMin1; uiNumCand++) + { + mrgCtx.interDirNeighbours[cnt] = mvpMrgCtx2->interDirNeighbours[uiNumCand]; + mrgCtx.mvFieldNeighbours[cnt << 1] = mvpMrgCtx2->mvFieldNeighbours[uiNumCand << 1]; + mrgCtx.useAltHpelIf[cnt] = mvpMrgCtx2->useAltHpelIf[uiNumCand]; + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = mvpMrgCtx2->mvFieldNeighbours[(uiNumCand << 1) + 1]; +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) +#endif + { + mrgCtx.candCost[cnt] = mvpMrgCtx2->candCost[uiNumCand]; + if (mrgCandIdx == cnt) + { + mrgCtx.numValidMergeCand = cnt + 1; + return; + } + cnt++; + } + } + } +#endif +#endif + + if (cnt != maxNumMergeCandMin1) + { + bool isGt4x4 = true; + bool bFound = addBMMergeHMVPCand(cs, mrgCtx, mrgCandIdx, maxNumMergeCandMin1, cnt + , isAvailableA1, miLeft, isAvailableB1, miAbove + , CU::isIBC(*pu.cu) + , isGt4x4 +#if TM_MRG + , mvThreshod +#endif + ); + + if (bFound) + { + return; + } + } + + { + if (cnt > 1 && cnt < maxNumMergeCand) + { + mrgCtx.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID); + mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID); +#if INTER_LIC + mrgCtx.LICFlags[cnt] = false; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt].clear(); +#endif + mrgCtx.BcwIdx[cnt] = BCW_DEFAULT; + // calculate average MV for L0 and L1 seperately + unsigned char interDir = 0; + mrgCtx.useAltHpelIf[cnt] = (mrgCtx.useAltHpelIf[0] == mrgCtx.useAltHpelIf[1]) ? mrgCtx.useAltHpelIf[0] : false; + for (int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++) + { + const short refIdxI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].refIdx; + const short refIdxJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].refIdx; + + // both MVs are invalid, skip + if (refIdxI != refIdxJ) + { + continue; + } + + interDir += 1 << refListId; + 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; + roundAffineMv(avgMv.hor, avgMv.ver, 1); + + mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI); + } + + mrgCtx.interDirNeighbours[cnt] = interDir; + if (interDir == 3 && isBiPredFromDifferentDirEqDistPoc(pu, mrgCtx.mvFieldNeighbours[cnt * 2 + 0].refIdx, mrgCtx.mvFieldNeighbours[cnt * 2 + 1].refIdx)) + { +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) +#endif + cnt++; + } + } + + // early termination + if (cnt == maxNumMergeCand) + { + mrgCtx.numValidMergeCand = cnt; + return; + } + } + + mrgCtx.numCandToTestEnc = cnt; + + if (cnt < maxNumMergeCand) + { + mrgCtx.interDirNeighbours[cnt] = 3; + mrgCtx.BcwIdx[cnt] = BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = false; +#endif +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt].clear(); +#endif + mrgCtx.useAltHpelIf[cnt] = false; + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(0, 0), 0); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(0, 0), 0); +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) +#endif + { + if (mrgCandIdx == cnt) + { + mrgCtx.numValidMergeCand = cnt + 1; + return; + } + cnt++; + } + } + mrgCtx.numValidMergeCand = cnt; +} +#endif + +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) +{ + const CodingStructure &cs = *pu.cs; + const Slice &slice = *pu.cs->slice; + + const uint32_t mvThreshod = 1; + const uint32_t maxNumMergeCand = NUM_TMVP_CANDS; + for (uint32_t ui = 0; ui < maxNumMergeCand; ++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; + } + + int cnt = 0; + +#if INTER_RM_SIZE_CONSTRAINTS + if (slice.getPicHeader()->getEnableTMVPFlag()) +#else + if (slice.getPicHeader()->getEnableTMVPFlag() && (pu.lumaSize().width + pu.lumaSize().height > 12)) +#endif + { + //>> MTK colocated-RightBottom + // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to + const PreCalcValues& pcv = *cs.pcv; + bool C0Avail; + bool C1Avail; + bool boundaryCond; + const SubPic& curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + Position posRB = pu.Y().bottomRight().offset(-3, -3); + Position posCenter = pu.Y().center(); + Position posC0; + Position posC1; + + int iRefIdx = 0; + bool bExistMV0, bExistMV1; + Mv cColMv0, cColMv1; + int dir; + + int offsetX0 = 0, offsetX1 = 0, offsetX2 = 0, offsetX3 = pu.Y().width >> 1; + int offsetY0 = 0, offsetY1 = 0, offsetY2 = 0, offsetY3 = pu.Y().height >> 1; + + const int iNACANDIDATE_NUM[5] = { 2, 2, 2, 2, 2 }; + const int idxMap[5][2] = { { 0, 1 },{ 0, 2 },{ 0, 2 },{ 0, 2 },{ 0, 2 } }; + for (int iDistanceIndex = 0; iDistanceIndex < TMVP_DISTANCE_LEVEL && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * iDistanceIndex; + const int iNADistanceVer = pu.Y().height * iDistanceIndex; + + for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++) + { + switch (idxMap[iDistanceIndex][NASPIdx]) + { + case 0: offsetX0 = offsetX2 = 4 + iNADistanceHor; offsetY0 = offsetY2 = 4 + iNADistanceVer; offsetX1 = iNADistanceHor; offsetY1 = iNADistanceVer; break; + case 1: offsetX0 = 4; offsetY0 = 0; offsetX1 = 0; offsetY1 = 4; break; + case 2: offsetX0 = offsetX2; offsetY0 = 4 - offsetY3; offsetX1 = 4 - offsetX3; offsetY1 = offsetY2; break; + default: printf("error!"); exit(0); break; + } + C0Avail = false; + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + offsetX0) <= curSubPic.getSubPicRight() && (posRB.y + offsetY0) <= curSubPic.getSubPicBottom()); + } + else + { + boundaryCond = ((posRB.x + offsetX0) < pcv.lumaWidth) && ((posRB.y + offsetY0) < pcv.lumaHeight); + } + if (boundaryCond) + { + int posYInCtu = posRB.y & pcv.maxCUHeightMask; + if (posYInCtu + offsetY0 < pcv.maxCUHeight) + { + posC0 = posRB.offset(offsetX0, offsetY0); + C0Avail = true; + } + } + + if (idxMap[iDistanceIndex][NASPIdx] == 0) + { + C1Avail = false; + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posCenter.x + offsetX1) <= curSubPic.getSubPicRight() && (posCenter.y + offsetY1) <= curSubPic.getSubPicBottom()); + } + else + { + boundaryCond = ((posCenter.x + offsetX1) < pcv.lumaWidth) && ((posCenter.y + offsetY1) < pcv.lumaHeight); + } + if (boundaryCond) + { + int posYInCtu = posCenter.y & pcv.maxCUHeightMask; + if (posYInCtu + offsetY1 < pcv.maxCUHeight) + { + posC1 = posCenter.offset(offsetX1, offsetY1); + C1Avail = true; + } + } + } + else + { + C1Avail = false; + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + offsetX1) <= curSubPic.getSubPicRight() && (posRB.y + offsetY1) <= curSubPic.getSubPicBottom()); + } + else + { + boundaryCond = ((posRB.x + offsetX1) < pcv.lumaWidth) && ((posRB.y + offsetY1) < pcv.lumaHeight); + } + if (boundaryCond) + { + int posYInCtu = posRB.y & pcv.maxCUHeightMask; + if (posYInCtu + offsetY1 < pcv.maxCUHeight) + { + posC1 = posRB.offset(offsetX1, offsetY1); + C1Avail = true; + } + } + } + + bExistMV0 = bExistMV1 = false; + + // Candidate with L0 and L1 + dir = 0; + bExistMV0 = (C0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv0, iRefIdx, false)) + || (C1Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv0, iRefIdx, false)); + if (bExistMV0) + { + dir |= 1; + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(cColMv0, iRefIdx); + } + else + { + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(Mv(), NOT_VALID); + } + if (slice.isInterB()) + { + bExistMV1 = (C0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv1, iRefIdx, false)) + || (C1Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv1, iRefIdx, false)); + if (bExistMV1) + { + dir |= 2; + mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(cColMv1, iRefIdx); + } + else + { + mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(Mv(), NOT_VALID); + } + } + if (dir != 0) + { + bool addTMvp = isBiPredFromDifferentDirEqDistPoc(pu, mrgCtx.mvFieldNeighbours[2 * cnt + 0].refIdx, mrgCtx.mvFieldNeighbours[2 * cnt + 1].refIdx); + if (addTMvp) + { + mrgCtx.interDirNeighbours[cnt] = dir; + mrgCtx.useAltHpelIf[cnt] = false; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt].clear(); +#endif + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod + )) + { + cnt++; + if (cnt == maxNumMergeCand) + { + break; + } + } + } + } + } + } +} + + mrgCtx.numValidMergeCand = cnt; +} +#endif + +#if NON_ADJACENT_MRG_CAND && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) +{ + const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; + const CodingStructure &cs = *pu.cs; + + const uint32_t mvThreshod = getBDMVRMvdThreshold(pu); + + const uint32_t maxNumMergeCand = NUM_NON_ADJ_CANDS; + + for (uint32_t ui = 0; ui < maxNumMergeCand; ++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; + } + + int cnt = 0; + + const Position posLT = pu.Y().topLeft(); + + MotionInfo miNeighbor; + int offsetX = 0; + int offsetY = 0; + int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1; + int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1; + + const int iNACANDIDATE_NUM[7] = { 5, 9, 9, 9, 9, 9, 9 }; + const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++) + { + switch (idxMap[iDistanceIndex][NASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break; + case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX2; offsetY = offsetY1; break; + case 3:offsetX = offsetX0; offsetY = offsetY2; break; + case 4:offsetX = offsetX0; offsetY = offsetY1; break; + case 5:offsetX = -1; offsetY = offsetY0; break; + case 6:offsetX = offsetX1; offsetY = -1; break; + case 7:offsetX = offsetX0 >> 1; offsetY = offsetY0; break; + case 8:offsetX = offsetX1; offsetY = offsetY1 >> 1; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + + if (isAvailableNonAdjacent) + { + miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + + if (isBiPredFromDifferentDirEqDistPoc(pu, miNeighbor.refIdx[0], miNeighbor.refIdx[1]) + ) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); + + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) + { + cnt++; + } + } + } + } + } + + const int iNACANDIDATE_NUM2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM2[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++) + { + switch (idxMap2[iDistanceIndex][NASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; + case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; + case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + + if (isAvailableNonAdjacent) + { + miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + + if (isBiPredFromDifferentDirEqDistPoc(pu, miNeighbor.refIdx[0], miNeighbor.refIdx[1]) + ) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + // get Mv from Above-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); + + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) + { + cnt++; + } + } + } + } + } + + mrgCtx.numValidMergeCand = cnt; +} +#endif + +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) +{ + const CodingStructure &cs = *pu.cs; + const Slice &slice = *pu.cs->slice; + + const uint32_t mvdSimilarityThresh = 1; + const uint32_t maxNumMergeCand = NUM_TMVP_CANDS; + for (uint32_t ui = 0; ui < maxNumMergeCand; ++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; + } + + int cnt = 0; + +#if INTER_RM_SIZE_CONSTRAINTS + if (slice.getPicHeader()->getEnableTMVPFlag()) +#else + if (slice.getPicHeader()->getEnableTMVPFlag() && (pu.lumaSize().width + pu.lumaSize().height > 12)) +#endif + { + //>> MTK colocated-RightBottom + // offset the pos to be sure to "point" to the same position the uiAbsPartIdx would've pointed to + const PreCalcValues& pcv = *cs.pcv; + bool C0Avail; + bool C1Avail; + bool boundaryCond; + const SubPic& curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + Position posRB = pu.Y().bottomRight().offset(-3, -3); + Position posCenter = pu.Y().center(); + Position posC0; + Position posC1; + + int iRefIdx = 0; + bool bExistMV0, bExistMV1; + Mv cColMv0, cColMv1; + int dir; + + int offsetX0 = 0, offsetX1 = 0, offsetX2 = 0, offsetX3 = pu.Y().width >> 1; + int offsetY0 = 0, offsetY1 = 0, offsetY2 = 0, offsetY3 = pu.Y().height >> 1; + + const int iNACANDIDATE_NUM[5] = { 2, 2, 2, 2, 2 }; + const int idxMap[5][2] = { { 0, 1 },{ 0, 2 },{ 0, 2 },{ 0, 2 },{ 0, 2 } }; + for (int iDistanceIndex = 0; iDistanceIndex < TMVP_DISTANCE_LEVEL && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * iDistanceIndex; + const int iNADistanceVer = pu.Y().height * iDistanceIndex; + + for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++) + { + switch (idxMap[iDistanceIndex][NASPIdx]) + { + case 0: offsetX0 = offsetX2 = 4 + iNADistanceHor; offsetY0 = offsetY2 = 4 + iNADistanceVer; offsetX1 = iNADistanceHor; offsetY1 = iNADistanceVer; break; + case 1: offsetX0 = 4; offsetY0 = 0; offsetX1 = 0; offsetY1 = 4; break; + case 2: offsetX0 = offsetX2; offsetY0 = 4 - offsetY3; offsetX1 = 4 - offsetX3; offsetY1 = offsetY2; break; + default: printf("error!"); exit(0); break; + } + C0Avail = false; + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + offsetX0) <= curSubPic.getSubPicRight() && (posRB.y + offsetY0) <= curSubPic.getSubPicBottom()); + } + else + { + boundaryCond = ((posRB.x + offsetX0) < pcv.lumaWidth) && ((posRB.y + offsetY0) < pcv.lumaHeight); + } + if (boundaryCond) + { + int posYInCtu = posRB.y & pcv.maxCUHeightMask; + if (posYInCtu + offsetY0 < pcv.maxCUHeight) + { + posC0 = posRB.offset(offsetX0, offsetY0); + C0Avail = true; + } + } + + if (idxMap[iDistanceIndex][NASPIdx] == 0) + { + C1Avail = false; + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posCenter.x + offsetX1) <= curSubPic.getSubPicRight() && (posCenter.y + offsetY1) <= curSubPic.getSubPicBottom()); + } + else + { + boundaryCond = ((posCenter.x + offsetX1) < pcv.lumaWidth) && ((posCenter.y + offsetY1) < pcv.lumaHeight); + } + if (boundaryCond) + { + int posYInCtu = posCenter.y & pcv.maxCUHeightMask; + if (posYInCtu + offsetY1 < pcv.maxCUHeight) + { + posC1 = posCenter.offset(offsetX1, offsetY1); + C1Avail = true; + } + } + } + else + { + C1Avail = false; + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + offsetX1) <= curSubPic.getSubPicRight() && (posRB.y + offsetY1) <= curSubPic.getSubPicBottom()); + } + else + { + boundaryCond = ((posRB.x + offsetX1) < pcv.lumaWidth) && ((posRB.y + offsetY1) < pcv.lumaHeight); + } + if (boundaryCond) + { + int posYInCtu = posRB.y & pcv.maxCUHeightMask; + if (posYInCtu + offsetY1 < pcv.maxCUHeight) + { + posC1 = posRB.offset(offsetX1, offsetY1); + C1Avail = true; + } + } + } + + bExistMV0 = bExistMV1 = false; + + // Candidate with L0 and L1 + dir = 0; + int refIdx[NUM_REF_PIC_LIST_01] = { 0, 0 }; + bExistMV0 = (C0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv0, iRefIdx, false, &refIdx[REF_PIC_LIST_0])) + || (C1Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv0, iRefIdx, false, &refIdx[REF_PIC_LIST_0])); + + if (bExistMV0) + { + dir |= 1; + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(cColMv0, refIdx[REF_PIC_LIST_0]); + } + else + { + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(Mv(), NOT_VALID); + } + if (slice.isInterB()) + { + bExistMV1 = (C0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv1, iRefIdx, false, &refIdx[REF_PIC_LIST_1])) + || (C1Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv1, iRefIdx, false, &refIdx[REF_PIC_LIST_1])); + + if (bExistMV1) + { + dir |= 2; + mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(cColMv1, refIdx[REF_PIC_LIST_1]); + } + else + { + mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(Mv(), NOT_VALID); + } + } + if (dir != 0) + { + mrgCtx.interDirNeighbours[cnt] = dir; + mrgCtx.BcwIdx[cnt] = BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = false; +#endif + mrgCtx.useAltHpelIf[cnt] = false; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt].clear(); +#endif +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) + { +#endif + cnt++; + if (cnt == maxNumMergeCand) + { + break; + } +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + + if (!slice.getCheckLDC() && bExistMV0 && bExistMV1) + { + // Candidate without L1 + dir = 0; + dir |= 1; + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(cColMv0, refIdx[REF_PIC_LIST_0]); + mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(Mv(), NOT_VALID); + if (dir != 0) + { + mrgCtx.interDirNeighbours[cnt] = dir; + mrgCtx.BcwIdx[cnt] = BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = false; +#endif + mrgCtx.useAltHpelIf[cnt] = false; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt].clear(); +#endif +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) + { +#endif + cnt++; + if (cnt == maxNumMergeCand) break; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + + // Candidate without L0 + dir = 0; + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(Mv(), NOT_VALID); + dir |= 2; + mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(cColMv1, refIdx[REF_PIC_LIST_1]); + if (dir != 0) + { + mrgCtx.interDirNeighbours[cnt] = dir; + mrgCtx.BcwIdx[cnt] = BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = false; +#endif + mrgCtx.useAltHpelIf[cnt] = false; +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt].clear(); #endif #if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) - { + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh #endif - if (mrgCandIdx == cnt) - { - mrgCtx.numValidMergeCand = cnt + 1; - return; - } - - cnt++; + )) + { +#endif + cnt++; + if (cnt == maxNumMergeCand) + { + break; + } #if NON_ADJACENT_MRG_CAND || TM_MRG - } + } #endif + } + } } } } - // early termination - if (cnt == maxNumMergeCand) + mrgCtx.numValidMergeCand = cnt; +} +#endif + +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM && NON_ADJACENT_MRG_CAND +void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) +{ + const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; + const CodingStructure &cs = *pu.cs; + const Slice &slice = *pu.cs->slice; + + const uint32_t mvdSimilarityThresh = getBDMVRMvdThreshold(pu); + const uint32_t maxNumMergeCand = NUM_NON_ADJ_CANDS; + + for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { - mrgCtx.numValidMergeCand = cnt; - return; + 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; } - int maxNumMergeCandMin1 = maxNumMergeCand - 1; -#if NON_ADJACENT_MRG_CAND + int cnt = 0; + + const Position posLT = pu.Y().topLeft(); + MotionInfo miNeighbor; int offsetX = 0; int offsetY = 0; - 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 } }; + int offsetX0 = 0; int offsetX1 = 0; int offsetX2 = pu.Y().width >> 1; + int offsetY0 = 0; int offsetY1 = 0; int offsetY2 = pu.Y().height >> 1; - for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCandMin1; iDistanceIndex++) + const int iNACANDIDATE_NUM[7] = { 5, 9, 9, 9, 9, 9, 9 }; + const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) { const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); - for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCandMin1; NASPIdx++) + for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++) { switch (idxMap[iDistanceIndex][NASPIdx]) { - case 0:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height + iNADistanceVer - 1; break; - case 1:offsetX = pu.Y().width + iNADistanceHor - 1; offsetY = -iNADistanceVer - 1; break; - case 2:offsetX = pu.Y().width >> 1; offsetY = -iNADistanceVer - 1; break; - case 3:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height >> 1; break; - case 4:offsetX = -iNADistanceHor - 1; offsetY = -iNADistanceVer - 1; break; + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break; + case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX2; offsetY = offsetY1; break; + case 3:offsetX = offsetX0; offsetY = offsetY2; break; + case 4:offsetX = offsetX0; offsetY = offsetY1; break; + case 5:offsetX = -1; offsetY = offsetY0; break; + case 6:offsetX = offsetX1; offsetY = -1; break; + case 7:offsetX = offsetX0 >> 1; offsetY = offsetY0; break; + case 8:offsetX = offsetX1; offsetY = offsetY1 >> 1; break; default: printf("error!"); exit(0); break; } @@ -2867,135 +3845,98 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, { miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); - - if (isBiPredFromDifferentDirEqDistPoc(pu, miNeighbor.refIdx[0], miNeighbor.refIdx[1]) - ) + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + // get Mv from Above-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + // get Mv from Above-right + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->BcwIdx : BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = miNeighbor.usesLIC; +#endif + if (slice.isInterB()) { - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; - // get Mv from Above-Left - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); - mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); - -#if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData; #endif - { - if (mrgCandIdx == cnt) - { - mrgCtx.numValidMergeCand = cnt + 1; - return; - } - cnt++; - } } - } - } - } -#endif - if (cnt != maxNumMergeCandMin1) - { - bool isGt4x4 = true; - bool bFound = addBMMergeHMVPCand(cs, mrgCtx, mrgCandIdx, maxNumMergeCandMin1, cnt - , isAvailableA1, miLeft, isAvailableB1, miAbove - , CU::isIBC(*pu.cu) - , isGt4x4 +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt #if TM_MRG - , mvThreshod -#endif - ); - - if (bFound) - { - return; - } - } - - { - if (cnt > 1 && cnt < maxNumMergeCand) - { - mrgCtx.mvFieldNeighbours[cnt * 2].setMvField(Mv(0, 0), NOT_VALID); - mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField(Mv(0, 0), NOT_VALID); -#if INTER_LIC - mrgCtx.LICFlags[cnt] = false; + , mvdSimilarityThresh #endif -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt].clear(); + )) #endif - mrgCtx.BcwIdx[cnt] = BCW_DEFAULT; - // calculate average MV for L0 and L1 seperately - unsigned char interDir = 0; - mrgCtx.useAltHpelIf[cnt] = (mrgCtx.useAltHpelIf[0] == mrgCtx.useAltHpelIf[1]) ? mrgCtx.useAltHpelIf[0] : false; - for (int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++) - { - const short refIdxI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].refIdx; - const short refIdxJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].refIdx; - - // both MVs are invalid, skip - if (refIdxI != refIdxJ) { - continue; + cnt++; } + } - interDir += 1 << refListId; - 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; - roundAffineMv(avgMv.hor, avgMv.ver, 1); + const int iNACANDIDATE_NUM2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; - mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField(avgMv, refIdxI); - } + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); - mrgCtx.interDirNeighbours[cnt] = interDir; - if (interDir == 3 && isBiPredFromDifferentDirEqDistPoc(pu, mrgCtx.mvFieldNeighbours[cnt * 2 + 0].refIdx, mrgCtx.mvFieldNeighbours[cnt * 2 + 1].refIdx)) + for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM2[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++) + { + switch (idxMap2[iDistanceIndex][NASPIdx]) { -#if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) -#endif - cnt++; + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; + case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; + case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; + default: printf("error!"); exit(0); break; } - } - // early termination - if (cnt == maxNumMergeCand) - { - mrgCtx.numValidMergeCand = cnt; - return; - } - } + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); - mrgCtx.numCandToTestEnc = cnt; + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); - if (cnt < maxNumMergeCand) - { - mrgCtx.interDirNeighbours[cnt] = 3; - mrgCtx.BcwIdx[cnt] = BCW_DEFAULT; + if (isAvailableNonAdjacent) + { + miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; + // get Mv from Above-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); + mrgCtx.useAltHpelIf[cnt] = miNeighbor.useAltHpelIf; + // get Mv from Above-right + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->BcwIdx : BCW_DEFAULT; #if INTER_LIC - mrgCtx.LICFlags[cnt] = false; + mrgCtx.LICFlags[cnt] = miNeighbor.usesLIC; #endif + if (slice.isInterB()) + { + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); #if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt].clear(); + mrgCtx.addHypNeighbours[cnt] = puNonAdjacent->addHypData; #endif - mrgCtx.useAltHpelIf[cnt] = false; - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(0, 0), 0); - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(0, 0), 0); + } + #if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh #endif - { - if (mrgCandIdx == cnt) - { - mrgCtx.numValidMergeCand = cnt + 1; - return; + )) +#endif + { + cnt++; + } } - cnt++; } } + mrgCtx.numValidMergeCand = cnt; } #endif @@ -3198,7 +4139,11 @@ void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, } } } -bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &_pos, Mv& rcMv, const int &refIdx, bool sbFlag) +bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &_pos, Mv& rcMv, const int &refIdx, bool sbFlag +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , int* targetRefIdx +#endif +) { // don't perform MV compression when generally disabled or subPuMvp is used const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4); @@ -3280,7 +4225,56 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList CHECK( pColSlice == nullptr, "Slice segment not found" ); const Slice &colSlice = *pColSlice; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + if (targetRefIdx != nullptr) + { + *targetRefIdx = slice.getImRefIdx(mi.sliceIdx, eColRefPicList, eRefPicList, iColRefIdx); + if (*targetRefIdx == -1) + { + return false; + } + + const bool bIsCurrRefLongTerm = slice.getRefPic(eRefPicList, *targetRefIdx)->longTerm; + const bool bIsColRefLongTerm = colSlice.getIsUsedAsLongTerm(eColRefPicList, iColRefIdx); + if (bIsCurrRefLongTerm != bIsColRefLongTerm) + { + return false; + } + + // Scale the vector. + Mv cColMv = mi.mv[eColRefPicList]; + cColMv.setHor(roundMvComp(cColMv.getHor())); + cColMv.setVer(roundMvComp(cColMv.getVer())); + + if (bIsCurrRefLongTerm /*|| bIsColRefLongTerm*/) + { + rcMv = cColMv; + rcMv.clipToStorageBitDepth(); + } + else + { + const int currPOC = slice.getPOC(); + const int colPOC = colSlice.getPOC(); + const int colRefPOC = colSlice.getRefPOC(eColRefPicList, iColRefIdx); + const int currRefPOC = slice.getRefPic(eRefPicList, *targetRefIdx)->getPOC(); + const int distscale = xGetDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC); + + if (distscale == 4096) + { + rcMv = cColMv; + rcMv.clipToStorageBitDepth(); + } + else + { + rcMv = cColMv.scaleMv(distscale); + } + } + return true; + } + else + { +#endif const bool bIsCurrRefLongTerm = slice.getRefPic(eRefPicList, refIdx)->longTerm; const bool bIsColRefLongTerm = colSlice.getIsUsedAsLongTerm(eColRefPicList, iColRefIdx); @@ -3320,6 +4314,9 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList } return true; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + } +#endif } bool PU::isDiffMER(const Position &pos1, const Position &pos2, const unsigned plevel) @@ -4683,7 +5680,11 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx Mv cColMv; int refIdx = 0; - bool bExistMV = C0Avail && getColocatedMVP( pu, REF_PIC_LIST_0, posC0, cColMv, refIdx, false ); + bool bExistMV = C0Avail && getColocatedMVP( pu, REF_PIC_LIST_0, posC0, cColMv, refIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , &refIdx +#endif + ); if ( bExistMV ) { mi[3].mv[0] = cColMv; @@ -4694,7 +5695,11 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if ( slice.isInterB() ) { - bExistMV = C0Avail && getColocatedMVP( pu, REF_PIC_LIST_1, posC0, cColMv, refIdx, false ); + bExistMV = C0Avail && getColocatedMVP( pu, REF_PIC_LIST_1, posC0, cColMv, refIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , &refIdx +#endif + ); if ( bExistMV ) { mi[3].mv[1] = cColMv; @@ -5090,10 +6095,18 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b { RefPicList currRefPicList = RefPicList(currRefListId); - if (getColocatedMVP(pu, currRefPicList, centerPos, cColMv, refIdx, true)) + if (getColocatedMVP(pu, currRefPicList, centerPos, cColMv, refIdx, true +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , &refIdx +#endif + )) { // set as default, for further motion vector field spanning +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + mrgCtx.mvFieldNeighbours[(count << 1) + currRefListId].setMvField(cColMv, refIdx); +#else mrgCtx.mvFieldNeighbours[(count << 1) + currRefListId].setMvField(cColMv, 0); +#endif mrgCtx.interDirNeighbours[count] |= (1 << currRefListId); LICFlag = tempLICFlag; mrgCtx.BcwIdx[count] = BCW_DEFAULT; @@ -5143,9 +6156,17 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++) { RefPicList currRefPicList = RefPicList(currRefListId); - if (getColocatedMVP(pu, currRefPicList, colPos, cColMv, refIdx, true)) + if (getColocatedMVP(pu, currRefPicList, colPos, cColMv, refIdx, true +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , &refIdx +#endif + )) { +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + mi.refIdx[currRefListId] = refIdx; +#else mi.refIdx[currRefListId] = 0; +#endif mi.mv[currRefListId] = cColMv; found = true; } diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 43b0a2a259c4b9adc6d6bc7d022bcb2ee96c381d..ed70fc18edc2039724acbc199a42de30b388de6b 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -173,12 +173,25 @@ namespace PU #endif void getInterMergeCandidates (const PredictionUnit &pu, MergeCtx& mrgCtx, int mmvdList, - const int& mrgCandIdx = -1 ); + const int& mrgCandIdx = -1 +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , MergeCtx* mvpMrgCtx1 = NULL + , MergeCtx* mvpMrgCtx2 = NULL +#endif + ); +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + void getTmvpMergeCand (const PredictionUnit &pu, MergeCtx& mvpMrgCtx); + void getNonAdjacentMergeCand (const PredictionUnit &pu, MergeCtx& mvpMrgCtx); +#endif void getIBCMergeCandidates (const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1); void getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1); int getDistScaleFactor(const int &currPOC, const int &currRefPOC, const int &colPOC, const int &colRefPOC); bool isDiffMER (const Position &pos1, const Position &pos2, const unsigned plevel); - bool getColocatedMVP (const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &pos, Mv& rcMv, const int &refIdx, bool sbFlag); + bool getColocatedMVP (const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &pos, Mv& rcMv, const int &refIdx, bool sbFlag +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , int* targetRefIdx = nullptr +#endif + ); void fillMvpCand ( PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo #if TM_AMVP , InterPrediction* interPred = nullptr @@ -250,7 +263,16 @@ namespace PU #endif ); void getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, - const int& mrgCandIdx = -1); + const int& mrgCandIdx = -1 +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , MergeCtx* mvpMrgCtx1 = NULL + , MergeCtx* mvpMrgCtx2 = NULL +#endif + ); +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + void getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mvpMrgCtx); + void getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mvpMrgCtx); +#endif #endif bool getInterMergeSubPuRecurCand(const PredictionUnit &pu, MergeCtx &mrgCtx, const int count); bool isBiPredFromDifferentDirEqDistPoc(const PredictionUnit &pu); diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 6d3fb02d4ba3bcfc18b690200c81c3f09cc0e09c..9f22f67b51c384b0180558fd0041074742a5d356 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -1513,10 +1513,48 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #if JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); + + uint8_t bmDir = pu.bmDir; + MergeCtx tmvpMergeCandCtx; + PU::getTmvpBMCand(pu, tmvpMergeCandCtx); + pu.bmDir = 0; + if (tplAvail) + { + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1, pu.mergeIdx); + } + else + { + tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand); + } + MergeCtx namvpMergeCandCtx; + PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx); + pu.bmDir = 0; + if (tplAvail) + { + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 3, pu.mergeIdx); + } + else + { + namvpMergeCandCtx.numValidMergeCand = std::min(3, namvpMergeCandCtx.numValidMergeCand); + } + PU::getInterBMCandidates(pu, mrgCtx, -1, &tmvpMergeCandCtx, &namvpMergeCandCtx); +#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); uint8_t bmDir = pu.bmDir; +#endif pu.bmDir = 0; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + if (tplAvail) + { + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, mergeIdx + 1, mergeIdx); + } +#else m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, mergeIdx); +#endif pu.bmDir = bmDir; } else @@ -1528,8 +1566,42 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #if JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); + + MergeCtx tmvpMergeCandCtx; + PU::getTmvpMergeCand(pu, tmvpMergeCandCtx); + if (tplAvail) + { + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1, pu.mergeIdx); + } + else + { + tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand); + } + MergeCtx namvpMergeCandCtx; + PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx); + if (tplAvail) + { + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 9, pu.mergeIdx); + } + else + { + namvpMergeCandCtx.numValidMergeCand = std::min(9, namvpMergeCandCtx.numValidMergeCand); + } + + PU::getInterMergeCandidates(pu, mrgCtx, 0, -1, &tmvpMergeCandCtx, &namvpMergeCandCtx); + + if (tplAvail) + { + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx); + } +#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); m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, pu.mergeIdx); +#endif } else { diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp index c4bae4749469d8c411b906b288b607aac11a3c0a..1ed5c08285ff856eadd0a56ea130d624d5342315 100644 --- a/source/Lib/DecoderLib/DecSlice.cpp +++ b/source/Lib/DecoderLib/DecSlice.cpp @@ -138,6 +138,75 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb { clipMv = clipMvInPic; } + +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + if (slice->getPicHeader()->getEnableTMVPFlag()) + { + const Picture* const pColPic = slice->getRefPic(RefPicList(slice->isInterB() ? 1 - slice->getColFromL0Flag() : 0), slice->getColRefIdx()); + if (pColPic) + { + const int currPOC = slice->getPOC(); + const int colPOC = pColPic->getPOC(); + + slice->resizeImBuf(pColPic->numSlices); + Slice *pColSlice = nullptr; + for (int sliceIdx = 0; sliceIdx < pColPic->numSlices; sliceIdx++) + { + pColSlice = pColPic->slices[sliceIdx]; + if (pColSlice->isIntra()) + { + continue; + } + + for (int colRefPicListIdx = 0; colRefPicListIdx < (pColSlice->isInterB() ? 2 : 1); colRefPicListIdx++) + { + for (int colRefIdx = 0; colRefIdx < pColSlice->getNumRefIdx(RefPicList(colRefPicListIdx)); colRefIdx++) + { + const bool bIsColRefLongTerm = pColSlice->getIsUsedAsLongTerm(RefPicList(colRefPicListIdx), colRefIdx); + const int colRefPOC = pColSlice->getRefPOC(RefPicList(colRefPicListIdx), colRefIdx); + + for (int curRefPicListIdx = 0; curRefPicListIdx < (slice->isInterB() ? 2 : 1); curRefPicListIdx++) + { + double bestDistScale = 1000; + int targetRefIdx = -1; + for (int curRefIdx = 0; curRefIdx < slice->getNumRefIdx(RefPicList(curRefPicListIdx)); curRefIdx++) + { + const int currRefPOC = slice->getRefPic(RefPicList(curRefPicListIdx), curRefIdx)->getPOC(); + const bool bIsCurrRefLongTerm = slice->getRefPic(RefPicList(curRefPicListIdx), curRefIdx)->longTerm; + if (bIsCurrRefLongTerm != bIsColRefLongTerm) + { + continue; + } + if (bIsCurrRefLongTerm) + { + targetRefIdx = curRefIdx; + bestDistScale = 1; + break; + } + else if (colPOC - colRefPOC == currPOC - currRefPOC) + { + targetRefIdx = curRefIdx; + bestDistScale = 1; + break; + } + else + { + if (abs(1.0 - (abs(currPOC - currRefPOC) * 1.0 / abs(colPOC - colRefPOC) * 1.0)) < bestDistScale) + { + bestDistScale = abs(1.0 - (abs(currPOC - currRefPOC) * 1.0 / abs(colPOC - colRefPOC) * 1.0)); + targetRefIdx = curRefIdx; + } + } + } // curRefIdx + slice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx); + } // curRefPicListIdx + } + } + } + } + } +#endif + // for every CTU in the slice segment... unsigned subStrmId = 0; for( unsigned ctuIdx = 0; ctuIdx < slice->getNumCtuInSlice(); ctuIdx++ ) diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 64c14cc3f3089f32aa4c7aa82625a0dfa640207e..d2c67cb0bc2bf5819e7b0172d521566b26786aa8 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -2856,15 +2856,73 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.cs = tempCS; #if TM_MRG pu.tmMergeFlag = false; +#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; + PU::getTmvpMergeCand(pu, tmvpMergeCandCtx); + if (sps.getUseAML()) + { + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1); + } + else + { + tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand); + } + } + MergeCtx namvpMergeCandCtx; + PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx); + if (sps.getUseAML()) + { + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 9); + } + else + { + namvpMergeCandCtx.numValidMergeCand = std::min(9, namvpMergeCandCtx.numValidMergeCand); + } + } #endif PU::getInterMergeCandidates(pu, mergeCtx , 0 +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , -1 + , &tmvpMergeCandCtx + , &namvpMergeCandCtx +#endif ); +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + if (sps.getUseAML()) + { + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, mergeCtx, pu.cs->sps->getMaxNumMergeCand()); + } + } + PU::getInterMergeCandidates(pu, mergeCtxtmp, 0); +#endif + #if JVET_X0141_CIIP_TIMD_TM && TM_MRG if (cu.cs->sps->getUseCiipTmMrg()) { pu.tmMergeFlag = true; pu.ciipFlag = true; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + ciipTmMrgCtx = mergeCtxtmp; + ciipTmMrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand()); + memcpy(ciipTmMrgCtx.BcwIdx, mergeCtxtmp.BcwIdx, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(uint8_t)); + memcpy(ciipTmMrgCtx.interDirNeighbours, mergeCtxtmp.interDirNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(unsigned char)); + memcpy(ciipTmMrgCtx.mvFieldNeighbours, mergeCtxtmp.mvFieldNeighbours, (CIIP_TM_MRG_MAX_NUM_CANDS << 1) * sizeof(MvField)); + memcpy(ciipTmMrgCtx.useAltHpelIf, mergeCtxtmp.useAltHpelIf, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool)); + memcpy(ciipTmMrgCtx.LICFlags, mergeCtxtmp.LICFlags, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool)); + memcpy(ciipTmMrgCtx.addHypNeighbours, mergeCtxtmp.addHypNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(MultiHypVec)); +#else ciipTmMrgCtx = mergeCtx; ciipTmMrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand()); memcpy(ciipTmMrgCtx.BcwIdx, mergeCtx.BcwIdx, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(uint8_t)); @@ -2873,6 +2931,7 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& memcpy(ciipTmMrgCtx.useAltHpelIf, mergeCtx.useAltHpelIf, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool)); memcpy(ciipTmMrgCtx.LICFlags, mergeCtx.LICFlags, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(bool)); memcpy(ciipTmMrgCtx.addHypNeighbours, mergeCtx.addHypNeighbours, CIIP_TM_MRG_MAX_NUM_CANDS * sizeof(MultiHypVec)); +#endif for (uint32_t uiMergeCand = 0; uiMergeCand < ciipTmMrgCtx.numValidMergeCand; uiMergeCand++) { @@ -2904,9 +2963,16 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& } #endif #if JVET_W0097_GPM_MMVD_TM +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + m_mergeCand.copyMergeCtx(mergeCtxtmp); +#else m_mergeCand.copyMergeCtx(mergeCtx); +#endif m_mergeCandAvail = true; #endif +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + PU::getInterMMVDMergeCandidates(pu, mergeCtxtmp); +#else PU::getInterMMVDMergeCandidates(pu, mergeCtx); #if JVET_W0090_ARMC_TM mergeCtxtmp = mergeCtx; @@ -2915,16 +2981,62 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& m_pcInterSearch->adjustInterMergeCandidates(pu, mergeCtx); } #endif +#endif #if TM_MRG && MERGE_ENC_OPT if (cu.cs->sps->getUseDMVDMode()) { cu.firstPU = &pu; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + MergeCtx tmvpTmMergeCandCtx; + PU::getTmvpMergeCand(pu, tmvpTmMergeCandCtx); + if (sps.getUseAML()) + { + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpTmMergeCandCtx, 1); + } + else + { + tmvpTmMergeCandCtx.numValidMergeCand = std::min(1, tmvpTmMergeCandCtx.numValidMergeCand); + } + } + MergeCtx namvpTmMergeCandCtx; + PU::getNonAdjacentMergeCand(pu, namvpTmMergeCandCtx); + if (sps.getUseAML()) + { + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, namvpTmMergeCandCtx, 9); + } + else + { + namvpTmMergeCandCtx.numValidMergeCand = std::min(9, namvpTmMergeCandCtx.numValidMergeCand); + } + } +#endif pu.tmMergeFlag = true; - PU::getInterMergeCandidates(pu, tmMrgCtx, 0); + PU::getInterMergeCandidates(pu, tmMrgCtx, 0 +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , -1 + , &tmvpTmMergeCandCtx + , &namvpTmMergeCandCtx +#endif + ); #if JVET_W0090_ARMC_TM if (sps.getUseAML()) { +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmMrgCtx, pu.cs->sps->getMaxNumTMMergeCand()); + } + if (tmMrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) + { + tmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); + } +#else m_pcInterSearch->adjustInterMergeCandidates(pu, tmMrgCtx); +#endif } #endif @@ -3024,12 +3136,59 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& if (checkBmMrg) { pu.bmMergeFlag = true; - PU::getInterBMCandidates(pu, bmMrgCtx); +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + MergeCtx tmvpMergeCandCtx2; + PU::getTmvpBMCand(pu, tmvpMergeCandCtx2); + if (sps.getUseAML()) + { + pu.bmDir = 0; + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx2, 1); + } + else + { + tmvpMergeCandCtx2.numValidMergeCand = std::min(1, tmvpMergeCandCtx2.numValidMergeCand); + } + } + MergeCtx namvpMergeCandCtx2; + PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx2); + if (sps.getUseAML()) + { + pu.bmDir = 0; + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx2, 3); + } + else + { + namvpMergeCandCtx2.numValidMergeCand = std::min(3, namvpMergeCandCtx2.numValidMergeCand); + } + } +#endif + PU::getInterBMCandidates(pu, bmMrgCtx +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , -1 + , &tmvpMergeCandCtx2 + , &namvpMergeCandCtx2 +#endif + ); #if JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { pu.bmDir = 0; +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + if (tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroup(pu, bmMrgCtx, pu.cs->sps->getMaxNumBMMergeCand()); + } + if (bmMrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumBMMergeCand()) + { + bmMrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumBMMergeCand(); + } +#else m_pcInterSearch->adjustInterMergeCandidates(pu, bmMrgCtx); +#endif } #endif if (bmMrgCtx.numValidMergeCand == 0) @@ -9986,7 +10145,11 @@ 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 + const uint32_t maxNumCand = ::min(mrgCtx.numValidMergeCand, mrgCtx.numCandToTestEnc); +#else const uint32_t maxNumCand = mrgCtx.numCandToTestEnc; +#endif bool subPuRefine[2] = { false, false }; Mv finalMvDir[2]; for (uint32_t candIdx = 0; candIdx < maxNumCand; candIdx++) diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index adf9dc97ce7573024d8078d8e41c0cbf9f623252..0388577b3a8bb36f6fd9f56e28df7e1409008bae 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -2671,6 +2671,77 @@ void EncGOP::compressGOP( int iPOCLast, int iNumPicRcvd, PicList& rcListPic, { picHeader->setEnableTMVPFlag( 0 ); } +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + if (picHeader->getEnableTMVPFlag()) + { + const Picture* const pColPic = pcSlice->getRefPic(RefPicList(pcSlice->isInterB() ? 1 - pcSlice->getColFromL0Flag() : 0), pcSlice->getColRefIdx()); + if (pColPic) + { + const int currPOC = pcSlice->getPOC(); + const int colPOC = pColPic->getPOC(); + + pcSlice->resizeImBuf(pColPic->numSlices); + Slice *pColSlice = nullptr; + for (int sliceIdx = 0; sliceIdx < pColPic->numSlices; sliceIdx++) + { + pColSlice = pColPic->slices[sliceIdx]; + if (pColSlice->isIntra()) + { + continue; + } + + for (int colRefPicListIdx = 0; colRefPicListIdx < (pColSlice->isInterB() ? 2 : 1); colRefPicListIdx++) + { + for (int colRefIdx = 0; colRefIdx < pColSlice->getNumRefIdx(RefPicList(colRefPicListIdx)); colRefIdx++) + { + const bool bIsColRefLongTerm = pColSlice->getIsUsedAsLongTerm(RefPicList(colRefPicListIdx), colRefIdx); + const int colRefPOC = pColSlice->getRefPOC(RefPicList(colRefPicListIdx), colRefIdx); + + for (int curRefPicListIdx = 0; curRefPicListIdx < (pcSlice->isInterB() ? 2 : 1); curRefPicListIdx++) + { + double bestDistScale = 1000; + int targetRefIdx = -1; + for (int curRefIdx = 0; curRefIdx < pcSlice->getNumRefIdx(RefPicList(curRefPicListIdx)); curRefIdx++) + { + const int currRefPOC = pcSlice->getRefPic(RefPicList(curRefPicListIdx), curRefIdx)->getPOC(); + const bool bIsCurrRefLongTerm = pcSlice->getRefPic(RefPicList(curRefPicListIdx), curRefIdx)->longTerm; + if (bIsCurrRefLongTerm != bIsColRefLongTerm) + { + continue; + } + if (bIsCurrRefLongTerm) + { + targetRefIdx = curRefIdx; + bestDistScale = 1; + break; + } + else if (colPOC - colRefPOC == currPOC - currRefPOC) + { + targetRefIdx = curRefIdx; + bestDistScale = 1; + break; + } + else + { + //printf("colRefPicListIdx:%d, curRefPicListIdx:%d, colRefIdx:%d, targetRefIdx:%d, curRefIdx:%d\n", colRefPicListIdx, curRefPicListIdx, colRefIdx, targetRefIdx, curRefIdx); + //printf("currPOC:%d, currRefPOC:%d, colPOC:%d, colRefPOC:%d\n", currPOC, currRefPOC, colPOC, colRefPOC); + //printf("bestDistScale:%.2f %.2f\n", bestDistScale, abs(1.0 - (abs(currPOC - currRefPOC) * 1.0 / abs(colPOC - colRefPOC) * 1.0))); + if (abs(1.0 - (abs(currPOC - currRefPOC) * 1.0 / abs(colPOC - colRefPOC) * 1.0)) < bestDistScale) + { + bestDistScale = abs(1.0 - (abs(currPOC - currRefPOC) * 1.0 / abs(colPOC - colRefPOC) * 1.0)); + targetRefIdx = curRefIdx; + } + } + } // curRefIdx + //printf("sliceIdx:%d, colRefPicListIdx:%d, curRefPicListIdx:%d, colRefIdx:%d, targetRefIdx:%d\n", sliceIdx, colRefPicListIdx, curRefPicListIdx, colRefIdx, targetRefIdx); + pcSlice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx); + } // curRefPicListIdx + } + } + } + } + } +#endif } pcSlice->scaleRefPicList( scaledRefPic, pcPic->cs->picHeader, m_pcEncLib->getApss(), picHeader->getLmcsAPS(), picHeader->getScalingListAPS(), false );