diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index fdce40a52b0f364cce33db557f1fbc6f4b288d85..4993b03c4565a92fd2bd013b60e7085d307483d8 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -863,7 +863,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("BIO", m_BIO, false, "Enable bi-directional optical flow") ("IMV", m_ImvMode, 1, "Adaptive MV precision Mode (IMV)\n" "\t0: disabled\n" - "\t1: enabled (Full-Pel and 4-PEL)\n") + "\t1: enabled (1/2-Pel, Full-Pel and 4-PEL)\n") ("IMV4PelFast", m_Imv4PelFast, 1, "Fast 4-Pel Adaptive MV precision Mode 0:disabled, 1:enabled) [default: 1]") ("LMChroma", m_LMChroma, 1, " LMChroma prediction " "\t0: Disable LMChroma\n" diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 5db6cf3680a895a12156aeb718f46dee273f4b82..04404df19cc168bc5d167144958cfdbed84b0dcf 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -329,6 +329,9 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) pu.mergeFlag = true; pu.mmvdMergeFlag = false; pu.interDir = interDirNeighbours[candIdx]; +#if JVET_O0057_ALTHPELIF + pu.cu->useAltHpelIf = !pu.cu->triangle && useAltHpelIf[candIdx]; +#endif pu.mergeIdx = candIdx; pu.mergeType = mrgTypeNeighbours[candIdx]; pu.mv [REF_PIC_LIST_0] = mvFieldNeighbours[(candIdx << 1) + 0].mv; @@ -345,6 +348,9 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) { pu.bv = pu.mv[REF_PIC_LIST_0]; pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); // used for only integer resolution +#if JVET_O0057_ALTHPELIF + pu.cu->useAltHpelIf = false; +#endif } pu.cu->GBiIdx = ( interDirNeighbours[candIdx] == 3 ) ? GBiIdx[candIdx] : GBI_DEFAULT; @@ -510,6 +516,9 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx) pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID; pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; +#if JVET_O0057_ALTHPELIF + pu.cu->useAltHpelIf = mmvdUseAltHpelIf[fPosBaseIdx]; +#endif pu.cu->GBiIdx = (interDirNeighbours[fPosBaseIdx] == 3) ? GBiIdx[fPosBaseIdx] : GBI_DEFAULT; diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index c9773cc5fdaba7e21f061eb84bdcb47db4497836..ba1335b4bac1eb3d09ad3ff929f6bff71dfcb79b 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -507,6 +507,10 @@ public: MotionBuf subPuMvpExtMiBuf; MvField mmvdBaseMv[MMVD_BASE_MV_NUM][2]; void setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx); +#if JVET_O0057_ALTHPELIF + bool mmvdUseAltHpelIf [ MMVD_BASE_MV_NUM ]; + bool useAltHpelIf [ MRG_MAX_NUM_CANDS ]; +#endif void setMergeInfo( PredictionUnit& pu, int candIdx ); }; diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index 45325644e93214be5bd670ae683d84a56acec741..f911ba05e5f3c03ca049f7201e51ae2beb761614 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -767,6 +767,15 @@ const CtxSet ContextSetCfg::ChromaQpAdjIdc = ContextSetCfg::addCtxSet { DWS, }, }); +#if JVET_O0057_ALTHPELIF +const CtxSet ContextSetCfg::ImvFlag = ContextSetCfg::addCtxSet +({ + { 212, 180, 183, 242, 242, }, + { 213, 166, 198, 244, 244, }, + { CNU, 182, CNU, CNU, CNU, }, + { 1, 5, 1, 0, 0, }, +}); +#else const CtxSet ContextSetCfg::ImvFlag = ContextSetCfg::addCtxSet ({ { 212, 180, 183, 242, }, @@ -774,6 +783,7 @@ const CtxSet ContextSetCfg::ImvFlag = ContextSetCfg::addCtxSet { CNU, 182, CNU, CNU, }, { 1, 5, 1, 0, }, }); +#endif const CtxSet ContextSetCfg::ctbAlfFlag = ContextSetCfg::addCtxSet ({ diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 09cd39ea4d49a444b11d8f7f1fe27ea2a07e51f4..a5809fdc752828337818ab0a485df8bec3a3e926 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -712,11 +712,19 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio if( yFrac == 0 ) { - m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng, bilinearMC, bilinearMC); + m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng, bilinearMC, bilinearMC +#if JVET_O0057_ALTHPELIF + , pu.cu->useAltHpelIf +#endif +); } else if( xFrac == 0 ) { - m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng, bilinearMC, bilinearMC); + m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng, bilinearMC, bilinearMC +#if JVET_O0057_ALTHPELIF + , pu.cu->useAltHpelIf +#endif +); } else { @@ -729,9 +737,17 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio { vFilterSize = NTAPS_BILINEAR; } - m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng, bilinearMC, bilinearMC); + m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng, bilinearMC, bilinearMC +#if JVET_O0057_ALTHPELIF + , pu.cu->useAltHpelIf +#endif +); JVET_J0090_SET_CACHE_ENABLE( false ); - m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng, bilinearMC, bilinearMC); + m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng, bilinearMC, bilinearMC +#if JVET_O0057_ALTHPELIF + , pu.cu->useAltHpelIf +#endif +); } JVET_J0090_SET_CACHE_ENABLE( srcPadStride == 0 ); // Enabled only in non-DMVR process, In DMVR process, srcPadStride is always non-zero if (bioApplied && compID == COMPONENT_Y) diff --git a/source/Lib/CommonLib/InterpolationFilter.cpp b/source/Lib/CommonLib/InterpolationFilter.cpp index ebae59bb1b4c26096254c5621673daec48d9bb1f..90bdd999ce59e6be8af3fe90b596ff91fde24fa6 100644 --- a/source/Lib/CommonLib/InterpolationFilter.cpp +++ b/source/Lib/CommonLib/InterpolationFilter.cpp @@ -94,6 +94,9 @@ const TFilterCoeff InterpolationFilter::m_lumaFilter[LUMA_INTERPOLATION_FILTER_S { 0, 1, -2, 4, 63, -3, 1, 0 } }; +#if JVET_O0057_ALTHPELIF +const TFilterCoeff InterpolationFilter::m_lumaAltHpelIFilter[NTAPS_LUMA] = { 0, 3, 9, 20, 20, 9, 3, 0 }; +#endif const TFilterCoeff InterpolationFilter::m_chromaFilter[CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_CHROMA] = { { 0, 64, 0, 0 }, @@ -577,7 +580,11 @@ void InterpolationFilter::filterVer(const ClpRng& clpRng, Pel const *src, int sr * \param fmt Chroma format * \param bitDepth Bit depth */ -void InterpolationFilter::filterHor( const ComponentID compID, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx, bool biMCForDMVR) +void InterpolationFilter::filterHor( const ComponentID compID, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx, bool biMCForDMVR +#if JVET_O0057_ALTHPELIF + , bool useAltHpelIf +#endif +) { if( frac == 0 ) { @@ -592,6 +599,14 @@ void InterpolationFilter::filterHor( const ComponentID compID, Pel const *src, i } else { +#if JVET_O0057_ALTHPELIF + if (frac == 8 && useAltHpelIf) + { + filterHor<NTAPS_LUMA>(clpRng, src, srcStride, dst, dstStride, width, height, isLast, m_lumaAltHpelIFilter, biMCForDMVR); + } + else +#endif + { if ((width == 4 && height == 4) || (width == 4 && height == (4 + NTAPS_LUMA - 1))) { filterHor<NTAPS_LUMA>(clpRng, src, srcStride, dst, dstStride, width, height, isLast, m_lumaFilter4x4[frac], biMCForDMVR); @@ -602,6 +617,7 @@ void InterpolationFilter::filterHor( const ComponentID compID, Pel const *src, i } } } + } else { const uint32_t csx = getComponentScaleX( compID, fmt ); @@ -627,7 +643,11 @@ void InterpolationFilter::filterHor( const ComponentID compID, Pel const *src, i * \param fmt Chroma format * \param bitDepth Bit depth */ -void InterpolationFilter::filterVer( const ComponentID compID, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isFirst, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx, bool biMCForDMVR) +void InterpolationFilter::filterVer( const ComponentID compID, Pel const *src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isFirst, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx, bool biMCForDMVR +#if JVET_O0057_ALTHPELIF + , bool useAltHpelIf +#endif +) { if( frac == 0 ) { @@ -642,6 +662,14 @@ void InterpolationFilter::filterVer( const ComponentID compID, Pel const *src, i } else { +#if JVET_O0057_ALTHPELIF + if (frac == 8 && useAltHpelIf) + { + filterVer<NTAPS_LUMA>(clpRng, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_lumaAltHpelIFilter, biMCForDMVR); + } + else +#endif + { if (width == 4 && height == 4) { filterVer<NTAPS_LUMA>(clpRng, src, srcStride, dst, dstStride, width, height, isFirst, isLast, m_lumaFilter4x4[frac], biMCForDMVR); @@ -652,6 +680,7 @@ void InterpolationFilter::filterVer( const ComponentID compID, Pel const *src, i } } } + } else { const uint32_t csy = getComponentScaleY( compID, fmt ); diff --git a/source/Lib/CommonLib/InterpolationFilter.h b/source/Lib/CommonLib/InterpolationFilter.h index d2ddad1e74626d313c51d6b4693968fa9485027d..039539522fe457deacf3069c596d65e914f1f5d0 100644 --- a/source/Lib/CommonLib/InterpolationFilter.h +++ b/source/Lib/CommonLib/InterpolationFilter.h @@ -57,6 +57,9 @@ class InterpolationFilter { static const TFilterCoeff m_lumaFilter4x4[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_LUMA]; static const TFilterCoeff m_lumaFilter[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_LUMA]; ///< Luma filter taps +#if JVET_O0057_ALTHPELIF + static const TFilterCoeff m_lumaAltHpelIFilter[NTAPS_LUMA]; ///< Luma filter taps +#endif static const TFilterCoeff m_chromaFilter[CHROMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_CHROMA]; ///< Chroma filter taps static const TFilterCoeff m_bilinearFilter[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_BILINEAR]; ///< bilinear filter taps static const TFilterCoeff m_bilinearFilterPrec4[LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS][NTAPS_BILINEAR]; ///< bilinear filter taps @@ -96,8 +99,16 @@ public: template <X86_VEXT vext> void _initInterpolationFilterX86(); #endif - void filterHor(const ComponentID compID, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx = 0, bool biMCForDMVR = false); - void filterVer(const ComponentID compID, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isFirst, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx = 0, bool biMCForDMVR = false); + void filterHor(const ComponentID compID, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx = 0, bool biMCForDMVR = false +#if JVET_O0057_ALTHPELIF + , bool useAltHpelIf = false +#endif +); + void filterVer(const ComponentID compID, Pel const* src, int srcStride, Pel *dst, int dstStride, int width, int height, int frac, bool isFirst, bool isLast, const ChromaFormat fmt, const ClpRng& clpRng, int nFilterIdx = 0, bool biMCForDMVR = false +#if JVET_O0057_ALTHPELIF + , bool useAltHpelIf = false +#endif +); #if JVET_J0090_MEMORY_BANDWITH_MEASURE void cacheAssign( CacheModel *cache ) { m_cacheModel = cache; } #endif diff --git a/source/Lib/CommonLib/MotionInfo.h b/source/Lib/CommonLib/MotionInfo.h index 4ebd998ddd81a81fee4957c596bb7c788fd98bb4..f7abf293528c09a9401a46ec35d34a84410dc294 100644 --- a/source/Lib/CommonLib/MotionInfo.h +++ b/source/Lib/CommonLib/MotionInfo.h @@ -103,14 +103,25 @@ struct MotionInfo bool isInter; bool isIBCmot; char interDir; +#if JVET_O0057_ALTHPELIF + bool useAltHpelIf; +#endif uint16_t sliceIdx; Mv mv [ NUM_REF_PIC_LIST_01 ]; int16_t refIdx [ NUM_REF_PIC_LIST_01 ]; uint8_t GBiIdx; Mv bv; +#if JVET_O0057_ALTHPELIF + MotionInfo() : isInter(false), isIBCmot(false), interDir(0), useAltHpelIf(false), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID }, GBiIdx(0) { } +#else MotionInfo() : isInter(false), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ NOT_VALID, NOT_VALID }, GBiIdx(0) { } +#endif // ensure that MotionInfo(0) produces '\x000....' bit pattern - needed to work with AreaBuf - don't use this constructor for anything else +#if JVET_O0057_ALTHPELIF + MotionInfo(int i) : isInter(i != 0), isIBCmot(false), interDir(0), useAltHpelIf(false), sliceIdx(0), refIdx{ 0, 0 }, GBiIdx(0) { CHECKD(i != 0, "The argument for this constructor has to be '0'"); } +#else MotionInfo(int i) : isInter(i != 0), isIBCmot(false), interDir(0), sliceIdx(0), refIdx{ 0, 0 }, GBiIdx(0) { CHECKD(i != 0, "The argument for this constructor has to be '0'"); } +#endif bool operator==( const MotionInfo& mi ) const { diff --git a/source/Lib/CommonLib/Mv.cpp b/source/Lib/CommonLib/Mv.cpp index 981ba6a02b6030d6b6c297066307d864270e434f..624c41dca590aaf1e2e4f35f1ab49001923e7645 100644 --- a/source/Lib/CommonLib/Mv.cpp +++ b/source/Lib/CommonLib/Mv.cpp @@ -40,7 +40,11 @@ #include "Common.h" #include "Slice.h" +#if JVET_O0057_ALTHPELIF +const MvPrecision Mv::m_amvrPrecision[4] = { MV_PRECISION_QUARTER, MV_PRECISION_INT, MV_PRECISION_4PEL, MV_PRECISION_HALF }; // for cu.imv=0, 1, 2 and 3 +#else const MvPrecision Mv::m_amvrPrecision[3] = { MV_PRECISION_QUARTER, MV_PRECISION_INT, MV_PRECISION_4PEL }; // for cu.imv=0, 1 and 2 +#endif const MvPrecision Mv::m_amvrPrecAffine[3] = { MV_PRECISION_QUARTER, MV_PRECISION_SIXTEENTH, MV_PRECISION_INT }; // for cu.imv=0, 1 and 2 const MvPrecision Mv::m_amvrPrecIbc[3] = { MV_PRECISION_INT, MV_PRECISION_INT, MV_PRECISION_4PEL }; // for cu.imv=0, 1 and 2 diff --git a/source/Lib/CommonLib/Mv.h b/source/Lib/CommonLib/Mv.h index 5d714d1c05c7731372260725669d043eac769930..4ebc0bfc055865970828de5037fcb1c5da3acfdd 100644 --- a/source/Lib/CommonLib/Mv.h +++ b/source/Lib/CommonLib/Mv.h @@ -61,7 +61,11 @@ enum MvPrecision class Mv { private: +#if JVET_O0057_ALTHPELIF + static const MvPrecision m_amvrPrecision[4]; +#else static const MvPrecision m_amvrPrecision[3]; +#endif static const MvPrecision m_amvrPrecAffine[3]; static const MvPrecision m_amvrPrecIbc[3]; diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 9e02da853f08c6db42ef12b7af2c3789bca37310..69380a10e02abb9cb7f0452fa76388bcccf43f7b 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -64,6 +64,8 @@ #define JVET_O0409_EXCLUDE_CODED_SUB_BLK_FLAG_FROM_COUNT 1 // JVET-O0409: exclude coded_subblock_flag from counting context-coded bins in transform skip +#define JVET_O0057_ALTHPELIF 1 //AMVR_HPEL + #define JVET_O1136_TS_BDPCM_SIGNALLING 1 // JVET-O1136: Unified syntax for JVET-O0165/O0200/O0783 on TS and BDPCM signalling #define JVET_O0219_LFNST_TRANSFORM_SET_FOR_LMCMODE 1 @@ -970,8 +972,14 @@ enum EncModeFeature enum ImvMode { IMV_OFF = 0, +#if JVET_O0057_ALTHPELIF + IMV_FPEL, + IMV_4PEL, + IMV_HPEL, +#else IMV_DEFAULT, IMV_4PEL, +#endif NUM_IMV_MODES }; diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 74a3cc0ec6952f1ad9fffc7a7190dcd94d78d326..39b4431eb2b0a6b2a925124a07275830e20d70ab 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -278,6 +278,9 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) tileIdx = other.tileIdx; imv = other.imv; imvNumCand = other.imvNumCand; +#if JVET_O0057_ALTHPELIF + useAltHpelIf = other.useAltHpelIf; +#endif GBiIdx = other.GBiIdx; for (int i = 0; i<2; i++) refIdxBi[i] = other.refIdxBi[i]; @@ -316,6 +319,9 @@ void CodingUnit::initData() tileIdx = 0; imv = 0; imvNumCand = 0; +#if JVET_O0057_ALTHPELIF + useAltHpelIf = false; +#endif GBiIdx = GBI_DEFAULT; for (int i = 0; i < 2; i++) refIdxBi[i] = -1; diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 16645400555f2678b53607cf743124a64b2d5c1a..093cc5ad1604ddde18cb3dadb9896741a07436b9 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -307,6 +307,9 @@ struct CodingUnit : public UnitArea int bdpcmMode; bool ipcm; uint8_t imv; +#if JVET_O0057_ALTHPELIF + bool useAltHpelIf; +#endif bool rootCbf; uint8_t sbtInfo; uint32_t tileIdx; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 8ec126e19eb745de437a395df7e7dfb28eed3b8e..61c7d3509458c9dc5daf2079f3d17ffd68d4b3ed 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -961,6 +961,9 @@ bool PU::addMergeHMVPCand(const CodingStructure &cs, MergeCtx& mrgCtx, bool isCa miNeighbor = lut[num_avai_candInLUT - mrgIdx]; mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir; mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[cnt] = !ibcFlag && miNeighbor.useAltHpelIf; +#endif if (slice.isInterB()) { mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]); @@ -982,6 +985,9 @@ bool PU::addMergeHMVPCand(const CodingStructure &cs, MergeCtx& mrgCtx, bool isCa } } } +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[cnt] = false; +#endif return false; } @@ -1136,6 +1142,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mrgTypeNeighbours [ui] = MRG_TYPE_DEFAULT_N; mrgCtx.mvFieldNeighbours[(ui << 1) ].refIdx = NOT_VALID; mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[ui] = false; +#endif } mrgCtx.numValidMergeCand = maxNumMergeCand; @@ -1163,6 +1172,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miLeft.interDir; +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[cnt] = miLeft.useAltHpelIf; +#endif mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeft->cu->GBiIdx : GBI_DEFAULT; // get Mv from Left mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miLeft.mv[0], miLeft.refIdx[0]); @@ -1203,6 +1215,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miAbove.interDir; +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[cnt] = miAbove.useAltHpelIf; +#endif // get Mv from Above mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAbove->cu->GBiIdx : GBI_DEFAULT; mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAbove.mv[0], miAbove.refIdx[0] ); @@ -1245,6 +1260,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir; +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[cnt] = miAboveRight.useAltHpelIf; +#endif // get Mv from Above-right mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveRight->cu->GBiIdx : GBI_DEFAULT; mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] ); @@ -1285,6 +1303,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[cnt] = miBelowLeft.useAltHpelIf; +#endif mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puLeftBottom->cu->GBiIdx : GBI_DEFAULT; // get Mv from Bottom-Left mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] ); @@ -1328,6 +1349,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[cnt] = miAboveLeft.useAltHpelIf; +#endif mrgCtx.GBiIdx[cnt] = (mrgCtx.interDirNeighbours[cnt] == 3) ? puAboveLeft->cu->GBiIdx : GBI_DEFAULT; // get Mv from Above-Left mrgCtx.mvFieldNeighbours[cnt << 1].setMvField( miAboveLeft.mv[0], miAboveLeft.refIdx[0] ); @@ -1405,6 +1429,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, isCandInter [uiArrayAddr] = true; #endif mrgCtx.GBiIdx[uiArrayAddr] = GBI_DEFAULT; +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[uiArrayAddr] = false; +#endif if (mrgCandIdx == cnt && canFastExit) { return; @@ -1462,6 +1489,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, unsigned char interDir = 0; +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[cnt] = (mrgCtx.useAltHpelIf[0] == mrgCtx.useAltHpelIf[1]) ? mrgCtx.useAltHpelIf[0] : false; +#endif for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ ) { const short refIdxI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].refIdx; @@ -1573,6 +1603,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.interDirNeighbours [uiArrayAddr ] = 1; mrgCtx.GBiIdx [uiArrayAddr ] = GBI_DEFAULT; mrgCtx.mvFieldNeighbours [uiArrayAddr << 1].setMvField(Mv(0, 0), r); +#if JVET_O0057_ALTHPELIF + mrgCtx.useAltHpelIf[uiArrayAddr] = false; +#endif if (slice.isInterB()) { @@ -1800,6 +1833,9 @@ void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, mrgCtx.mmvdBaseMv[currBaseNum][0] = MvField(Mv(0, 0), -1); mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[(k << 1) + 1]; } +#if JVET_O0057_ALTHPELIF + mrgCtx.mmvdUseAltHpelIf[currBaseNum] = mrgCtx.useAltHpelIf[k]; +#endif currBaseNum++; @@ -3727,6 +3763,9 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) if( mi.isInter ) { mi.interDir = pu.interDir; +#if JVET_O0057_ALTHPELIF + mi.useAltHpelIf = pu.cu->useAltHpelIf; +#endif for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ ) { @@ -3923,6 +3962,9 @@ void PU::getTriangleMergeCandidates( const PredictionUnit &pu, MergeCtx& triangl triangleMrgCtx.mvFieldNeighbours[(i << 1) + 1].refIdx = NOT_VALID; triangleMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv(); triangleMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv(); +#if JVET_O0057_ALTHPELIF + triangleMrgCtx.useAltHpelIf[i] = false; +#endif } PU::getInterMergeCandidates(pu, tmpMergeCtx, 0); diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 7e6fd7e5a87716fed81a4e73a31d60fec5fe705d..fc6b2f36a0bce64d40b865dbe87578fb9c6889ff 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -928,14 +928,34 @@ void CABACReader::imv_mode( CodingUnit& cu, MergeCtx& mrgCtx ) value = m_BinDecoder.decodeBin( Ctx::ImvFlag( 0 ) ); DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", value, 0 ); +#if JVET_O0057_ALTHPELIF + cu.imv = value; +#endif if( sps->getAMVREnabledFlag() && value ) { +#if JVET_O0057_ALTHPELIF + if (!CU::isIBC(cu)) + { + value = m_BinDecoder.decodeBin(Ctx::ImvFlag(4)); + DTRACE(g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", value, 4); + cu.imv = value ? 1 : IMV_HPEL; + cu.useAltHpelIf = cu.imv == IMV_HPEL; + } + if (value) + { +#endif value = m_BinDecoder.decodeBin( Ctx::ImvFlag( 1 ) ); DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", value, 1 ); value++; +#if JVET_O0057_ALTHPELIF + cu.imv = value; + } +#endif } +#if !JVET_O0057_ALTHPELIF cu.imv = value; +#endif DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() IMVFlag=%d\n", cu.imv ); } diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index e27ef8e22a08bca20b8e5d09466093e7f6bfdc98..143527ae1ee2464c3fb4f2f45dd8bdd1ba7abc9a 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -1679,8 +1679,20 @@ void CABACWriter::imv_mode( const CodingUnit& cu ) if( sps->getAMVREnabledFlag() && cu.imv > 0 ) { +#if JVET_O0057_ALTHPELIF + if (!CU::isIBC(cu)) + { + m_BinEncoder.encodeBin(cu.imv < IMV_HPEL, Ctx::ImvFlag(4)); + DTRACE(g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", cu.imv < 3, 4); + } + if (cu.imv < IMV_HPEL) + { +#endif m_BinEncoder.encodeBin( (cu.imv > 1), Ctx::ImvFlag( 1 ) ); DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() value=%d ctx=%d\n", (cu.imv > 1), 1 ); +#if JVET_O0057_ALTHPELIF + } +#endif } DTRACE( g_trace_ctx, D_SYNTAX, "imv_mode() IMVFlag=%d\n", cu.imv ); @@ -2233,6 +2245,23 @@ void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv ) int verMvd = rMvd.getVer(); if ( imv > 0 ) { +#if JVET_O0057_ALTHPELIF + CHECK((horMvd % 2) != 0 && (verMvd % 2) != 0, "IMV: MVD is not a multiple of 2"); + horMvd >>= 1; + verMvd >>= 1; + if (imv < IMV_HPEL) + { + CHECK((horMvd % 2) != 0 && (verMvd % 2) != 0, "IMV: MVD is not a multiple of 4"); + horMvd >>= 1; + verMvd >>= 1; + if (imv == IMV_4PEL)//IMV_4PEL + { + CHECK((horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 16"); + horMvd >>= 2; + verMvd >>= 2; + } + } +#else CHECK( (horMvd % 4) != 0 && (verMvd % 4) != 0, "IMV: MVD is not a multiple of 4" ); horMvd >>= 2; verMvd >>= 2; @@ -2242,6 +2271,7 @@ void CABACWriter::mvd_coding( const Mv &rMvd, int8_t imv ) horMvd >>= 2; verMvd >>= 2; } +#endif } unsigned horAbs = unsigned( horMvd < 0 ? -horMvd : horMvd ); unsigned verAbs = unsigned( verMvd < 0 ? -verMvd : verMvd ); diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index b16f155702f2f65ff5ed3ef95e7e7a877bec2885..198993a5f820f818a767c7f7345fa30eeaf275e2 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -654,6 +654,9 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par int startShareThisLevel = 0; m_pcInterSearch->resetSavedAffineMotion(); +#if JVET_O0057_ALTHPELIF + double bestIntPelCost = MAX_DOUBLE; +#endif do { EncTestMode currTestMode = m_modeCtrl->currTestMode(); @@ -697,9 +700,21 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par { if( ( currTestMode.opts & ETO_IMV ) != 0 ) { +#if JVET_O0057_ALTHPELIF + const bool skipAltHpelIF = ( int( ( currTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT ) == 4 ) && ( bestIntPelCost > 1.25 * bestCS->cost ); + if( !skipAltHpelIF ) + { +#endif tempCS->bestCS = bestCS; - xCheckRDCostInterIMV( tempCS, bestCS, partitioner, currTestMode ); + xCheckRDCostInterIMV( tempCS, bestCS, partitioner, currTestMode +#if JVET_O0057_ALTHPELIF + , bestIntPelCost +#endif + ); tempCS->bestCS = nullptr; +#if JVET_O0057_ALTHPELIF + } +#endif } else { @@ -3273,6 +3288,9 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best cu.qp = encTestMode.qp; cu.imv = 0; cu.sbtInfo = 0; +#if JVET_O0057_ALTHPELIF + cu.useAltHpelIf = false; +#endif CU::addPUs(cu); @@ -3539,12 +3557,22 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC -bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ) +bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode +#if JVET_O0057_ALTHPELIF +, double &bestIntPelCost +#endif +) { int iIMV = int( ( encTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT ); m_pcInterSearch->setAffineModeSelected(false); +#if JVET_O0057_ALTHPELIF + // Only Half-Pel, int-Pel, 4-Pel and fast 4-Pel allowed + CHECK(iIMV < 1 || iIMV > 4, "Unsupported IMV Mode"); + const bool testAltHpelFilter = iIMV == 4; +#else // Only int-Pel, 4-Pel and fast 4-Pel allowed CHECK( iIMV != 1 && iIMV != 2 && iIMV != 3, "Unsupported IMV Mode" ); +#endif // Fast 4-Pel Mode m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false; @@ -3615,11 +3643,27 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be CU::addPUs( cu ); +#if JVET_O0057_ALTHPELIF + if (testAltHpelFilter) + { + cu.imv = IMV_HPEL; + cu.useAltHpelIf = true; + } + else + { + cu.imv = iIMV == 1 ? IMV_FPEL : IMV_4PEL; + } +#else cu.imv = iIMV > 1 ? 2 : 1; +#endif bool testGbi; uint8_t gbiIdx; +#if JVET_O0057_ALTHPELIF + bool affineAmvrEanbledFlag = !testAltHpelFilter && cu.slice->getSPS()->getAffineAmvrEnabledFlag(); +#else bool affineAmvrEanbledFlag = cu.slice->getSPS()->getAffineAmvrEnabledFlag(); +#endif cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx]; gbiIdx = cu.GBiIdx; @@ -3684,6 +3728,12 @@ bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&be , &equGBiCost ); +#if JVET_O0057_ALTHPELIF + if( cu.imv == IMV_FPEL && tempCS->cost < bestIntPelCost ) + { + bestIntPelCost = tempCS->cost; + } +#endif tempCS->initStructData(encTestMode.qp, encTestMode.lossless); double skipTH = MAX_DOUBLE; diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index 67ef7f05fe518c8696cd083004a1919fccc4e2c9..431c04bc2661cd025d4212481a383c36ab5589c0 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -196,7 +196,11 @@ protected: void xCheckRDCostAffineMerge2Nx2N ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ); void xCheckRDCostInter ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); - bool xCheckRDCostInterIMV ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); + bool xCheckRDCostInterIMV ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode +#if JVET_O0057_ALTHPELIF + , double &bestIntPelCost +#endif +); void xEncodeDontSplit ( CodingStructure &cs, Partitioner &partitioner); void xCheckRDCostMerge2Nx2N ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); diff --git a/source/Lib/EncoderLib/EncModeCtrl.cpp b/source/Lib/EncoderLib/EncModeCtrl.cpp index e59cca54ea2c5c10aaeff097391aad3904be5e53..acfb5f43ad30f8f93bb5d7b29ca9fba51a7aedcc 100644 --- a/source/Lib/EncoderLib/EncModeCtrl.cpp +++ b/source/Lib/EncoderLib/EncModeCtrl.cpp @@ -1330,6 +1330,12 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru { const int qp = std::max( qpLoop, lowestQP ); const bool lossless = useLossless && qpLoop == minQP; +#if JVET_O0057_ALTHPELIF + if (m_pcEncCfg->getIMV()) + { + m_ComprCUCtxList.back().testModes.push_back({ ETM_INTER_ME, EncTestModeOpts( 4 << ETO_IMV_SHIFT ), qp, lossless }); + } +#endif if( m_pcEncCfg->getIMV() || m_pcEncCfg->getUseAffineAmvr() ) { int imv = m_pcEncCfg->getIMV4PelFast() ? 3 : 2; diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 9aaac4ded7edcc3ff8ef90f5afc19a24b88d726d..08e267cd891e66ca062c0b0db121b674de412ae5 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -1285,6 +1285,9 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, cStruct.pcPatternKey = pcPatternKey; cStruct.iRefStride = refBuf.stride; cStruct.piRefY = refBuf.buf; +#if JVET_O0057_ALTHPELIF + CHECK(pu.cu->imv == IMV_HPEL || pu.cu->useAltHpelIf, "IF_IBC"); +#endif cStruct.imvShift = pu.cu->imv << 1; cStruct.subShiftMode = 0; // used by intra pattern search function @@ -2274,9 +2277,15 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) WPScalingParam *wp0; WPScalingParam *wp1; int tryBipred = 0; +#if JVET_O0057_ALTHPELIF + bool checkAffine = (pu.cu->imv == 0 || pu.cu->slice->getSPS()->getAffineAmvrEnabledFlag()) && pu.cu->imv != IMV_HPEL; + bool checkNonAffine = pu.cu->imv == 0 || pu.cu->imv == IMV_HPEL || (pu.cu->slice->getSPS()->getAMVREnabledFlag() && + pu.cu->imv <= (pu.cu->slice->getSPS()->getAMVREnabledFlag() ? IMV_4PEL : 0)); +#else bool checkAffine = pu.cu->imv == 0 || pu.cu->slice->getSPS()->getAffineAmvrEnabledFlag(); bool checkNonAffine = pu.cu->imv == 0 || ( pu.cu->slice->getSPS()->getAMVREnabledFlag() && pu.cu->imv <= (pu.cu->slice->getSPS()->getAMVREnabledFlag() ? IMV_4PEL : 0)); +#endif CodingUnit *bestCU = pu.cu->cs->bestCS != nullptr ? pu.cu->cs->bestCS->getCU( CHANNEL_TYPE_LUMA ) : nullptr; bool trySmvd = ( bestCU != nullptr && pu.cu->imv == 2 && checkAffine ) ? ( !bestCU->firstPU->mergeFlag && !bestCU->affine ) : true; if ( pu.cu->imv && bestCU != nullptr && checkAffine ) @@ -2331,7 +2340,11 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) m_pcRdCost->selectMotionLambda( cu.transQuantBypass ); +#if JVET_O0057_ALTHPELIF + unsigned imvShift = pu.cu->imv == IMV_HPEL ? 1 : (pu.cu->imv << 1); +#else unsigned imvShift = pu.cu->imv << 1; +#endif if ( checkNonAffine ) { // Uni-directional prediction @@ -3161,7 +3174,11 @@ void InterSearch::xCopyAMVPInfo (AMVPInfo* pSrc, AMVPInfo* pDst) void InterSearch::xCheckBestMVP ( RefPicList eRefPicList, Mv cMv, Mv& rcMvPred, int& riMVPIdx, AMVPInfo& amvpInfo, uint32_t& ruiBits, Distortion& ruiCost, const uint8_t imv ) { +#if JVET_O0057_ALTHPELIF + if ( imv > 0 && imv < 3 ) +#else if( imv > 0 ) +#endif { return; } @@ -3327,7 +3344,12 @@ void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Ref cStruct.pcPatternKey = pcPatternKey; cStruct.iRefStride = buf.stride; cStruct.piRefY = buf.buf; +#if JVET_O0057_ALTHPELIF + cStruct.imvShift = pu.cu->imv == IMV_HPEL ? 1 : (pu.cu->imv << 1); + cStruct.useAltHpelIf = pu.cu->useAltHpelIf; +#else cStruct.imvShift = pu.cu->imv << 1; +#endif cStruct.inCtuSearch = false; cStruct.zeroMV = false; { @@ -3461,7 +3483,11 @@ void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Ref DTRACE( g_trace_ctx, D_ME, "%d %d %d :MECostFPel<L%d,%d>: %d,%d,%dx%d, %d", DTRACE_GET_COUNTER( g_trace_ctx, D_ME ), pu.cu->slice->getPOC(), 0, ( int ) eRefPicList, ( int ) bBi, pu.Y().x, pu.Y().y, pu.Y().width, pu.Y().height, ruiCost ); // sub-pel refinement for sub-pel resolution +#if JVET_O0057_ALTHPELIF + if ( pu.cu->imv == 0 || pu.cu->imv == IMV_HPEL ) +#else if( pu.cu->imv == 0 ) +#endif { if( m_pcEncCfg->getMCTSEncConstraint() ) { @@ -4196,7 +4222,11 @@ void InterSearch::xTZSearchSelective( const PredictionUnit& pu, void InterSearch::xPatternSearchIntRefine(PredictionUnit& pu, IntTZSearchStruct& cStruct, Mv& rcMv, Mv& rcMvPred, int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost, const AMVPInfo& amvpInfo, double fWeight) { +#if JVET_O0057_ALTHPELIF + CHECK( pu.cu->imv == 0 || pu.cu->imv == IMV_HPEL , "xPatternSearchIntRefine(): Sub-pel MV used."); +#else CHECK( pu.cu->imv == 0, "xPatternSearchIntRefine(): IMV not used."); +#endif CHECK( amvpInfo.mvCand[riMVPIdx] != rcMvPred, "xPatternSearchIntRefine(): MvPred issue."); const SPS &sps = *pu.cs->sps; @@ -4326,14 +4356,22 @@ void InterSearch::xPatternSearchFracDIF( Mv baseRefMv(0, 0); rcMvHalf.setZero(); m_pcRdCost->setCostScale(0); +#if JVET_O0057_ALTHPELIF + xExtDIFUpSamplingH(&cPatternRoi, cStruct.useAltHpelIf); +#else xExtDIFUpSamplingH(&cPatternRoi); +#endif rcMvQter = rcMvInt; rcMvQter <<= 2; // for mv-cost ruiCost = xPatternRefinement(cStruct.pcPatternKey, baseRefMv, 1, rcMvQter, !bIsLosslessCoded && !pu.cs->slice->getDisableSATDForRD()); return; } +#if JVET_O0057_ALTHPELIF + if (cStruct.imvShift > IMV_FPEL || (m_useCompositeRef && cStruct.zeroMV)) +#else if (cStruct.imvShift || (m_useCompositeRef && cStruct.zeroMV)) +#endif { m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY + iOffset, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, 0, 1, m_pcEncCfg->getUseHADME() && !bIsLosslessCoded && !pu.cs->slice->getDisableSATDForRD()); ruiCost = m_cDistParam.distFunc( m_cDistParam ); @@ -4343,13 +4381,21 @@ void InterSearch::xPatternSearchFracDIF( // Half-pel refinement m_pcRdCost->setCostScale(1); +#if JVET_O0057_ALTHPELIF + xExtDIFUpSamplingH(&cPatternRoi, cStruct.useAltHpelIf); +#else xExtDIFUpSamplingH ( &cPatternRoi ); +#endif rcMvHalf = rcMvInt; rcMvHalf <<= 1; // for mv-cost Mv baseRefMv(0, 0); ruiCost = xPatternRefinement(cStruct.pcPatternKey, baseRefMv, 2, rcMvHalf, (!bIsLosslessCoded && !pu.cs->slice->getDisableSATDForRD())); // quarter-pel refinement +#if JVET_O0057_ALTHPELIF + if (cStruct.imvShift == IMV_OFF) + { +#endif m_pcRdCost->setCostScale( 0 ); xExtDIFUpSamplingQ ( &cPatternRoi, rcMvHalf ); baseRefMv = rcMvHalf; @@ -4358,6 +4404,9 @@ void InterSearch::xPatternSearchFracDIF( rcMvQter = rcMvInt; rcMvQter <<= 1; // for mv-cost rcMvQter += rcMvHalf; rcMvQter <<= 1; ruiCost = xPatternRefinement(cStruct.pcPatternKey, baseRefMv, 1, rcMvQter, (!bIsLosslessCoded && !pu.cs->slice->getDisableSATDForRD())); +#if JVET_O0057_ALTHPELIF + } +#endif } Distortion InterSearch::xGetSymmetricCost( PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eCurRefPicList, const MvField& cCurMvField, MvField& cTarMvField, int gbiIdx ) @@ -4512,7 +4561,11 @@ void InterSearch::xSymmetricMotionEstimation( PredictionUnit& pu, PelUnitBuf& or int nDiamondRound = 8; int nCrossRound = 1; +#if JVET_O0057_ALTHPELIF + nSearchStepShift += pu.cu->imv == IMV_HPEL ? 1 : (pu.cu->imv << 1); +#else nSearchStepShift += (pu.cu->imv << 1); +#endif nDiamondRound >>= pu.cu->imv; ruiCost = xSymmeticRefineMvSearch( pu, origBuf, rcMvCurPred, rcMvTarPred, eRefPicList, rCurMvField, rTarMvField, ruiCost, 2, nSearchStepShift, nDiamondRound, gbiIdx ); @@ -5914,7 +5967,11 @@ void InterSearch::xCopyAffineAMVPInfo (AffineAMVPInfo& src, AffineAMVPInfo& dst) * \param pattern Reference picture ROI * \param biPred Flag indicating whether block is for biprediction */ +#if JVET_O0057_ALTHPELIF +void InterSearch::xExtDIFUpSamplingH(CPelBuf* pattern, bool useAltHpelIf) +#else void InterSearch::xExtDIFUpSamplingH( CPelBuf* pattern ) +#endif { const ClpRng& clpRng = m_lumaClpRng; int width = pattern->width; @@ -5931,15 +5988,27 @@ void InterSearch::xExtDIFUpSamplingH( CPelBuf* pattern ) const ChromaFormat chFmt = m_currChromaFormat; - m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0][0], intStride, width + 1, height + filterSize, 0 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng); + m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[0][0], intStride, width + 1, height + filterSize, 0 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng +#if JVET_O0057_ALTHPELIF + , 0, false, useAltHpelIf +#endif +); if (!m_skipFracME) { - m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2][0], intStride, width + 1, height + filterSize, 2 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng); + m_if.filterHor(COMPONENT_Y, srcPtr, srcStride, m_filteredBlockTmp[2][0], intStride, width + 1, height + filterSize, 2 << MV_FRACTIONAL_BITS_DIFF, false, chFmt, clpRng +#if JVET_O0057_ALTHPELIF + , 0, false, useAltHpelIf +#endif +); } intPtr = m_filteredBlockTmp[0][0] + halfFilterSize * intStride + 1; dstPtr = m_filteredBlock[0][0][0]; - m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng); + m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng +#if JVET_O0057_ALTHPELIF + , 0, false, useAltHpelIf +#endif +); if (m_skipFracME) { return; @@ -5947,15 +6016,27 @@ void InterSearch::xExtDIFUpSamplingH( CPelBuf* pattern ) intPtr = m_filteredBlockTmp[0][0] + (halfFilterSize - 1) * intStride + 1; dstPtr = m_filteredBlock[2][0][0]; - m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng); + m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 0, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng +#if JVET_O0057_ALTHPELIF + , 0, false, useAltHpelIf +#endif +); intPtr = m_filteredBlockTmp[2][0] + halfFilterSize * intStride; dstPtr = m_filteredBlock[0][2][0]; - m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 1, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng); + m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 1, height + 0, 0 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng +#if JVET_O0057_ALTHPELIF + , 0, false, useAltHpelIf +#endif +); intPtr = m_filteredBlockTmp[2][0] + (halfFilterSize - 1) * intStride; dstPtr = m_filteredBlock[2][2][0]; - m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 1, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng); + m_if.filterVer(COMPONENT_Y, intPtr, intStride, dstPtr, dstStride, width + 1, height + 1, 2 << MV_FRACTIONAL_BITS_DIFF, false, true, chFmt, clpRng +#if JVET_O0057_ALTHPELIF + , 0, false, useAltHpelIf +#endif +); } diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h index 105d518086ac59677d9724f86162eec45d2faf85..5d58579d44ea98d3faf07c66e2982fbac11fba05 100644 --- a/source/Lib/EncoderLib/InterSearch.h +++ b/source/Lib/EncoderLib/InterSearch.h @@ -349,6 +349,9 @@ protected: uint8_t ucPointNr; int subShiftMode; unsigned imvShift; +#if JVET_O0057_ALTHPELIF + bool useAltHpelIf; +#endif bool inCtuSearch; bool zeroMV; } IntTZSearchStruct; @@ -592,7 +595,11 @@ public: ); protected: - void xExtDIFUpSamplingH ( CPelBuf* pcPattern ); + void xExtDIFUpSamplingH ( CPelBuf* pcPattern +#if JVET_O0057_ALTHPELIF + , bool useAltHpelIf +#endif +); void xExtDIFUpSamplingQ ( CPelBuf* pcPatternKey, Mv halfPelRef ); uint32_t xDetermineBestMvp ( PredictionUnit& pu, Mv acMvTemp[3], int& mvpIdx, const AffineAMVPInfo& aamvpi ); // -------------------------------------------------------------------------------------------------------------------