From fd970b23feebe4e96fd42fd75a7a7e8ef739d3d9 Mon Sep 17 00:00:00 2001 From: Xiaoyu Xiu <xiaoyuxiu@kwai.com> Date: Tue, 23 Jul 2019 21:41:52 +0200 Subject: [PATCH] use m_pcEncCfg->getUseAffineAmvrEncOpt() to control the effect of m_pcEncCfg->getIntraPeriod() != ( uint32_t ) -1, i.e., low delay setting. --- source/Lib/CommonLib/Rom.cpp | 8 + source/Lib/CommonLib/Rom.h | 6 + source/Lib/CommonLib/TypeDef.h | 2 + source/Lib/EncoderLib/EncCu.cpp | 17 ++ source/Lib/EncoderLib/EncModeCtrl.cpp | 12 ++ source/Lib/EncoderLib/EncModeCtrl.h | 9 + source/Lib/EncoderLib/EncSlice.cpp | 3 + source/Lib/EncoderLib/InterSearch.cpp | 285 ++++++++++++++++++++++++++ source/Lib/EncoderLib/InterSearch.h | 100 +++++++++ 9 files changed, 442 insertions(+) diff --git a/source/Lib/CommonLib/Rom.cpp b/source/Lib/CommonLib/Rom.cpp index 7cc906bc1..e32c236ea 100644 --- a/source/Lib/CommonLib/Rom.cpp +++ b/source/Lib/CommonLib/Rom.cpp @@ -430,6 +430,10 @@ void initROM() } } #endif + +#if JVET_O0592_ENC_ME_IMP + ::memset(g_isReusedUniMVsFilled, 0, sizeof(g_isReusedUniMVsFilled)); +#endif } void destroyROM() @@ -753,5 +757,9 @@ uint8_t g_triangleMvStorage[TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 1][MA #if JVET_O0280_SIMD_TRIANGLE_WEIGHTING int16_t *g_triangleWeights[2][TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG2 + 2][MAX_CU_DEPTH - MIN_CU_LOG2 + 2]; #endif +#if JVET_O0592_ENC_ME_IMP +Mv g_reusedUniMVs[32][32][8][8][2][33]; +bool g_isReusedUniMVsFilled[32][32][8][8]; +#endif //! \} diff --git a/source/Lib/CommonLib/Rom.h b/source/Lib/CommonLib/Rom.h index ac26cd734..877b947d7 100644 --- a/source/Lib/CommonLib/Rom.h +++ b/source/Lib/CommonLib/Rom.h @@ -226,5 +226,11 @@ extern int16_t *g_triangleWeights[2][TRIANGLE_DIR_NUM][MAX_CU_DEPTH - MIN_CU_LOG extern bool g_mctsDecCheckEnabled; +#if JVET_O0592_ENC_ME_IMP +class Mv; +extern Mv g_reusedUniMVs[32][32][8][8][2][33]; +extern bool g_isReusedUniMVsFilled[32][32][8][8]; +#endif + #endif //__TCOMROM__ diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 384a0c6cf..20b82d923 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -114,6 +114,8 @@ #define JVET_O0126_BPWA_INDEX_CODING_FIX 1 // JVET-O0126 align BPWA index coding with specification +#define JVET_O0592_ENC_ME_IMP 1 // JVET-O0592 encoder ME improvement + #define FIX_DB_MAX_TRANSFORM_SIZE 1 #define MRG_SHARELIST_SHARSIZE 32 diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 2ae45ae5a..167cc7935 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -266,6 +266,9 @@ void EncCu::init( EncLib* pcEncLib, const SPS& sps PARL_PARAM( const int tId ) ) m_modeCtrl->init( m_pcEncCfg, m_pcRateCtrl, m_pcRdCost ); m_pcInterSearch->setModeCtrl( m_modeCtrl ); +#if JVET_O0592_ENC_ME_IMP + m_modeCtrl->setInterSearch(m_pcInterSearch); +#endif m_pcIntraSearch->setModeCtrl( m_modeCtrl ); if ( ( m_pcEncCfg->getIBCHashSearch() && m_pcEncCfg->getIBCMode() ) || m_pcEncCfg->getAllowDisFracMMVD() ) @@ -1188,6 +1191,14 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, AffineMVInfo tmpMVInfo; bool isAffMVInfoSaved; m_pcInterSearch->savePrevAffMVInfo(0, tmpMVInfo, isAffMVInfoSaved); +#if JVET_O0592_ENC_ME_IMP + BlkUniMvInfo tmpUniMvInfo; + bool isUniMvInfoSaved = false; + if (!tempCS->slice->isIntra()) + { + m_pcInterSearch->savePrevUniMvInfo(tempCS->area.Y(), tmpUniMvInfo, isUniMvInfoSaved); + } +#endif do { @@ -1319,6 +1330,12 @@ void EncCu::xCheckModeSplit(CodingStructure *&tempCS, CodingStructure *&bestCS, if (isAffMVInfoSaved) m_pcInterSearch->addAffMVInfo(tmpMVInfo); +#if JVET_O0592_ENC_ME_IMP + if (!tempCS->slice->isIntra() && isUniMvInfoSaved) + { + m_pcInterSearch->addUniMvInfo(tmpUniMvInfo); + } +#endif tempCS->motionLut = oldMotionLut; diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index 1c1622bcd..e91d16737 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1795,6 +1795,18 @@ bool EncModeCtrlMTnoRQT::tryMode( const EncTestMode& encTestmode, const CodingSt { CHECK( encTestmode.type != ETM_POST_DONT_SPLIT, "Unknown mode" ); +#if JVET_O0592_ENC_ME_IMP + if ((cuECtx.get<double>(BEST_NO_IMV_COST) == (MAX_DOUBLE * .5) || cuECtx.get<bool>(IS_REUSING_CU)) && !slice.isIntra()) + { + unsigned idx1, idx2, idx3, idx4; + getAreaIdx(partitioner.currArea().Y(), *slice.getPPS()->pcv, idx1, idx2, idx3, idx4); + if (g_isReusedUniMVsFilled[idx1][idx2][idx3][idx4]) + { + m_pcInterSearch->insertUniMvCands(partitioner.currArea().Y(), g_reusedUniMVs[idx1][idx2][idx3][idx4]); + } + } +#endif + if( !bestCS || ( bestCS && isModeSplit( bestMode ) ) ) { return false; diff --git a/source/Lib/EncoderLib/EncModeCtrl.h b/source/Lib/EncoderLib/EncModeCtrl.h index 9fe9e3189..d29d095c4 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.h +++ b/source/Lib/EncoderLib/EncModeCtrl.h @@ -43,6 +43,9 @@ #include "CommonLib/CommonDef.h" #include "CommonLib/CodingStructure.h" +#if JVET_O0592_ENC_ME_IMP +#include "InterSearch.h" +#endif #include <typeinfo> #include <vector> @@ -258,6 +261,9 @@ protected: #if ENABLE_SPLIT_PARALLELISM int m_runNextInParallel; #endif +#if JVET_O0592_ENC_ME_IMP + InterSearch* m_pcInterSearch; +#endif public: @@ -315,6 +321,9 @@ public: void setBestCostWithoutSplitFlags ( double cost ) { m_ComprCUCtxList.back().bestCostWithoutSplitFlags = cost; } double getMtsFirstPassNoIspCost () const { return m_ComprCUCtxList.back().bestCostMtsFirstPassNoIsp; } void setMtsFirstPassNoIspCost ( double cost ) { m_ComprCUCtxList.back().bestCostMtsFirstPassNoIsp = cost; } +#if JVET_O0592_ENC_ME_IMP + void setInterSearch (InterSearch* pcInterSearch) { m_pcInterSearch = pcInterSearch; } +#endif protected: void xExtractFeatures ( const EncTestMode encTestmode, CodingStructure& cs ); diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 9fd85ab2f..1e75780bb 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -1415,6 +1415,9 @@ void EncSlice::compressSlice( Picture* pcPic, const bool bCompressEntireSlice, c writeBlockStatisticsHeader(sps); #endif m_pcInterSearch->resetAffineMVList(); +#if JVET_O0592_ENC_ME_IMP + m_pcInterSearch->resetUniMvList(); +#endif encodeCtus( pcPic, bCompressEntireSlice, bFastDeltaQP, startCtuTsAddr, boundingCtuTsAddr, m_pcLib ); diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 9827166bd..6d82bae56 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -112,6 +112,11 @@ InterSearch::InterSearch() m_affMVList = nullptr; m_affMVListSize = 0; m_affMVListIdx = 0; +#if JVET_O0592_ENC_ME_IMP + m_uniMvList = nullptr; + m_uniMvListSize = 0; + m_uniMvListIdx = 0; +#endif m_histBestSbt = MAX_UCHAR; m_histBestMtsIdx = MAX_UCHAR; } @@ -156,6 +161,15 @@ void InterSearch::destroy() } m_affMVListIdx = 0; m_affMVListSize = 0; +#if JVET_O0592_ENC_ME_IMP + if (m_uniMvList) + { + delete[] m_uniMvList; + m_uniMvList = nullptr; + } + m_uniMvListIdx = 0; + m_uniMvListSize = 0; +#endif m_isInitialized = false; } @@ -255,6 +269,15 @@ void InterSearch::init( EncCfg* pcEncCfg, m_affMVList = new AffineMVInfo[m_affMVListMaxSize]; m_affMVListIdx = 0; m_affMVListSize = 0; +#if JVET_O0592_ENC_ME_IMP + m_uniMvListMaxSize = 15; + if (!m_uniMvList) + { + m_uniMvList = new BlkUniMvInfo[m_uniMvListMaxSize]; + } + m_uniMvListIdx = 0; + m_uniMvListSize = 0; +#endif m_isInitialized = true; } @@ -2399,6 +2422,18 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) } } +#if JVET_O0592_ENC_ME_IMP + ::memcpy(cMvHevcTemp, cMvTemp, sizeof(cMvTemp)); + if (cu.imv == 0 && (!cu.slice->getSPS()->getUseGBi() || gbiIdx == GBI_DEFAULT)) + { + insertUniMvCands(pu.Y(), cMvTemp); + + unsigned idx1, idx2, idx3, idx4; + getAreaIdx(cu.Y(), *cu.slice->getPPS()->pcv, idx1, idx2, idx3, idx4); + ::memcpy(&(g_reusedUniMVs[idx1][idx2][idx3][idx4][0][0]), cMvTemp, 2 * 33 * sizeof(Mv)); + g_isReusedUniMVsFilled[idx1][idx2][idx3][idx4] = true; + } +#else if (cu.Y().width > 8 && cu.Y().height > 8 && cu.slice->getSPS()->getUseAffine() && checkAffine && (gbiIdx == GBI_DEFAULT || m_affineModeSelected || !m_pcEncCfg->getUseGBiFast()) @@ -2406,6 +2441,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) { ::memcpy( cMvHevcTemp, cMvTemp, sizeof( cMvTemp ) ); } +#endif // Bi-predictive Motion estimation if( ( cs.slice->isInterB() ) && ( PU::isBipredRestriction( pu ) == false ) && (cu.slice->getCheckLDC() || gbiIdx == GBI_DEFAULT || !m_affineModeSelected || !m_pcEncCfg->getUseGBiFast()) @@ -2648,11 +2684,48 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) costStart += m_pcRdCost->getCost(bits); std::vector<Mv> symmvdCands; +#if JVET_O0592_ENC_ME_IMP + auto smmvdCandsGen = [&](Mv mvCand, bool mvPrecAdj) + { + if (mvPrecAdj && pu.cu->imv) + { + mvCand.roundIbcPrecInternal2Amvr(pu.cu->imv); + } + + bool toAddMvCand = true; + for (std::vector<Mv>::iterator pos = symmvdCands.begin(); pos != symmvdCands.end(); pos++) + { + if (*pos == mvCand) + { + toAddMvCand = false; + break; + } + } + + if (toAddMvCand) + { + symmvdCands.push_back(mvCand); + } + }; + + smmvdCandsGen(cMvHevcTemp[curRefList][refIdxCur], false); + smmvdCandsGen(cMvTemp[curRefList][refIdxCur], false); + if (iRefIdxBi[curRefList] == refIdxCur) + { + smmvdCandsGen(cMvBi[curRefList], false); + } + for (int i = 0; i < m_uniMvListSize; i++) + { + BlkUniMvInfo* curMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - i + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + smmvdCandsGen(curMvInfo->uniMvs[curRefList][refIdxCur], true); + } +#else symmvdCands.push_back(cMvTemp[curRefList][refIdxCur]); if (iRefIdxBi[curRefList] == refIdxCur && cMvBi[curRefList] != cMvTemp[curRefList][refIdxCur]) { symmvdCands.push_back(cMvBi[curRefList]); } +#endif for (auto mvStart : symmvdCands) { @@ -2662,7 +2735,13 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) checked |= (mvStart == aacAMVPInfo[curRefList][refIdxCur].mvCand[i]); } if (checked) +#if JVET_O0592_ENC_ME_IMP + { + continue; + } +#else break; +#endif Distortion bestCost = costStart; symmvdCheckBestMvp(pu, origBuf, mvStart, (RefPicList)curRefList, aacAMVPInfo, gbiIdx, cMvPredSym, mvpIdxSym, costStart); @@ -3288,13 +3367,63 @@ void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Ref // Do integer search if( ( m_motionEstimationSearchMethod == MESEARCH_FULL ) || bBi || bQTBTMV ) { +#if JVET_O0592_ENC_ME_IMP + cStruct.subShiftMode = m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE3 ? 2 : 0; + m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode); + + Mv bestInitMv = (bBi ? rcMv : rcMvPred); + Mv cTmpMv = bestInitMv; + clipMv(cTmpMv, pu.cu->lumaPos(), pu.cu->lumaSize(), *pu.cs->sps); + cTmpMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + m_cDistParam.cur.buf = cStruct.piRefY + (cTmpMv.ver * cStruct.iRefStride) + cTmpMv.hor; + Distortion uiBestSad = m_cDistParam.distFunc(m_cDistParam); + uiBestSad += m_pcRdCost->getCostOfVectorWithPredictor(cTmpMv.hor, cTmpMv.ver, cStruct.imvShift); + + for (int i = 0; i < m_uniMvListSize; i++) + { + BlkUniMvInfo* curMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - i + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + + int j = 0; + for (; j < i; j++) + { + BlkUniMvInfo *prevMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - j + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + if (curMvInfo->uniMvs[eRefPicList][iRefIdxPred] == prevMvInfo->uniMvs[eRefPicList][iRefIdxPred]) + { + break; + } + } + if (j < i) + continue; + + cTmpMv = curMvInfo->uniMvs[eRefPicList][iRefIdxPred]; + clipMv(cTmpMv, pu.cu->lumaPos(), pu.cu->lumaSize(), *pu.cs->sps); + cTmpMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + m_cDistParam.cur.buf = cStruct.piRefY + (cTmpMv.ver * cStruct.iRefStride) + cTmpMv.hor; + + Distortion uiSad = m_cDistParam.distFunc(m_cDistParam); + uiSad += m_pcRdCost->getCostOfVectorWithPredictor(cTmpMv.hor, cTmpMv.ver, cStruct.imvShift); + if (uiSad < uiBestSad) + { + uiBestSad = uiSad; + bestInitMv = curMvInfo->uniMvs[eRefPicList][iRefIdxPred]; + m_cDistParam.maximumDistortionForEarlyExit = uiSad; + } + } +#endif + if( !bQTBTMV ) { +#if JVET_O0592_ENC_ME_IMP + xSetSearchRange(pu, bestInitMv, iSrchRng, cStruct.searchRange +#else xSetSearchRange(pu, (bBi ? rcMv : rcMvPred), iSrchRng, cStruct.searchRange +#endif , cStruct ); } +#if !JVET_O0592_ENC_ME_IMP cStruct.subShiftMode = m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE3 ? 2 : 0; +#endif xPatternSearch( cStruct, rcMv, ruiCost); } else if( bQTBTMV2 ) @@ -3303,7 +3432,11 @@ void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Ref cStruct.subShiftMode = ( !m_pcEncCfg->getRestrictMESampling() && m_pcEncCfg->getMotionEstimationSearchMethod() == MESEARCH_SELECTIVE ) ? 1 : ( m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE3 ) ? 2 : 0; +#if JVET_O0592_ENC_ME_IMP + xTZSearch(pu, eRefPicList, iRefIdxPred, cStruct, rcMv, ruiCost, NULL, false, true); +#else xTZSearch( pu, cStruct, rcMv, ruiCost, NULL, false, true ); +#endif } else { @@ -3311,7 +3444,11 @@ void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Ref ( m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE3 ) ? 2 : 0; rcMv = rcMvPred; const Mv *pIntegerMv2Nx2NPred = 0; +#if JVET_O0592_ENC_ME_IMP + xPatternSearchFast(pu, eRefPicList, iRefIdxPred, cStruct, rcMv, ruiCost, pIntegerMv2Nx2NPred); +#else xPatternSearchFast( pu, cStruct, rcMv, ruiCost, pIntegerMv2Nx2NPred ); +#endif if( blkCache ) { blkCache->setMv( pu.cs->area, eRefPicList, iRefIdxPred, rcMv ); @@ -3471,6 +3608,10 @@ void InterSearch::xPatternSearch( IntTZSearchStruct& cStruct, void InterSearch::xPatternSearchFast( const PredictionUnit& pu, +#if JVET_O0592_ENC_ME_IMP + RefPicList eRefPicList, + int iRefIdxPred, +#endif IntTZSearchStruct& cStruct, Mv& rcMv, Distortion& ruiSAD, @@ -3479,15 +3620,27 @@ void InterSearch::xPatternSearchFast( const PredictionUnit& pu, switch ( m_motionEstimationSearchMethod ) { case MESEARCH_DIAMOND: +#if JVET_O0592_ENC_ME_IMP + xTZSearch ( pu, eRefPicList, iRefIdxPred, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred, false ); +#else xTZSearch ( pu, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred, false ); +#endif break; case MESEARCH_SELECTIVE: +#if JVET_O0592_ENC_ME_IMP + xTZSearchSelective( pu, eRefPicList, iRefIdxPred, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred ); +#else xTZSearchSelective( pu, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred ); +#endif break; case MESEARCH_DIAMOND_ENHANCED: +#if JVET_O0592_ENC_ME_IMP + xTZSearch ( pu, eRefPicList, iRefIdxPred, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred, true ); +#else xTZSearch ( pu, cStruct, rcMv, ruiSAD, pIntegerMv2Nx2NPred, true ); +#endif break; case MESEARCH_FULL: // shouldn't get here. @@ -3498,6 +3651,10 @@ void InterSearch::xPatternSearchFast( const PredictionUnit& pu, void InterSearch::xTZSearch( const PredictionUnit& pu, +#if JVET_O0592_ENC_ME_IMP + RefPicList eRefPicList, + int iRefIdxPred, +#endif IntTZSearchStruct& cStruct, Mv& rcMv, Distortion& ruiSAD, @@ -3588,6 +3745,41 @@ void InterSearch::xTZSearch( const PredictionUnit& pu, xTZSearchHelp( cStruct, integerMv2Nx2NPred.getHor(), integerMv2Nx2NPred.getVer(), 0, 0); } } + +#if JVET_O0592_ENC_ME_IMP + for (int i = 0; i < m_uniMvListSize; i++) + { + BlkUniMvInfo* curMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - i + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + + int j = 0; + for (; j < i; j++) + { + BlkUniMvInfo *prevMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - j + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + if (curMvInfo->uniMvs[eRefPicList][iRefIdxPred] == prevMvInfo->uniMvs[eRefPicList][iRefIdxPred]) + { + break; + } + } + if (j < i) + continue; + + Mv cTmpMv = curMvInfo->uniMvs[eRefPicList][iRefIdxPred]; + clipMv(cTmpMv, pu.cu->lumaPos(), pu.cu->lumaSize(), *pu.cs->sps); + cTmpMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + m_cDistParam.cur.buf = cStruct.piRefY + (cTmpMv.ver * cStruct.iRefStride) + cTmpMv.hor; + + Distortion uiSad = m_cDistParam.distFunc(m_cDistParam); + uiSad += m_pcRdCost->getCostOfVectorWithPredictor(cTmpMv.hor, cTmpMv.ver, cStruct.imvShift); + if (uiSad < cStruct.uiBestSad) + { + cStruct.uiBestSad = uiSad; + cStruct.iBestX = cTmpMv.hor; + cStruct.iBestY = cTmpMv.ver; + m_cDistParam.maximumDistortionForEarlyExit = uiSad; + } + } +#endif + { // set search range Mv currBestMv(cStruct.iBestX, cStruct.iBestY ); @@ -3804,6 +3996,10 @@ void InterSearch::xTZSearch( const PredictionUnit& pu, void InterSearch::xTZSearchSelective( const PredictionUnit& pu, +#if JVET_O0592_ENC_ME_IMP + RefPicList eRefPicList, + int iRefIdxPred, +#endif IntTZSearchStruct& cStruct, Mv &rcMv, Distortion &ruiSAD, @@ -3859,6 +4055,41 @@ void InterSearch::xTZSearchSelective( const PredictionUnit& pu, xTZSearchHelp( cStruct, integerMv2Nx2NPred.getHor(), integerMv2Nx2NPred.getVer(), 0, 0); } + +#if JVET_O0592_ENC_ME_IMP + for (int i = 0; i < m_uniMvListSize; i++) + { + BlkUniMvInfo* curMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - i + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + + int j = 0; + for (; j < i; j++) + { + BlkUniMvInfo *prevMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - j + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + if (curMvInfo->uniMvs[eRefPicList][iRefIdxPred] == prevMvInfo->uniMvs[eRefPicList][iRefIdxPred]) + { + break; + } + } + if (j < i) + continue; + + Mv cTmpMv = curMvInfo->uniMvs[eRefPicList][iRefIdxPred]; + clipMv(cTmpMv, pu.cu->lumaPos(), pu.cu->lumaSize(), *pu.cs->sps); + cTmpMv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + m_cDistParam.cur.buf = cStruct.piRefY + (cTmpMv.ver * cStruct.iRefStride) + cTmpMv.hor; + + Distortion uiSad = m_cDistParam.distFunc(m_cDistParam); + uiSad += m_pcRdCost->getCostOfVectorWithPredictor(cTmpMv.hor, cTmpMv.ver, cStruct.imvShift); + if (uiSad < cStruct.uiBestSad) + { + cStruct.uiBestSad = uiSad; + cStruct.iBestX = cTmpMv.hor; + cStruct.iBestY = cTmpMv.ver; + m_cDistParam.maximumDistortionForEarlyExit = uiSad; + } + } +#endif + { // set search range Mv currBestMv(cStruct.iBestX, cStruct.iBestY ); @@ -5445,6 +5676,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, const uint32_t mvShift = mvShiftTable[pu.cu->imv]; if (uiCostBest <= AFFINE_ME_LIST_MVP_TH*m_hevcCost) { +#if !JVET_O0592_ENC_ME_IMP //search 8 nearest neighbors; integer distance int testPos[8][2] = { { -1, 0 },{ 0, -1 },{ 0, 1 },{ 1, 0 },{ -1, -1 },{ -1, 1 },{ 1, 1 },{ 1, -1 } }; const int maxSearchRound = 3; @@ -5491,6 +5723,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, } } } +#endif Mv mvPredTmp[3] = { acMvPred[0], acMvPred[1], acMvPred[2] }; Mv mvME[3]; @@ -5535,6 +5768,57 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, checkCPMVRdCost(acMvTemp); } +#if JVET_O0592_ENC_ME_IMP + // 8 nearest neighbor search + int testPos[8][2] = { { -1, 0 },{ 0, -1 },{ 0, 1 },{ 1, 0 },{ -1, -1 },{ -1, 1 },{ 1, 1 },{ 1, -1 } }; + const int maxSearchRound = (pu.cu->imv) ? 3 : ((m_pcEncCfg->getUseAffineAmvrEncOpt() && m_pcEncCfg->getIntraPeriod() == (uint32_t)-1) ? 2 : 3); + + for (int rnd = 0; rnd < maxSearchRound; rnd++) + { + bool modelChange = false; + //search the model parameters with finear granularity; + for (int j = 0; j < mvNum; j++) + { + bool loopChange = false; + for (int iter = 0; iter < 2; iter++) + { + if (iter == 1 && !loopChange) + { + break; + } + Mv centerMv[3]; + memcpy(centerMv, acMv, sizeof(Mv) * 3); + memcpy(acMvTemp, acMv, sizeof(Mv) * 3); + + for (int i = ((iter == 0) ? 0 : 4); i < ((iter == 0) ? 4 : 8); i++) + { + acMvTemp[j].set(centerMv[j].getHor() + (testPos[i][0] << mvShift), centerMv[j].getVer() + (testPos[i][1] << mvShift)); + clipMv(acMvTemp[j], pu.cu->lumaPos(), pu.cu->lumaSize(), *pu.cs->sps); + xPredAffineBlk(COMPONENT_Y, pu, refPic, acMvTemp, predBuf, false, pu.cu->slice->clpRng(COMPONENT_Y)); + + Distortion costTemp = m_pcRdCost->getDistPart(predBuf.Y(), pBuf->Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, distFunc); + uint32_t bitsTemp = ruiBits; + bitsTemp += xCalcAffineMVBits(pu, acMvTemp, acMvPred); + costTemp = (Distortion)(floor(fWeight * (double)costTemp) + (double)m_pcRdCost->getCost(bitsTemp)); + + if (costTemp < uiCostBest) + { + uiCostBest = costTemp; + uiBitsBest = bitsTemp; + ::memcpy(acMv, acMvTemp, sizeof(Mv) * 3); + modelChange = true; + loopChange = true; + } + } + } + } + + if (!modelChange) + { + break; + } + } +#else { const int threshold = 4 << (MV_PRECISION_INTERNAL - MV_PRECISION_SIXTEENTH); dMv = acMv[1] - acMv[0]; @@ -5551,6 +5835,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, } } } +#endif } acMvPred[0] = aamvpi.mvCandLT[mvpIdx]; acMvPred[1] = aamvpi.mvCandRT[mvpIdx]; diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h index fa1541039..105d51808 100644 --- a/source/Lib/EncoderLib/InterSearch.h +++ b/source/Lib/EncoderLib/InterSearch.h @@ -78,6 +78,14 @@ struct AffineMVInfo int x, y, w, h; }; +#if JVET_O0592_ENC_ME_IMP +struct BlkUniMvInfo +{ + Mv uniMvs[2][33]; + int x, y, w, h; +}; +#endif + typedef struct { Mv acMvAffine4Para[2][3]; @@ -116,6 +124,12 @@ private: int m_affMVListIdx; int m_affMVListSize; int m_affMVListMaxSize; +#if JVET_O0592_ENC_ME_IMP + BlkUniMvInfo* m_uniMvList; + int m_uniMvListIdx; + int m_uniMvListSize; + int m_uniMvListMaxSize; +#endif Distortion m_hevcCost; EncAffineMotion m_affineMotion; PatentBvCand m_defaultCachedBvs; @@ -232,6 +246,80 @@ public: m_affMVListSize = std::min(m_affMVListSize + 1, m_affMVListMaxSize); } } +#if JVET_O0592_ENC_ME_IMP + void resetUniMvList() { m_uniMvListIdx = 0; m_uniMvListSize = 0; } + void insertUniMvCands(CompArea blkArea, Mv cMvTemp[2][33]) + { + BlkUniMvInfo* curMvInfo = m_uniMvList + m_uniMvListIdx; + int j = 0; + for (; j < m_uniMvListSize; j++) + { + BlkUniMvInfo* prevMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - j + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + if ((blkArea.x == prevMvInfo->x) && (blkArea.y == prevMvInfo->y) && (blkArea.width == prevMvInfo->w) && (blkArea.height == prevMvInfo->h)) + { + break; + } + } + + if (j < m_uniMvListSize) + { + curMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - j + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + } + + ::memcpy(curMvInfo->uniMvs, cMvTemp, 2 * 33 * sizeof(Mv)); + if (j == m_uniMvListSize) // new element + { + curMvInfo->x = blkArea.x; + curMvInfo->y = blkArea.y; + curMvInfo->w = blkArea.width; + curMvInfo->h = blkArea.height; + m_uniMvListSize = std::min(m_uniMvListSize + 1, m_uniMvListMaxSize); + m_uniMvListIdx = (m_uniMvListIdx + 1) % (m_uniMvListMaxSize); + } + } + void savePrevUniMvInfo(CompArea blkArea, BlkUniMvInfo &tmpUniMvInfo, bool& isUniMvInfoSaved) + { + int j = 0; + BlkUniMvInfo* curUniMvInfo = nullptr; + for (; j < m_uniMvListSize; j++) + { + curUniMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - j + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + if ((blkArea.x == curUniMvInfo->x) && (blkArea.y == curUniMvInfo->y) && (blkArea.width == curUniMvInfo->w) && (blkArea.height == curUniMvInfo->h)) + { + break; + } + } + + if (j < m_uniMvListSize) + { + isUniMvInfoSaved = true; + tmpUniMvInfo = *curUniMvInfo; + } + } + void addUniMvInfo(BlkUniMvInfo &tmpUniMVInfo) + { + int j = 0; + BlkUniMvInfo* prevUniMvInfo = nullptr; + for (; j < m_uniMvListSize; j++) + { + prevUniMvInfo = m_uniMvList + ((m_uniMvListIdx - 1 - j + m_uniMvListMaxSize) % (m_uniMvListMaxSize)); + if ((tmpUniMVInfo.x == prevUniMvInfo->x) && (tmpUniMVInfo.y == prevUniMvInfo->y) && (tmpUniMVInfo.w == prevUniMvInfo->w) && (tmpUniMVInfo.h == prevUniMvInfo->h)) + { + break; + } + } + if (j < m_uniMvListSize) + { + *prevUniMvInfo = tmpUniMVInfo; + } + else + { + m_uniMvList[m_uniMvListIdx] = tmpUniMVInfo; + m_uniMvListIdx = (m_uniMvListIdx + 1) % m_uniMvListMaxSize; + m_uniMvListSize = std::min(m_uniMvListSize + 1, m_uniMvListMaxSize); + } + } +#endif void resetSavedAffineMotion(); void storeAffineMotion( Mv acAffineMv[2][3], int16_t affineRefIdx[2], EAffineModel affineType, int gbiIdx ); protected: @@ -364,6 +452,10 @@ protected: ); void xTZSearch ( const PredictionUnit& pu, +#if JVET_O0592_ENC_ME_IMP + RefPicList eRefPicList, + int iRefIdxPred, +#endif IntTZSearchStruct& cStruct, Mv& rcMv, Distortion& ruiSAD, @@ -373,6 +465,10 @@ protected: ); void xTZSearchSelective ( const PredictionUnit& pu, +#if JVET_O0592_ENC_ME_IMP + RefPicList eRefPicList, + int iRefIdxPred, +#endif IntTZSearchStruct& cStruct, Mv& rcMv, Distortion& ruiSAD, @@ -387,6 +483,10 @@ protected: ); void xPatternSearchFast ( const PredictionUnit& pu, +#if JVET_O0592_ENC_ME_IMP + RefPicList eRefPicList, + int iRefIdxPred, +#endif IntTZSearchStruct& cStruct, Mv& rcMv, Distortion& ruiSAD, -- GitLab