From 74a2660897ea4a3a0bae71ae607bc6ddc049de40 Mon Sep 17 00:00:00 2001 From: jamesxxiu <xiaoyuxiu@kwai.com> Date: Tue, 2 Apr 2019 10:03:53 -0700 Subject: [PATCH] JVET-N0334: MV Overflow Prevention --- source/Lib/CommonLib/ContextModelling.cpp | 11 +++++++ source/Lib/CommonLib/InterPrediction.cpp | 4 +++ source/Lib/CommonLib/Mv.h | 13 ++++++++ source/Lib/CommonLib/TypeDef.h | 2 ++ source/Lib/CommonLib/UnitTools.cpp | 37 +++++++++++++++++++++++ source/Lib/CommonLib/UnitTools.h | 3 ++ source/Lib/DecoderLib/DecCu.cpp | 10 ++++++ source/Lib/EncoderLib/EncCu.cpp | 28 +++++++++++++++++ 8 files changed, 108 insertions(+) diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index 823198497..2a1eefb20 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -524,5 +524,16 @@ void MergeCtx::setMmvdMergeCandiInfo(PredictionUnit& pu, int candIdx) pu.cu->GBiIdx = (interDirNeighbours[fPosBaseIdx] == 3) ? GBiIdx[fPosBaseIdx] : GBI_DEFAULT; +#if JVET_N0334_MVCLIPPING + for (int refList = 0; refList < 2; refList++) + { + if (pu.refIdx[refList] >= 0) + { + pu.mv[refList].clipToStorageBitDepth(); + } + } +#endif + + PU::restrictBiPredMergeCandsOne(pu); } diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 1967564ce..aea57502c 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -1767,6 +1767,10 @@ void InterPrediction::xProcessDMVR(PredictionUnit& pu, PelUnitBuf &pcYuvDst, con subPu.mv[0] = mergeMv[REF_PIC_LIST_0] + pu.mvdL0SubPu[num]; subPu.mv[1] = mergeMv[REF_PIC_LIST_1] - pu.mvdL0SubPu[num]; +#if JVET_N0334_MVCLIPPING + subPu.mv[0].clipToStorageBitDepth(); + subPu.mv[1].clipToStorageBitDepth(); +#endif m_cYuvRefBuffSubCuDMVRL0 = m_cYuvRefBuffDMVRL0.subBuf(UnitAreaRelative(pu, subPu)); m_cYuvRefBuffSubCuDMVRL1 = m_cYuvRefBuffDMVRL1.subBuf(UnitAreaRelative(pu, subPu)); xFinalPaddedMCForDMVR(subPu, srcPred0, srcPred1, m_cYuvRefBuffSubCuDMVRL0, m_cYuvRefBuffSubCuDMVRL1, bioApplied, mergeMv); diff --git a/source/Lib/CommonLib/Mv.h b/source/Lib/CommonLib/Mv.h index 51d08d682..dcb77eb16 100644 --- a/source/Lib/CommonLib/Mv.h +++ b/source/Lib/CommonLib/Mv.h @@ -61,6 +61,10 @@ class Mv { private: static const MvPrecision m_amvrPrecision[3]; +#if JVET_N0334_MVCLIPPING + static const int mvClipPeriod = (1 << 18); + static const int halMvClipPeriod = (1 << 17); +#endif public: int hor; ///< horizontal component of motion vector @@ -213,6 +217,15 @@ public: hor = Clip3( -(1 << 17), (1 << 17) - 1, hor ); ver = Clip3( -(1 << 17), (1 << 17) - 1, ver ); } +#if JVET_N0334_MVCLIPPING + void mvCliptoStorageBitDepth() // periodic clipping + { + hor = (hor + mvClipPeriod) & (mvClipPeriod - 1); + hor = (hor >= halMvClipPeriod) ? (hor - mvClipPeriod) : hor; + ver = (ver + mvClipPeriod) & (mvClipPeriod - 1); + ver = (ver >= halMvClipPeriod) ? (ver - mvClipPeriod) : ver; + } +#endif };// END CLASS DEFINITION MV namespace std diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 80270fd95..512a2540c 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_N0334_MVCLIPPING 1 // prevention of MV stroage overflow and alignment with spec of MV/CPMV modular for AMVP mode + #define JVET_N0477_LMCS_CLEANUP 1 #define JVET_N0220_LMCS_SIMPLIFICATION 1 diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 534ec8017..6ac8d767a 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -87,6 +87,10 @@ void CS::setRefinedMotionField(CodingStructure &cs) subPu.mv[1] = pu.mv[1]; subPu.mv[REF_PIC_LIST_0] += pu.mvdL0SubPu[num]; subPu.mv[REF_PIC_LIST_1] -= pu.mvdL0SubPu[num]; +#if JVET_N0334_MVCLIPPING + subPu.mv[REF_PIC_LIST_0].clipToStorageBitDepth(); + subPu.mv[REF_PIC_LIST_1].clipToStorageBitDepth(); +#endif pu.mvdL0SubPu[num].setZero(); num++; PU::spanMotionInfo(subPu); @@ -3182,16 +3186,25 @@ void PU::getAffineControlPointCand( const PredictionUnit &pu, MotionInfo mi[4], case 1: // 1 : LT, RT, RB cMv[l][2].hor = cMv[l][3].hor + cMv[l][0].hor - cMv[l][1].hor; cMv[l][2].ver = cMv[l][3].ver + cMv[l][0].ver - cMv[l][1].ver; +#if JVET_N0334_MVCLIPPING + cMv[l][2].clipToStorageBitDepth(); +#endif break; case 2: // 2 : LT, LB, RB cMv[l][1].hor = cMv[l][3].hor + cMv[l][0].hor - cMv[l][2].hor; cMv[l][1].ver = cMv[l][3].ver + cMv[l][0].ver - cMv[l][2].ver; +#if JVET_N0334_MVCLIPPING + cMv[l][1].clipToStorageBitDepth(); +#endif break; case 3: // 3 : RT, LB, RB cMv[l][0].hor = cMv[l][1].hor + cMv[l][2].hor - cMv[l][3].hor; cMv[l][0].ver = cMv[l][1].ver + cMv[l][2].ver - cMv[l][3].ver; +#if JVET_N0334_MVCLIPPING + cMv[l][0].clipToStorageBitDepth(); +#endif break; case 4: // 4 : LT, RT @@ -3202,6 +3215,9 @@ void PU::getAffineControlPointCand( const PredictionUnit &pu, MotionInfo mi[4], vy = (cMv[l][0].ver << shift) - ((cMv[l][2].hor - cMv[l][0].hor) << shiftHtoW); roundAffineMv( vx, vy, shift ); cMv[l][1].set( vx, vy ); +#if JVET_N0334_MVCLIPPING + cMv[l][1].clipToStorageBitDepth(); +#endif break; default: @@ -3625,7 +3641,11 @@ void PU::setAllAffineMvField( PredictionUnit &pu, MvField *mvField, RefPicList e pu.refIdx[eRefList] = mvField[0].refIdx; } +#if JVET_N0334_MVCLIPPING +void PU::setAllAffineMv(PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList, bool setHighPrec, bool clipCPMVs) +#else void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList, bool setHighPrec) +#endif { int width = pu.Y().width; int shift = MAX_CU_DEPTH; @@ -3635,6 +3655,17 @@ void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPi affRT.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); affLB.changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); } +#if JVET_N0334_MVCLIPPING + if (clipCPMVs) + { + affLT.mvCliptoStorageBitDepth(); + affRT.mvCliptoStorageBitDepth(); + if (pu.cu->affineType == AFFINEMODEL_6PARAM) + { + affLB.mvCliptoStorageBitDepth(); + } + } +#endif int deltaMvHorX, deltaMvHorY, deltaMvVerX, deltaMvVerY; deltaMvHorX = (affRT - affLT).getHor() << (shift - g_aucLog2[width]); deltaMvHorY = (affRT - affLT).getVer() << (shift - g_aucLog2[width]); @@ -4039,6 +4070,9 @@ void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interP pu.mvpIdx[0] = mvp_idx; pu.mv [0] = amvpInfo.mvCand[mvp_idx] + pu.mvd[0]; pu.mv[0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); +#if JVET_N0334_MVCLIPPING + pu.mv[0].mvCliptoStorageBitDepth(); +#endif } if (pu.interDir != 1 /* PRED_L0 */) @@ -4054,6 +4088,9 @@ void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interP pu.mvpIdx[1] = mvp_idx; pu.mv [1] = amvpInfo.mvCand[mvp_idx] + pu.mvd[1]; pu.mv[1].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); +#if JVET_N0334_MVCLIPPING + pu.mv[1].mvCliptoStorageBitDepth(); +#endif } } else diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 344bac8fb..c2c3387d6 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -160,6 +160,9 @@ namespace PU void setAllAffineMvField ( PredictionUnit &pu, MvField *mvField, RefPicList eRefList ); void setAllAffineMv ( PredictionUnit &pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList , bool setHighPrec = false +#if JVET_N0334_MVCLIPPING + , bool clipCPMVs = false +#endif ); bool getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx &mrgCtx, bool& LICFlag, const int count , int mmvdList diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 30ee7bbb1..d4b9c5863 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -745,7 +745,11 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) mvLB.changePrecision( MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL ); } } +#if JVET_N0334_MVCLIPPING + PU::setAllAffineMv(pu, mvLT, mvRT, mvLB, eRefList, false, true); +#else PU::setAllAffineMv( pu, mvLT, mvRT, mvLB, eRefList ); +#endif } } } @@ -761,6 +765,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) mvd <<= 2; pu.mv[REF_PIC_LIST_0] = amvpInfo.mvCand[pu.mvpIdx[REF_PIC_LIST_0]] + mvd; pu.mv[REF_PIC_LIST_0].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); +#if JVET_N0334_MVCLIPPING + pu.mv[REF_PIC_LIST_0].mvCliptoStorageBitDepth(); +#endif } else { @@ -774,6 +781,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) pu.mvpNum [eRefList] = amvpInfo.numCand; pu.mv[eRefList] = amvpInfo.mvCand[pu.mvpIdx[eRefList]] + pu.mvd[eRefList]; pu.mv[eRefList].changePrecision(MV_PRECISION_QUARTER, MV_PRECISION_INTERNAL); +#if JVET_N0334_MVCLIPPING + pu.mv[eRefList].mvCliptoStorageBitDepth(); +#endif } } } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 51f0e9386..7b78b3708 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -3784,6 +3784,34 @@ void EncCu::xEncodeInterResidual( CodingStructure *&tempCS } } } +#if JVET_N0334_MVCLIPPING + // avoid MV exceeding 18-bit dynamic range + const int maxMv = 1 << 17; + if (!cu->affine && !pu.mergeFlag) + { + if ( (pu.refIdx[0] >= 0 && (pu.mv[0].getAbsHor() >= maxMv || pu.mv[0].getAbsVer() >= maxMv)) + || (pu.refIdx[1] >= 0 && (pu.mv[1].getAbsHor() >= maxMv || pu.mv[1].getAbsVer() >= maxMv))) + { + return; + } + } + if (cu->affine && !pu.mergeFlag) + { + for (int refList = 0; refList < NUM_REF_PIC_LIST_01; refList++) + { + if (pu.refIdx[refList] >= 0) + { + for (int ctrlP = 1 + (cu->affineType == AFFINEMODEL_6PARAM); ctrlP >= 0; ctrlP--) + { + if (pu.mvAffi[refList][ctrlP].getAbsHor() >= maxMv || pu.mvAffi[refList][ctrlP].getAbsVer() >= maxMv) + { + return; + } + } + } + } + } +#endif const bool mtsAllowed = tempCS->sps->getUseInterMTS() && CU::isInter( *cu ) && partitioner.currArea().lwidth() <= MTS_INTER_MAX_CU_SIZE && partitioner.currArea().lheight() <= MTS_INTER_MAX_CU_SIZE; uint8_t sbtAllowed = cu->checkAllowedSbt(); uint8_t numRDOTried = 0; -- GitLab