diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 950f8b25c19484757eca0c1572b19972f1e71691..c2c07fe906fb108a12252bc7ea8c7422bbb201cd 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -113,6 +113,13 @@ #define NULL 0 #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +static const int SUB_TMVP_CANDIDATE_NUM = 10; +static const int SUB_TMVP_INDEX = 3; // 1: 2 subtmvp; 2: 4 subtmvp +static const int SUB_TMVP_NUM = 2 * SUB_TMVP_INDEX; +static const int SUB_TMVP_MV_THRESHOLD = 2; +static const int AMVP_TMVP_INDEX = 1; // 1: 2 AMVP tmvp; 2: 4 AMVP tmvp +#endif typedef enum { AFFINEMODEL_4PARAM, diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 1ff03737a41e4769938c43cb5d78036c0e7bf947..2c0c808a4c2bf246a3dad48210b77486c46c0d81 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -492,7 +492,38 @@ void MergeCtx::convertRegularMergeCandToBi(int candIdx) } } #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void MergeCtx::saveMergeInfo(PredictionUnit& puTmp, PredictionUnit pu) +{ + puTmp.mergeIdx = pu.mergeIdx; +#if !JVET_Z0075_IBC_HMVP_ENLARGE + CHECK(candIdx >= numValidMergeCand, "Merge candidate does not exist"); +#endif + + puTmp.regularMergeFlag = pu.regularMergeFlag; + puTmp.mergeFlag = pu.mergeFlag; + puTmp.mmvdMergeFlag = pu.mmvdMergeFlag; + puTmp.interDir = pu.interDir; + puTmp.cu->imv = pu.cu->imv; + puTmp.mergeType = pu.mergeType; + puTmp.mv[REF_PIC_LIST_0] = pu.mv[REF_PIC_LIST_0]; + puTmp.mv[REF_PIC_LIST_1] = pu.mv[REF_PIC_LIST_1]; +#if MULTI_PASS_DMVR + puTmp.bdmvrRefine = pu.bdmvrRefine; +#endif + puTmp.refIdx[REF_PIC_LIST_0] = pu.refIdx[REF_PIC_LIST_0]; + puTmp.refIdx[REF_PIC_LIST_1] = pu.refIdx[REF_PIC_LIST_1]; + + puTmp.bv = pu.bv; + puTmp.cu->BcwIdx = pu.cu->BcwIdx; + puTmp.addHypData = pu.addHypData; + puTmp.numMergedAddHyps = pu.numMergedAddHyps; + + puTmp.mmvdEncOptMode = pu.mmvdEncOptMode; + puTmp.cu->LICFlag = pu.cu->LICFlag; +} +#endif void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) { #if JVET_X0049_ADAPT_DMVR @@ -584,7 +615,33 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) } #endif } +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +bool MergeCtx::xCheckSimilarMotionSubTMVP(int mergeCandIndex, uint32_t mvdSimilarityThresh) const +{ + if (interDirNeighbours[mergeCandIndex] == 0) + { + return true; + } + Mv cVector; + + CHECK(interDirNeighbours[mergeCandIndex] != 1 && interDirNeighbours[mergeCandIndex] != 2, "Wrong interDir."); + + cVector = (interDirNeighbours[mergeCandIndex] == 1) ? mvFieldNeighbours[(mergeCandIndex << 1)].mv : mvFieldNeighbours[(mergeCandIndex << 1) + 1].mv; + cVector.changePrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + for (uint32_t ui = 0; ui < mergeCandIndex; ui++) + { + Mv cTempVector = (interDirNeighbours[ui] == 1) ? mvFieldNeighbours[(ui << 1)].mv : mvFieldNeighbours[(ui << 1) + 1].mv; + cTempVector.changePrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + Mv mvDiff = cTempVector - cVector; + if (mvDiff.getAbsHor() < mvdSimilarityThresh && mvDiff.getAbsVer() < mvdSimilarityThresh) + { + return true; + } + } + return false; +} +#endif #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) || JVET_Y0058_IBC_LIST_MODIFY #if JVET_Z0075_IBC_HMVP_ENLARGE bool MergeCtx::xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh, int compareNum) const diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 2b5c4ec0061402659a9e3d27424a2c0d044764b0..1a97a2a139227ed06a68770a229a2b038ef9cfb4 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -598,7 +598,11 @@ public: #endif bool hasMergedCandList; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MotionBuf subPuMvpMiBuf[SUB_TMVP_NUM]; +#else MotionBuf subPuMvpMiBuf; +#endif MotionBuf subPuMvpExtMiBuf; MvField mmvdBaseMv[MMVD_BASE_MV_NUM][2]; #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED @@ -615,6 +619,9 @@ public: bool useAltHpelIf [ NUM_MERGE_CANDS ]; #else bool useAltHpelIf [ MRG_MAX_NUM_CANDS ]; +#endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void saveMergeInfo(PredictionUnit& puTmp, PredictionUnit pu); #endif void setMergeInfo( PredictionUnit& pu, int candIdx ); #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) || JVET_Y0058_IBC_LIST_MODIFY @@ -634,6 +641,9 @@ public: bool xCheckSimilarIBCMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1) const; #endif #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + bool xCheckSimilarMotionSubTMVP(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1) const; +#endif #if TM_MRG void copyRegularMergeCand( int dstCandIdx, MergeCtx& srcCtx, int srcCandIdx ); void convertRegularMergeCandToBi(int candIdx); @@ -665,6 +675,9 @@ public: MergeCtx *mrgCtx; MergeType mergeType[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int colIdx[RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE]; +#endif #if JVET_AB0112_AFFINE_DMVR bool xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1) const; #endif @@ -688,6 +701,9 @@ public: MergeCtx *mrgCtx; MergeType mergeType[AFFINE_MRG_MAX_NUM_CANDS]; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int colIdx[AFFINE_MRG_MAX_NUM_CANDS]; +#endif #if JVET_AB0112_AFFINE_DMVR bool xCheckSimilarMotion(int mergeCandIndex, uint32_t mvdSimilarityThresh = 1) const; #endif diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 3316da46f482bd699032318cd8d20b8adc5eb9fb..d2847ca2ac4f0d33ff71deb022fa0494f84545f5 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -678,7 +678,30 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, cons // ==================================================================================================================== // Public member functions // ==================================================================================================================== +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +bool InterPrediction::xCheckIdenticalMotionSubTMVP(const PredictionUnit &pu) +{ + const Slice &slice = *pu.cs->slice; + + if (slice.isInterB() && !pu.cs->pps->getWPBiPred()) + { + if (pu.interDir == 3) + { + int refPOCL0 = slice.getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->getPOC(); + int refPOCL1 = slice.getRefPic(REF_PIC_LIST_1, pu.refIdx[1])->getPOC(); + if (refPOCL0 == refPOCL1) + { + if (pu.mv[0] == pu.mv[1]) + { + return true; + } + } + } + } + return false; +} +#endif bool InterPrediction::xCheckIdenticalMotion( const PredictionUnit &pu ) { const Slice &slice = *pu.cs->slice; @@ -4167,150 +4190,226 @@ void InterPrediction::xWeightedAverageY(const PredictionUnit& pu, const CPelUnit #endif #if JVET_W0090_ARMC_TM -void InterPrediction::xPredAffineTpl(const PredictionUnit &pu, const RefPicList &eRefPicList, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate) +void InterPrediction::xPredAffineTpl(const PredictionUnit &pu, const RefPicList &eRefPicList, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , AffineMergeCtx affMrgCtx, bool isBilinear +#endif +) { int iRefIdx = pu.refIdx[eRefPicList]; CHECK(iRefIdx < 0, "iRefIdx incorrect."); const Picture* refPic = pu.cu->slice->getRefPic(eRefPicList, iRefIdx)->unscaledPic; - Mv mvLT = pu.mvAffi[eRefPicList][0]; - Mv mvRT = pu.mvAffi[eRefPicList][1]; - Mv mvLB = pu.mvAffi[eRefPicList][2]; - // get affine sub-block width and height - const int width = pu.Y().width; - const int height = pu.Y().height; - int blockWidth = AFFINE_MIN_BLOCK_SIZE; - int blockHeight = AFFINE_MIN_BLOCK_SIZE; - - CHECK(blockWidth > width, "Sub Block width > Block width"); - CHECK(blockHeight > height, "Sub Block height > Block height"); - - const int cxWidth = width; - const int cxHeight = height; - const int iBit = MAX_CU_DEPTH; - int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY; - iDMvHorX = (mvRT - mvLT).getHor() << (iBit - floorLog2(width)); - iDMvHorY = (mvRT - mvLT).getVer() << (iBit - floorLog2(width)); - if (pu.cu->affineType == AFFINEMODEL_6PARAM) +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) { - iDMvVerX = (mvLB - mvLT).getHor() << (iBit - floorLog2(height)); - iDMvVerY = (mvLB - mvLT).getVer() << (iBit - floorLog2(height)); + Size puSize = pu.lumaSize(); + int numPartLine = std::max(puSize.width >> ATMVP_SUB_BLOCK_SIZE, 1u); + int numPartCol = std::max(puSize.height >> ATMVP_SUB_BLOCK_SIZE, 1u); + int puHeight = numPartCol == 1 ? puSize.height : 1 << ATMVP_SUB_BLOCK_SIZE; + int puWidth = numPartLine == 1 ? puSize.width : 1 << ATMVP_SUB_BLOCK_SIZE; + for (int h = 0; h < puSize.height; h += puHeight) + { + for (int w = 0; w < puSize.width; w += puWidth) + { + if (w == 0 || h == 0) + { + int iMvScaleTmpHor, iMvScaleTmpVer; + MotionBuf mb = affMrgCtx.mrgCtx->subPuMvpMiBuf[pu.colIdx]; + iMvScaleTmpHor = mb.buf[(w >> ATMVP_SUB_BLOCK_SIZE) + (h >> ATMVP_SUB_BLOCK_SIZE) * (affMrgCtx.mrgCtx->subPuMvpMiBuf[0].stride)].mv[eRefPicList].hor; + iMvScaleTmpVer = mb.buf[(w >> ATMVP_SUB_BLOCK_SIZE) + (h >> ATMVP_SUB_BLOCK_SIZE) * (affMrgCtx.mrgCtx->subPuMvpMiBuf[0].stride)].mv[eRefPicList].ver; + Mv tmpMv(iMvScaleTmpHor, iMvScaleTmpVer); + // clip and scale + if (refPic->isRefScaled(pu.cs->pps) == false) + { + clipMv(tmpMv, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + iMvScaleTmpHor = tmpMv.getHor(); + iMvScaleTmpVer = tmpMv.getVer(); + } + + xGetSublkAMLTemplate(*pu.cu, COMPONENT_Y, *refPic, Mv(iMvScaleTmpHor, iMvScaleTmpVer), puWidth, puHeight, w, h, numTemplate, refLeftTemplate, refAboveTemplate +#if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , (pu.afMmvdFlag +#else + , pu.afMmvdFlag +#endif +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + && pu.cs->sps->getUseTMMMVD() +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + ) +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + || (isBilinear +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + && pu.cs->sps->getUseTMMMVD()) +#endif +#endif +#endif + ); + } + } + } } else { - iDMvVerX = -iDMvHorY; - iDMvVerY = iDMvHorX; - } - int iMvScaleHor = mvLT.getHor() << iBit; - int iMvScaleVer = mvLT.getVer() << iBit; +#endif + Mv mvLT = pu.mvAffi[eRefPicList][0]; + Mv mvRT = pu.mvAffi[eRefPicList][1]; + Mv mvLB = pu.mvAffi[eRefPicList][2]; + // get affine sub-block width and height + const int width = pu.Y().width; + const int height = pu.Y().height; + int blockWidth = AFFINE_MIN_BLOCK_SIZE; + int blockHeight = AFFINE_MIN_BLOCK_SIZE; - const int shift = iBit - 4 + MV_FRACTIONAL_BITS_INTERNAL; + CHECK(blockWidth > width, "Sub Block width > Block width"); + CHECK(blockHeight > height, "Sub Block height > Block height"); + + const int cxWidth = width; + const int cxHeight = height; + const int iBit = MAX_CU_DEPTH; + int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY; + iDMvHorX = (mvRT - mvLT).getHor() << (iBit - floorLog2(width)); + iDMvHorY = (mvRT - mvLT).getVer() << (iBit - floorLog2(width)); + if (pu.cu->affineType == AFFINEMODEL_6PARAM) + { + iDMvVerX = (mvLB - mvLT).getHor() << (iBit - floorLog2(height)); + iDMvVerY = (mvLB - mvLT).getVer() << (iBit - floorLog2(height)); + } + else + { + iDMvVerX = -iDMvHorY; + iDMvVerY = iDMvHorX; + } + int iMvScaleHor = mvLT.getHor() << iBit; + int iMvScaleVer = mvLT.getVer() << iBit; + + const int shift = iBit - 4 + MV_FRACTIONAL_BITS_INTERNAL; #if !AFFINE_RM_CONSTRAINTS_AND_OPT - const bool subblkMVSpreadOverLimit = isSubblockVectorSpreadOverLimit(iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY, pu.interDir); + const bool subblkMVSpreadOverLimit = isSubblockVectorSpreadOverLimit(iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY, pu.interDir); #endif #if AFFINE_RM_CONSTRAINTS_AND_OPT - if (iDMvHorX == 0 && iDMvHorY == 0) - blockWidth = width; - else - { - int maxDmv = std::max(abs(iDMvHorX), abs(iDMvHorY)) * blockWidth; - int TH = 1 << (iBit - 1); // Half pel - while (maxDmv < TH && blockWidth < width) + if (iDMvHorX == 0 && iDMvHorY == 0) + blockWidth = width; + else { - blockWidth <<= 1; - maxDmv <<= 1; + int maxDmv = std::max(abs(iDMvHorX), abs(iDMvHorY)) * blockWidth; + int TH = 1 << (iBit - 1); // Half pel + while (maxDmv < TH && blockWidth < width) + { + blockWidth <<= 1; + maxDmv <<= 1; + } } - } - if (iDMvVerX == 0 && iDMvVerY == 0) - blockHeight = height; - else - { - int maxDmv = std::max(abs(iDMvVerX), abs(iDMvVerY)) * blockHeight; - int TH = 1 << (iBit - 1); // Half pel - while (maxDmv < TH && blockHeight < height) + if (iDMvVerX == 0 && iDMvVerY == 0) + blockHeight = height; + else { - blockHeight <<= 1; - maxDmv <<= 1; + int maxDmv = std::max(abs(iDMvVerX), abs(iDMvVerY)) * blockHeight; + int TH = 1 << (iBit - 1); // Half pel + while (maxDmv < TH && blockHeight < height) + { + blockHeight <<= 1; + maxDmv <<= 1; + } } - } #endif - int iMvScaleTmpHor0 = iMvScaleHor + ((iDMvHorX * blockWidth + iDMvVerX * blockHeight) >> 1); - int iMvScaleTmpVer0 = iMvScaleVer + ((iDMvHorY * blockWidth + iDMvVerY * blockHeight) >> 1); + int iMvScaleTmpHor0 = iMvScaleHor + ((iDMvHorX * blockWidth + iDMvVerX * blockHeight) >> 1); + int iMvScaleTmpVer0 = iMvScaleVer + ((iDMvHorY * blockWidth + iDMvVerY * blockHeight) >> 1); #if JVET_Z0139_NA_AFF - const CodingUnit *const cuAbove = pu.cu->cs->getCU(pu.cu->blocks[COMPONENT_Y].pos().offset(0, -1), toChannelType(COMPONENT_Y)); - const CodingUnit *const cuLeft = pu.cu->cs->getCU(pu.cu->blocks[COMPONENT_Y].pos().offset(-1, 0), toChannelType(COMPONENT_Y)); + const CodingUnit *const cuAbove = pu.cu->cs->getCU(pu.cu->blocks[COMPONENT_Y].pos().offset(0, -1), toChannelType(COMPONENT_Y)); + const CodingUnit *const cuLeft = pu.cu->cs->getCU(pu.cu->blocks[COMPONENT_Y].pos().offset(-1, 0), toChannelType(COMPONENT_Y)); - // get prediction block by block - for (int h = 0; (cuLeft && h < cxHeight) || h < 1; h += blockHeight) - { - for (int w = 0; (cuAbove && w < cxWidth) || w < 1; w += blockWidth) + // get prediction block by block + for (int h = 0; (cuLeft && h < cxHeight) || h < 1; h += blockHeight) + { + for (int w = 0; (cuAbove && w < cxWidth) || w < 1; w += blockWidth) #else - for (int h = 0; h < cxHeight; h += blockHeight) - { - for (int w = 0; w < cxWidth; w += blockWidth) -#endif + for (int h = 0; h < cxHeight; h += blockHeight) { - if (w == 0 || h == 0) + for (int w = 0; w < cxWidth; w += blockWidth) +#endif { - int iMvScaleTmpHor, iMvScaleTmpVer; + if (w == 0 || h == 0) + { + int iMvScaleTmpHor, iMvScaleTmpVer; #if !AFFINE_RM_CONSTRAINTS_AND_OPT - if (!subblkMVSpreadOverLimit) + if (!subblkMVSpreadOverLimit) #endif - { - iMvScaleTmpHor = iMvScaleTmpHor0 + iDMvHorX * w + iDMvVerX * h; - iMvScaleTmpVer = iMvScaleTmpVer0 + iDMvHorY * w + iDMvVerY * h; - } + { + iMvScaleTmpHor = iMvScaleTmpHor0 + iDMvHorX * w + iDMvVerX * h; + iMvScaleTmpVer = iMvScaleTmpVer0 + iDMvHorY * w + iDMvVerY * h; + } #if !AFFINE_RM_CONSTRAINTS_AND_OPT - else - { - iMvScaleTmpHor = iMvScaleHor + iDMvHorX * (cxWidth >> 1) + iDMvVerX * (cxHeight >> 1); - iMvScaleTmpVer = iMvScaleVer + iDMvHorY * (cxWidth >> 1) + iDMvVerY * (cxHeight >> 1); - } + else + { + iMvScaleTmpHor = iMvScaleHor + iDMvHorX * (cxWidth >> 1) + iDMvVerX * (cxHeight >> 1); + iMvScaleTmpVer = iMvScaleVer + iDMvHorY * (cxWidth >> 1) + iDMvVerY * (cxHeight >> 1); + } #endif - roundAffineMv(iMvScaleTmpHor, iMvScaleTmpVer, shift); - Mv tmpMv(iMvScaleTmpHor, iMvScaleTmpVer); - tmpMv.clipToStorageBitDepth(); - iMvScaleTmpHor = tmpMv.getHor(); - iMvScaleTmpVer = tmpMv.getVer(); - - // clip and scale -#if JVET_AA0146_WRAP_AROUND_FIX - bool wrapRef = false; - if ( refPic->isWrapAroundEnabled( pu.cs->pps ) ) - { + roundAffineMv(iMvScaleTmpHor, iMvScaleTmpVer, shift); Mv tmpMv(iMvScaleTmpHor, iMvScaleTmpVer); - wrapRef = wrapClipMv( tmpMv, pu.lumaPos(), pu.lumaSize(), pu.cs->sps, pu.cs->pps ); + tmpMv.clipToStorageBitDepth(); iMvScaleTmpHor = tmpMv.getHor(); iMvScaleTmpVer = tmpMv.getVer(); - } - else - { - wrapRef = false; + + // clip and scale +#if JVET_AA0146_WRAP_AROUND_FIX + bool wrapRef = false; + if (refPic->isWrapAroundEnabled(pu.cs->pps)) + { + Mv tmpMv(iMvScaleTmpHor, iMvScaleTmpVer); + wrapRef = wrapClipMv(tmpMv, pu.lumaPos(), pu.lumaSize(), pu.cs->sps, pu.cs->pps); + iMvScaleTmpHor = tmpMv.getHor(); + iMvScaleTmpVer = tmpMv.getVer(); + } + else + { + wrapRef = false; #endif - if (refPic->isRefScaled(pu.cs->pps) == false) - { - clipMv(tmpMv, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); - iMvScaleTmpHor = tmpMv.getHor(); - iMvScaleTmpVer = tmpMv.getVer(); - } + if (refPic->isRefScaled(pu.cs->pps) == false) + { + clipMv(tmpMv, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + iMvScaleTmpHor = tmpMv.getHor(); + iMvScaleTmpVer = tmpMv.getVer(); + } #if JVET_AA0146_WRAP_AROUND_FIX - } + } #endif - xGetSublkAMLTemplate(*pu.cu, COMPONENT_Y, *refPic, Mv(iMvScaleTmpHor, iMvScaleTmpVer), blockWidth, blockHeight, w, h, numTemplate, refLeftTemplate, refAboveTemplate + xGetSublkAMLTemplate(*pu.cu, COMPONENT_Y, *refPic, Mv(iMvScaleTmpHor, iMvScaleTmpVer), blockWidth, blockHeight, w, h, numTemplate, refLeftTemplate, refAboveTemplate #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED - , pu.afMmvdFlag +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , (pu.afMmvdFlag +#else + , pu.afMmvdFlag +#endif #if JVET_AA0132_CONFIGURABLE_TM_TOOLS - && pu.cs->sps->getUseTMMMVD() + && pu.cs->sps->getUseTMMMVD() +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + ) +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + || (isBilinear +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + && pu.cs->sps->getUseTMMMVD() +#endif + ) #endif #endif #if JVET_AA0146_WRAP_AROUND_FIX - , wrapRef + , wrapRef #endif - ); + ); + } } } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION } +#endif } #endif @@ -7711,11 +7810,19 @@ void InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC //Store if (pu.interDir == 3) { - getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft, posList0, posList1, load0, load1); + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + false, affMrgCtx, +#endif + posList0, posList1, load0, load1); } else { - getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , false, affMrgCtx +#endif + ); } if (m_bAMLTemplateAvailabe[0]) { @@ -7876,7 +7983,11 @@ void InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC 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))); - getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , affMrgCtx +#endif + ); if (m_bAMLTemplateAvailabe[0]) { @@ -7920,7 +8031,82 @@ void InterPrediction::sortAffineMergeCandidates(PredictionUnit pu, AffineMergeC } #endif #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void InterPrediction::adjustMergeCandidatesInOneCandidateGroupSubTMVP(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))); + + getBlkAMLRefTemplateSubTMVP(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]; + } +} +#endif #if JVET_W0090_ARMC_TM #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &pu, MergeCtx& mvpMergeCandCtx, int numRetrievedMergeCand, int mrgCandIdx) @@ -7950,6 +8136,13 @@ void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &p int nHeight = pu.lumaSize().height; auto origMergeIdx = pu.mergeIdx; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + PredictionUnit puTmp; + CodingUnit cuTmp; + puTmp.cu = &cuTmp; + mvpMergeCandCtx.saveMergeInfo(puTmp, pu); +#endif + for (uint32_t uiMergeCand = 0; uiMergeCand < mvpMergeCandCtx.numValidMergeCand; uiMergeCand++) { if (mvpMergeCandCtx.candCost[uiMergeCand] == MAX_UINT64) @@ -7996,6 +8189,9 @@ void InterPrediction::adjustMergeCandidatesInOneCandidateGroup(PredictionUnit &p { mvpMergeCandCtx.candCost[idx] = candCostList[idx]; } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + mvpMergeCandCtx.saveMergeInfo(pu, puTmp); +#endif } #if JVET_AB0079_TM_BCW_MRG @@ -9065,7 +9261,226 @@ void InterPrediction::updateCandInfo(MergeCtx& mrgCtx, uint32_t(*RdCandList)[MR } } #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void InterPrediction::getBlkAMLRefTemplateSubTMVP(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft) +{ + Mv mvCurr; + const int lumaShift = 2 + MV_FRACTIONAL_BITS_DIFF; + const int horShift = (lumaShift + ::getComponentScaleX(COMPONENT_Y, pu.chromaFormat)); + const int verShift = (lumaShift + ::getComponentScaleY(COMPONENT_Y, pu.chromaFormat)); + + if (xCheckIdenticalMotionSubTMVP(pu)) + { + mvCurr = pu.mv[0]; + /*const int horIntMv = (mvCurr.getHor() + ((1 << horShift) >> 1)) >> horShift; + const int verIntMv = (mvCurr.getVer() + ((1 << verShift) >> 1)) >> verShift; + Mv subPelMv(horIntMv << horShift, verIntMv << verShift);*/ + Mv subPelMv = mvCurr; + clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + CHECK(pu.refIdx[0] < 0, "invalid ref idx"); + + if (m_bAMLTemplateAvailabe[0]) + { + Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); + mvTop += subPelMv; + + clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvTop, pcBufPredRefTop, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + if (m_bAMLTemplateAvailabe[1]) + { + Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); + mvLeft += subPelMv; + + clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(REF_PIC_LIST_0, pu.refIdx[0]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0]), mvLeft, pcBufPredRefLeft, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + } + else + { + for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + if (!(pu.interDir & (1 << refList))) + { + continue; + } + RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + CHECK(pu.refIdx[refList] >= pu.cu->slice->getNumRefIdx(eRefPicList), "Invalid reference index"); + + m_iRefListIdx = refList; + mvCurr = pu.mv[refList]; + Mv subPelMv = mvCurr; + clipMv(mvCurr, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + if (m_bAMLTemplateAvailabe[0]) + { + Mv mvTop(0, -(AML_MERGE_TEMPLATE_SIZE << verShift)); + mvTop += subPelMv; + + clipMv(mvTop, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + PelUnitBuf pcMbBuf = + PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[refList][0], pcBufPredRefTop.Y())); + + if (pu.interDir == 3) + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, + pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, true, + pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, + pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, + mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, true, + pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + else + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvTop, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvTop, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + } + if (m_bAMLTemplateAvailabe[1]) + { + Mv mvLeft(-(AML_MERGE_TEMPLATE_SIZE << horShift), 0); + mvLeft += subPelMv; + + clipMv(mvLeft, pu.lumaPos(), pu.lumaSize(), *pu.cs->sps, *pu.cs->pps); + + PelUnitBuf pcMbBuf = + PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefLeftTemplate[refList][0], pcBufPredRefLeft.Y())); + + if (pu.interDir == 3) + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + true, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + else + { +#if RPR_ENABLE + const Picture* picRef = pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList])->unscaledPic; + const std::pair<int, int>& scalingRatio = pu.cu->slice->getScalingRatio(eRefPicList, pu.refIdx[refList]); +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, picRef, mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, scalingRatio, 0, 0, false, NULL, 0, true); +#endif +#else +#if INTER_LIC + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true, true, mvCurr); +#else + xPredInterBlk(COMPONENT_Y, pu, pu.cu->slice->getRefPic(eRefPicList, pu.refIdx[refList]), mvLeft, pcMbBuf, + false, pu.cu->slice->clpRng(COMPONENT_Y), false, false, SCALE_1X, 0, 0, false, NULL, 0, true); +#endif +#endif + } + } + } + if (m_bAMLTemplateAvailabe[0]) + { + CPelUnitBuf srcPred0 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[0][0], pcBufPredRefTop.Y())); + CPelUnitBuf srcPred1 = CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvRefAboveTemplate[1][0], pcBufPredRefTop.Y())); + xWeightedAverageY(pu, srcPred0, srcPred1, pcBufPredRefTop, pu.cu->slice->getSPS()->getBitDepths(), + pu.cu->slice->clpRngs()); + } + if (m_bAMLTemplateAvailabe[1]) + { + 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 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) @@ -9420,10 +9835,16 @@ void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer #if INTER_LIC pu.cu->LICFlag = affMrgCtx.LICFlags[uiMergeCand]; #endif - +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affMrgCtx.colIdx[uiMergeCand]; +#endif pu.mergeType = affMrgCtx.mergeType[uiMergeCand]; #if JVET_Z0139_NA_AFF +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if ((pu.mergeType == MRG_TYPE_DEFAULT_N) || (pu.mergeType == MRG_TYPE_SUBPU_ATMVP && uiMergeCand)) +#else if (pu.mergeType == MRG_TYPE_DEFAULT_N) +#endif #else if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) { @@ -9468,7 +9889,11 @@ void InterPrediction::adjustAffineMergeCandidates(PredictionUnit &pu, AffineMer { #endif - getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.cs->sps->getUseFastSubTmvp(), affMrgCtx +#endif + ); if (m_bAMLTemplateAvailabe[0]) { @@ -9602,6 +10027,9 @@ void InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtxTmp.affineType[i] = AFFINEMODEL_4PARAM; affMrgCtxTmp.mergeType[i] = MRG_TYPE_DEFAULT_N; affMrgCtxTmp.BcwIdx[i] = BCW_DEFAULT; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtxTmp.colIdx[i] = 0; +#endif #if INTER_LIC affMrgCtxTmp.LICFlags[i] = false; #endif @@ -9623,6 +10051,9 @@ void InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtxTmp.affineType[uiMergeCand] = affMrgCtx.affineType[uiMergeCand]; affMrgCtxTmp.mergeType[uiMergeCand] = affMrgCtx.mergeType[uiMergeCand]; affMrgCtxTmp.BcwIdx[uiMergeCand] = affMrgCtx.BcwIdx[uiMergeCand]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtxTmp.colIdx[uiMergeCand] = affMrgCtx.colIdx[uiMergeCand]; +#endif #if INTER_LIC affMrgCtxTmp.LICFlags[uiMergeCand] = affMrgCtx.LICFlags[uiMergeCand]; #endif @@ -9651,6 +10082,9 @@ void InterPrediction::updateAffineCandInfo(PredictionUnit &pu, AffineMergeCtx& affMrgCtx.affineType[uiMergeCand] = affMrgCtxTmp.affineType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; affMrgCtx.mergeType[uiMergeCand] = affMrgCtxTmp.mergeType[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; affMrgCtx.BcwIdx[uiMergeCand] = affMrgCtxTmp.BcwIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[uiMergeCand] = affMrgCtxTmp.colIdx[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; +#endif #if INTER_LIC affMrgCtx.LICFlags[uiMergeCand] = affMrgCtxTmp.LICFlags[RdCandList[uiMergeCand / ADAPTIVE_AFFINE_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_AFFINE_SUB_GROUP_SIZE]]; #endif @@ -9723,9 +10157,17 @@ 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) +void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + bool isBilinear, AffineMergeCtx affMrgCtx, +#endif + int8_t posList0, int8_t posList1, bool load0, bool load1) #else -void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft) +void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + AffineMergeCtx affMrgCtx, +#endif +) #endif { #if JVET_AA0093_ENHANCED_MMVD_EXTENSION @@ -9750,7 +10192,11 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf #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); + xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , affMrgCtx, isBilinear +#endif + ); #if INTER_LIC if (pu.cu->LICFlag) { @@ -9802,7 +10248,11 @@ void InterPrediction::getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBuf } #endif int numTemplate[2] = { 0, 0 }; // 0:Above, 1:Left - xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate); + xPredAffineTpl(pu, eRefPicList, numTemplate, refLeftTemplate, refAboveTemplate +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , affMrgCtx, isBilinear +#endif + ); #if INTER_LIC if (pu.cu->LICFlag) { @@ -10271,6 +10721,9 @@ void InterPrediction::adjustAffineMergeCandidatesOneGroup(PredictionUnit &pu, A pu.cu->BcwIdx = affMrgCtx.BcwIdx[uiMergeCand]; #if INTER_LIC pu.cu->LICFlag = affMrgCtx.LICFlags[uiMergeCand]; +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affMrgCtx.colIdx[uiMergeCand]; #endif pu.mergeType = affMrgCtx.mergeType[uiMergeCand]; #if JVET_Z0139_NA_AFF @@ -10310,8 +10763,11 @@ void InterPrediction::adjustAffineMergeCandidatesOneGroup(PredictionUnit &pu, A { #endif - getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft); - + getAffAMLRefTemplate(pu, pcBufPredRefTop, pcBufPredRefLeft +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , true, affMrgCtx +#endif + ); if (m_bAMLTemplateAvailabe[0]) { m_pcRdCost->setDistParam(cDistParam, pcBufPredCurTop.Y(), pcBufPredRefTop.Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, false); @@ -10355,6 +10811,9 @@ void InterPrediction::updateAffineCandInfo2(PredictionUnit &pu, AffineMergeCtx& affMrgCtxTmp.affineType[uiMergeCand] = affMrgCtx.affineType[uiMergeCand]; affMrgCtxTmp.mergeType[uiMergeCand] = affMrgCtx.mergeType[uiMergeCand]; affMrgCtxTmp.BcwIdx[uiMergeCand] = affMrgCtx.BcwIdx[uiMergeCand]; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtxTmp.colIdx[uiMergeCand] = affMrgCtx.colIdx[uiMergeCand]; +#endif #if INTER_LIC affMrgCtxTmp.LICFlags[uiMergeCand] = affMrgCtx.LICFlags[uiMergeCand]; #endif @@ -13014,6 +13473,29 @@ bool InterPrediction::readTplAmvpBuffer(AMVPInfo& dst, const CodingUnit& cu, Ref } #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void InterPrediction::writeMergeBuffer(const MergeCtx& srcList0, const MergeCtx& srcList1, const CodingUnit& cu) +{ + m_pcMergeCtxList0 = srcList0; + m_pcMergeCtxList1 = srcList1; +} +bool InterPrediction::readMergeBuffer( MergeCtx& dstList0, MergeCtx& dstList1, const CodingUnit& cu) +{ + if (m_pcMergeCtxList0.numValidMergeCand > 0 || m_pcMergeCtxList1.numValidMergeCand > 0) + { + dstList0 = m_pcMergeCtxList0; + dstList1 = m_pcMergeCtxList1; + return true; + } + return false; +} +void InterPrediction::clearAmvpTmvpBuffer() +{ + m_pcMergeCtxList0 = MergeCtx(); + m_pcMergeCtxList1 = MergeCtx(); +} +#endif + #if MULTI_PASS_DMVR #if JVET_X0049_ADAPT_DMVR bool InterPrediction::processBDMVRPU2Dir(PredictionUnit& pu, bool subPURefine[2], Mv(&finalMvDir)[2]) @@ -15997,7 +16479,12 @@ void InterPrediction::reorderRefCombList(PredictionUnit &pu, std::vector<RefList tmpPU.mvAffi[eRefList][2] = mvLB; #if !JVET_Z0067_RPR_ENABLE +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + AffineMergeCtx tmp; + getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft, tmp); +#else getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft); +#endif #endif uiCost = 0; @@ -16009,7 +16496,12 @@ void InterPrediction::reorderRefCombList(PredictionUnit &pu, std::vector<RefList else { #if JVET_Z0067_RPR_ENABLE +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + AffineMergeCtx tmp; + getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft, pu.cs->sps->getUseFastSubTmvp(), tmp); +#else getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft); +#endif #endif if (m_bAMLTemplateAvailabe[0]) { @@ -16468,7 +16960,12 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP #endif #if !JVET_Z0067_RPR_ENABLE - getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + AffineMergeCtx tmp; + getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft, tmp); +#else + getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft); +#endif #endif uiCost = 0; @@ -16485,7 +16982,12 @@ void InterPrediction::reorderRefPairList(PredictionUnit &pu, std::vector<RefPicP else { #if JVET_Z0067_RPR_ENABLE +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + AffineMergeCtx tmp; + getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft, pu.cs->sps->getUseFastSubTmvp(), tmp); +#else getAffAMLRefTemplate(tmpPU, pcBufPredRefTop, pcBufPredRefLeft); +#endif #endif if (m_bAMLTemplateAvailabe[0]) { diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index 818e7d060af3e431db1fff81c1d5329f5996a2d2..a00ac8f6318c6f6c4383144d10b144523956672a 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -118,7 +118,10 @@ private: AMVPInfo m_tplAmvpInfoLIC[NUM_IMV_MODES][NUM_REF_PIC_LIST_01][MAX_NUM_REF]; #endif #endif - +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MergeCtx m_pcMergeCtxList0; + MergeCtx m_pcMergeCtxList1; +#endif #if JVET_AC0144_AFFINE_DMVR_REGRESSION const Picture* m_bmRefPic[2]; CPelBuf m_bmRefBuf[2]; @@ -338,7 +341,11 @@ protected: void xWeightedAverageY(const PredictionUnit& pu, const CPelUnitBuf& pcYuvSrc0, const CPelUnitBuf& pcYuvSrc1, PelUnitBuf& pcYuvDst, const BitDepths& clipBitDepths, const ClpRngs& clpRngs); #endif #if JVET_W0090_ARMC_TM - void xPredAffineTpl(const PredictionUnit &pu, const RefPicList &eRefPicList, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate); + void xPredAffineTpl(const PredictionUnit &pu, const RefPicList &eRefPicList, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , AffineMergeCtx affMrgCtx, bool isBilinear +#endif + ); #endif #if AFFINE_ENC_OPT #if JVET_Z0136_OOB @@ -366,7 +373,11 @@ protected: void xSubPuBio(PredictionUnit& pu, PelUnitBuf& predBuf, const RefPicList &eRefPicList = REF_PIC_LIST_X, PelUnitBuf* yuvDstTmp = NULL); #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MotionInfo m_SubPuMiBuf[SUB_TMVP_NUM][(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#else MotionInfo m_SubPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#endif #if JVET_W0090_ARMC_TM || JVET_Z0056_GPM_SPLIT_MODE_REORDERING || JVET_Z0061_TM_OBMC || JVET_AA0061_IBC_MBVD Pel* m_acYuvCurAMLTemplate[2][MAX_NUM_COMPONENT]; //0: top, 1: left bool m_bAMLTemplateAvailabe[2]; @@ -607,7 +618,11 @@ public: void sortAffineMergeCandidates(PredictionUnit pu, AffineMergeCtx& affMrgCtx, uint32_t * affMmvdLUT, uint32_t afMMVDIdx = -1); #endif #endif - +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void getBlkAMLRefTemplateSubTMVP(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft); + static bool xCheckIdenticalMotionSubTMVP(const PredictionUnit& pu); + void adjustMergeCandidatesInOneCandidateGroupSubTMVP(PredictionUnit &pu, MergeCtx& smvpMergeCandCtx, int numRetrievedMergeCand, int mrgCandIdx = -1); +#endif #if JVET_W0090_ARMC_TM void adjustInterMergeCandidates(PredictionUnit &pu, MergeCtx& mrgCtx, int mrgCandIdx = -1); #endif @@ -662,7 +677,11 @@ public: #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); + void getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + bool isBilinear, AffineMergeCtx affMrgCtx, +#endif + int8_t posList0 = -1, int8_t posList1 = -1, bool loadSave0 = false, bool loadSave1 = false); #else void getAffAMLRefTemplate(PredictionUnit &pu, PelUnitBuf &pcBufPredRefTop, PelUnitBuf &pcBufPredRefLeft); #endif @@ -781,6 +800,11 @@ public: void clearTplAmvpBuffer (); void writeTplAmvpBuffer (const AMVPInfo& src, const CodingUnit& cu, RefPicList eRefList, int refIdx); bool readTplAmvpBuffer ( AMVPInfo& dst, const CodingUnit& cu, RefPicList eRefList, int refIdx); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void writeMergeBuffer(const MergeCtx& srcList0, const MergeCtx& srcList1, const CodingUnit& cu); + bool readMergeBuffer( MergeCtx& dstList0, MergeCtx& dstList1, const CodingUnit& cu); + void clearAmvpTmvpBuffer(); +#endif #endif #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM || MULTI_PASS_DMVR static Distortion getDecoderSideDerivedMvCost (const Mv& mvStart, const Mv& mvCur, int searchRangeInFullPel, int weight); diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 7b870e1cda765a639a8bd419075b01c92cb55259..4db0a4ee53f36376c29eb0765ebe717c9fa4529c 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1778,6 +1778,9 @@ private: #if JVET_W0090_ARMC_TM || JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0075_IBC_HMVP_ENLARGE bool m_AML; #endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + bool m_fastSubTmvp; +#endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC bool m_armcRefinedMotion; #endif @@ -2333,6 +2336,10 @@ void setCCALFEnabledFlag( bool b ) void setUseAML ( bool b ) { m_AML = b; } bool getUseAML () const { return m_AML; } #endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void setUseFastSubTmvp ( bool b ) { m_fastSubTmvp = b; } + bool getUseFastSubTmvp () const { return m_fastSubTmvp; } +#endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC void setUseArmcRefinedMotion ( bool b ) { m_armcRefinedMotion = b; } bool getUseArmcRefinedMotion () const { return m_armcRefinedMotion; } @@ -2910,6 +2917,10 @@ private: bool m_enableTMVPFlag; //!< enable temporal motion vector prediction bool m_picColFromL0Flag; //!< syntax element collocated_from_l0_flag uint32_t m_colRefIdx; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + bool m_picColFromL0Flag2nd; //!< syntax element collocated_from_l0_flag + uint32_t m_colRefIdx2nd; +#endif #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC uint32_t m_costForARMC; //!< Cost for diversity criterion #endif @@ -3053,6 +3064,12 @@ public: #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC void setCostForARMC(uint32_t cost) { m_costForARMC = cost; } uint32_t getCostForARMC() { return m_costForARMC; } +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void setPicColFromL0Flag2nd(bool val) { m_picColFromL0Flag2nd = val; } + bool getPicColFromL0Flag2nd() const { return m_picColFromL0Flag2nd; } + void setColRefIdx2nd(uint32_t refIdx) { m_colRefIdx2nd = refIdx; } + uint32_t getColRefIdx2nd() { return m_colRefIdx2nd; } #endif void setMvdL1ZeroFlag( bool b ) { m_mvdL1ZeroFlag = b; } bool getMvdL1ZeroFlag() const { return m_mvdL1ZeroFlag; } @@ -3294,11 +3311,19 @@ private: uint32_t m_colRefIdx; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + bool m_colFromL0Flag2nd; // collocated picture from List0 flag + uint32_t m_colRefIdx2nd; +#endif #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC uint32_t m_costForARMC; #endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + std::vector<int> m_implicitRefIdx[2][NUM_REF_PIC_LIST_01][NUM_REF_PIC_LIST_01][MAX_NUM_REF + 1]; +#else std::vector<int> m_implicitRefIdx[NUM_REF_PIC_LIST_01][NUM_REF_PIC_LIST_01][MAX_NUM_REF + 1]; +#endif #endif double m_lambdas[MAX_NUM_COMPONENT]; #if INTER_LIC @@ -3455,11 +3480,37 @@ public: int getDepth() const { return m_iDepth; } bool getColFromL0Flag() const { return m_colFromL0Flag; } uint32_t getColRefIdx() const { return m_colRefIdx; } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + bool getColFromL0Flag2nd() const { return m_colFromL0Flag2nd; } + uint32_t getColRefIdx2nd() const { return m_colRefIdx2nd; } +#endif 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 +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void resizeImBuf(int numSlices, int col) + { + for (int refIdx = 0; refIdx < MAX_NUM_REF + 1; refIdx++) + { + m_implicitRefIdx[col][REF_PIC_LIST_0][REF_PIC_LIST_0][refIdx].resize(numSlices); + std::fill(m_implicitRefIdx[col][REF_PIC_LIST_0][REF_PIC_LIST_0][refIdx].begin(), m_implicitRefIdx[col][REF_PIC_LIST_0][REF_PIC_LIST_0][refIdx].end(), -1); + + m_implicitRefIdx[col][REF_PIC_LIST_0][REF_PIC_LIST_1][refIdx].resize(numSlices); + std::fill(m_implicitRefIdx[col][REF_PIC_LIST_0][REF_PIC_LIST_1][refIdx].begin(), m_implicitRefIdx[col][REF_PIC_LIST_0][REF_PIC_LIST_1][refIdx].end(), -1); + + m_implicitRefIdx[col][REF_PIC_LIST_1][REF_PIC_LIST_0][refIdx].resize(numSlices); + std::fill(m_implicitRefIdx[col][REF_PIC_LIST_1][REF_PIC_LIST_0][refIdx].begin(), m_implicitRefIdx[col][REF_PIC_LIST_1][REF_PIC_LIST_0][refIdx].end(), -1); + + m_implicitRefIdx[col][REF_PIC_LIST_1][REF_PIC_LIST_1][refIdx].resize(numSlices); + std::fill(m_implicitRefIdx[col][REF_PIC_LIST_1][REF_PIC_LIST_1][refIdx].begin(), m_implicitRefIdx[col][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, int col) { m_implicitRefIdx[col][colRefPicList][curRefPicList][col_refIdx][sliceIdx] = cur_refIdx; } + int getImRefIdx(int sliceIdx, RefPicList colRefPicList, RefPicList curRefPicList, int col_refIdx, int col = 0) { return m_implicitRefIdx[col][colRefPicList][curRefPicList][col_refIdx][sliceIdx]; } + int getImRefIdx(int sliceIdx, RefPicList colRefPicList, RefPicList curRefPicList, int col_refIdx, int col = 0) const { return m_implicitRefIdx[col][colRefPicList][curRefPicList][col_refIdx][sliceIdx]; } +#else void resizeImBuf(int numSlices) { for (int refIdx = 0; refIdx < MAX_NUM_REF + 1; refIdx++) @@ -3480,6 +3531,7 @@ public: 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 #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; } @@ -3555,7 +3607,10 @@ public: void setColFromL0Flag( bool colFromL0 ) { m_colFromL0Flag = colFromL0; } void setColRefIdx( uint32_t refIdx) { m_colRefIdx = refIdx; } void setCheckLDC( bool b ) { m_bCheckLDC = b; } - +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void setColFromL0Flag2nd(bool colFromL0) { m_colFromL0Flag2nd = colFromL0; } + void setColRefIdx2nd(uint32_t refIdx) { m_colRefIdx2nd = refIdx; } +#endif #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC void setCostForARMC(uint32_t cost) { m_costForARMC = cost; } #endif diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index c8fdd89766535155e639cf999c0931fed79f05c3..99144a7f161f7b7bc90c9a6567773f8bbe644747 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -262,6 +262,7 @@ #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 +#define JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION 1 // JVET-AC0185: Enhanced temporal motion information derivation #endif // Transform and coefficient coding #define TCQ_8STATES 1 diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index d46719512cd6471042e06147132dfed2222a3d5f..0d08e36191087818d9a107ee15d67a5e62eee9e8 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -775,6 +775,9 @@ void PredictionUnit::initData() #endif #endif // inter data +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + colIdx = 0; +#endif mergeFlag = false; regularMergeFlag = false; mergeIdx = MAX_UCHAR; @@ -927,6 +930,9 @@ PredictionUnit& PredictionUnit::operator=(const IntraPredictionData& predData) PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData) { +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + colIdx = predData.colIdx; +#endif mergeFlag = predData.mergeFlag; regularMergeFlag = predData.regularMergeFlag; mergeIdx = predData.mergeIdx; @@ -1070,6 +1076,9 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other ) mergeFlag = other.mergeFlag; regularMergeFlag = other.regularMergeFlag; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + colIdx = other.colIdx; +#endif mergeIdx = other.mergeIdx; #if ENABLE_DIMD || JVET_W0123_TIMD_FUSION parseLumaMode = other.parseLumaMode; diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index d80c7e115554f7e99868f6de2b6efe032d67c27c..574aa7cfa87c5b8214590543747ce7a4a3466263 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -503,6 +503,9 @@ struct IntraPredictionData struct InterPredictionData { +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + uint8_t colIdx; +#endif bool mergeFlag; bool regularMergeFlag; #if JVET_AA0093_ENHANCED_MMVD_EXTENSION diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 22841fb9e14af439c955dc6735fa8bad19e23ba6..b0cee170f99d8203ddae99fc0d4dec0fc4a66bcd 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -2785,7 +2785,119 @@ uint8_t PU::getLFNSTIdx( int intraMode, int mtsMode ) return g_lfnstLut[ intraMode ]; } #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void PU::addMergeHMVPCandSubTMVP(const CodingStructure &cs, MergeCtx &mrgCtx, const int &mrgCandIdx, + const uint32_t maxNumMergeCand, int &cnt, const bool isAvailableA1, + const MotionInfo miLeft, const bool isAvailableB1, const MotionInfo miAbove, +#if !JVET_Z0075_IBC_HMVP_ENLARGE + , const bool ibcFlag + , const bool isGt4x4 +#endif + const PredictionUnit &pu, int col +#if TM_MRG || (JVET_Z0084_IBC_TM && !JVET_Z0075_IBC_HMVP_ENLARGE) + , const uint32_t mvdSimilarityThresh +#endif +) +{ + const Slice& slice = *cs.slice; + MotionInfo miNeighbor; + + const Picture *pColPic = slice.getRefPic(RefPicList(col == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), col == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); +#if JVET_Z0075_IBC_HMVP_ENLARGE +#if JVET_Z0118_GDR + bool isClean = cs.isClean(pu.cu->Y().bottomRight(), CHANNEL_TYPE_LUMA); +#endif // JVET_Z0118_GDR + +#if JVET_Z0118_GDR + auto &lut = (isClean) ? cs.motionLut.lut1 : cs.motionLut.lut0; +#else + auto &lut = cs.motionLut.lut; +#endif // JVET_Z0118_GDR +#else + +#if JVET_Z0118_GDR + auto &lut = ibcFlag ? (isClean ? cs.motionLut.lutIbc1 : cs.motionLut.lutIbc0) : (isClean ? cs.motionLut.lut1 : cs.motionLut.lut0); +#else + auto &lut = ibcFlag ? cs.motionLut.lutIbc : cs.motionLut.lut; +#endif // JVET_Z0118_GDR + +#endif // JVET_Z0075_IBC_HMVP_ENLARGE + int numCandInLUT = (int)lut.size(); + + for (int mrgIdx = 1; mrgIdx <= numCandInLUT; mrgIdx++) + { + miNeighbor = lut[numCandInLUT - mrgIdx]; + +#if !JVET_X0083_BM_AMVP_MERGE_MODE +#if JVET_Y0128_NON_CTC + bool isValidAmMode = checkIsValidMergeMvCand(pu, miNeighbor.refIdx); +#else + bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miNeighbor.refIdx); +#endif + if (isValidAmMode && +#if JVET_Z0075_IBC_HMVP_ENLARGE + (mrgIdx > 2 +#else + (mrgIdx > 2 || ((mrgIdx > 1 || !isGt4x4) && ibcFlag) +#endif + || ((!isAvailableA1 || (miLeft != miNeighbor)) && (!isAvailableB1 || (miAbove != miNeighbor)))) + ) +#else +#if JVET_Z0075_IBC_HMVP_ENLARGE + if (mrgIdx > 2 +#else + if (mrgIdx > 2 || ((mrgIdx > 1 || !isGt4x4) && ibcFlag) +#endif + || ((!isAvailableA1 || (miLeft != miNeighbor)) && (!isAvailableB1 || (miAbove != miNeighbor)))) +#endif + { + int index = 0; + if ((miNeighbor.interDir & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, miNeighbor.refIdx[0]) == pColPic) + { + index = 1; + } + else if (slice.isInterB() && (miNeighbor.interDir & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, miNeighbor.refIdx[1]) == pColPic) + { + index = 2; + } + if (index > 0) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = index; + miNeighbor.mv[index - 1].roundToPrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + if (index == 1) + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[index - 1], miNeighbor.refIdx[index - 1]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(), NOT_VALID); + } + else + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[index - 1], miNeighbor.refIdx[index - 1]); + } + +#if NON_ADJACENT_MRG_CAND + if (mrgCtx.xCheckSimilarMotionSubTMVP(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) + { + continue; + } +#endif + cnt++; + if (cnt == maxNumMergeCand) + { + break; + } + } + } + return; + } +} +#endif bool PU::addMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const int &mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const bool isAvailableA1, const MotionInfo miLeft, const bool isAvailableB1, const MotionInfo miAbove @@ -4110,55 +4222,25 @@ int PU::reorderInterMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, } } #endif - -void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, - int mmvdList, - const int& mrgCandIdx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void PU::getInterMergeCandidatesSubTMVP(const PredictionUnit &pu, MergeCtx& mrgCtx, + int col, + const int& mrgCandIdx #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM - , MergeCtx* tmvpMrgCtx - , MergeCtx* namvpMrgCtx + , MergeCtx* namvpMrgCtx #endif ) { -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM - if (!pu.cs->sps->getUseAML() || !pu.cs->sps->getUseTmvpNmvpReordering()) - { - tmvpMrgCtx = nullptr; - namvpMrgCtx = nullptr; - } -#endif const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; - const CodingStructure &cs = *pu.cs; - const Slice &slice = *pu.cs->slice; + const CodingStructure &cs = *pu.cs; + const Slice &slice = *pu.cs->slice; + const Picture *pColPic = slice.getRefPic(RefPicList(col == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), col == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); #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 = -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS - !pu.cs->sps->getUseAML() || !pu.cs->sps->getUseTmvpNmvpReordering() ? - (pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand()) : -#endif - (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 + const uint32_t mvdSimilarityThresh = SUB_TMVP_MV_THRESHOLD; #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM - const uint32_t maxNumMergeCand = pu.tmMergeFlag ? ((pu.cs->sps->getUseAML() -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS - && pu.cs->sps->getUseTmvpNmvpReordering() -#endif - ) ? TM_MRG_MAX_NUM_INIT_CANDS : pu.cs->sps->getMaxNumTMMergeCand()) : pu.cs->sps->getMaxNumMergeCand(); + const uint32_t maxNumMergeCand = pu.tmMergeFlag ? TM_MRG_MAX_NUM_INIT_CANDS : SUB_TMVP_CANDIDATE_NUM; #else - const uint32_t maxNumMergeCand = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand(); -#endif + const uint32_t maxNumMergeCand = pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand(); #endif #else const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumMergeCand(); @@ -4168,15 +4250,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.BcwIdx[ui] = BCW_DEFAULT; #if INTER_LIC mrgCtx.LICFlags[ui] = false; -#endif -#if JVET_AC0112_IBC_LIC - mrgCtx.ibcLicFlags[ui] = false; -#endif -#if JVET_AA0070_RRIBC - mrgCtx.rribcFlipTypes[ui] = 0; #endif mrgCtx.interDirNeighbours[ui] = 0; - mrgCtx.mvFieldNeighbours[(ui << 1) ].refIdx = NOT_VALID; + mrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; mrgCtx.useAltHpelIf[ui] = false; #if MULTI_HYP_PRED @@ -4186,63 +4262,10 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.candCost[ui] = MAX_UINT64; #endif } - - mrgCtx.numValidMergeCand = maxNumMergeCand; #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND mrgCtx.numCandToTestEnc = maxNumMergeCand; #endif // compute the location of the current PU -#if JVET_X0083_BM_AMVP_MERGE_MODE -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - int amvpMergeCtxMergeDir = -1; - RefPicList amvpRefList = REF_PIC_LIST_X; - bool useAmvpMergeMode = false; -#endif -#if JVET_Y0128_NON_CTC - if (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]) - { - mrgCtx.numValidMergeCand = (mrgCandIdx + 1) > maxNumMergeCand ? maxNumMergeCand : (mrgCandIdx + 1); -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - useAmvpMergeMode = true; - if (pu.amvpMergeModeFlag[0] == true) - { - amvpMergeCtxMergeDir = 1; - amvpRefList = REF_PIC_LIST_1; - } - else - { - amvpMergeCtxMergeDir = 2; - amvpRefList = REF_PIC_LIST_0; - } -#endif - } -#else - const int curPoc = slice.getPOC(); -#if !JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - RefPicList amvpRefList = REF_PIC_LIST_X; -#endif - RefPicList mergeRefList = REF_PIC_LIST_X; - int amvpPoc = -1; - if (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]) - { - mergeRefList = pu.amvpMergeModeFlag[0] ? REF_PIC_LIST_0 : REF_PIC_LIST_1; - amvpRefList = RefPicList(1 - mergeRefList); - amvpPoc = slice.getRefPOC(amvpRefList, pu.refIdx[amvpRefList]); -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - useAmvpMergeMode = true; - if (pu.amvpMergeModeFlag[0] == true) - { - amvpMergeCtxMergeDir = 1; - } - else - { - amvpMergeCtxMergeDir = 2; - } -#endif - mrgCtx.numValidMergeCand = (mrgCandIdx + 1) > maxNumMergeCand ? maxNumMergeCand : (mrgCandIdx + 1); - } -#endif -#endif int cnt = 0; @@ -4264,70 +4287,48 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, { miAbove = puAbove->getMotionInfo(posRT.offset(0, -1)); -#if JVET_X0083_BM_AMVP_MERGE_MODE -#if JVET_Y0128_NON_CTC - bool isValidAmMode = checkIsValidMergeMvCand(pu, miAbove.refIdx); -#else - bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miAbove.refIdx); -#endif - if (isValidAmMode) - { -#endif - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miAbove.interDir; - mrgCtx.useAltHpelIf[cnt] = miAbove.useAltHpelIf; - // get Mv from Above - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->BcwIdx : BCW_DEFAULT; -#if INTER_LIC - mrgCtx.LICFlags[cnt] = miAbove.usesLIC; -#endif - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]); - - if (slice.isInterB()) + int index = 0; + if ((miAbove.interDir & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, miAbove.refIdx[0]) == pColPic) { - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAbove.mv[1], miAbove.refIdx[1]); -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt] = puAbove->addHypData; -#endif + index = 1; } -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - if (useAmvpMergeMode) + else if (slice.isInterB() && (miAbove.interDir & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, miAbove.refIdx[1]) == pColPic) { - mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; - mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + index = 2; } -#endif -#if NON_ADJACENT_MRG_CAND || TM_MRG - if( !mrgCtx.xCheckSimilarMotion(cnt -#if TM_MRG - , mvdSimilarityThresh -#endif - ) ) - { -#endif - if (mrgCandIdx == cnt) + if (index > 0) { -#if TM_MRG - if( !pu.tmMergeFlag ) -#endif - return; - } + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = index; + miAbove.mv[index - 1].roundToPrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + if (index == 1) + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[index - 1], miAbove.refIdx[index - 1]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(), NOT_VALID); + } + else + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAbove.mv[index - 1], miAbove.refIdx[index - 1]); + } - cnt++; #if NON_ADJACENT_MRG_CAND || TM_MRG - } + if (!mrgCtx.xCheckSimilarMotionSubTMVP(cnt +#if TM_MRG + , mvdSimilarityThresh #endif -#if JVET_X0083_BM_AMVP_MERGE_MODE - } // if (isValidAmMode) + )) #endif + { + cnt++; + } + } } // early termination if (cnt == maxNumMergeCand) { -#if TM_MRG - if (!pu.tmMergeFlag) -#endif + mrgCtx.numValidMergeCand = cnt; return; } @@ -4344,303 +4345,803 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, { miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0)); -#if JVET_X0083_BM_AMVP_MERGE_MODE -#if JVET_Y0128_NON_CTC - bool isValidAmMode = checkIsValidMergeMvCand(pu, miLeft.refIdx); -#else - bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miLeft.refIdx); -#endif - if (isValidAmMode && (!isAvailableB1 || (miAbove != miLeft))) -#else - if (!isAvailableB1 || (miAbove != miLeft)) -#endif { - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miLeft.interDir; - mrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf; - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->BcwIdx : BCW_DEFAULT; -#if INTER_LIC - mrgCtx.LICFlags[cnt] = miLeft.usesLIC; -#endif - // get Mv from Left - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); - - if (slice.isInterB()) + int index = 0; + if ((miLeft.interDir & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, miLeft.refIdx[0]) == pColPic) { - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]); -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt] = puLeft->addHypData; -#endif + index = 1; } -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - if (useAmvpMergeMode) + else if (slice.isInterB() && (miLeft.interDir & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, miLeft.refIdx[1]) == pColPic) { - mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; - mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + index = 2; } -#endif + if (index > 0) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = index; + miLeft.mv[index - 1].roundToPrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + if (index == 1) + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[index - 1], miLeft.refIdx[index - 1]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(), NOT_VALID); + } + else + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[index - 1], miLeft.refIdx[index - 1]); + } + #if NON_ADJACENT_MRG_CAND || TM_MRG - if( !mrgCtx.xCheckSimilarMotion(cnt + if (!mrgCtx.xCheckSimilarMotionSubTMVP(cnt #if TM_MRG - , mvdSimilarityThresh -#endif - ) ) - { + , mvdSimilarityThresh #endif - if (mrgCandIdx == cnt) - { -#if TM_MRG - if (!pu.tmMergeFlag) + )) #endif - return; - } - - cnt++; -#if NON_ADJACENT_MRG_CAND || TM_MRG + { + cnt++; + } } -#endif } } // early termination - if( cnt == maxNumMergeCand ) + if (cnt == maxNumMergeCand) { -#if TM_MRG - if (!pu.tmMergeFlag) -#endif + mrgCtx.numValidMergeCand = cnt; return; } // above right - const PredictionUnit *puAboveRight = cs.getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType ); + const PredictionUnit *puAboveRight = cs.getPURestricted(posRT.offset(1, -1), pu, pu.chType); #if JVET_Y0065_GPM_INTRA - bool isAvailableB0 = puAboveRight && isDiffMER( pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter( *puAboveRight->cu ) && puAboveRight->getMotionInfo( posRT.offset( 1, -1 ) ).isInter; + bool isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu) && puAboveRight->getMotionInfo(posRT.offset(1, -1)).isInter; #else - bool isAvailableB0 = puAboveRight && isDiffMER( pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter( *puAboveRight->cu ); + bool isAvailableB0 = puAboveRight && isDiffMER(pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter(*puAboveRight->cu); #endif - if( isAvailableB0 ) + if (isAvailableB0) { - miAboveRight = puAboveRight->getMotionInfo( posRT.offset( 1, -1 ) ); + miAboveRight = puAboveRight->getMotionInfo(posRT.offset(1, -1)); -#if JVET_X0083_BM_AMVP_MERGE_MODE -#if JVET_Y0128_NON_CTC - bool isValidAmMode = checkIsValidMergeMvCand(pu, miAboveRight.refIdx); -#else - bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miAboveRight.refIdx); -#endif - if (isValidAmMode && (!isAvailableB1 || ( miAbove != miAboveRight ))) -#else - if( !isAvailableB1 || ( miAbove != miAboveRight ) ) -#endif { - - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir; - mrgCtx.useAltHpelIf[cnt] = miAboveRight.useAltHpelIf; - // get Mv from Above-right - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->BcwIdx : BCW_DEFAULT; -#if INTER_LIC - mrgCtx.LICFlags[cnt] = miAboveRight.usesLIC; -#endif - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] ); - - if( slice.isInterB() ) + int index = 0; + if ((miAboveRight.interDir & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, miAboveRight.refIdx[0]) == pColPic) { - mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveRight.mv[1], miAboveRight.refIdx[1] ); -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt] = puAboveRight->addHypData; -#endif + index = 1; } -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - if (useAmvpMergeMode) + else if (slice.isInterB() && (miAboveRight.interDir & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, miAboveRight.refIdx[1]) == pColPic) { - mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; - mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + index = 2; } -#endif + if (index > 0) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = index; + miAboveRight.mv[index - 1].roundToPrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + if (index == 1) + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[index - 1], miAboveRight.refIdx[index - 1]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(), NOT_VALID); + } + else + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveRight.mv[index - 1], miAboveRight.refIdx[index - 1]); + } #if NON_ADJACENT_MRG_CAND || TM_MRG - if( !mrgCtx.xCheckSimilarMotion(cnt + if (!mrgCtx.xCheckSimilarMotionSubTMVP(cnt #if TM_MRG - , mvdSimilarityThresh -#endif - ) ) - { + , mvdSimilarityThresh #endif - if (mrgCandIdx == cnt) - { -#if TM_MRG - if (!pu.tmMergeFlag) + )) #endif - return; - } - - cnt++; -#if NON_ADJACENT_MRG_CAND || TM_MRG + { + cnt++; + } } -#endif } } // early termination - if( cnt == maxNumMergeCand ) + if (cnt == maxNumMergeCand) { -#if TM_MRG - if (!pu.tmMergeFlag) -#endif + mrgCtx.numValidMergeCand = cnt; return; } //left bottom - const PredictionUnit *puLeftBottom = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); + const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); #if JVET_Y0065_GPM_INTRA - bool isAvailableA0 = puLeftBottom && isDiffMER( pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter( *puLeftBottom->cu ) && puLeftBottom->getMotionInfo( posLB.offset( -1, 1 ) ).isInter; + bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu) && puLeftBottom->getMotionInfo(posLB.offset(-1, 1)).isInter; #else - bool isAvailableA0 = puLeftBottom && isDiffMER( pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter( *puLeftBottom->cu ); + bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu); #endif - if( isAvailableA0 ) + if (isAvailableA0) { - miBelowLeft = puLeftBottom->getMotionInfo( posLB.offset( -1, 1 ) ); + miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1)); -#if JVET_X0083_BM_AMVP_MERGE_MODE -#if JVET_Y0128_NON_CTC - bool isValidAmMode = checkIsValidMergeMvCand(pu, miBelowLeft.refIdx); -#else - bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miBelowLeft.refIdx); -#endif - if (isValidAmMode && (!isAvailableA1 || ( miBelowLeft != miLeft ))) -#else - if( !isAvailableA1 || ( miBelowLeft != miLeft ) ) -#endif { - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; - mrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf; - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->BcwIdx : BCW_DEFAULT; -#if INTER_LIC - mrgCtx.LICFlags[cnt] = miBelowLeft.usesLIC; -#endif - // get Mv from Bottom-Left - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] ); - - if( slice.isInterB() ) + int index = 0; + if ((miBelowLeft.interDir & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, miBelowLeft.refIdx[0]) == pColPic) { - mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miBelowLeft.mv[1], miBelowLeft.refIdx[1] ); -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt] = puLeftBottom->addHypData; -#endif + index = 1; } -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - if (useAmvpMergeMode) + else if (slice.isInterB() && (miBelowLeft.interDir & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, miBelowLeft.refIdx[1]) == pColPic) { - mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; - mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + index = 2; } -#endif + if (index > 0) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = index; + miBelowLeft.mv[index - 1].roundToPrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + if (index == 1) + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[index - 1], miBelowLeft.refIdx[index - 1]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(), NOT_VALID); + } + else + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miBelowLeft.mv[index - 1], miBelowLeft.refIdx[index - 1]); + } #if NON_ADJACENT_MRG_CAND || TM_MRG - if( !mrgCtx.xCheckSimilarMotion(cnt + if (!mrgCtx.xCheckSimilarMotionSubTMVP(cnt #if TM_MRG - , mvdSimilarityThresh -#endif - ) ) - { + , mvdSimilarityThresh #endif - if (mrgCandIdx == cnt) - { -#if TM_MRG - if (!pu.tmMergeFlag) + )) #endif - return; - } - - cnt++; -#if NON_ADJACENT_MRG_CAND || TM_MRG + { + cnt++; + } } -#endif } } // early termination - if( cnt == maxNumMergeCand ) + if (cnt == maxNumMergeCand) { -#if TM_MRG - if (!pu.tmMergeFlag) -#endif + mrgCtx.numValidMergeCand = cnt; return; } -#if TM_MRG - if (pu.tmMergeFlag) - { - cnt = PU::reorderInterMergeCandidates(pu, mrgCtx, cnt, mvdSimilarityThresh); - - if ((mrgCandIdx >= 0 && mrgCandIdx < cnt) || cnt >= maxNumMergeCand) - { - return; - } - } -#endif - // above left - if ( cnt < 4 ) + if (cnt < 4) { - const PredictionUnit *puAboveLeft = cs.getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType ); + const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType); #if JVET_Y0065_GPM_INTRA - bool isAvailableB2 = puAboveLeft && isDiffMER( pu.lumaPos(), posLT.offset(-1, -1), plevel ) && CU::isInter( *puAboveLeft->cu ) && puAboveLeft->getMotionInfo( posLT.offset( -1, -1 ) ).isInter; + bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu) && puAboveLeft->getMotionInfo(posLT.offset(-1, -1)).isInter; #else - bool isAvailableB2 = puAboveLeft && isDiffMER( pu.lumaPos(), posLT.offset(-1, -1), plevel ) && CU::isInter( *puAboveLeft->cu ); + bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu); #endif - if( isAvailableB2 ) + if (isAvailableB2) { - miAboveLeft = puAboveLeft->getMotionInfo( posLT.offset( -1, -1 ) ); + miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1)); -#if JVET_X0083_BM_AMVP_MERGE_MODE -#if JVET_Y0128_NON_CTC - bool isValidAmMode = checkIsValidMergeMvCand(pu, miAboveLeft.refIdx); -#else - bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miAboveLeft.refIdx); -#endif - if (isValidAmMode && ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) )) -#else - if( ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) ) ) -#endif { - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; - mrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf; - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->BcwIdx : BCW_DEFAULT; -#if INTER_LIC - mrgCtx.LICFlags[cnt] = miAboveLeft.usesLIC; -#endif - // get Mv from Above-Left - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveLeft.mv[0], miAboveLeft.refIdx[0] ); - - if( slice.isInterB() ) + int index = 0; + if ((miAboveLeft.interDir & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, miAboveLeft.refIdx[0]) == pColPic) { - mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveLeft.mv[1], miAboveLeft.refIdx[1] ); -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[cnt] = puAboveLeft->addHypData; -#endif + index = 1; } -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - if (useAmvpMergeMode) + else if (slice.isInterB() && (miAboveLeft.interDir & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, miAboveLeft.refIdx[1]) == pColPic) { - mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; - mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + index = 2; } -#endif - -#if NON_ADJACENT_MRG_CAND || TM_MRG - if( !mrgCtx.xCheckSimilarMotion(cnt -#if TM_MRG - , mvdSimilarityThresh -#endif + if (index > 0) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = index; + miAboveLeft.mv[index - 1].roundToPrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + if (index == 1) + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[index - 1], miAboveLeft.refIdx[index - 1]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(), NOT_VALID); + } + else + { + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveLeft.mv[index - 1], miAboveLeft.refIdx[index - 1]); + } + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotionSubTMVP(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) +#endif + { + cnt++; + } + } + } + } + // early termination + if (cnt == maxNumMergeCand) + { + mrgCtx.numValidMergeCand = cnt; + return; + } + } +#if NON_ADJACENT_MRG_CAND + if (namvpMrgCtx != NULL) + { + for (uint32_t ui = 0; ui < namvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand; ++ui) + { + mrgCtx.interDirNeighbours[cnt] = namvpMrgCtx->interDirNeighbours[ui]; + mrgCtx.mvFieldNeighbours[cnt << 1] = namvpMrgCtx->mvFieldNeighbours[ui << 1]; + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = namvpMrgCtx->mvFieldNeighbours[(ui << 1) + 1]; + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotionSubTMVP(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) + { +#endif + mrgCtx.candCost[cnt] = namvpMrgCtx->candCost[ui]; + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } +#endif + + if (cnt != maxNumMergeCand) + { + addMergeHMVPCandSubTMVP(cs, mrgCtx, mrgCandIdx, maxNumMergeCand, cnt + , isAvailableA1, miLeft, isAvailableB1, miAbove, pu, col +#if TM_MRG + , mvdSimilarityThresh +#endif + ); + } + mrgCtx.numValidMergeCand = cnt; + + return; +} +#endif +void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, + int mmvdList, + const int& mrgCandIdx +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , MergeCtx* tmvpMrgCtx + , MergeCtx* namvpMrgCtx +#endif +) +{ +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + if (!pu.cs->sps->getUseAML() || !pu.cs->sps->getUseTmvpNmvpReordering()) + { + tmvpMrgCtx = nullptr; + namvpMrgCtx = nullptr; + } +#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_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 = +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + !pu.cs->sps->getUseAML() || !pu.cs->sps->getUseTmvpNmvpReordering() ? + (pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : pu.cs->sps->getMaxNumMergeCand()) : +#endif + (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() +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + && pu.cs->sps->getUseTmvpNmvpReordering() +#endif + ) ? 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 + for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) + { + mrgCtx.BcwIdx[ui] = BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[ui] = false; +#endif +#if JVET_AC0112_IBC_LIC + mrgCtx.ibcLicFlags[ui] = false; +#endif +#if JVET_AA0070_RRIBC + mrgCtx.rribcFlipTypes[ui] = 0; +#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 +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + mrgCtx.candCost[ui] = MAX_UINT64; +#endif + } + + mrgCtx.numValidMergeCand = maxNumMergeCand; +#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND + mrgCtx.numCandToTestEnc = maxNumMergeCand; +#endif + // compute the location of the current PU +#if JVET_X0083_BM_AMVP_MERGE_MODE +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + int amvpMergeCtxMergeDir = -1; + RefPicList amvpRefList = REF_PIC_LIST_X; + bool useAmvpMergeMode = false; +#endif +#if JVET_Y0128_NON_CTC + if (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]) + { + mrgCtx.numValidMergeCand = (mrgCandIdx + 1) > maxNumMergeCand ? maxNumMergeCand : (mrgCandIdx + 1); +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + useAmvpMergeMode = true; + if (pu.amvpMergeModeFlag[0] == true) + { + amvpMergeCtxMergeDir = 1; + amvpRefList = REF_PIC_LIST_1; + } + else + { + amvpMergeCtxMergeDir = 2; + amvpRefList = REF_PIC_LIST_0; + } +#endif + } +#else + const int curPoc = slice.getPOC(); +#if !JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + RefPicList amvpRefList = REF_PIC_LIST_X; +#endif + RefPicList mergeRefList = REF_PIC_LIST_X; + int amvpPoc = -1; + if (pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]) + { + mergeRefList = pu.amvpMergeModeFlag[0] ? REF_PIC_LIST_0 : REF_PIC_LIST_1; + amvpRefList = RefPicList(1 - mergeRefList); + amvpPoc = slice.getRefPOC(amvpRefList, pu.refIdx[amvpRefList]); +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + useAmvpMergeMode = true; + if (pu.amvpMergeModeFlag[0] == true) + { + amvpMergeCtxMergeDir = 1; + } + else + { + amvpMergeCtxMergeDir = 2; + } +#endif + mrgCtx.numValidMergeCand = (mrgCandIdx + 1) > maxNumMergeCand ? maxNumMergeCand : (mrgCandIdx + 1); + } +#endif +#endif + + int cnt = 0; + + const Position posLT = pu.Y().topLeft(); + const Position posRT = pu.Y().topRight(); + const Position posLB = pu.Y().bottomLeft(); + MotionInfo miAbove, miLeft, miAboveLeft, miAboveRight, miBelowLeft; + + // above + const PredictionUnit *puAbove = cs.getPURestricted(posRT.offset(0, -1), pu, pu.chType); + +#if JVET_Y0065_GPM_INTRA + bool isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && pu.cu != puAbove->cu && CU::isInter(*puAbove->cu) && puAbove->getMotionInfo(posRT.offset(0, -1)).isInter; +#else + bool isAvailableB1 = puAbove && isDiffMER(pu.lumaPos(), posRT.offset(0, -1), plevel) && pu.cu != puAbove->cu && CU::isInter(*puAbove->cu); +#endif + + if (isAvailableB1) + { + miAbove = puAbove->getMotionInfo(posRT.offset(0, -1)); + +#if JVET_X0083_BM_AMVP_MERGE_MODE +#if JVET_Y0128_NON_CTC + bool isValidAmMode = checkIsValidMergeMvCand(pu, miAbove.refIdx); +#else + bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miAbove.refIdx); +#endif + if (isValidAmMode) + { +#endif + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miAbove.interDir; + mrgCtx.useAltHpelIf[cnt] = miAbove.useAltHpelIf; + // get Mv from Above + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->BcwIdx : BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = miAbove.usesLIC; +#endif + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAbove.mv[0], miAbove.refIdx[0]); + + if (slice.isInterB()) + { + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAbove.mv[1], miAbove.refIdx[1]); +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = puAbove->addHypData; +#endif + } +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + if (useAmvpMergeMode) + { + mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; + mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + } +#endif +#if NON_ADJACENT_MRG_CAND || TM_MRG + if( !mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + ) ) + { +#endif + if (mrgCandIdx == cnt) + { +#if TM_MRG + if( !pu.tmMergeFlag ) +#endif + return; + } + + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif +#if JVET_X0083_BM_AMVP_MERGE_MODE + } // if (isValidAmMode) +#endif + } + + // early termination + if (cnt == maxNumMergeCand) + { +#if TM_MRG + if (!pu.tmMergeFlag) +#endif + return; + } + + //left + const PredictionUnit* puLeft = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + +#if JVET_Y0065_GPM_INTRA + const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && pu.cu != puLeft->cu && CU::isInter(*puLeft->cu) && puLeft->getMotionInfo(posLB.offset(-1, 0)).isInter; +#else + const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posLB.offset(-1, 0), plevel) && pu.cu != puLeft->cu && CU::isInter(*puLeft->cu); +#endif + + if (isAvailableA1) + { + miLeft = puLeft->getMotionInfo(posLB.offset(-1, 0)); + +#if JVET_X0083_BM_AMVP_MERGE_MODE +#if JVET_Y0128_NON_CTC + bool isValidAmMode = checkIsValidMergeMvCand(pu, miLeft.refIdx); +#else + bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miLeft.refIdx); +#endif + if (isValidAmMode && (!isAvailableB1 || (miAbove != miLeft))) +#else + if (!isAvailableB1 || (miAbove != miLeft)) +#endif + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miLeft.interDir; + mrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf; + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->BcwIdx : BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = miLeft.usesLIC; +#endif + // get Mv from Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); + + if (slice.isInterB()) + { + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]); +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = puLeft->addHypData; +#endif + } +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + if (useAmvpMergeMode) + { + mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; + mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + } +#endif +#if NON_ADJACENT_MRG_CAND || TM_MRG + if( !mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + ) ) + { +#endif + if (mrgCandIdx == cnt) + { +#if TM_MRG + if (!pu.tmMergeFlag) +#endif + return; + } + + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } + + // early termination + if( cnt == maxNumMergeCand ) + { +#if TM_MRG + if (!pu.tmMergeFlag) +#endif + return; + } + + // above right + const PredictionUnit *puAboveRight = cs.getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType ); + +#if JVET_Y0065_GPM_INTRA + bool isAvailableB0 = puAboveRight && isDiffMER( pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter( *puAboveRight->cu ) && puAboveRight->getMotionInfo( posRT.offset( 1, -1 ) ).isInter; +#else + bool isAvailableB0 = puAboveRight && isDiffMER( pu.lumaPos(), posRT.offset(1, -1), plevel) && CU::isInter( *puAboveRight->cu ); +#endif + + if( isAvailableB0 ) + { + miAboveRight = puAboveRight->getMotionInfo( posRT.offset( 1, -1 ) ); + +#if JVET_X0083_BM_AMVP_MERGE_MODE +#if JVET_Y0128_NON_CTC + bool isValidAmMode = checkIsValidMergeMvCand(pu, miAboveRight.refIdx); +#else + bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miAboveRight.refIdx); +#endif + if (isValidAmMode && (!isAvailableB1 || ( miAbove != miAboveRight ))) +#else + if( !isAvailableB1 || ( miAbove != miAboveRight ) ) +#endif + { + + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir; + mrgCtx.useAltHpelIf[cnt] = miAboveRight.useAltHpelIf; + // get Mv from Above-right + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->BcwIdx : BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = miAboveRight.usesLIC; +#endif + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] ); + + if( slice.isInterB() ) + { + mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveRight.mv[1], miAboveRight.refIdx[1] ); +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = puAboveRight->addHypData; +#endif + } +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + if (useAmvpMergeMode) + { + mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; + mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + } +#endif + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if( !mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + ) ) + { +#endif + if (mrgCandIdx == cnt) + { +#if TM_MRG + if (!pu.tmMergeFlag) +#endif + return; + } + + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } + // early termination + if( cnt == maxNumMergeCand ) + { +#if TM_MRG + if (!pu.tmMergeFlag) +#endif + return; + } + + //left bottom + const PredictionUnit *puLeftBottom = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); + +#if JVET_Y0065_GPM_INTRA + bool isAvailableA0 = puLeftBottom && isDiffMER( pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter( *puLeftBottom->cu ) && puLeftBottom->getMotionInfo( posLB.offset( -1, 1 ) ).isInter; +#else + bool isAvailableA0 = puLeftBottom && isDiffMER( pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter( *puLeftBottom->cu ); +#endif + + if( isAvailableA0 ) + { + miBelowLeft = puLeftBottom->getMotionInfo( posLB.offset( -1, 1 ) ); + +#if JVET_X0083_BM_AMVP_MERGE_MODE +#if JVET_Y0128_NON_CTC + bool isValidAmMode = checkIsValidMergeMvCand(pu, miBelowLeft.refIdx); +#else + bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miBelowLeft.refIdx); +#endif + if (isValidAmMode && (!isAvailableA1 || ( miBelowLeft != miLeft ))) +#else + if( !isAvailableA1 || ( miBelowLeft != miLeft ) ) +#endif + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; + mrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf; + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->BcwIdx : BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = miBelowLeft.usesLIC; +#endif + // get Mv from Bottom-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] ); + + if( slice.isInterB() ) + { + mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miBelowLeft.mv[1], miBelowLeft.refIdx[1] ); +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = puLeftBottom->addHypData; +#endif + } +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + if (useAmvpMergeMode) + { + mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; + mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + } +#endif + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if( !mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + ) ) + { +#endif + if (mrgCandIdx == cnt) + { +#if TM_MRG + if (!pu.tmMergeFlag) +#endif + return; + } + + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } + // early termination + if( cnt == maxNumMergeCand ) + { +#if TM_MRG + if (!pu.tmMergeFlag) +#endif + return; + } + +#if TM_MRG + if (pu.tmMergeFlag) + { + cnt = PU::reorderInterMergeCandidates(pu, mrgCtx, cnt, mvdSimilarityThresh); + + if ((mrgCandIdx >= 0 && mrgCandIdx < cnt) || cnt >= maxNumMergeCand) + { + return; + } + } +#endif + + // above left + if ( cnt < 4 ) + { + const PredictionUnit *puAboveLeft = cs.getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType ); + +#if JVET_Y0065_GPM_INTRA + bool isAvailableB2 = puAboveLeft && isDiffMER( pu.lumaPos(), posLT.offset(-1, -1), plevel ) && CU::isInter( *puAboveLeft->cu ) && puAboveLeft->getMotionInfo( posLT.offset( -1, -1 ) ).isInter; +#else + bool isAvailableB2 = puAboveLeft && isDiffMER( pu.lumaPos(), posLT.offset(-1, -1), plevel ) && CU::isInter( *puAboveLeft->cu ); +#endif + + if( isAvailableB2 ) + { + miAboveLeft = puAboveLeft->getMotionInfo( posLT.offset( -1, -1 ) ); + +#if JVET_X0083_BM_AMVP_MERGE_MODE +#if JVET_Y0128_NON_CTC + bool isValidAmMode = checkIsValidMergeMvCand(pu, miAboveLeft.refIdx); +#else + bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, miAboveLeft.refIdx); +#endif + if (isValidAmMode && ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) )) +#else + if( ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) ) ) +#endif + { + + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; + mrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf; + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->BcwIdx : BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = miAboveLeft.usesLIC; +#endif + // get Mv from Above-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveLeft.mv[0], miAboveLeft.refIdx[0] ); + + if( slice.isInterB() ) + { + mrgCtx.mvFieldNeighbours[( cnt << 1 ) + 1].setMvField( miAboveLeft.mv[1], miAboveLeft.refIdx[1] ); +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt] = puAboveLeft->addHypData; +#endif + } +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + if (useAmvpMergeMode) + { + mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; + mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + } +#endif + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if( !mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif ) ) { #endif @@ -4679,7 +5180,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, Position posC0; Position posC1 = pu.Y().center(); - bool C0Avail = false; + bool isC0Avail = false; bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); const SubPic& curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); if (curSubPic.getTreatedAsPicFlag()) @@ -4693,7 +5194,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, if (posYInCtu + 4 < pcv.maxCUHeight) { posC0 = posRB.offset(4, 4); - C0Avail = true; + isC0Avail = true; } } @@ -4701,91 +5202,120 @@ 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 -#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING - , &iRefIdx +#if !ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int cntTmp = cnt; + for (int colIdx = 0; colIdx < (pu.cu->slice->isInterB() ? 2 : 1); colIdx++) + { + if (colIdx && cnt != cntTmp) + { + break; + } #endif - ) ) - || getColocatedMVP( pu, REF_PIC_LIST_0, posC1, cColMv, iRefIdx, false + bool bExistMV = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv, iRefIdx, false #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING - , &iRefIdx +#if !ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , colIdx +#elif JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 #endif - ); - if (bExistMV) - { - dir |= 1; - mrgCtx.mvFieldNeighbours[2 * uiArrayAddr].setMvField(cColMv, iRefIdx); - } - - if (slice.isInterB()) - { - 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 + )) + || getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv, iRefIdx, false #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING - , &iRefIdx +#if !ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , colIdx +#elif JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 +#endif + , &iRefIdx #endif - ); + ); if (bExistMV) { - dir |= 2; - mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].setMvField(cColMv, iRefIdx); + dir |= 1; + mrgCtx.mvFieldNeighbours[2 * uiArrayAddr].setMvField(cColMv, iRefIdx); + } + + if (slice.isInterB()) + { + bExistMV = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv, iRefIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING +#if !ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , colIdx +#elif JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 +#endif + , &iRefIdx +#endif + )) + || getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv, iRefIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING +#if !ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , colIdx +#elif JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 +#endif + , &iRefIdx +#endif + ); + if (bExistMV) + { + dir |= 2; + mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].setMvField(cColMv, iRefIdx); + } } - } #if JVET_X0083_BM_AMVP_MERGE_MODE - int8_t tempRefIdx[2] = { mrgCtx.mvFieldNeighbours[2 * uiArrayAddr].refIdx, mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].refIdx }; + int8_t tempRefIdx[2] = { mrgCtx.mvFieldNeighbours[2 * uiArrayAddr].refIdx, mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].refIdx }; #if JVET_Y0128_NON_CTC - bool isValidAmMode = checkIsValidMergeMvCand(pu, tempRefIdx); + bool isValidAmMode = checkIsValidMergeMvCand(pu, tempRefIdx); #else - bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, tempRefIdx); + bool isValidAmMode = checkIsValidMergeMvCand(cs, pu, curPoc, amvpPoc, tempRefIdx); #endif - if (isValidAmMode && ( dir != 0 )) + if (isValidAmMode && (dir != 0)) #else - if( dir != 0 ) + if (dir != 0) #endif - { - bool addTMvp = true; - if( addTMvp ) { - mrgCtx.interDirNeighbours[uiArrayAddr] = dir; -#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE - if (useAmvpMergeMode) + bool addTMvp = true; + if (addTMvp) { - mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; - mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); - } + mrgCtx.interDirNeighbours[uiArrayAddr] = dir; +#if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE + if (useAmvpMergeMode) + { + mrgCtx.interDirNeighbours[cnt] = amvpMergeCtxMergeDir; + mrgCtx.mvFieldNeighbours[(cnt << 1) + amvpRefList].setMvField(Mv(), -1); + } #endif - mrgCtx.BcwIdx[uiArrayAddr] = BCW_DEFAULT; + mrgCtx.BcwIdx[uiArrayAddr] = BCW_DEFAULT; #if INTER_LIC - mrgCtx.LICFlags[uiArrayAddr] = false; + mrgCtx.LICFlags[uiArrayAddr] = false; #endif - mrgCtx.useAltHpelIf[uiArrayAddr] = false; + 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 + if (!mrgCtx.xCheckSimilarMotion(cnt #if TM_MRG - , mvdSimilarityThresh + , mvdSimilarityThresh #endif - ) ) - { + )) + { #endif - if (mrgCandIdx == cnt) - { - return; - } + if (mrgCandIdx == cnt) + { + return; + } - cnt++; + cnt++; #if NON_ADJACENT_MRG_CAND || TM_MRG - } + } #endif + } } - } #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM } else if (tmvpMrgCtx->numValidMergeCand > 0) @@ -4794,9 +5324,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #if TM_MRG if (!pu.tmMergeFlag #if JVET_AA0132_CONFIGURABLE_TM_TOOLS - || !pu.cs->sps->getUseTMMrgMode() + || !pu.cs->sps->getUseTMMrgMode() #endif - ) + ) #endif { for (uint32_t ui = 0; ui < tmvpMrgCtx->numValidMergeCand && cnt < maxNumMergeCand - 1; ++ui) @@ -4805,9 +5335,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #if INTER_LIC mrgCtx.LICFlags[cnt] = tmvpMrgCtx->LICFlags[ui]; #endif - mrgCtx.interDirNeighbours[cnt] = tmvpMrgCtx->interDirNeighbours[ui]; + mrgCtx.interDirNeighbours[cnt] = tmvpMrgCtx->interDirNeighbours[ui]; mrgCtx.mvFieldNeighbours[cnt << 1] = tmvpMrgCtx->mvFieldNeighbours[ui << 1]; - mrgCtx.useAltHpelIf[cnt] = tmvpMrgCtx->useAltHpelIf[ui]; + mrgCtx.useAltHpelIf[cnt] = tmvpMrgCtx->useAltHpelIf[ui]; if (slice.isInterB()) { mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = tmvpMrgCtx->mvFieldNeighbours[(ui << 1) + 1]; @@ -4819,9 +5349,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #if NON_ADJACENT_MRG_CAND || TM_MRG if (!mrgCtx.xCheckSimilarMotion(cnt #if TM_MRG - , mvdSimilarityThresh + , mvdSimilarityThresh #endif - )) + )) { #endif mrgCtx.candCost[cnt] = tmvpMrgCtx->candCost[ui]; @@ -4843,9 +5373,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #if INTER_LIC mrgCtx.LICFlags[cnt] = tmvpMrgCtx->LICFlags[0]; #endif - mrgCtx.interDirNeighbours[cnt] = tmvpMrgCtx->interDirNeighbours[0]; + mrgCtx.interDirNeighbours[cnt] = tmvpMrgCtx->interDirNeighbours[0]; mrgCtx.mvFieldNeighbours[cnt << 1] = tmvpMrgCtx->mvFieldNeighbours[0]; - mrgCtx.useAltHpelIf[cnt] = tmvpMrgCtx->useAltHpelIf[0]; + mrgCtx.useAltHpelIf[cnt] = tmvpMrgCtx->useAltHpelIf[0]; if (slice.isInterB()) { mrgCtx.mvFieldNeighbours[(cnt << 1) + 1] = tmvpMrgCtx->mvFieldNeighbours[1]; @@ -4857,9 +5387,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #if NON_ADJACENT_MRG_CAND || TM_MRG if (!mrgCtx.xCheckSimilarMotion(cnt #if TM_MRG - ,mvdSimilarityThresh + , mvdSimilarityThresh #endif - )) + )) { #endif mrgCtx.candCost[cnt] = tmvpMrgCtx->candCost[0]; @@ -4911,6 +5441,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #endif } #endif +#endif +#if !ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + } #endif } @@ -4928,7 +5461,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, MotionInfo miNeighbor; int offsetX = 0; int offsetY = 0; - const int iNACANDIDATE_NUM[4] = { 3, 5, 5, 5 }; + const int numNACandidate[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 @@ -4947,9 +5480,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, 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++) + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) #else - for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCand - 1; NASPIdx++) + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand - 1; iNASPIdx++) #endif { #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC @@ -4958,7 +5491,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, continue; } #endif - switch (idxMap[iDistanceIndex][NASPIdx]) + switch (idxMap[iDistanceIndex][iNASPIdx]) { case 0:offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height + iNADistanceVer - 1; break; case 1:offsetX = pu.Y().width + iNADistanceHor - 1; offsetY = -iNADistanceVer - 1; break; @@ -5458,11 +5991,11 @@ bool PU::addBMMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const i #endif #endif - int num_avai_candInLUT = (int)lut.size(); + int numCandInLUT = (int)lut.size(); - for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++) + for (int mrgIdx = 1; mrgIdx <= numCandInLUT; mrgIdx++) { - miNeighbor = lut[num_avai_candInLUT - mrgIdx]; + miNeighbor = lut[numCandInLUT - mrgIdx]; #if JVET_Z0075_IBC_HMVP_ENLARGE if ( mrgIdx > 2 @@ -6750,25 +7283,280 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveRight.mv[0], miAboveRight.refIdx[0]); mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveRight.mv[1], miAboveRight.refIdx[1]); #if JVET_Y0089_DMVR_BCW - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->BcwIdx : BCW_DEFAULT; + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->BcwIdx : BCW_DEFAULT; +#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 + } + } + } + // early termination + if (cnt == maxNumMergeCand) + { + mrgCtx.numValidMergeCand = cnt; + return; + } + + //left bottom + const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); + +#if JVET_Y0065_GPM_INTRA + bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu) && puLeftBottom->getMotionInfo(posLB.offset(-1, 1)).isInter; +#else + bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu); +#endif + + if (isAvailableA0) + { + miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1)); + + if (!isAvailableA1 || (miBelowLeft != miLeft)) + { + if (isBiPredFromDifferentDirEqDistPoc(pu, miBelowLeft.refIdx[0], miBelowLeft.refIdx[1]) + ) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; + mrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf; + // get Mv from Bottom-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miBelowLeft.mv[1], miBelowLeft.refIdx[1]); +#if JVET_Y0089_DMVR_BCW + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->BcwIdx : BCW_DEFAULT; +#endif + +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) + { +#endif + if (mrgCandIdx == cnt) + { +#if TM_MRG + if (!pu.tmMergeFlag) +#endif + return; + } + cnt++; +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } + } + // early termination + if (cnt == maxNumMergeCand) + { + mrgCtx.numValidMergeCand = cnt; + return; + } + + + const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType); + +#if JVET_Y0065_GPM_INTRA + bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu) && puAboveLeft->getMotionInfo(posLT.offset(-1, -1)).isInter; +#else + bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu); +#endif + + if (isAvailableB2) + { + miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1)); + + if ((!isAvailableA1 || (miLeft != miAboveLeft)) && (!isAvailableB1 || (miAbove != miAboveLeft))) + { + if (isBiPredFromDifferentDirEqDistPoc(pu, miAboveLeft.refIdx[0], miAboveLeft.refIdx[1]) + ) + { + + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; + mrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf; + // get Mv from Above-Left + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveLeft.mv[1], miAboveLeft.refIdx[1]); +#if JVET_Y0089_DMVR_BCW + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->BcwIdx : BCW_DEFAULT; +#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 + } + } + } + // early termination + if (cnt == maxNumMergeCand) + { + mrgCtx.numValidMergeCand = cnt; + return; + } + +#if INTER_RM_SIZE_CONSTRAINTS + if (slice.getPicHeader()->getEnableTMVPFlag()) +#else + 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); + const PreCalcValues& pcv = *cs.pcv; + + Position posC0; + Position posC1 = pu.Y().center(); + bool isC0Avail = false; + bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + const SubPic& curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + } + if (boundaryCond) + { + int posYInCtu = posRB.y & pcv.maxCUHeightMask; + if (posYInCtu + 4 < pcv.maxCUHeight) + { + posC0 = posRB.offset(4, 4); + isC0Avail = true; + } + } + + Mv cColMv; + int iRefIdx = 0; + int dir = 0; + unsigned uiArrayAddr = cnt; + bool bExistMV = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv, iRefIdx, false)) + || getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv, iRefIdx, false); + if (bExistMV) + { + dir |= 1; + mrgCtx.mvFieldNeighbours[2 * uiArrayAddr].setMvField(cColMv, iRefIdx); + } + + if (slice.isInterB()) + { + bExistMV = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv, iRefIdx, false)) + || getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv, iRefIdx, false); + if (bExistMV) + { + dir |= 2; + mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].setMvField(cColMv, iRefIdx); + } + } + + if (dir != 0) + { + bool addTMvp = isBiPredFromDifferentDirEqDistPoc(pu, mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 0].refIdx, mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].refIdx); + if (addTMvp) + { + mrgCtx.interDirNeighbours[uiArrayAddr] = dir; + mrgCtx.useAltHpelIf[uiArrayAddr] = false; +#if MULTI_HYP_PRED + 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 + } +#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++; -#if NON_ADJACENT_MRG_CAND || TM_MRG } + } + } +#else + 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 JVET_Y0089_DMVR_BCW + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? mvpMrgCtx1->BcwIdx[0] : BCW_DEFAULT; +#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 +#endif } + // early termination if (cnt == maxNumMergeCand) { @@ -6776,111 +7564,271 @@ void PU::getInterBMCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, return; } - //left bottom - const PredictionUnit *puLeftBottom = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); - -#if JVET_Y0065_GPM_INTRA - bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu) && puLeftBottom->getMotionInfo(posLB.offset(-1, 1)).isInter; +#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + int maxNumMergeCandMin1 = maxNumMergeCand; +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + maxNumMergeCandMin1 -= !pu.cs->sps->getUseAML() ? 1 : 0; +#endif #else - bool isAvailableA0 = puLeftBottom && isDiffMER(pu.lumaPos(), posLB.offset(-1, 1), plevel) && CU::isInter(*puLeftBottom->cu); + int maxNumMergeCandMin1 = maxNumMergeCand - 1; +#endif +#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 numNACandidate[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 (isAvailableA0) + for (int iDistanceIndex = 0; iDistanceIndex < NADISTANCE_LEVEL && cnt < maxNumMergeCandMin1; iDistanceIndex++) { - miBelowLeft = puLeftBottom->getMotionInfo(posLB.offset(-1, 1)); + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); - if (!isAvailableA1 || (miBelowLeft != miLeft)) + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCandMin1; iNASPIdx++) { - if (isBiPredFromDifferentDirEqDistPoc(pu, miBelowLeft.refIdx[0], miBelowLeft.refIdx[1]) - ) + switch (idxMap[iDistanceIndex][iNASPIdx]) { - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; - mrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf; - // get Mv from Bottom-Left - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miBelowLeft.mv[0], miBelowLeft.refIdx[0]); - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miBelowLeft.mv[1], miBelowLeft.refIdx[1]); + 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); + +#if JVET_Y0065_GPM_INTRA + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter; +#else + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); +#endif + + if (isAvailableNonAdjacent) + { + miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + + + 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 JVET_Y0089_DMVR_BCW - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->BcwIdx : BCW_DEFAULT; + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->BcwIdx : BCW_DEFAULT; #endif #if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) - { + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) #endif - if (mrgCandIdx == cnt) { -#if TM_MRG - if (!pu.tmMergeFlag) -#endif + if (mrgCandIdx == cnt) + { + mrgCtx.numValidMergeCand = cnt + 1; return; + } + cnt++; } - cnt++; -#if NON_ADJACENT_MRG_CAND || TM_MRG } -#endif } } } - // early termination - if (cnt == maxNumMergeCand) +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + } + else { - mrgCtx.numValidMergeCand = cnt; - return; + 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 JVET_Y0089_DMVR_BCW + mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? mvpMrgCtx2->BcwIdx[uiNumCand] : BCW_DEFAULT; +#endif +#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) + { +#if !JVET_Z0075_IBC_HMVP_ENLARGE + bool isGt4x4 = true; +#endif + bool bFound = addBMMergeHMVPCand(cs, mrgCtx, mrgCandIdx, maxNumMergeCandMin1, cnt + , isAvailableA1, miLeft, isAvailableB1, miAbove +#if !JVET_Z0075_IBC_HMVP_ENLARGE + , CU::isIBC(*pu.cu) + , isGt4x4 +#endif +#if TM_MRG + , mvThreshod +#endif + ); - const PredictionUnit *puAboveLeft = cs.getPURestricted(posLT.offset(-1, -1), pu, pu.chType); + if (bFound) + { + return; + } + } -#if JVET_Y0065_GPM_INTRA - bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu) && puAboveLeft->getMotionInfo(posLT.offset(-1, -1)).isInter; -#else - bool isAvailableB2 = puAboveLeft && isDiffMER(pu.lumaPos(), posLT.offset(-1, -1), plevel) && CU::isInter(*puAboveLeft->cu); +#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC) +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + if (!pu.cs->sps->getUseAML()) #endif - - if (isAvailableB2) { - miAboveLeft = puAboveLeft->getMotionInfo(posLT.offset(-1, -1)); - - if ((!isAvailableA1 || (miLeft != miAboveLeft)) && (!isAvailableB1 || (miAbove != miAboveLeft))) + if (cnt > 1 && cnt < maxNumMergeCand) { - if (isBiPredFromDifferentDirEqDistPoc(pu, miAboveLeft.refIdx[0], miAboveLeft.refIdx[1]) - ) + 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; - // get Inter Dir - mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; - mrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf; - // get Mv from Above-Left - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miAboveLeft.mv[0], miAboveLeft.refIdx[0]); - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miAboveLeft.mv[1], miAboveLeft.refIdx[1]); -#if JVET_Y0089_DMVR_BCW - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->BcwIdx : BCW_DEFAULT; + // 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; + } + } +#endif + + mrgCtx.numCandToTestEnc = cnt; + +#if JVET_Y0128_NON_CTC + while(cnt < maxNumMergeCand) +#else + if (cnt < maxNumMergeCand) +#endif + { + mrgCtx.interDirNeighbours[cnt] = 3; + mrgCtx.BcwIdx[cnt] = BCW_DEFAULT; +#if INTER_LIC + mrgCtx.LICFlags[cnt] = false; #endif - -#if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) - { +#if MULTI_HYP_PRED + mrgCtx.addHypNeighbours[cnt].clear(); #endif - if (mrgCandIdx == cnt) - { - mrgCtx.numValidMergeCand = cnt + 1; - return; - } - - cnt++; + mrgCtx.useAltHpelIf[cnt] = false; +#if JVET_Y0128_NON_CTC + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(0, 0), pu.cs->slice->getBMDefaultRefIdx(0)); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(0, 0), pu.cs->slice->getBMDefaultRefIdx(1)); +#else + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(0, 0), 0); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(0, 0), 0); +#endif +#if !JVET_Y0128_NON_CTC #if NON_ADJACENT_MRG_CAND || TM_MRG - } + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) #endif +#endif + { + if (mrgCandIdx == cnt) + { + mrgCtx.numValidMergeCand = cnt + 1; + return; } + cnt++; } } - // early termination - if (cnt == maxNumMergeCand) + mrgCtx.numValidMergeCand = cnt; +} +#endif + +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) +{ +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + if (!pu.cs->sps->getUseTmvpNmvpReordering()) { - mrgCtx.numValidMergeCand = cnt; + mrgCtx.numValidMergeCand = 0; return; } +#endif + + 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()) @@ -6888,182 +7836,242 @@ 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); const PreCalcValues& pcv = *cs.pcv; - - Position posC0; - Position posC1 = pu.Y().center(); - bool C0Avail = false; - bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + bool isC0Avail; + bool isC1Avail; + bool boundaryCond; const SubPic& curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); - if (curSubPic.getTreatedAsPicFlag()) - { - boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && - (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); - } - if (boundaryCond) - { - int posYInCtu = posRB.y & pcv.maxCUHeightMask; - if (posYInCtu + 4 < pcv.maxCUHeight) - { - posC0 = posRB.offset(4, 4); - C0Avail = true; - } - } + Position posRB = pu.Y().bottomRight().offset(-3, -3); + Position posCenter = pu.Y().center(); + Position posC0; + Position posC1; - Mv cColMv; 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); - if (bExistMV) - { - dir |= 1; - mrgCtx.mvFieldNeighbours[2 * uiArrayAddr].setMvField(cColMv, iRefIdx); - } + bool bExistMV0, bExistMV1; + Mv cColMv0, cColMv1; + int dir; - 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); - if (bExistMV) - { - dir |= 2; - mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].setMvField(cColMv, iRefIdx); - } - } + int offsetX0 = 0, offsetX1 = 0, offsetX2 = 0, offsetX3 = pu.Y().width >> 1; + int offsetY0 = 0, offsetY1 = 0, offsetY2 = 0, offsetY3 = pu.Y().height >> 1; - if (dir != 0) + const int numNACandidate[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++) { - bool addTMvp = isBiPredFromDifferentDirEqDistPoc(pu, mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 0].refIdx, mrgCtx.mvFieldNeighbours[2 * uiArrayAddr + 1].refIdx); - if (addTMvp) + const int iNADistanceHor = pu.Y().width * iDistanceIndex; + const int iNADistanceVer = pu.Y().height * iDistanceIndex; + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) { - mrgCtx.interDirNeighbours[uiArrayAddr] = dir; - mrgCtx.useAltHpelIf[uiArrayAddr] = false; -#if MULTI_HYP_PRED - mrgCtx.addHypNeighbours[uiArrayAddr].clear(); -#endif -#if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) + switch (idxMap[iDistanceIndex][iNASPIdx]) { -#endif - if (mrgCandIdx == cnt) + 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; + } + isC0Avail = 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) { - mrgCtx.numValidMergeCand = cnt + 1; - return; + posC0 = posRB.offset(offsetX0, offsetY0); + isC0Avail = true; } + } - cnt++; -#if NON_ADJACENT_MRG_CAND || TM_MRG + if (idxMap[iDistanceIndex][iNASPIdx] == 0) + { + isC1Avail = 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); + isC1Avail = true; + } + } } + else + { + isC1Avail = 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); + isC1Avail = true; + } + } + } + + bExistMV0 = bExistMV1 = false; + + // Candidate with L0 and L1 + dir = 0; + bExistMV0 = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv0, iRefIdx, false +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 #endif - } - } -#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)) + )) + || (isC1Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv0, iRefIdx, false +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 #endif + )); + if (bExistMV0) { - mrgCtx.candCost[cnt] = mvpMrgCtx1->candCost[uiNumCand]; - if (mrgCandIdx == cnt) + dir |= 1; + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(cColMv0, iRefIdx); + } + else + { + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(Mv(), NOT_VALID); + } + if (slice.isInterB()) + { + bExistMV1 = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv1, iRefIdx, false +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 +#endif + )) + || (isC1Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv1, iRefIdx, false +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 +#endif + )); + if (bExistMV1) { - mrgCtx.numValidMergeCand = cnt + 1; - return; + dir |= 2; + mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(cColMv1, iRefIdx); } - cnt++; - } - } - } -#else - 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]; + 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] = mvpMrgCtx1->addHypNeighbours[0]; -#endif -#if JVET_Y0089_DMVR_BCW - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? mvpMrgCtx1->BcwIdx[0] : BCW_DEFAULT; -#endif -#if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) + mrgCtx.addHypNeighbours[cnt].clear(); #endif - { - mrgCtx.candCost[cnt] = mvpMrgCtx1->candCost[0]; - if (mrgCandIdx == cnt) - { - mrgCtx.numValidMergeCand = cnt + 1; - return; + if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod + )) + { + cnt++; + if (cnt == maxNumMergeCand) + { + break; + } + } + } } - cnt++; } } +} + + mrgCtx.numValidMergeCand = cnt; +} #endif -#endif - } - // early termination - if (cnt == maxNumMergeCand) +#if NON_ADJACENT_MRG_CAND && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM +void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) +{ +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + if (!pu.cs->sps->getUseTmvpNmvpReordering()) { - mrgCtx.numValidMergeCand = cnt; + mrgCtx.numValidMergeCand = 0; return; } - -#if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC - int maxNumMergeCandMin1 = maxNumMergeCand; -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS - maxNumMergeCandMin1 -= !pu.cs->sps->getUseAML() ? 1 : 0; -#endif -#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) + 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; - 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 numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 }; + const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) { const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); - for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && cnt < maxNumMergeCandMin1; NASPIdx++) + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) { - switch (idxMap[iDistanceIndex][NASPIdx]) + switch (idxMap[iDistanceIndex][iNASPIdx]) { - 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; } @@ -7079,192 +8087,80 @@ 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; mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); -#if JVET_Y0089_DMVR_BCW - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puNonAdjacent->cu->BcwIdx : BCW_DEFAULT; -#endif -#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 JVET_Y0089_DMVR_BCW - mrgCtx.BcwIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? mvpMrgCtx2->BcwIdx[uiNumCand] : BCW_DEFAULT; -#endif -#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) - { -#if !JVET_Z0075_IBC_HMVP_ENLARGE - bool isGt4x4 = true; -#endif - bool bFound = addBMMergeHMVPCand(cs, mrgCtx, mrgCandIdx, maxNumMergeCandMin1, cnt - , isAvailableA1, miLeft, isAvailableB1, miAbove -#if !JVET_Z0075_IBC_HMVP_ENLARGE - , CU::isIBC(*pu.cu) - , isGt4x4 -#endif -#if TM_MRG - , mvThreshod -#endif - ); - if (bFound) - { - return; - } - } + const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; -#if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC) -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC - if (!pu.cs->sps->getUseAML()) -#endif + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) { - 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); - } + 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 iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap2[iDistanceIndex][iNASPIdx]) { -#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; - } - } -#endif - mrgCtx.numCandToTestEnc = cnt; + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); -#if JVET_Y0128_NON_CTC - while(cnt < maxNumMergeCand) -#else - if (cnt < maxNumMergeCand) -#endif - { - 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; -#if JVET_Y0128_NON_CTC - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(0, 0), pu.cs->slice->getBMDefaultRefIdx(0)); - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(0, 0), pu.cs->slice->getBMDefaultRefIdx(1)); +#if JVET_Y0065_GPM_INTRA + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter; #else - mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(0, 0), 0); - mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(0, 0), 0); -#endif -#if !JVET_Y0128_NON_CTC -#if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod)) -#endif + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); #endif - { - if (mrgCandIdx == cnt) + + if (isAvailableNonAdjacent) { - mrgCtx.numValidMergeCand = cnt + 1; - return; + 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++; + } + } } - cnt++; } } + mrgCtx.numValidMergeCand = cnt; } #endif #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM -void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) +void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) { #if JVET_AA0132_CONFIGURABLE_TM_TOOLS if (!pu.cs->sps->getUseTmvpNmvpReordering()) @@ -7273,12 +8169,21 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) return; } #endif - const CodingStructure &cs = *pu.cs; const Slice &slice = *pu.cs->slice; - const uint32_t mvThreshod = 1; +#if TM_MRG + const uint32_t mvdSimilarityThresh = 1; +#endif +#if TM_MRG && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC + const uint32_t maxNumMergeCand = +#if JVET_AA0132_CONFIGURABLE_TM_TOOLS + pu.cs->sps->getUseTMMrgMode() && +#endif + 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; @@ -7296,7 +8201,6 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) } int cnt = 0; - #if INTER_RM_SIZE_CONSTRAINTS if (slice.getPicHeader()->getEnableTMVPFlag()) #else @@ -7306,8 +8210,8 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) //>> 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 isC0Avail; + bool isC1Avail; bool boundaryCond; const SubPic& curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); Position posRB = pu.Y().bottomRight().offset(-3, -3); @@ -7323,23 +8227,23 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) 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 numNACandidate[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++) + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) { - switch (idxMap[iDistanceIndex][NASPIdx]) + switch (idxMap[iDistanceIndex][iNASPIdx]) { 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; + isC0Avail = false; if (curSubPic.getTreatedAsPicFlag()) { boundaryCond = ((posRB.x + offsetX0) <= curSubPic.getSubPicRight() && (posRB.y + offsetY0) <= curSubPic.getSubPicBottom()); @@ -7354,13 +8258,13 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) if (posYInCtu + offsetY0 < pcv.maxCUHeight) { posC0 = posRB.offset(offsetX0, offsetY0); - C0Avail = true; + isC0Avail = true; } } - if (idxMap[iDistanceIndex][NASPIdx] == 0) + if (idxMap[iDistanceIndex][iNASPIdx] == 0) { - C1Avail = false; + isC1Avail = false; if (curSubPic.getTreatedAsPicFlag()) { boundaryCond = ((posCenter.x + offsetX1) <= curSubPic.getSubPicRight() && (posCenter.y + offsetY1) <= curSubPic.getSubPicBottom()); @@ -7375,13 +8279,13 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) if (posYInCtu + offsetY1 < pcv.maxCUHeight) { posC1 = posCenter.offset(offsetX1, offsetY1); - C1Avail = true; + isC1Avail = true; } } } else { - C1Avail = false; + isC1Avail = false; if (curSubPic.getTreatedAsPicFlag()) { boundaryCond = ((posRB.x + offsetX1) <= curSubPic.getSubPicRight() && (posRB.y + offsetY1) <= curSubPic.getSubPicBottom()); @@ -7396,7 +8300,7 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) if (posYInCtu + offsetY1 < pcv.maxCUHeight) { posC1 = posRB.offset(offsetX1, offsetY1); - C1Avail = true; + isC1Avail = true; } } } @@ -7405,12 +8309,22 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) // 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)); + int refIdx[NUM_REF_PIC_LIST_01] = { 0, 0 }; + bExistMV0 = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv0, iRefIdx, false, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + 0, +#endif + &refIdx[REF_PIC_LIST_0])) + || (isC1Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv0, iRefIdx, false, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + 0, +#endif + &refIdx[REF_PIC_LIST_0])); + if (bExistMV0) { dir |= 1; - mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(cColMv0, iRefIdx); + mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(cColMv0, refIdx[REF_PIC_LIST_0]); } else { @@ -7418,12 +8332,21 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) } 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)); + bExistMV1 = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv1, iRefIdx, false, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + 0, +#endif + &refIdx[REF_PIC_LIST_1])) + || (isC1Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv1, iRefIdx, false, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + 0, +#endif + &refIdx[REF_PIC_LIST_1])); + if (bExistMV1) { dir |= 2; - mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(cColMv1, iRefIdx); + mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(cColMv1, refIdx[REF_PIC_LIST_1]); } else { @@ -7432,50 +8355,350 @@ void PU::getTmvpBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) } 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.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 +#if TM_MRG + , mvdSimilarityThresh +#endif + )) + { +#endif + cnt++; + if (cnt == maxNumMergeCand) + { + break; + } +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } + } + } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if (pu.tmMergeFlag) + { + offsetX0 = 0, offsetX1 = 0, offsetX2 = 0, offsetX3 = pu.Y().width >> 1; + offsetY0 = 0, offsetY1 = 0, offsetY2 = 0, offsetY3 = pu.Y().height >> 1; + + for (int iDistanceIndex = 0; iDistanceIndex < TMVP_DISTANCE_LEVEL && cnt < (maxNumMergeCand + 1); iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * iDistanceIndex; + const int iNADistanceVer = pu.Y().height * iDistanceIndex; + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < (maxNumMergeCand + 1); iNASPIdx++) + { + switch (idxMap[iDistanceIndex][iNASPIdx]) + { + 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; + } + isC0Avail = 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); + isC0Avail = true; + } + } + + if (idxMap[iDistanceIndex][iNASPIdx] == 0) + { + isC1Avail = 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); + isC1Avail = true; + } + } + } + else + { + isC1Avail = 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); + isC1Avail = true; + } + } + } + + bExistMV0 = bExistMV1 = false; + + // Candidate with L0 and L1 + dir = 0; + int refIdx[NUM_REF_PIC_LIST_01] = { 0, 0 }; + bExistMV0 = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv0, iRefIdx, false, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + 1, +#endif + &refIdx[REF_PIC_LIST_0])) + || (isC1Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv0, iRefIdx, false, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + 1, +#endif + &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 = (isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv1, iRefIdx, false, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + 1, +#endif + &refIdx[REF_PIC_LIST_1])) + || (isC1Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv1, iRefIdx, false, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + 1, +#endif + &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 (!mrgCtx.xCheckSimilarMotion(cnt, mvThreshod - )) +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(cnt +#if TM_MRG + , mvdSimilarityThresh +#endif + )) + { +#endif + cnt++; + if (cnt == (maxNumMergeCand + 1)) + { + 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 + 1)) 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) { - cnt++; - if (cnt == maxNumMergeCand) + 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 + )) { - break; +#endif + cnt++; + if (cnt == (maxNumMergeCand + 1)) + { + break; + } +#if NON_ADJACENT_MRG_CAND || TM_MRG } +#endif } } } } } -} +#endif + } 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) +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM && NON_ADJACENT_MRG_CAND +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void PU::getNonAdjacentMergeCandSubTMVP(const PredictionUnit &pu, MergeCtx& mrgCtx, int col) { -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS - if (!pu.cs->sps->getUseTmvpNmvpReordering()) - { - mrgCtx.numValidMergeCand = 0; - return; - } -#endif const unsigned plevel = pu.cs->sps->getLog2ParallelMergeLevelMinus2() + 2; const CodingStructure &cs = *pu.cs; + const Slice &slice = *pu.cs->slice; - const uint32_t mvThreshod = getBDMVRMvdThreshold(pu); - + const uint32_t mvdSimilarityThresh = SUB_TMVP_MV_THRESHOLD; const uint32_t maxNumMergeCand = NUM_NON_ADJ_CANDS; + const Picture *pColPic = slice.getRefPic(RefPicList(col == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), col == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); + for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { mrgCtx.BcwIdx[ui] = BCW_DEFAULT; @@ -7502,7 +8725,7 @@ void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) 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 numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 }; const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) @@ -7510,7 +8733,7 @@ void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) 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++) + for (int NASPIdx = 0; NASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; NASPIdx++) { switch (idxMap[iDistanceIndex][NASPIdx]) { @@ -7528,362 +8751,114 @@ void PU::getNonAdjacentBMCand(const PredictionUnit &pu, MergeCtx& mrgCtx) const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); -#if JVET_Y0065_GPM_INTRA - bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter; -#else - bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); -#endif - - if (isAvailableNonAdjacent) - { - miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); - - 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); - -#if JVET_Y0065_GPM_INTRA - bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu) && puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)).isInter; -#else bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); -#endif if (isAvailableNonAdjacent) { miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); - 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) -{ -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS - if (!pu.cs->sps->getUseTmvpNmvpReordering()) - { - mrgCtx.numValidMergeCand = 0; - return; - } -#endif - const CodingStructure &cs = *pu.cs; - const Slice &slice = *pu.cs->slice; - -#if TM_MRG - const uint32_t mvdSimilarityThresh = 1; -#endif -#if TM_MRG && JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC - const uint32_t maxNumMergeCand = -#if JVET_AA0132_CONFIGURABLE_TM_TOOLS - pu.cs->sps->getUseTMMrgMode() && -#endif - 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; -#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) + int index = 0; + if ((miNeighbor.interDir & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, miNeighbor.refIdx[0]) == pColPic) { - dir |= 1; - mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(cColMv0, refIdx[REF_PIC_LIST_0]); + index = 1; } - else + else if (slice.isInterB() && (miNeighbor.interDir & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, miNeighbor.refIdx[1]) == pColPic) { - mrgCtx.mvFieldNeighbours[2 * cnt].setMvField(Mv(), NOT_VALID); + index = 2; } - if (slice.isInterB()) + if (index > 0) { - 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) + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = index; + miNeighbor.mv[index - 1].roundToPrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + if (index == 1) { - dir |= 2; - mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(cColMv1, refIdx[REF_PIC_LIST_1]); + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[index - 1], miNeighbor.refIdx[index - 1]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(), NOT_VALID); } else { - mrgCtx.mvFieldNeighbours[2 * cnt + 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[index - 1], miNeighbor.refIdx[index - 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 + if (!mrgCtx.xCheckSimilarMotionSubTMVP(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) + } + } + + const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; + + for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) + { + const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); + const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); + + for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) + { + switch (idxMap2[iDistanceIndex][iNASPIdx]) + { + case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; + case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; + case 2:offsetX = offsetX0; offsetY = offsetY0 + ((offsetY2 - offsetY0) >> 1); break; + case 3:offsetX = offsetX0 + ((offsetX2 - offsetX0) >> 1); offsetY = offsetY0; break; + default: printf("error!"); exit(0); break; + } + + const PredictionUnit *puNonAdjacent = cs.getPURestricted(posLT.offset(offsetX, offsetY), pu, pu.chType); + + bool isAvailableNonAdjacent = puNonAdjacent && isDiffMER(pu.lumaPos(), posLT.offset(offsetX, offsetY), plevel) && CU::isInter(*puNonAdjacent->cu); + + if (isAvailableNonAdjacent) + { + miNeighbor = puNonAdjacent->getMotionInfo(posLT.offset(offsetX, offsetY)); + + int index = 0; + if ((miNeighbor.interDir & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, miNeighbor.refIdx[0]) == pColPic) { - // 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) + index = 1; + } + else if (slice.isInterB() && (miNeighbor.interDir & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, miNeighbor.refIdx[1]) == pColPic) + { + index = 2; + } + if (index > 0) + { + // get Inter Dir + mrgCtx.interDirNeighbours[cnt] = index; + miNeighbor.mv[index - 1].roundToPrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + if (index == 1) { - 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 + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[index - 1], miNeighbor.refIdx[index - 1]); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(Mv(), NOT_VALID); } - - // 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) + else { - 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 + mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(Mv(), NOT_VALID); + mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[index - 1], miNeighbor.refIdx[index - 1]); + } + } #if NON_ADJACENT_MRG_CAND || TM_MRG - if (!mrgCtx.xCheckSimilarMotion(cnt + if (!mrgCtx.xCheckSimilarMotionSubTMVP(cnt #if TM_MRG - , mvdSimilarityThresh -#endif - )) - { + , mvdSimilarityThresh #endif - cnt++; - if (cnt == maxNumMergeCand) - { - break; - } -#if NON_ADJACENT_MRG_CAND || TM_MRG - } + )) #endif - } + { + cnt++; } } } @@ -7892,8 +8867,6 @@ void PU::getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) 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) { #if JVET_AA0132_CONFIGURABLE_TM_TOOLS @@ -7951,7 +8924,7 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) 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 numNACandidate[7] = { 5, 9, 9, 9, 9, 9, 9 }; const int idxMap[7][9] = { { 0, 1, 2, 3, 4 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 },{ 0, 1, 2, 3, 4, 5, 6, 7, 8 } }; for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) @@ -7959,9 +8932,9 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) 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++) + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) { - switch (idxMap[iDistanceIndex][NASPIdx]) + switch (idxMap[iDistanceIndex][iNASPIdx]) { case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY0 = pu.Y().height + iNADistanceVer - 1; break; case 1:offsetX = offsetX1 = pu.Y().width + iNADistanceHor - 1; offsetY = offsetY1 = -iNADistanceVer - 1; break; @@ -8020,7 +8993,7 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) } } - const int iNACANDIDATE_NUM2[7] = { 4, 4, 4, 4, 4, 4, 4 }; + const int numNACandidate2[7] = { 4, 4, 4, 4, 4, 4, 4 }; const int idxMap2[7][5] = { { 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 },{ 0, 1, 2, 3 } }; for (int iDistanceIndex = 0; iDistanceIndex < 7 && cnt < maxNumMergeCand; iDistanceIndex++) @@ -8028,9 +9001,9 @@ void PU::getNonAdjacentMergeCand(const PredictionUnit &pu, MergeCtx& mrgCtx) 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++) + for (int iNASPIdx = 0; iNASPIdx < numNACandidate2[iDistanceIndex] && cnt < maxNumMergeCand; iNASPIdx++) { - switch (idxMap2[iDistanceIndex][NASPIdx]) + switch (idxMap2[iDistanceIndex][iNASPIdx]) { case 0:offsetX = offsetX0 = -iNADistanceHor - 1; offsetY = offsetY2 + ((pu.Y().height + iNADistanceVer - 1 - offsetY2) >> 1); break; case 1:offsetX = offsetX2 + ((pu.Y().width + iNADistanceHor - 1 - offsetX2) >> 1); offsetY = offsetY0 = -iNADistanceVer - 1; break; @@ -8361,6 +9334,9 @@ 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 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , int col +#endif , int* targetRefIdx #endif ) @@ -8374,7 +9350,11 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList const Slice &slice = *pu.cs->slice; // use coldir. +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + const Picture* const pColPic = slice.getRefPic(RefPicList(col == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), col == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); +#else const Picture* const pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0), slice.getColRefIdx()); +#endif if( !pColPic ) { @@ -8390,7 +9370,13 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList return false; } } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int pocCur = slice.getPOC(); + int pocCol = pColPic->getPOC(); + RefPicList eColRefPicList = slice.getCheckLDC() ? eRefPicList : RefPicList(pocCur > pocCol); +#else RefPicList eColRefPicList = slice.getCheckLDC() ? eRefPicList : RefPicList(slice.getColFromL0Flag()); +#endif const MotionInfo& mi = pColPic->cs->getMotionInfo( pos ); @@ -8448,7 +9434,11 @@ bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING if (targetRefIdx != nullptr) { - *targetRefIdx = slice.getImRefIdx(mi.sliceIdx, eColRefPicList, eRefPicList, iColRefIdx); + *targetRefIdx = slice.getImRefIdx(mi.sliceIdx, eColRefPicList, eRefPicList, iColRefIdx +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , col +#endif + ); if (*targetRefIdx == -1) { return false; @@ -8888,24 +9878,227 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in if( !bAdded ) { - addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, *pInfo ); + addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, *pInfo ); + } + } + } + + for( int i = 0; i < pInfo->numCand; i++ ) + { + pInfo->mvCand[i].roundTransPrecInternal2Amvr(pu.cu->imv); + } + + if( pInfo->numCand == 2 ) + { + if( pInfo->mvCand[0] == pInfo->mvCand[1] ) + { + pInfo->numCand = 1; + } + } + +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +#if TM_AMVP + if (cs.picHeader->getEnableTMVPFlag() && pInfo->numCand < pInfo->maxStorageSize && (pu.lumaSize().width + pu.lumaSize().height > 8)) +#else + if (cs.picHeader->getEnableTMVPFlag() && pInfo->numCand < AMVP_MAX_NUM_CANDS && (pu.lumaSize().width + pu.lumaSize().height > 8)) +#endif + { + MergeCtx mrgCtxAll[2]; + MergeCtx MrgTmvp[2]; + MergeCtx namvpMergeCandCtx[2]; + bool isSaved = true; + if (pu.cs->sps->getUseAML() && interPred != NULL) + { + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + bool tplAvail = interPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); + if (tplAvail) + { + int poc0 = pu.cu->slice->getRefPic(RefPicList(1 - pu.cu->slice->getColFromL0Flag()), pu.cu->slice->getColRefIdx())->getPOC(); + int poc1 = pu.cu->slice->getRefPic(RefPicList(1 - pu.cu->slice->getColFromL0Flag2nd()), pu.cu->slice->getColRefIdx2nd())->getPOC(); + for (int col = 0; col < ((pu.cu->slice->getCheckLDC() || (poc0 == poc1)) ? 1 : 2); col++) + { + if (col == 0 || (!pu.cs->sps->getUseFastSubTmvp())) + { +#if JVET_Z0054_BLK_REF_PIC_REORDER + if (!interPred->readMergeBuffer(mrgCtxAll[0], mrgCtxAll[1], *pu.cu)) +#else + if (cs.pcv->isEncoder && interPred->readMergeBuffer(mrgCtxAll[0], mrgCtxAll[1], *pu.cu)) +#endif + { + PU::getNonAdjacentMergeCandSubTMVP(pu, namvpMergeCandCtx[col], col); + interPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx[col], 9); + PU::getInterMergeCandidatesSubTMVP(pu, mrgCtxAll[col], col, -1, &namvpMergeCandCtx[col]); + isSaved = false; + } + + PU::getTMVPCandOpt(pu, eRefPicList, refIdx, MrgTmvp[col], mrgCtxAll[col], col); + interPred->adjustMergeCandidatesInOneCandidateGroup(pu, MrgTmvp[col], AMVP_TMVP_INDEX); + if (MrgTmvp[col].numValidMergeCand > 0) + { + Mv mvTmp = MrgTmvp[col].mvFieldNeighbours[eRefPicList].mv; + mvTmp.roundTransPrecInternal2Amvr(pu.cu->imv); +#if TM_AMVP + pInfo->mvCand[pInfo->numCand] = mvTmp; + if (!pInfo->xCheckSimilarMotion(pInfo->numCand)) + { + pInfo->numCand++; + } +#else + pInfo->mvCand[pInfo->numCand++] = cColMv; +#endif + } + } + else + { + // Get Temporal Motion Predictor + const int refIdxCol = refIdx; + + Position posRB = pu.Y().bottomRight().offset(-3, -3); + + const PreCalcValues& pcv = *cs.pcv; + + Position posC0; + bool isC0Avail = false; + Position posC1 = pu.Y().center(); + Mv cColMv; + + bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + const SubPic &curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + } + if (boundaryCond) + { + int posYInCtu = posRB.y & pcv.maxCUHeightMask; + if (posYInCtu + 4 < pcv.maxCUHeight) + { + posC0 = posRB.offset(4, 4); + isC0Avail = true; + } + } + for (int colIdx = 1; colIdx < (pu.cu->slice->isInterB() ? 2 : 1); colIdx++) + { + if ((isC0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdxCol, false, colIdx)) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdxCol, false, colIdx)) + { + cColMv.roundTransPrecInternal2Amvr(pu.cu->imv); +#if TM_AMVP + pInfo->mvCand[pInfo->numCand] = cColMv; + if (!pInfo->xCheckSimilarMotion(pInfo->numCand)) + { + pInfo->numCand++; + } +#else + pInfo->mvCand[pInfo->numCand++] = cColMv; +#endif + } + } + } + } + } + else + { + // Get Temporal Motion Predictor + const int refIdxCol = refIdx; + + Position posRB = pu.Y().bottomRight().offset(-3, -3); + + const PreCalcValues& pcv = *cs.pcv; + + Position posC0; + bool isC0Avail = false; + Position posC1 = pu.Y().center(); + Mv cColMv; + + bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + const SubPic &curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + } + if (boundaryCond) + { + int posYInCtu = posRB.y & pcv.maxCUHeightMask; + if (posYInCtu + 4 < pcv.maxCUHeight) + { + posC0 = posRB.offset(4, 4); + isC0Avail = true; + } + } + for (int colIdx = 0; colIdx < (pu.cu->slice->isInterB() ? 2 : 1); colIdx++) + { + if ((isC0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdxCol, false, colIdx)) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdxCol, false, colIdx)) + { + cColMv.roundTransPrecInternal2Amvr(pu.cu->imv); +#if TM_AMVP + pInfo->mvCand[pInfo->numCand] = cColMv; + if (!pInfo->xCheckSimilarMotion(pInfo->numCand)) + { + pInfo->numCand++; + } +#else + pInfo->mvCand[pInfo->numCand++] = cColMv; +#endif + } + } + } + } + else + { + // Get Temporal Motion Predictor + const int refIdxCol = refIdx; + + Position posRB = pu.Y().bottomRight().offset(-3, -3); + + const PreCalcValues& pcv = *cs.pcv; + + Position posC0; + bool isC0Avail = false; + Position posC1 = pu.Y().center(); + Mv cColMv; + + bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); + const SubPic &curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); + if (curSubPic.getTreatedAsPicFlag()) + { + boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + } + if (boundaryCond) + { + int posYInCtu = posRB.y & pcv.maxCUHeightMask; + if (posYInCtu + 4 < pcv.maxCUHeight) + { + posC0 = posRB.offset(4, 4); + isC0Avail = true; + } + } + for (int colIdx = 0; colIdx < (pu.cu->slice->isInterB() ? 2 : 1); colIdx++) + { + if ((isC0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdxCol, false, colIdx)) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdxCol, false, colIdx)) + { + cColMv.roundTransPrecInternal2Amvr(pu.cu->imv); +#if TM_AMVP + pInfo->mvCand[pInfo->numCand] = cColMv; + if (!pInfo->xCheckSimilarMotion(pInfo->numCand)) + { + pInfo->numCand++; + } +#else + pInfo->mvCand[pInfo->numCand++] = cColMv; +#endif + } } } - } - - for( int i = 0; i < pInfo->numCand; i++ ) - { - pInfo->mvCand[i].roundTransPrecInternal2Amvr(pu.cu->imv); - } - - if( pInfo->numCand == 2 ) - { - if( pInfo->mvCand[0] == pInfo->mvCand[1] ) + if (!isSaved) { - pInfo->numCand = 1; + interPred->writeMergeBuffer(mrgCtxAll[0], mrgCtxAll[1], *pu.cu); } } - +#else #if TM_AMVP if (cs.picHeader->getEnableTMVPFlag() && pInfo->numCand < pInfo->maxStorageSize && (pu.lumaSize().width + pu.lumaSize().height > 12)) #else @@ -8913,14 +10106,14 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in #endif { // Get Temporal Motion Predictor - const int refIdx_Col = refIdx; + const int refIdxCol = refIdx; Position posRB = pu.Y().bottomRight().offset(-3, -3); const PreCalcValues& pcv = *cs.pcv; Position posC0; - bool C0Avail = false; + bool isC0Avail = false; Position posC1 = pu.Y().center(); Mv cColMv; @@ -8929,7 +10122,7 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in if (curSubPic.getTreatedAsPicFlag()) { boundaryCond = ((posRB.x + pcv.minCUWidth) <= curSubPic.getSubPicRight() && - (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); + (posRB.y + pcv.minCUHeight) <= curSubPic.getSubPicBottom()); } if (boundaryCond) { @@ -8937,23 +10130,51 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in if (posYInCtu + 4 < pcv.maxCUHeight) { posC0 = posRB.offset(4, 4); - C0Avail = true; + isC0Avail = true; } } - if ( ( C0Avail && getColocatedMVP( pu, eRefPicList, posC0, cColMv, refIdx_Col, false ) ) || getColocatedMVP( pu, eRefPicList, posC1, cColMv, refIdx_Col, false ) ) +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +#if !ENABLE_INTER_TEMPLATE_MATCHING + int count = 0; +#endif + for (int colIdx = 0; colIdx < (pu.cu->slice->isInterB() ? 2 : 1); colIdx++) { - cColMv.roundTransPrecInternal2Amvr(pu.cu->imv); -#if TM_AMVP - pInfo->mvCand[pInfo->numCand] = cColMv; - if (!pInfo->xCheckSimilarMotion(pInfo->numCand)) +#endif +#if !ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if (count) { - pInfo->numCand++; + break; } +#endif + if ((isC0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdxCol, false +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , colIdx +#endif + )) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdxCol, false +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , colIdx +#endif + )) + { +#if !ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + count++; +#endif + cColMv.roundTransPrecInternal2Amvr(pu.cu->imv); +#if TM_AMVP + pInfo->mvCand[pInfo->numCand] = cColMv; + if (!pInfo->xCheckSimilarMotion(pInfo->numCand)) + { + pInfo->numCand++; + } #else - pInfo->mvCand[pInfo->numCand++] = cColMv; + pInfo->mvCand[pInfo->numCand++] = cColMv; #endif + } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION } +#endif } +#endif #if TM_AMVP // Non-adjacent candidates @@ -8963,7 +10184,7 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in MotionInfo miNeighbor; int offsetX = 0; int offsetY = 0; - const int iNACANDIDATE_NUM[4] = { 3, 5, 5, 5 }; + const int numNACandidate[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 && pInfo->numCand < pInfo->maxStorageSize; iDistanceIndex++) @@ -8971,9 +10192,9 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in const int iNADistanceHor = pu.Y().width * (iDistanceIndex + 1); const int iNADistanceVer = pu.Y().height * (iDistanceIndex + 1); - for (int NASPIdx = 0; NASPIdx < iNACANDIDATE_NUM[iDistanceIndex] && pInfo->numCand < pInfo->maxStorageSize; NASPIdx++) + for (int iNASPIdx = 0; iNASPIdx < numNACandidate[iDistanceIndex] && pInfo->numCand < pInfo->maxStorageSize; iNASPIdx++) { - switch (idxMap[iDistanceIndex][NASPIdx]) + switch (idxMap[iDistanceIndex][iNASPIdx]) { case 0: offsetX = -iNADistanceHor - 1; offsetY = pu.Y().height + iNADistanceVer - 1; break; case 1: offsetX = pu.Y().width + iNADistanceHor - 1; offsetY = -iNADistanceVer - 1; break; @@ -10512,17 +11733,17 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co bC0Avail = true; } } - if ( (bC0Avail && getColocatedMVP( pu, eRefPicList, posC0, cColMv, refIdxCol, false ) ) || getColocatedMVP( pu, eRefPicList, posC1, cColMv, refIdxCol, false ) ) - { - cColMv.roundAffinePrecInternal2Amvr(pu.cu->imv); - affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = cColMv; - affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = cColMv; - affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = cColMv; + if ((bC0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdxCol, false)) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdxCol, false)) + { + cColMv.roundAffinePrecInternal2Amvr(pu.cu->imv); + affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = cColMv; + affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = cColMv; + affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = cColMv; #if JVET_Z0139_HIST_AFF - if (checkLastAffineAMVPCandRedundancy(pu, affiAMVPInfo)) + if (checkLastAffineAMVPCandRedundancy(pu, affiAMVPInfo)) #endif - affiAMVPInfo.numCand++; - } + affiAMVPInfo.numCand++; + } } #if JVET_Z0139_NA_AFF @@ -10909,6 +12130,9 @@ void PU::getAffineControlPointCand(const PredictionUnit &pu, MotionInfo mi[4], b affMrgType.mvFieldNeighbours[(affMrgType.numValidMergeCand << 1) + 1][i].mv = cMv[1][i]; affMrgType.mvFieldNeighbours[(affMrgType.numValidMergeCand << 1) + 1][i].refIdx = refIdx[1]; } +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgType.colIdx[affMrgType.numValidMergeCand] = 0; +#endif affMrgType.interDirNeighbours[affMrgType.numValidMergeCand] = dir; affMrgType.affineType[affMrgType.numValidMergeCand] = curType; affMrgType.BcwIdx[affMrgType.numValidMergeCand] = (dir == 3) ? bcwIdx : BCW_DEFAULT; @@ -11833,6 +13057,9 @@ const int getAvailableAffineNeighboursForAbovePredictor( const PredictionUnit &p } void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MergeCtx mrgCtxIn[2], +#endif #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION && JVET_W0090_ARMC_TM InterPrediction* m_pcInterSearch, #endif @@ -11882,6 +13109,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION affMrgCtx.numAffCandToTestEnc = maxNumAffineMergeCand; affMrgCtx.candCost[i] = MAX_UINT64; +#endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[i] = 0; #endif } @@ -11897,88 +13127,141 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx bool tmpLICFlag = false; #if JVET_Z0139_NA_AFF && JVET_W0090_ARMC_TM +#if !JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION if (cs.pcv->isEncoder || isZeroCandIdx) +#endif { +#endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + CHECK(mrgCtx.subPuMvpMiBuf[i].area() == 0 || !mrgCtx.subPuMvpMiBuf[i].buf, "Buffer not initialized"); + mrgCtx.subPuMvpMiBuf[i].fill(MotionInfo()); + } +#else + CHECK(mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized"); + mrgCtx.subPuMvpMiBuf.fill(MotionInfo()); #endif - CHECK( mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized" ); - mrgCtx.subPuMvpMiBuf.fill( MotionInfo() ); + #if JVET_Z0139_NA_AFF && JVET_W0090_ARMC_TM } #endif int pos = 0; +#if !(JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION && ENABLE_INTER_TEMPLATE_MATCHING) // Get spatial MV const Position posCurLB = pu.Y().bottomLeft(); MotionInfo miLeft; //left - const PredictionUnit* puLeft = cs.getPURestricted( posCurLB.offset( -1, 0 ), pu, pu.chType ); + const PredictionUnit* puLeft = cs.getPURestricted(posCurLB.offset(-1, 0), pu, pu.chType); #if JVET_Y0065_GPM_INTRA - const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posCurLB.offset(-1, 0), plevel) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu ) && puLeft->getMotionInfo( posCurLB.offset( -1, 0 ) ).isInter; + const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posCurLB.offset(-1, 0), plevel) && pu.cu != puLeft->cu && CU::isInter(*puLeft->cu) && puLeft->getMotionInfo(posCurLB.offset(-1, 0)).isInter; #else - const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posCurLB.offset(-1, 0), plevel) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu ); + const bool isAvailableA1 = puLeft && isDiffMER(pu.lumaPos(), posCurLB.offset(-1, 0), plevel) && pu.cu != puLeft->cu && CU::isInter(*puLeft->cu); #endif - if ( isAvailableA1 ) + if (isAvailableA1) { #if INTER_LIC affMrgCtx.mrgCtx->LICFlags[pos] = false; #endif - miLeft = puLeft->getMotionInfo( posCurLB.offset( -1, 0 ) ); + miLeft = puLeft->getMotionInfo(posCurLB.offset(-1, 0)); // get Inter Dir mrgCtx.interDirNeighbours[pos] = miLeft.interDir; // get Mv from Left - mrgCtx.mvFieldNeighbours[pos << 1].setMvField( miLeft.mv[0], miLeft.refIdx[0] ); + mrgCtx.mvFieldNeighbours[pos << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); - if ( slice.isInterB() ) + if (slice.isInterB()) { - mrgCtx.mvFieldNeighbours[(pos << 1) + 1].setMvField( miLeft.mv[1], miLeft.refIdx[1] ); + mrgCtx.mvFieldNeighbours[(pos << 1) + 1].setMvField(miLeft.mv[1], miLeft.refIdx[1]); } pos++; } mrgCtx.numValidMergeCand = pos; +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int poc0 = pu.cu->slice->getRefPic(RefPicList(1 - pu.cu->slice->getColFromL0Flag()), pu.cu->slice->getColRefIdx())->getPOC(); + int poc1 = pu.cu->slice->getRefPic(RefPicList(1 - pu.cu->slice->getColFromL0Flag2nd()), pu.cu->slice->getColRefIdx2nd())->getPOC(); +#if ENABLE_INTER_TEMPLATE_MATCHING + for (int index = 0; index < SUB_TMVP_INDEX; index++) + { +#endif + for (int colFrameIdx = 0; colFrameIdx < ((pu.cu->slice->getCheckLDC() || (poc0 == poc1)) ? 1 : 2); colFrameIdx++) + { +#endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if (index > 0 && colFrameIdx == 1) + { + continue; + } +#endif +#if !ENABLE_INTER_TEMPLATE_MATCHING + if (affMrgCtx.numValidMergeCand == 1) + { + break; + } +#endif #if JVET_Z0139_NA_AFF && JVET_W0090_ARMC_TM - isAvailableSubPu = getInterMergeSubPuMvpCand(pu, mrgCtx, tmpLICFlag, pos, (!isZeroCandIdx && !cs.pcv->isEncoder) ? 1: 0); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + isAvailableSubPu = getInterMergeSubPuMvpCand(pu, mrgCtx, tmpLICFlag, 0, index, mrgCtxIn[colFrameIdx], colFrameIdx); #else - isAvailableSubPu = getInterMergeSubPuMvpCand(pu, mrgCtx, tmpLICFlag, pos, 0); + isAvailableSubPu = getInterMergeSubPuMvpCand(pu, mrgCtx, tmpLICFlag, pos, (!isZeroCandIdx && !cs.pcv->isEncoder) ? 1 : 0); #endif - if ( isAvailableSubPu ) - { - for ( int mvNum = 0; mvNum < 3; mvNum++ ) - { - affMrgCtx.mvFieldNeighbours[(affMrgCtx.numValidMergeCand << 1) + 0][mvNum].setMvField( mrgCtx.mvFieldNeighbours[(pos << 1) + 0].mv, mrgCtx.mvFieldNeighbours[(pos << 1) + 0].refIdx ); - affMrgCtx.mvFieldNeighbours[(affMrgCtx.numValidMergeCand << 1) + 1][mvNum].setMvField( mrgCtx.mvFieldNeighbours[(pos << 1) + 1].mv, mrgCtx.mvFieldNeighbours[(pos << 1) + 1].refIdx ); - } - affMrgCtx.interDirNeighbours[affMrgCtx.numValidMergeCand] = mrgCtx.interDirNeighbours[pos]; +#else + isAvailableSubPu = getInterMergeSubPuMvpCand(pu, mrgCtx, tmpLICFlag, pos +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , colFrameIdx +#else + , 0 +#endif + ); +#endif + if (isAvailableSubPu) + { + for (int mvNum = 0; mvNum < 3; mvNum++) + { + affMrgCtx.mvFieldNeighbours[(affMrgCtx.numValidMergeCand << 1) + 0][mvNum].setMvField(mrgCtx.mvFieldNeighbours[(pos << 1) + 0].mv, mrgCtx.mvFieldNeighbours[(pos << 1) + 0].refIdx); + affMrgCtx.mvFieldNeighbours[(affMrgCtx.numValidMergeCand << 1) + 1][mvNum].setMvField(mrgCtx.mvFieldNeighbours[(pos << 1) + 1].mv, mrgCtx.mvFieldNeighbours[(pos << 1) + 1].refIdx); + } + affMrgCtx.interDirNeighbours[affMrgCtx.numValidMergeCand] = mrgCtx.interDirNeighbours[pos]; - affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = AFFINE_MODEL_NUM; - affMrgCtx.mergeType[affMrgCtx.numValidMergeCand] = MRG_TYPE_SUBPU_ATMVP; + affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = AFFINE_MODEL_NUM; + affMrgCtx.mergeType[affMrgCtx.numValidMergeCand] = MRG_TYPE_SUBPU_ATMVP; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[affMrgCtx.numValidMergeCand] = (index << 1) + colFrameIdx; +#endif #if AFFINE_MMVD - mrgCandIdx += (isAfMmvd && mrgCandIdx >= 0 ? 1 : 0); + mrgCandIdx += (isAfMmvd && mrgCandIdx >= 0 ? 1 : 0); #endif - if ( affMrgCtx.numValidMergeCand == mrgCandIdx ) - { - affMrgCtx.numValidMergeCand++; - return; - } + if (affMrgCtx.numValidMergeCand == mrgCandIdx) + { + return; + } - affMrgCtx.numValidMergeCand++; + affMrgCtx.numValidMergeCand++; #if JVET_Z0139_NA_AFF && JVET_W0090_ARMC_TM - if (isZeroCandIdx && !cs.pcv->isEncoder) - { - return; - } + if (isZeroCandIdx && !cs.pcv->isEncoder) + { + return; + } #endif - // early termination - if ( affMrgCtx.numValidMergeCand == maxNumAffineMergeCand ) - { - return; + // early termination + if (affMrgCtx.numValidMergeCand == maxNumAffineMergeCand) + { + return; + } + } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION } +#if ENABLE_INTER_TEMPLATE_MATCHING } +#endif +#endif } if ( slice.getSPS()->getUseAffine() ) @@ -12070,6 +13353,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx affMrgCtx.interDirNeighbours[affMrgCtx.numValidMergeCand] = puNeigh->interDir; affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = (EAffineModel)(puNeigh->cu->affineType); affMrgCtx.BcwIdx[affMrgCtx.numValidMergeCand] = puNeigh->cu->BcwIdx; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[affMrgCtx.numValidMergeCand] = 0; +#endif #if INTER_LIC CHECK( puNeigh->interDir == 3 && puNeigh->cu->LICFlag, "LIC should not be enabled for affine bi-pred" ); affMrgCtx.LICFlags[affMrgCtx.numValidMergeCand] = puNeigh->cu->LICFlag; @@ -12115,7 +13401,18 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx affMrgCtxTemp.candCost[i] = MAX_UINT64; } affMrgCtxTemp.numValidMergeCand = 0; +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if (pu.cs->sps->getUseFastSubTmvp()) + { + affMrgCtxTemp.maxNumMergeCand = 17; + } + else + { + affMrgCtxTemp.maxNumMergeCand = 16; + } +#else affMrgCtxTemp.maxNumMergeCand = RMVF_AFFINE_MRG_MAX_CAND_LIST_SIZE; +#endif std::vector<RMVFInfo> mvpInfoVec[2][4]; collectNeiMotionInfo(mvpInfoVec, pu); @@ -12300,7 +13597,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx const PreCalcValues& pcv = *cs.pcv; Position posC0; - bool C0Avail = false; + bool isC0Avail = false; bool boundaryCond = ((posRB.x + pcv.minCUWidth) < pcv.lumaWidth) && ((posRB.y + pcv.minCUHeight) < pcv.lumaHeight); const SubPic &curSubPic = pu.cs->slice->getPPS()->getSubPicFromPos(pu.lumaPos()); @@ -12315,15 +13612,18 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if (posYInCtu + 4 < pcv.maxCUHeight) { posC0 = posRB.offset(4, 4); - C0Avail = true; + isC0Avail = true; } } Mv cColMv; int refIdx = 0; - bool bExistMV = C0Avail && getColocatedMVP( pu, REF_PIC_LIST_0, posC0, cColMv, refIdx, false + bool bExistMV = isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_0, posC0, cColMv, refIdx, false #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING - , &refIdx +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 +#endif + , &refIdx #endif ); if ( bExistMV ) @@ -12342,9 +13642,12 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx if ( slice.isInterB() ) { - bExistMV = C0Avail && getColocatedMVP( pu, REF_PIC_LIST_1, posC0, cColMv, refIdx, false + bExistMV = isC0Avail && getColocatedMVP(pu, REF_PIC_LIST_1, posC0, cColMv, refIdx, false #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING - , &refIdx +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , 0 +#endif + , &refIdx #endif ); if ( bExistMV ) @@ -12585,7 +13888,18 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx } const int MAX_PAIRWISE_NUM = 9; const int preDefinedPairs[MAX_PAIRWISE_NUM][2] = { {0, 1}, {0, 2}, {1, 2}, {0, 3}, {1, 3}, { 2, 3}, { 0, 4}, {1, 4}, { 2, 4} }; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int iATMVPoffset = 0; + for (int index = 0; index < affMrgCtx.numValidMergeCand; index++) + { + if (affMrgCtx.mergeType[index] == MRG_TYPE_SUBPU_ATMVP) + { + iATMVPoffset++; + } + } +#else int iATMVPoffset = affMrgCtx.mergeType[0] == MRG_TYPE_SUBPU_ATMVP ? 1 : 0; +#endif int currSize = affMrgCtx.numValidMergeCand; for (int pairIdx = 0; pairIdx < MAX_PAIRWISE_NUM; pairIdx++) { @@ -12680,6 +13994,9 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx affMrgCtx.mvFieldNeighbours[(cnt << 1) + 0][mvNum].setMvField( Mv( 0, 0 ), 0 ); } affMrgCtx.interDirNeighbours[cnt] = 1; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + affMrgCtx.colIdx[cnt] = 0; +#endif if ( slice.isInterB() ) { @@ -12993,6 +14310,29 @@ void PU::setAllAffineMv(PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPic void clipColPos(int& posX, int& posY, const PredictionUnit& pu) { +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + Position puPos = pu.lumaPos(); + int log2CtuSize = floorLog2(pu.cs->sps->getCTUSize()); + int ctuY = ((puPos.y >> log2CtuSize) << log2CtuSize); + int horMax; + int horMin; + const SubPic &curSubPic = pu.cu->slice->getPPS()->getSubPicFromPos(puPos); + if (curSubPic.getTreatedAsPicFlag()) + { + horMax = (int)curSubPic.getSubPicRight(); + horMin = (int)curSubPic.getSubPicLeft(); + } + else + { + horMax = (int)pu.cs->pps->getPicWidthInLumaSamples() - 1; + horMin = 0; + } + int verMax = std::min((int)pu.cs->pps->getPicHeightInLumaSamples() - 1, ctuY + (int)pu.cs->sps->getCTUSize() - 1); + int verMin = std::max((int)0, ctuY); + + posX = std::min(horMax, std::max(horMin, posX)); + posY = std::min(verMax, std::max(verMin, posY)); +#else Position puPos = pu.lumaPos(); int log2CtuSize = floorLog2(pu.cs->sps->getCTUSize()); int ctuX = ((puPos.x >> log2CtuSize) << log2CtuSize); @@ -13008,15 +14348,131 @@ void clipColPos(int& posX, int& posY, const PredictionUnit& pu) horMax = std::min((int)pu.cs->pps->getPicWidthInLumaSamples() - 1, ctuX + (int)pu.cs->sps->getCTUSize() + 3); } int horMin = std::max((int)0, ctuX); - int verMax = std::min( (int)pu.cs->pps->getPicHeightInLumaSamples() - 1, ctuY + (int)pu.cs->sps->getCTUSize() - 1 ); + int verMax = std::min((int)pu.cs->pps->getPicHeightInLumaSamples() - 1, ctuY + (int)pu.cs->sps->getCTUSize() - 1); int verMin = std::max((int)0, ctuY); posX = std::min(horMax, std::max(horMin, posX)); posY = std::min(verMax, std::max(verMin, posY)); +#endif } +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +void PU::getTMVPCandOpt(const PredictionUnit &pu, RefPicList refList, int refIdx, MergeCtx& mrgCtx, MergeCtx mergeCtxIn, int col) +{ + const uint32_t maxNumMergeCand = NUM_TMVP_CANDS; + for (uint32_t ui = 0; ui < pu.cs->sps->getMaxNumMergeCand(); ++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 +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + mrgCtx.candCost[ui] = MAX_UINT64; +#endif + } + mrgCtx.numValidMergeCand = 0; +#if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND + mrgCtx.numCandToTestEnc = 0; +#endif + + const Slice &slice = *pu.cs->slice; + const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4); + const unsigned mask = ~(scale - 1); + const Picture *pColPic = slice.getRefPic(RefPicList(col == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), col == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); + + Mv cTMv; + for (int i = 0; i < mergeCtxIn.numValidMergeCand; i++) + { + if ((mergeCtxIn.interDirNeighbours[i] & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, mergeCtxIn.mvFieldNeighbours[i << 1].refIdx) == pColPic) + { + cTMv = mergeCtxIn.mvFieldNeighbours[i << 1].mv; + } + else if (slice.isInterB() && (mergeCtxIn.interDirNeighbours[i] & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, mergeCtxIn.mvFieldNeighbours[(i << 1) + 1].refIdx) == pColPic) + { + cTMv = mergeCtxIn.mvFieldNeighbours[(i << 1) + 1].mv; + } + else + { + CHECK(true, "Wrong TMVP candidate"); + } + + /////////////////////////////////////////////////////////////////////// + //////// GET Initial Temporal Vector //////// + /////////////////////////////////////////////////////////////////////// + + Mv cTempVector = cTMv; + Mv cColMv; + + // compute the location of the current PU + Position puPos = pu.lumaPos(); + Size puSize = pu.lumaSize(); + Position centerPos; + cTempVector = cTMv; + + cTempVector.changePrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT); + int tempX = cTempVector.getHor(); + int tempY = cTempVector.getVer(); + + centerPos.x = puPos.x + (puSize.width >> 1) + tempX; + centerPos.y = puPos.y + (puSize.height >> 1) + tempY; + + clipColPos(centerPos.x, centerPos.y, pu); + + centerPos = Position{ PosType(centerPos.x & mask), PosType(centerPos.y & mask) }; + + // derivation of center motion parameters from the collocated CU + const MotionInfo &mi = pColPic->cs->getMotionInfo(centerPos); + + if (mi.isInter && mi.isIBCmot == false) + { + if (getColocatedMVP(pu, refList, centerPos, cColMv, refIdx, false +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + , col +#endif + )) + { + // set as default, for further motion vector field spanning +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING + mrgCtx.mvFieldNeighbours[(mrgCtx.numValidMergeCand << 1) + refList].setMvField(cColMv, refIdx); + mrgCtx.mvFieldNeighbours[(mrgCtx.numValidMergeCand << 1) + 1 - refList].setMvField(Mv(), NOT_VALID); +#else + mrgCtx.mvFieldNeighbours[(mrgCtx.numValidMergeCand << 1) + currRefListId].setMvField(cColMv, 0); +#endif + mrgCtx.interDirNeighbours[mrgCtx.numValidMergeCand] = refList + 1; + mrgCtx.BcwIdx[mrgCtx.numValidMergeCand] = BCW_DEFAULT; + } +#if NON_ADJACENT_MRG_CAND || TM_MRG + if (!mrgCtx.xCheckSimilarMotion(mrgCtx.numValidMergeCand)) + { +#endif + mrgCtx.numValidMergeCand++; + if (mrgCtx.numValidMergeCand == maxNumMergeCand) + { + break; + } +#if NON_ADJACENT_MRG_CAND || TM_MRG + } +#endif + } + } + } +#endif bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, bool& LICFlag, const int count +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +#if ENABLE_INTER_TEMPLATE_MATCHING + , int subIdx, MergeCtx mergeCtxIn +#endif + , int col +#else , int mmvdList +#endif ) { const Slice &slice = *pu.cs->slice; @@ -13026,20 +14482,43 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b LICFlag = false; #endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + const Picture *pColPic = slice.getRefPic(RefPicList(col == 0 ? 1 - slice.getColFromL0Flag() : 1 - slice.getColFromL0Flag2nd()), col == 0 ? slice.getColRefIdx() : slice.getColRefIdx2nd()); +#else const Picture *pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0), slice.getColRefIdx()); +#endif Mv cTMv; - if ( count ) +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if (subIdx > mergeCtxIn.numValidMergeCand) + { + return false; + } + else if (subIdx < mergeCtxIn.numValidMergeCand) + { + if ((mergeCtxIn.interDirNeighbours[subIdx] & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, mergeCtxIn.mvFieldNeighbours[subIdx << 1].refIdx) == pColPic) + { + cTMv = mergeCtxIn.mvFieldNeighbours[subIdx << 1].mv; + } + else if (slice.isInterB() && (mergeCtxIn.interDirNeighbours[subIdx] & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, mergeCtxIn.mvFieldNeighbours[(subIdx << 1) + 1].refIdx) == pColPic) + { + cTMv = mergeCtxIn.mvFieldNeighbours[(subIdx << 1) + 1].mv; + } + } + +#else + if (count) { - if ( (mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_0)) && slice.getRefPic( REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[REF_PIC_LIST_0].refIdx ) == pColPic ) + if ((mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_0)) && slice.getRefPic(REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[REF_PIC_LIST_0].refIdx) == pColPic) { cTMv = mrgCtx.mvFieldNeighbours[REF_PIC_LIST_0].mv; } - else if ( slice.isInterB() && (mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_1)) && slice.getRefPic( REF_PIC_LIST_1, mrgCtx.mvFieldNeighbours[REF_PIC_LIST_1].refIdx ) == pColPic ) + else if (slice.isInterB() && (mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_1)) && slice.getRefPic(REF_PIC_LIST_1, mrgCtx.mvFieldNeighbours[REF_PIC_LIST_1].refIdx) == pColPic) { cTMv = mrgCtx.mvFieldNeighbours[REF_PIC_LIST_1].mv; } } +#endif /////////////////////////////////////////////////////////////////////// //////// GET Initial Temporal Vector //////// @@ -13090,7 +14569,10 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b if (getColocatedMVP(pu, currRefPicList, centerPos, cColMv, refIdx, true #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING - , &refIdx +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , col +#endif + , &refIdx #endif )) { @@ -13112,17 +14594,22 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b } } } - if (!found) { return false; } +#if !JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION if (mmvdList != 1) { +#endif int xOff = (puWidth >> 1) + tempX; int yOff = (puHeight >> 1) + tempY; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MotionBuf &mb = mrgCtx.subPuMvpMiBuf[(subIdx << 1) + col]; +#else MotionBuf &mb = mrgCtx.subPuMvpMiBuf; +#endif const bool isBiPred = isBipredRestriction(pu); @@ -13140,8 +14627,8 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b MotionInfo mi; - found = false; - mi.isInter = true; + found = false; + mi.isInter = true; mi.sliceIdx = slice.getIndependentSliceIdx(); mi.isIBCmot = false; if (colMi.isInter && colMi.isIBCmot == false) @@ -13151,6 +14638,9 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b RefPicList currRefPicList = RefPicList(currRefListId); if (getColocatedMVP(pu, currRefPicList, colPos, cColMv, refIdx, true #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , col +#endif , &refIdx #endif )) @@ -13160,15 +14650,15 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b #else mi.refIdx[currRefListId] = 0; #endif - mi.mv[currRefListId] = cColMv; - found = true; + mi.mv[currRefListId] = cColMv; + found = true; } } } if (!found) { - mi.mv[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].mv; - mi.mv[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].mv; + mi.mv[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].mv; + mi.mv[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].mv; mi.refIdx[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].refIdx; mi.refIdx[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].refIdx; } @@ -13177,8 +14667,8 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b if (isBiPred && mi.interDir == 3) { - mi.interDir = 1; - mi.mv[1] = Mv(); + mi.interDir = 1; + mi.mv[1] = Mv(); mi.refIdx[1] = NOT_VALID; } @@ -13186,12 +14676,18 @@ bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, b .fill(mi); } } +#if !JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION } +#endif return true; } #if MULTI_PASS_DMVR -void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx, Mv* bdmvrSubPuMv0, Mv* bdmvrSubPuMv1, Mv* bdofSubPuMvOffset) +void PU::spanMotionInfo(PredictionUnit &pu, const MergeCtx &mrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int colIdx, +#endif + Mv* bdmvrSubPuMv0, Mv* bdmvrSubPuMv1, Mv* bdofSubPuMvOffset) #else void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) #endif @@ -13326,11 +14822,22 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) } else if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) { - CHECK(mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized"); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + CHECK(mrgCtx.subPuMvpMiBuf[i].area() == 0 || !mrgCtx.subPuMvpMiBuf[i].buf, "Buffer not initialized"); + } +#else + CHECK(mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized"); +#endif #if MULTI_PASS_DMVR MotionBuf mb = pu.getMotionBuf(); #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + mb.copyFrom(mrgCtx.subPuMvpMiBuf[pu.colIdx]); +#else mb.copyFrom(mrgCtx.subPuMvpMiBuf); +#endif #if JVET_W0123_TIMD_FUSION spanIpmInfoInter(pu, mb, ib); #endif @@ -13339,7 +14846,11 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) #if JVET_W0123_TIMD_FUSION #if MULTI_PASS_DMVR -void PU::spanMotionInfo2( PredictionUnit &pu, const MergeCtx &mrgCtx, Mv* bdmvrSubPuMv0, Mv* bdmvrSubPuMv1, Mv* bdofSubPuMvOffset) +void PU::spanMotionInfo2(PredictionUnit &pu, const MergeCtx &mrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int colIdx, +#endif + Mv* bdmvrSubPuMv0, Mv* bdmvrSubPuMv1, Mv* bdofSubPuMvOffset) #else void PU::spanMotionInfo2( PredictionUnit &pu, const MergeCtx &mrgCtx ) #endif @@ -13422,11 +14933,22 @@ void PU::spanMotionInfo2( PredictionUnit &pu, const MergeCtx &mrgCtx ) } else if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) { +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + CHECK(mrgCtx.subPuMvpMiBuf[i].area() == 0 || !mrgCtx.subPuMvpMiBuf[i].buf, "Buffer not initialized"); + } +#else CHECK(mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized"); +#endif #if MULTI_PASS_DMVR MotionBuf mb = pu.getMotionBuf(); #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + mb.copyFrom(mrgCtx.subPuMvpMiBuf[pu.colIdx]); +#else mb.copyFrom(mrgCtx.subPuMvpMiBuf); +#endif } } diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 775e1fe64c944a4eaf7abe5194abc04431f1320f..4c4183b2b46af8ab9ee6989ae065b9b825e720b8 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -242,7 +242,15 @@ namespace PU #endif ); #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM - void getTmvpMergeCand (const PredictionUnit &pu, MergeCtx& mvpMrgCtx); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void getNonAdjacentMergeCandSubTMVP(const PredictionUnit &pu, MergeCtx& mvpMrgCtx, int col); + void getInterMergeCandidatesSubTMVP(const PredictionUnit &pu, MergeCtx& mrgCtx, int col, const int& mrgCandIdx = -1 +#if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM + , MergeCtx* mvpMrgCtx1 = NULL +#endif + ); +#endif + void getTmvpMergeCand(const PredictionUnit &pu, MergeCtx& mvpMrgCtxz); void getNonAdjacentMergeCand (const PredictionUnit &pu, MergeCtx& mvpMrgCtx); #endif void getIBCMergeCandidates (const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx = -1); @@ -264,6 +272,9 @@ namespace PU 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 #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , int col = 0 +#endif , int* targetRefIdx = nullptr #endif ); @@ -319,6 +330,19 @@ namespace PU , const uint32_t mvdSimilarityThresh = 1 #endif ); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void addMergeHMVPCandSubTMVP(const CodingStructure &cs, MergeCtx& mrgCtx, const int& mrgCandIdx, const uint32_t maxNumMergeCand, int &cnt + , const bool isAvailableA1, const MotionInfo miLeft, const bool isAvailableB1, const MotionInfo miAbove +#if !JVET_Z0075_IBC_HMVP_ENLARGE + , const bool ibcFlag + , const bool isGt4x4 +#endif + , const PredictionUnit &pu, int col +#if TM_MRG || (JVET_Z0084_IBC_TM && !JVET_Z0075_IBC_HMVP_ENLARGE) + , const uint32_t mvdSimilarityThresh = 1 +#endif + ); +#endif #if JVET_X0083_BM_AMVP_MERGE_MODE #if JVET_Y0128_NON_CTC bool checkIsValidMergeMvCand (const PredictionUnit &pu, int8_t mergeRefIdx[ NUM_REF_PIC_LIST_01 ]); @@ -381,13 +405,21 @@ namespace PU ); bool isBipredRestriction (const PredictionUnit &pu); #if MULTI_PASS_DMVR - void spanMotionInfo ( PredictionUnit &pu, const MergeCtx &mrgCtx = MergeCtx(), Mv* bdmvrSubPuMv0 = nullptr, Mv* bdmvrSubPuMv1 = nullptr, Mv* bdofSubPuMvOffset = nullptr ); + void spanMotionInfo ( PredictionUnit &pu, const MergeCtx &mrgCtx = MergeCtx(), +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int colIdx = 0, +#endif + Mv* bdmvrSubPuMv0 = nullptr, Mv* bdmvrSubPuMv1 = nullptr, Mv* bdofSubPuMvOffset = nullptr ); #else void spanMotionInfo ( PredictionUnit &pu, const MergeCtx &mrgCtx = MergeCtx() ); #endif #if JVET_W0123_TIMD_FUSION #if MULTI_PASS_DMVR - void spanMotionInfo2 ( PredictionUnit &pu, const MergeCtx &mrgCtx = MergeCtx(), Mv* bdmvrSubPuMv0 = nullptr, Mv* bdmvrSubPuMv1 = nullptr, Mv* bdofSubPuMvOffset = nullptr ); + void spanMotionInfo2 ( PredictionUnit &pu, const MergeCtx &mrgCtx = MergeCtx(), +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int colIdx = 0, +#endif + Mv* bdmvrSubPuMv0 = nullptr, Mv* bdmvrSubPuMv1 = nullptr, Mv* bdofSubPuMvOffset = nullptr ); #else void spanMotionInfo2 ( PredictionUnit &pu, const MergeCtx &mrgCtx = MergeCtx() ); #endif @@ -418,6 +450,9 @@ namespace PU int getNonAdjAffParaDivFun(int num1, int num2); #endif void getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MergeCtx mrgCtx[2], +#endif #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION && JVET_W0090_ARMC_TM InterPrediction* m_pcInterSearch, #endif @@ -437,7 +472,19 @@ namespace PU #endif void setAllAffineMvField ( PredictionUnit &pu, MvField *mvField, RefPicList eRefList ); void setAllAffineMv ( PredictionUnit &pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList, bool clipCPMVs = false ); - bool getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx &mrgCtx, bool& LICFlag, const int count, int mmvdList); + bool getInterMergeSubPuMvpCand (const PredictionUnit &pu, MergeCtx& mrgCtx, bool& LICFlag, const int count +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION +#if ENABLE_INTER_TEMPLATE_MATCHING + , int subIdx, MergeCtx mergeCtxIn +#endif + , int col = 0 +#else + , int mmvdList +#endif + ); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + void getTMVPCandOpt(const PredictionUnit &pu, RefPicList refList, int refIdx, MergeCtx &mrgCtx, MergeCtx mergeCtx, int col = 0); +#endif #if JVET_Y0128_NON_CTC bool isBiRefScaled(const CodingStructure& cs, const int refIdx0, const int refIdx1); #endif diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index d36bc9f40f2199570df4503d992e1faa999136c2..6c7a904fdfca6780c85714cad1f10d16ccc52ff0 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -1411,9 +1411,13 @@ void DecCu::xReconInter(CodingUnit &cu) } #if MULTI_PASS_DMVR - if( cu.firstPU->bdmvrRefine ) + if (cu.firstPU->bdmvrRefine) { - PU::spanMotionInfo( *cu.firstPU, MergeCtx(), m_mvBufBDMVR[0], m_mvBufBDMVR[1], m_pcInterPred->getBdofSubPuMvOffset() ); + PU::spanMotionInfo(*cu.firstPU, MergeCtx(), +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + cu.firstPU->colIdx, +#endif + m_mvBufBDMVR[0], m_mvBufBDMVR[1], m_pcInterPred->getBdofSubPuMvOffset()); } #endif } @@ -1847,7 +1851,14 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) if (pu.cs->sps->getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(pu.lumaSize()); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif } int fPosBaseIdx = @@ -1876,7 +1887,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) mrgCtx.setMmvdMergeCandiInfo(pu, pu.mmvdMergeIdx); #endif - PU::spanMotionInfo(pu, mrgCtx); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } else { @@ -1979,30 +1994,79 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) { if( pu.cu->affine ) { +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MergeCtx mrgCtxAll[2]; + for (int i = 0; i < 2; i++) + { + mrgCtxAll[i].numValidMergeCand = 0; + } + if (pu.cs->picHeader->getEnableTMVPFlag()) + { + if (pu.cs->sps->getUseAML()) + { + MergeCtx namvpMergeCandCtx[2]; + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); + int poc0 = pu.cu->slice->getRefPic(RefPicList(1 - pu.cu->slice->getColFromL0Flag()), pu.cu->slice->getColRefIdx())->getPOC(); + int poc1 = pu.cu->slice->getRefPic(RefPicList(1 - pu.cu->slice->getColFromL0Flag2nd()), pu.cu->slice->getColRefIdx2nd())->getPOC(); + for (int col = 0; col < ((pu.cu->slice->getCheckLDC() || (poc0 == poc1)) ? 1 : 2); col++) + { + PU::getNonAdjacentMergeCandSubTMVP(pu, namvpMergeCandCtx[col], col); + if (col == 0 && tplAvail) + { + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroupSubTMVP(pu, namvpMergeCandCtx[col], 9); + } + else + { + namvpMergeCandCtx[col].numValidMergeCand = std::min(9, namvpMergeCandCtx[col].numValidMergeCand); + } + PU::getInterMergeCandidatesSubTMVP(pu, mrgCtxAll[col], col, -1, &namvpMergeCandCtx[col]); + if (col == 0 && tplAvail) + { + m_pcInterPred->adjustMergeCandidatesInOneCandidateGroupSubTMVP(pu, mrgCtxAll[col], pu.cs->sps->getMaxNumMergeCand()); + } + } + } + } +#endif AffineMergeCtx affineMergeCtx; if (pu.cs->sps->getSbTMVPEnabledFlag()) { - Size bufSize = g_miScaling.scale( pu.lumaSize() ); - mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize ); + Size bufSize = g_miScaling.scale(pu.lumaSize()); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else + mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif affineMergeCtx.mrgCtx = &mrgCtx; } #if AFFINE_MMVD #if JVET_W0090_ARMC_TM int affMrgIdx = pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumAffineMergeCand()) || (pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE * ADAPTIVE_AFFINE_SUB_GROUP_SIZE + ADAPTIVE_AFFINE_SUB_GROUP_SIZE - 1 : pu.mergeIdx; - if (pu.afMmvdFlag) - { + if (pu.afMmvdFlag) + { #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED - affMrgIdx = + affMrgIdx = #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_ENHANCED_MMVD_EXTENSION - !pu.cs->sps->getUseTMMMVD() ? - ECM3_AF_MMVD_BASE_NUM : + !pu.cs->sps->getUseTMMMVD() ? + ECM3_AF_MMVD_BASE_NUM : #endif - AF_MMVD_BASE_NUM; + AF_MMVD_BASE_NUM; #else - affMrgIdx = pu.afMmvdBaseIdx; + affMrgIdx = pu.afMmvdBaseIdx; #endif - } + } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.cu->imv = IMV_OFF; +#endif PU::getAffineMergeCand(pu, affineMergeCtx +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , mrgCtxAll +#endif #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION , m_pcInterPred #endif @@ -2080,6 +2144,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) pu.cu->BcwIdx = affineMergeCtx.BcwIdx[pu.mergeIdx]; #if INTER_LIC pu.cu->LICFlag = affineMergeCtx.LICFlags[pu.mergeIdx]; +#endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affineMergeCtx.colIdx[pu.mergeIdx]; #endif pu.mergeType = affineMergeCtx.mergeType[pu.mergeIdx]; if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP ) @@ -2125,7 +2192,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) } } #endif - PU::spanMotionInfo( pu, mrgCtx ); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } #if JVET_X0141_CIIP_TIMD_TM && TM_MRG else if (pu.ciipFlag && pu.tmMergeFlag) @@ -2162,7 +2233,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) mrgCtx.setMergeInfo(pu, storeMrgIdx); pu.bdmvrRefine = false; - PU::spanMotionInfo(pu, mrgCtx); + PU::spanMotionInfo(pu, mrgCtx +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } #endif else @@ -2917,7 +2992,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #if MULTI_PASS_DMVR if( !pu.bdmvrRefine ) { - PU::spanMotionInfo( pu, mrgCtx ); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } #else PU::spanMotionInfo( pu, mrgCtx ); @@ -2951,6 +3030,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) { #if TM_AMVP m_pcInterPred->clearTplAmvpBuffer(); +#endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + m_pcInterPred->clearAmvpTmvpBuffer(); #endif if (pu.cu->affine) { @@ -3291,7 +3373,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #if JVET_X0083_BM_AMVP_MERGE_MODE if (!pu.bdmvrRefine) #endif - PU::spanMotionInfo( pu, mrgCtx ); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } } if( !cu.geoFlag ) diff --git a/source/Lib/DecoderLib/DecCu.h b/source/Lib/DecoderLib/DecCu.h index 3b13c88f53e47d753a83cde4c4196afea2a5a5e8..021d98e9f0b7c28e7845fefd3593bcb0047da63c 100644 --- a/source/Lib/DecoderLib/DecCu.h +++ b/source/Lib/DecoderLib/DecCu.h @@ -99,7 +99,11 @@ private: PelStorage m_ciipBuffer; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MotionInfo m_SubPuMiBuf[SUB_TMVP_NUM][(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#else MotionInfo m_SubPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC bool applyBDMVR4BM[BM_MRG_MAX_NUM_INIT_CANDS]; #endif diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp index 8757ca244a52f180aa55b251aeed81aebf02d65e..0ffd2141c49f358fe7f2dac529b302a0945a4018 100644 --- a/source/Lib/DecoderLib/DecSlice.cpp +++ b/source/Lib/DecoderLib/DecSlice.cpp @@ -146,13 +146,23 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING if (slice->getPicHeader()->getEnableTMVPFlag()) { +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int colFrameIdx = 0; colFrameIdx < (slice->isInterB() ? 2 : 1); colFrameIdx++) + { + const Picture* const pColPic = slice->getRefPic(RefPicList(colFrameIdx == 0 ? 1 - slice->getColFromL0Flag() : 1 - slice->getColFromL0Flag2nd()), colFrameIdx == 0 ? slice->getColRefIdx() : slice->getColRefIdx2nd()); +#else const Picture* const pColPic = slice->getRefPic(RefPicList(slice->isInterB() ? 1 - slice->getColFromL0Flag() : 0), slice->getColRefIdx()); +#endif if (pColPic) { const int currPOC = slice->getPOC(); const int colPOC = pColPic->getPOC(); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + slice->resizeImBuf(pColPic->numSlices, colFrameIdx); +#else slice->resizeImBuf(pColPic->numSlices); +#endif Slice *pColSlice = nullptr; for (int sliceIdx = 0; sliceIdx < pColPic->numSlices; sliceIdx++) { @@ -202,12 +212,19 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb } } } // curRefIdx +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + slice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx, colFrameIdx); +#else slice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx); +#endif } // curRefPicListIdx } } } } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + } +#endif } #endif diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index f1ffb299495715d3568e1ffc284bc099f4deb63d..5eb2dbf5b89f9fed2b8c02d6c76e4389181fd3ac 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2238,6 +2238,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) } #endif #endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + READ_FLAG( uiCode, "sps_fast_sub_tmvp_enabled_flag"); pcSPS->setUseFastSubTmvp( uiCode != 0 ); +#endif #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM pcSPS->setUseTmvpNmvpReordering(false); if (pcSPS->getUseAML()) @@ -3792,10 +3795,17 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag { READ_CODE(1, uiCode, "ph_collocated_from_l0_flag"); picHeader->setPicColFromL0Flag(uiCode); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + READ_CODE(1, uiCode, "ph_collocated_from_l0_flag_2nd"); + picHeader->setPicColFromL0Flag2nd(uiCode); +#endif } else { picHeader->setPicColFromL0Flag(1); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + picHeader->setPicColFromL0Flag2nd(1); +#endif } if ((picHeader->getPicColFromL0Flag() == 1 && picHeader->getRPL(0)->getNumRefEntries() > 1) || (picHeader->getPicColFromL0Flag() == 0 && picHeader->getRPL(1)->getNumRefEntries() > 1)) @@ -3807,10 +3817,25 @@ void HLSyntaxReader::parsePictureHeader( PicHeader* picHeader, ParameterSetManag { picHeader->setColRefIdx(0); } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if ((picHeader->getPicColFromL0Flag2nd() == 1 && picHeader->getRPL(0)->getNumRefEntries() > 1) || + (picHeader->getPicColFromL0Flag2nd() == 0 && picHeader->getRPL(1)->getNumRefEntries() > 1)) + { + READ_UVLC(uiCode, "ph_collocated_ref_idx_2nd"); + picHeader->setColRefIdx2nd(uiCode); + } + else + { + picHeader->setColRefIdx2nd(0); + } +#endif } else { picHeader->setPicColFromL0Flag(0); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + picHeader->setPicColFromL0Flag2nd(0); +#endif } #if !JVET_R0324_REORDER @@ -4813,15 +4838,25 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, Par if( pcSlice->getSliceType() == P_SLICE ) { pcSlice->setColFromL0Flag( true ); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pcSlice->setColFromL0Flag2nd( true ); +#endif } else if( !pps->getRplInfoInPhFlag() && pcSlice->getSliceType() == B_SLICE ) { READ_FLAG( uiCode, "collocated_from_l0_flag" ); pcSlice->setColFromL0Flag( uiCode ); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + READ_FLAG( uiCode, "collocated_from_l0_flag_2nd" ); + pcSlice->setColFromL0Flag2nd( uiCode ); +#endif } else { pcSlice->setColFromL0Flag( picHeader->getPicColFromL0Flag() ); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pcSlice->setColFromL0Flag2nd(picHeader->getPicColFromL0Flag2nd()); +#endif } if (!pps->getRplInfoInPhFlag()) @@ -4837,11 +4872,26 @@ void HLSyntaxReader::parseSliceHeader (Slice* pcSlice, PicHeader* picHeader, Par { pcSlice->setColRefIdx(0); } - +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if (pcSlice->getSliceType() != I_SLICE && + ((pcSlice->getColFromL0Flag2nd() == 1 && pcSlice->getNumRefIdx(REF_PIC_LIST_0) > 1) || + (pcSlice->getColFromL0Flag2nd() == 0 && pcSlice->getNumRefIdx(REF_PIC_LIST_1) > 1))) + { + READ_UVLC(uiCode, "collocated_ref_idx_2nd"); + pcSlice->setColRefIdx2nd(uiCode); + } + else + { + pcSlice->setColRefIdx2nd(0); + } +#endif } else { pcSlice->setColRefIdx(picHeader->getColRefIdx()); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pcSlice->setColRefIdx2nd(picHeader->getColRefIdx2nd()); +#endif } } if ( (pps->getUseWP() && pcSlice->getSliceType()==P_SLICE) || (pps->getWPBiPred() && pcSlice->getSliceType()==B_SLICE) ) diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 1890bc029bee8330de3a2c532120cb500735b0c0..0d26828b77ff4fa2a8233119038222e0a3489bba 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -1037,6 +1037,9 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par if (!slice.isIntra()) { m_pcInterSearch->clearTplAmvpBuffer(); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + m_pcInterSearch->clearAmvpTmvpBuffer(); +#endif } #endif #if INTER_LIC @@ -3419,17 +3422,38 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& if (sps.getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(tempCS->area.lumaSize()); - mergeCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize ); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mergeCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + mrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else + mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif affineMergeCtx.mrgCtx = &mrgCtx; #if TM_MRG +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + tmMrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); +#if JVET_X0141_CIIP_TIMD_TM + ciipTmMrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); +#endif +#if JVET_AB0079_TM_BCW_MRG + mrgCtxCiip.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); +#endif + } +#else tmMrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); #if JVET_X0141_CIIP_TIMD_TM ciipTmMrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); #endif -#endif #if JVET_AB0079_TM_BCW_MRG mrgCtxCiip.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif +#endif #endif } #endif @@ -3608,7 +3632,43 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #endif PU::getInterMergeCandidates(pu, mergeCtxtmp, 0); #endif +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MergeCtx mrgCtxAll[2]; + for (int i = 0; i < 2; i++) + { + mrgCtxAll[i].numValidMergeCand = 0; + } + if (pu.cs->picHeader->getEnableTMVPFlag()) + { + if (pu.cs->sps->getUseAML()) + { + MergeCtx namvpMergeCandCtxSubTMVP[2]; + int nWidth = pu.lumaSize().width; + int nHeight = pu.lumaSize().height; + bool tplAvail = m_pcInterSearch->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); + int poc0 = slice.getRefPic(RefPicList(1 - slice.getColFromL0Flag()), slice.getColRefIdx())->getPOC(); + int poc1 = slice.getRefPic(RefPicList(1 - slice.getColFromL0Flag2nd()), slice.getColRefIdx2nd())->getPOC(); + for (int col = 0; col < ((pu.cu->slice->getCheckLDC() || (poc0 == poc1)) ? 1 : 2); col++) + { + PU::getNonAdjacentMergeCandSubTMVP(pu, namvpMergeCandCtxSubTMVP[col], col); + if (col == 0 && tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroupSubTMVP(pu, namvpMergeCandCtxSubTMVP[col], 9); + } + else + { + namvpMergeCandCtxSubTMVP[col].numValidMergeCand = std::min(9, namvpMergeCandCtxSubTMVP[col].numValidMergeCand); + } + PU::getInterMergeCandidatesSubTMVP(pu, mrgCtxAll[col], col, -1, &namvpMergeCandCtxSubTMVP[col]); + if (col == 0 && tplAvail) + { + m_pcInterSearch->adjustMergeCandidatesInOneCandidateGroupSubTMVP(pu, mrgCtxAll[col], pu.cs->sps->getMaxNumMergeCand()); + } + } + } + } +#endif #if JVET_X0141_CIIP_TIMD_TM && TM_MRG if (cu.cs->sps->getUseCiipTmMrg()) { @@ -3955,6 +4015,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.regularMergeFlag = false; cu.affine = true; PU::getAffineMergeCand(pu, affineMergeCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , mrgCtxAll +#endif #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION && JVET_W0090_ARMC_TM , m_pcInterSearch #endif @@ -5237,6 +5300,9 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& pu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand]; cu.affineType = affineMergeCtx.affineType[uiMergeCand]; cu.BcwIdx = affineMergeCtx.BcwIdx[uiMergeCand]; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affineMergeCtx.colIdx[uiMergeCand]; +#endif #if INTER_LIC cu.LICFlag = affineMergeCtx.LICFlags[uiMergeCand]; #endif @@ -5253,7 +5319,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& { pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx; pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx; - PU::spanMotionInfo(pu, mrgCtx); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } else { @@ -5344,10 +5414,18 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if MULTI_PASS_DMVR if( !pu.bdmvrRefine ) { - PU::spanMotionInfo( pu, mergeCtx ); + PU::spanMotionInfo(pu, mergeCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } #else - PU::spanMotionInfo( pu, mergeCtx ); + PU::spanMotionInfo(pu, mergeCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); #endif if( m_pcEncCfg->getMCTSEncConstraint() ) @@ -5489,18 +5567,30 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& if ( pu.tmMergeFlag ) #endif { - PU::spanMotionInfo( pu, mergeCtx, m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[( uiMergeCand << 1 ) + 1], m_pcInterSearch->getBdofSubPuMvOffset() ); + PU::spanMotionInfo(pu, mergeCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } else #endif #if JVET_X0049_ADAPT_DMVR if( pu.bmMergeFlag ) { - PU::spanMotionInfo( pu, bmMrgCtx, m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[( uiMergeCand << 1 ) + 1], m_pcInterSearch->getBdofSubPuMvOffset() ); + PU::spanMotionInfo(pu, bmMrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } else #endif - PU::spanMotionInfo(pu, mergeCtx, m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); + PU::spanMotionInfo(pu, mergeCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } #endif } @@ -5547,18 +5637,30 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if TM_MRG if( pu.tmMergeFlag ) { - PU::spanMotionInfo( pu, mergeCtx, m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[( uiMergeCand << 1 ) + 1], m_mvBufEncBDOF4TM[uiMergeCand] ); + PU::spanMotionInfo(pu, mergeCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4TM[uiMergeCand]); } else #endif #if JVET_X0049_ADAPT_DMVR if( pu.bmMergeFlag ) { - PU::spanMotionInfo( pu, bmMrgCtx, m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[( uiMergeCand << 1 ) + 1], m_mvBufEncBDOF4BM[uiMergeCand] ); + PU::spanMotionInfo(pu, bmMrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4BM[uiMergeCand]); } else #endif - PU::spanMotionInfo(pu, mergeCtx, m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1], m_mvBufEncBDOF[uiMergeCand]); + PU::spanMotionInfo(pu, mergeCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1], m_mvBufEncBDOF[uiMergeCand]); } #endif } @@ -5575,18 +5677,30 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if TM_MRG if( pu.tmMergeFlag ) { - PU::spanMotionInfo( pu, mergeCtx, m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[( uiMergeCand << 1 ) + 1], m_pcInterSearch->getBdofSubPuMvOffset() ); + PU::spanMotionInfo(pu, mergeCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4TM[uiMergeCand << 1], m_mvBufBDMVR4TM[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } else #endif #if JVET_X0049_ADAPT_DMVR if (pu.bmMergeFlag) { - PU::spanMotionInfo(pu, bmMrgCtx, m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4BM[uiMergeCand]); + PU::spanMotionInfo(pu, bmMrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4BM[uiMergeCand << 1], m_mvBufBDMVR4BM[(uiMergeCand << 1) + 1], m_mvBufEncBDOF4BM[uiMergeCand]); } else #endif - PU::spanMotionInfo(pu, mergeCtx, m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); + PU::spanMotionInfo(pu, mergeCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } #endif } @@ -5693,7 +5807,14 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #if TM_MRG for (int i = 0; i < GEO_NUM_TM_MV_CAND; i++) { +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int j = 0; j < SUB_TMVP_NUM; j++) + { + mergeCtx[i].subPuMvpMiBuf[j] = MotionBuf(m_SubPuMiBuf[j], bufSize); + } +#else mergeCtx[i].subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif } #else mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); @@ -8402,7 +8523,14 @@ void EncCu::xCheckRDCostMergeGeo2Nx2N(CodingStructure *&tempCS, CodingStructure if (sps.getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(tempCS->area.lumaSize()); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mergeCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif } CodingUnit &cu = tempCS->addCU(tempCS->area, pm.chType); @@ -9321,14 +9449,20 @@ void EncCu::xCheckSATDCostAffineMerge(CodingStructure *&tempCS, CodingUnit &cu, pu.mv[0].setZero(); pu.mv[1].setZero(); cu.imv = 0; - +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx = affineMergeCtx.colIdx[uiAffMergeCand]; +#endif pu.mergeType = affineMergeCtx.mergeType[uiAffMergeCand]; if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) { pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 0][0].refIdx; pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiAffMergeCand << 1) + 1][0].refIdx; // the SbTmvp use xSubPuMC which will need to access the motion buffer for subblock MV - PU::spanMotionInfo(pu, mrgCtx); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } else { @@ -10031,7 +10165,11 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct { pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx; pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx; - PU::spanMotionInfo( pu, mrgCtx ); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } else { @@ -10248,7 +10386,14 @@ void EncCu::xCheckRDCostAffineMmvd2Nx2N(CodingStructure *&tempCS, CodingStructur if (sps.getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(tempCS->area.lumaSize()); - mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mergeCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else + mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif affineMergeCtx.mrgCtx = &mrgCtx; } @@ -10560,7 +10705,14 @@ void EncCu::xCheckRDCostTMMerge2Nx2N(CodingStructure *&tempCS, CodingStructure * if (sps.getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(tempCS->area.lumaSize()); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mergeCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif } #if MULTI_PASS_DMVR bool applyBDMVR4TM[TM_MRG_MAX_NUM_CANDS] = { false }; @@ -10948,7 +11100,14 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct if (sps.getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(tempCS->area.lumaSize()); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mergeCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif } { @@ -11605,7 +11764,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct } #endif #else - PU::spanMotionInfo(pu, mergeCtxTm); + PU::spanMotionInfo(pu, mergeCtxTm +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); #endif #if JVET_AA0070_RRIBC @@ -12347,7 +12510,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct { bool mbvdCandMisAlign = mergeCtxTmp.setIbcMbvdMergeCandiInfo(pu, mergeCand - numPreviousBv, ibcMbvdLUT[mergeCand - numPreviousBv]); CHECK(mbvdCandMisAlign, "MBVD candidate is invalid"); - PU::spanMotionInfo(pu, mergeCtxTmp); + PU::spanMotionInfo(pu, mergeCtxTmp +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } else { @@ -12368,7 +12535,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct { #endif mergeCtxTm.setMergeInfo(pu, mergeCand); - PU::spanMotionInfo(pu, mergeCtxTm); + PU::spanMotionInfo(pu, mergeCtxTm +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); #if JVET_AC0112_IBC_GPM } #endif @@ -12386,7 +12557,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct { #endif mergeCtx.setMergeInfo(pu, mergeCand); - PU::spanMotionInfo(pu, mergeCtx); + PU::spanMotionInfo(pu, mergeCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); #if JVET_AC0112_IBC_GPM } #endif @@ -14724,7 +14899,11 @@ void EncCu::predInterSearchAdditionalHypothesisMulti(const MEResultVec& in, MERe if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP) { // the SbTmvp use xSubPuMC which will need to access the motion buffer for subblock MV - PU::spanMotionInfo(pu, mrgCtx); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } else if (x.cu.affine) { @@ -14782,7 +14961,14 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc if (sps.getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(tempCS->area.lumaSize()); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mrgCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif } // Hadamard-based pre-search @@ -14855,10 +15041,18 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc } else { - PU::spanMotionInfo(pu, mrgCtx); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } #else - PU::spanMotionInfo(pu, mrgCtx); + PU::spanMotionInfo(pu, mrgCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); #endif cu.skip = false; cu.mmvdSkip = false; @@ -14875,18 +15069,30 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc #if TM_MRG if( pu.tmMergeFlag ) { - PU::spanMotionInfo( pu, mrgCtx, m_mvBufBDMVR4TM[pu.mergeIdx << 1], m_mvBufBDMVR4TM[( pu.mergeIdx << 1 ) + 1], m_pcInterSearch->getBdofSubPuMvOffset() ); + PU::spanMotionInfo(pu, mrgCtx, +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4TM[pu.mergeIdx << 1], m_mvBufBDMVR4TM[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } else #endif #if JVET_X0049_ADAPT_DMVR if( pu.bmMergeFlag ) { - PU::spanMotionInfo( pu, mrgCtx, m_mvBufBDMVR4BM[pu.mergeIdx << 1], m_mvBufBDMVR4BM[( pu.mergeIdx << 1 ) + 1], m_pcInterSearch->getBdofSubPuMvOffset() ); + PU::spanMotionInfo(pu, mrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR4BM[pu.mergeIdx << 1], m_mvBufBDMVR4BM[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } else #endif - PU::spanMotionInfo(pu, mrgCtx, m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); + PU::spanMotionInfo(pu, mrgCtx, +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + m_mvBufBDMVR[pu.mergeIdx << 1], m_mvBufBDMVR[(pu.mergeIdx << 1) + 1], m_pcInterSearch->getBdofSubPuMvOffset()); } #endif pu.mvRefine = false; diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index 7f4663ebc7cb802c871a4ed49751f3d1a255bf9c..7227a30daa8c52b0c8a100d1dc8ef81080556fa9 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -327,7 +327,11 @@ private: #endif double m_AFFBestSATDCost; double m_mergeBestSATDCost; - MotionInfo m_SubPuMiBuf [( MAX_CU_SIZE * MAX_CU_SIZE ) >> ( MIN_CU_LOG2 << 1 )]; +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + MotionInfo m_SubPuMiBuf[SUB_TMVP_NUM][(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#else + MotionInfo m_SubPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; +#endif #if MULTI_PASS_DMVR Mv m_mvBufBDMVR[(MRG_MAX_NUM_CANDS << 1)][MAX_NUM_SUBCU_DMVR]; #if TM_MRG diff --git a/source/Lib/EncoderLib/EncGOP.cpp b/source/Lib/EncoderLib/EncGOP.cpp index eea8a14bc1d2ae6b295c82ba87ae0b3f512a211a..50fec0675de6fefe64419aa641c98796f1e56ab8 100644 --- a/source/Lib/EncoderLib/EncGOP.cpp +++ b/source/Lib/EncoderLib/EncGOP.cpp @@ -2675,88 +2675,198 @@ void EncGOP::compressGOP(int iPOCLast, int iNumPicRcvd, PicList &rcListPic, std: picHeader->setEnableTMVPFlag(0); } - if( pcSlice->getSliceType() != I_SLICE && picHeader->getEnableTMVPFlag() ) +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int poc1stCol = -1; + int list1stCol = 0; + int list2ndCol = 0; +#endif + if (pcSlice->getSliceType() != I_SLICE && picHeader->getEnableTMVPFlag()) { int colRefIdxL0 = -1, colRefIdxL1 = -1; const bool isResamplingPossible = pcSlice->getSPS()->getRprEnabledFlag(); - for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); refIdx++ ) + for (int refIdx = 0; refIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0); refIdx++) { - CHECK( pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->unscaledPic == nullptr, "unscaledPic is not set for L0 reference picture" ); - - if( !isResamplingPossible || !pcSlice->getRefPic( REF_PIC_LIST_0, refIdx )->isRefScaled( pcSlice->getPPS() ) ) + CHECK(pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->unscaledPic == nullptr, "unscaledPic is not set for L0 reference picture"); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if ((!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->isRefScaled(pcSlice->getPPS())) /*&& (pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->slices[0]->getSliceType() != I_SLICE)*/) +#else + if (!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->isRefScaled(pcSlice->getPPS())) +#endif { +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + poc1stCol = pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->getPOC(); + list1stCol = 0; +#endif colRefIdxL0 = refIdx; break; } } - if( pcSlice->getSliceType() == B_SLICE ) + if (pcSlice->getSliceType() == B_SLICE) { - for( int refIdx = 0; refIdx < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); refIdx++ ) +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + list2ndCol = 1; + if (colRefIdxL0 < 0) { - CHECK( pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->unscaledPic == nullptr, "unscaledPic is not set for L1 reference picture" ); - - if( !isResamplingPossible || !pcSlice->getRefPic( REF_PIC_LIST_1, refIdx )->isRefScaled( pcSlice->getPPS() ) ) + for (int refIdx = 0; refIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1); refIdx++) + { + CHECK(pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->unscaledPic == nullptr, "unscaledPic is not set for L1 reference picture"); + if ((!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->isRefScaled(pcSlice->getPPS())) /*&& (pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->slices[0]->getSliceType() != I_SLICE)*/) + { + poc1stCol = pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->getPOC(); + list1stCol = 1; + colRefIdxL0 = refIdx; + break; + } + } + } +#endif + for (int refIdx = 0; refIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1); refIdx++) + { + CHECK(pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->unscaledPic == nullptr, "unscaledPic is not set for L1 reference picture"); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + int poc2ndCol = pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->getPOC(); + if ((poc1stCol != poc2ndCol) && (!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->isRefScaled(pcSlice->getPPS())) /*&& (pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->slices[0]->getSliceType() != I_SLICE)*/) +#else + if (!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_1, refIdx)->isRefScaled(pcSlice->getPPS())) +#endif { +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + list2ndCol = 1; +#endif colRefIdxL1 = refIdx; break; } } } - - if( colRefIdxL0 >= 0 && colRefIdxL1 >= 0 ) +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + else { - const Picture *refPicL0 = pcSlice->getRefPic( REF_PIC_LIST_0, colRefIdxL0 ); - if( !refPicL0->slices.size() ) + for (int refIdx = 0; refIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0); refIdx++) + { + int poc2ndCol = pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->getPOC(); + CHECK(pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->unscaledPic == nullptr, "unscaledPic is not set for L0 reference picture"); + if ((poc1stCol != poc2ndCol) && (!isResamplingPossible || !pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->isRefScaled(pcSlice->getPPS())) /*&& (pcSlice->getRefPic(REF_PIC_LIST_0, refIdx)->slices[0]->getSliceType() != I_SLICE)*/) + { + colRefIdxL1 = refIdx; + break; + } + } + } +#endif + if (colRefIdxL0 >= 0 && colRefIdxL1 >= 0) + { +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + const Picture *refPicL0 = pcSlice->getRefPic(RefPicList(list1stCol), colRefIdxL0); + if (!refPicL0->slices.size()) { refPicL0 = refPicL0->unscaledPic; } - const Picture *refPicL1 = pcSlice->getRefPic( REF_PIC_LIST_1, colRefIdxL1 ); - if( !refPicL1->slices.size() ) + const Picture *refPicL1 = pcSlice->getRefPic(RefPicList(list2ndCol), colRefIdxL1); + if (!refPicL1->slices.size()) + { + refPicL1 = refPicL1->unscaledPic; + } + picHeader->setPicColFromL0Flag(1 - list1stCol); + pcSlice->setColFromL0Flag(1 - list1stCol); + pcSlice->setColRefIdx(colRefIdxL0); + picHeader->setColRefIdx(colRefIdxL0); + picHeader->setPicColFromL0Flag2nd(1 - list2ndCol); + pcSlice->setColFromL0Flag2nd(1 - list2ndCol); + pcSlice->setColRefIdx2nd(colRefIdxL1); + picHeader->setColRefIdx2nd(colRefIdxL1); + + int poc1st = refPicL0->getPOC(); + int poc2nd = refPicL1->getPOC(); + int pocCur = pcSlice->getPOC(); + if ((abs(poc1st - pocCur) == abs(poc2nd - pocCur)) && (refPicL0->slices[0]->getSliceQp() < refPicL1->slices[0]->getSliceQp())) + { + picHeader->setPicColFromL0Flag2nd(1 - list1stCol); + pcSlice->setColFromL0Flag2nd(1 - list1stCol); + pcSlice->setColRefIdx2nd(colRefIdxL0); + picHeader->setColRefIdx2nd(colRefIdxL0); + picHeader->setPicColFromL0Flag(1 - list2ndCol); + pcSlice->setColFromL0Flag(1 - list2ndCol); + pcSlice->setColRefIdx(colRefIdxL1); + picHeader->setColRefIdx(colRefIdxL1); + } +#else + const Picture *refPicL0 = pcSlice->getRefPic(REF_PIC_LIST_0, colRefIdxL0); + if (!refPicL0->slices.size()) + { + refPicL0 = refPicL0->unscaledPic; + } + + const Picture *refPicL1 = pcSlice->getRefPic(REF_PIC_LIST_1, colRefIdxL1); + if (!refPicL1->slices.size()) { refPicL1 = refPicL1->unscaledPic; } - CHECK( !refPicL0->slices.size(), "Wrong L0 reference picture" ); - CHECK( !refPicL1->slices.size(), "Wrong L1 reference picture" ); + CHECK(!refPicL0->slices.size(), "Wrong L0 reference picture"); + CHECK(!refPicL1->slices.size(), "Wrong L1 reference picture"); const uint32_t uiColFromL0 = refPicL0->slices[0]->getSliceQp() > refPicL1->slices[0]->getSliceQp(); - picHeader->setPicColFromL0Flag( uiColFromL0 ); - pcSlice->setColFromL0Flag( uiColFromL0 ); - pcSlice->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 ); - picHeader->setColRefIdx( uiColFromL0 ? colRefIdxL0 : colRefIdxL1 ); + picHeader->setPicColFromL0Flag(uiColFromL0); + pcSlice->setColFromL0Flag(uiColFromL0); + pcSlice->setColRefIdx(uiColFromL0 ? colRefIdxL0 : colRefIdxL1); + picHeader->setColRefIdx(uiColFromL0 ? colRefIdxL0 : colRefIdxL1); +#endif } - else if( colRefIdxL0 < 0 && colRefIdxL1 >= 0 ) +#if !JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + else if (colRefIdxL0 < 0 && colRefIdxL1 >= 0) { - picHeader->setPicColFromL0Flag( false ); - pcSlice->setColFromL0Flag( false ); - pcSlice->setColRefIdx( colRefIdxL1 ); - picHeader->setColRefIdx( colRefIdxL1 ); + picHeader->setPicColFromL0Flag(false); + pcSlice->setColFromL0Flag(false); + pcSlice->setColRefIdx(colRefIdxL1); + picHeader->setColRefIdx(colRefIdxL1); } - else if( colRefIdxL0 >= 0 && colRefIdxL1 < 0 ) +#endif + else if (colRefIdxL0 >= 0 && colRefIdxL1 < 0) { - picHeader->setPicColFromL0Flag( true ); - pcSlice->setColFromL0Flag( true ); - pcSlice->setColRefIdx( colRefIdxL0 ); - picHeader->setColRefIdx( colRefIdxL0 ); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + picHeader->setPicColFromL0Flag(1 - list1stCol); + pcSlice->setColFromL0Flag(1 - list1stCol); + pcSlice->setColRefIdx(colRefIdxL0); + picHeader->setColRefIdx(colRefIdxL0); + picHeader->setPicColFromL0Flag2nd(1 - list2ndCol); + pcSlice->setColFromL0Flag2nd(1 - list2ndCol); + pcSlice->setColRefIdx2nd(0); + picHeader->setColRefIdx2nd(0); +#else + picHeader->setPicColFromL0Flag(true); + pcSlice->setColFromL0Flag(true); + pcSlice->setColRefIdx(colRefIdxL0); + picHeader->setColRefIdx(colRefIdxL0); +#endif } else { - picHeader->setEnableTMVPFlag( 0 ); + picHeader->setEnableTMVPFlag(0); } #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING if (picHeader->getEnableTMVPFlag()) { +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int colFrameIdx = 0; colFrameIdx < (pcSlice->isInterB() ? 2 : 1); colFrameIdx++) + { + const Picture* const pColPic = pcSlice->getRefPic(RefPicList(colFrameIdx == 0 ? 1 - pcSlice->getColFromL0Flag() : 1 - pcSlice->getColFromL0Flag2nd()), colFrameIdx == 0 ? pcSlice->getColRefIdx() : pcSlice->getColRefIdx2nd()); +#else const Picture* const pColPic = pcSlice->getRefPic(RefPicList(pcSlice->isInterB() ? 1 - pcSlice->getColFromL0Flag() : 0), pcSlice->getColRefIdx()); +#endif if (pColPic) { const int currPOC = pcSlice->getPOC(); const int colPOC = pColPic->getPOC(); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pcSlice->resizeImBuf(pColPic->numSlices, colFrameIdx); +#else pcSlice->resizeImBuf(pColPic->numSlices); +#endif Slice *pColSlice = nullptr; for (int sliceIdx = 0; sliceIdx < pColPic->numSlices; sliceIdx++) { @@ -2810,12 +2920,19 @@ void EncGOP::compressGOP(int iPOCLast, int iNumPicRcvd, PicList &rcListPic, std: } } // curRefIdx //printf("sliceIdx:%d, colRefPicListIdx:%d, curRefPicListIdx:%d, colRefIdx:%d, targetRefIdx:%d\n", sliceIdx, colRefPicListIdx, curRefPicListIdx, colRefIdx, targetRefIdx); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pcSlice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx, colFrameIdx); +#else pcSlice->setImRefIdx(sliceIdx, RefPicList(colRefPicListIdx), RefPicList(curRefPicListIdx), colRefIdx, targetRefIdx); +#endif } // curRefPicListIdx } } } } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + } +#endif } #endif } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index 905d7651b29f0be9c0dd1be7cd080f769ee059e8..5527a960f3675b8b28b148de4e2c2e19ee7bdde8 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -1534,6 +1534,9 @@ void EncLib::xInitSPS( SPS& sps ) #if JVET_W0090_ARMC_TM sps.setUseAML ( m_AML ); #endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + sps.setUseFastSubTmvp ((m_sourceWidth * m_sourceHeight) > (m_intraPeriod == -1 ? 0 : 832 * 480)); +#endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC sps.setUseArmcRefinedMotion ( m_armcRefinedMotion ); #endif diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 127109a313a617db0342c96eec6905ca1ced0d3e..fe34ffa4bc8ae06713d3bdea586fb3cc70ea15b4 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -3578,7 +3578,14 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) if (cu.cs->sps->getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(pu.lumaSize()); +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + for (int i = 0; i < SUB_TMVP_NUM; i++) + { + mergeCtx.subPuMvpMiBuf[i] = MotionBuf(m_SubPuMiBuf[i], bufSize); + } +#else mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); +#endif } Distortion uiHevcCost = std::numeric_limits<Distortion>::max(); @@ -4693,7 +4700,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) if (!pu.bdmvrRefine) #endif { - PU::spanMotionInfo( pu, mergeCtx ); + PU::spanMotionInfo(pu, mergeCtx +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + , pu.colIdx +#endif + ); } m_skipPROF = false; @@ -4725,7 +4736,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) #if JVET_X0083_BM_AMVP_MERGE_MODE if (pu.bdmvrRefine) { - PU::spanMotionInfo( *cu.firstPU, MergeCtx(), mvBufEncAmBDMVR_L0, mvBufEncAmBDMVR_L1, getBdofSubPuMvOffset() ); + PU::spanMotionInfo(*cu.firstPU, MergeCtx(), +#if ENABLE_INTER_TEMPLATE_MATCHING && JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + pu.colIdx, +#endif + mvBufEncAmBDMVR_L0, mvBufEncAmBDMVR_L1, getBdofSubPuMvOffset()); } #endif #if INTER_LIC && (!TM_AMVP || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP)) diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 2561d7a85a641e98247b6a0fbe4df6b977b0db95..a5805daa57ad2301ae9bc52e950e6e8ebbc3f817 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1371,6 +1371,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) #endif WRITE_FLAG( pcSPS->getUseAML() ? 1 : 0, "sps_aml_enabled_flag" ); #endif +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + WRITE_FLAG( pcSPS->getUseFastSubTmvp() ? 1 : 0, "sps_fast_sub_tmvp_enabled_flag"); +#endif #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM if (pcSPS->getUseAML()) { @@ -2440,12 +2443,22 @@ void HLSWriter::codePictureHeader( PicHeader* picHeader, bool writeRbspTrailingB if (picHeader->getRPL(1)->getNumRefEntries() > 0) { WRITE_CODE(picHeader->getPicColFromL0Flag(), 1, "ph_collocated_from_l0_flag"); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + WRITE_CODE(picHeader->getPicColFromL0Flag2nd(), 1, "ph_collocated_from_l0_flag_2nd"); +#endif } if ((picHeader->getPicColFromL0Flag() && picHeader->getRPL(0)->getNumRefEntries() > 1) || (!picHeader->getPicColFromL0Flag() && picHeader->getRPL(1)->getNumRefEntries() > 1)) { WRITE_UVLC(picHeader->getColRefIdx(), "ph_collocated_ref_idx"); } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if ((picHeader->getPicColFromL0Flag2nd() && picHeader->getRPL(0)->getNumRefEntries() > 1) || + (!picHeader->getPicColFromL0Flag2nd() && picHeader->getRPL(1)->getNumRefEntries() > 1)) + { + WRITE_UVLC(picHeader->getColRefIdx2nd(), "ph_collocated_ref_idx_2nd"); + } +#endif } } else @@ -3000,6 +3013,9 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) if (pcSlice->getSliceType() == B_SLICE) { WRITE_FLAG(pcSlice->getColFromL0Flag(), "collocated_from_l0_flag"); +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + WRITE_FLAG(pcSlice->getColFromL0Flag2nd(), "collocated_from_l0_flag_2nd"); +#endif } } @@ -3009,6 +3025,14 @@ void HLSWriter::codeSliceHeader ( Slice* pcSlice ) { WRITE_UVLC( pcSlice->getColRefIdx(), "collocated_ref_idx" ); } +#if JVET_AC0185_ENHANCED_TEMPORAL_MOTION_DERIVATION + if (pcSlice->getSliceType() != I_SLICE && + ((pcSlice->getColFromL0Flag2nd() == 1 && pcSlice->getNumRefIdx(REF_PIC_LIST_0) > 1) || + (pcSlice->getColFromL0Flag2nd() == 0 && pcSlice->getNumRefIdx(REF_PIC_LIST_1) > 1))) + { + WRITE_UVLC(pcSlice->getColRefIdx2nd(), "collocated_ref_idx_2nd"); + } +#endif } if( ( pcSlice->getPPS()->getUseWP() && pcSlice->getSliceType() == P_SLICE ) || ( pcSlice->getPPS()->getWPBiPred() && pcSlice->getSliceType() == B_SLICE ) )