diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 69e1c5b811b30b8752a604b49226e5fa2f664aab..2d5d737f1fd1668bcdca59f9fa83ab728dabd989 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -798,6 +798,47 @@ void InterPrediction::xPredInterBlk ( const ComponentID& compID, const Predictio } } +#if JVET_N0068_AFFINE_MEM_BW +bool InterPrediction::isSubblockVectorSpreadOverLimit( int a, int b, int c, int d, int predType ) +{ + int s4 = ( 4 << 11 ); + int filterTap = 6; + + if ( predType == 3 ) + { + int refBlkWidth = std::max( std::max( 0, 4 * a + s4 ), std::max( 4 * c, 4 * a + 4 * c + s4 ) ) - std::min( std::min( 0, 4 * a + s4 ), std::min( 4 * c, 4 * a + 4 * c + s4 ) ); + int refBlkHeight = std::max( std::max( 0, 4 * b ), std::max( 4 * d + s4, 4 * b + 4 * d + s4 ) ) - std::min( std::min( 0, 4 * b ), std::min( 4 * d + s4, 4 * b + 4 * d + s4 ) ); + refBlkWidth = ( refBlkWidth >> 11 ) + filterTap + 3; + refBlkHeight = ( refBlkHeight >> 11 ) + filterTap + 3; + + if ( refBlkWidth * refBlkHeight > ( filterTap + 9 ) * ( filterTap + 9 ) ) + { + return true; + } + } + else + { + int refBlkWidth = std::max( 0, 4 * a + s4 ) - std::min( 0, 4 * a + s4 ); + int refBlkHeight = std::max( 0, 4 * b ) - std::min( 0, 4 * b ); + refBlkWidth = ( refBlkWidth >> 11 ) + filterTap + 3; + refBlkHeight = ( refBlkHeight >> 11 ) + filterTap + 3; + if ( refBlkWidth * refBlkHeight > ( filterTap + 9 ) * ( filterTap + 5 ) ) + { + return true; + } + + refBlkWidth = std::max( 0, 4 * c ) - std::min( 0, 4 * c ); + refBlkHeight = std::max( 0, 4 * d + s4 ) - std::min( 0, 4 * d + s4 ); + refBlkWidth = ( refBlkWidth >> 11 ) + filterTap + 3; + refBlkHeight = ( refBlkHeight >> 11 ) + filterTap + 3; + if ( refBlkWidth * refBlkHeight > ( filterTap + 5 ) * ( filterTap + 9 ) ) + { + return true; + } + } + return false; +} +#endif void InterPrediction::xPredAffineBlk( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng ) { if ( (pu.cu->affineType == AFFINEMODEL_6PARAM && _mv[0] == _mv[1] && _mv[0] == _mv[2]) @@ -873,6 +914,13 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio const int vFilterSize = isLuma(compID) ? NTAPS_LUMA : NTAPS_CHROMA; const int shift = iBit - 4 + MV_FRACTIONAL_BITS_INTERNAL; +#if JVET_N0068_AFFINE_MEM_BW + bool subblkMVSpreadOverLimit = false; + if ( isSubblockVectorSpreadOverLimit( iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY, pu.interDir ) ) + { + subblkMVSpreadOverLimit = true; + } +#endif // get prediction block by block @@ -888,9 +936,20 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio if(compID == COMPONENT_Y) #endif //JVET_N0671_AFFINE { - iMvScaleTmpHor = iMvScaleHor + iDMvHorX * (iHalfBW + w) + iDMvVerX * (iHalfBH + h); - iMvScaleTmpVer = iMvScaleVer + iDMvHorY * (iHalfBW + w) + iDMvVerY * (iHalfBH + h); - +#if JVET_N0068_AFFINE_MEM_BW + if ( !subblkMVSpreadOverLimit ) + { +#endif + iMvScaleTmpHor = iMvScaleHor + iDMvHorX * (iHalfBW + w) + iDMvVerX * (iHalfBH + h); + iMvScaleTmpVer = iMvScaleVer + iDMvHorY * (iHalfBW + w) + iDMvVerY * (iHalfBH + h); +#if JVET_N0068_AFFINE_MEM_BW + } + 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(); diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index 760e2268a27fb1831f5bc10f15e0592f6d3791b7..5130f46f8a5f76edbb1b5a33d1bc192594f5c0c8 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -190,6 +190,9 @@ public: #if ENABLE_SPLIT_PARALLELISM int getShareState() const { return m_shareState; } #endif +#if JVET_N0068_AFFINE_MEM_BW + bool isSubblockVectorSpreadOverLimit( int a, int b, int c, int d, int predType ); +#endif }; //! \} diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 63bd3f0f85c4cf54f759057a2b27ab2769dd233a..90dce7152866f1e8e27d27f2194b062dbdbf0c7b 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_N0068_AFFINE_MEM_BW 1 // memory bandwidth reduction for affine mode + #define JVET_N0308_MAX_CU_SIZE_FOR_ISP 1 #define JVET_N0280_RESIDUAL_CODING_TS 1 diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 3bab928cf55e03ebdefcb2d3a4c77929d5648118..9d343da3cccb3b16f26ffc67d7a851e3b34b3cd8 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -4032,14 +4032,30 @@ void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPi MotionBuf mb = pu.getMotionBuf(); int mvScaleTmpHor, mvScaleTmpVer; - +#if JVET_N0068_AFFINE_MEM_BW + bool subblkMVSpreadOverLimit = false; + InterPrediction temp; + subblkMVSpreadOverLimit = temp.isSubblockVectorSpreadOverLimit( deltaMvHorX, deltaMvHorY, deltaMvVerX, deltaMvVerY, pu.interDir ); +#endif for ( int h = 0; h < pu.Y().height; h += blockHeight ) { for ( int w = 0; w < pu.Y().width; w += blockWidth ) { - mvScaleTmpHor = mvScaleHor + deltaMvHorX * (halfBW + w) + deltaMvVerX * (halfBH + h); - mvScaleTmpVer = mvScaleVer + deltaMvHorY * (halfBW + w) + deltaMvVerY * (halfBH + h); +#if JVET_N0068_AFFINE_MEM_BW + if ( !subblkMVSpreadOverLimit ) + { +#endif + mvScaleTmpHor = mvScaleHor + deltaMvHorX * (halfBW + w) + deltaMvVerX * (halfBH + h); + mvScaleTmpVer = mvScaleVer + deltaMvHorY * (halfBW + w) + deltaMvVerY * (halfBH + h); +#if JVET_N0068_AFFINE_MEM_BW + } + else + { + mvScaleTmpHor = mvScaleHor + deltaMvHorX * ( pu.Y().width >> 1 ) + deltaMvVerX * ( pu.Y().height >> 1 ); + mvScaleTmpVer = mvScaleVer + deltaMvHorY * ( pu.Y().width >> 1 ) + deltaMvVerY * ( pu.Y().height >> 1 ); + } +#endif roundAffineMv( mvScaleTmpHor, mvScaleTmpVer, shift ); Mv curMv(mvScaleTmpHor, mvScaleTmpVer); curMv.clipToStorageBitDepth(); diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index af871b34e8c07ac79f4d44957391c7768a07a756..59e74f97b3c7aa574bb10f420160c2fa1e50029e 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -4306,7 +4306,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, for ( int iRefList = 0; iRefList < iNumPredDir; iRefList++ ) { RefPicList eRefPicList = ( iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0 ); - +#if JVET_N0068_AFFINE_MEM_BW + pu.interDir = ( iRefList ? 2 : 1 ); +#endif for (int iRefIdxTemp = 0; iRefIdxTemp < slice.getNumRefIdx(eRefPicList); iRefIdxTemp++) { // Get RefIdx bits @@ -4645,7 +4647,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, if ( slice.isInterB() && !PU::isBipredRestriction(pu) ) { tryBipred = 1; - +#if JVET_N0068_AFFINE_MEM_BW + pu.interDir = 3; +#endif // Set as best list0 and list1 iRefIdxBi[0] = iRefIdx[0]; iRefIdxBi[1] = iRefIdx[1]; @@ -4901,7 +4905,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, { lastMode = 2; affineCost = uiCostBi; - +#if JVET_N0068_AFFINE_MEM_BW + pu.interDir = 3; +#endif PU::setAllAffineMv( pu, cMvBi[0][0], cMvBi[0][1], cMvBi[0][2], REF_PIC_LIST_0 , changeToHighPrec ); @@ -4922,7 +4928,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, } } +#if !JVET_N0068_AFFINE_MEM_BW pu.interDir = 3; +#endif pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdxBi[0][iRefIdxBi[0]]; pu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdxBi[0]]; @@ -4933,7 +4941,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, { lastMode = 0; affineCost = uiCost[0]; - +#if JVET_N0068_AFFINE_MEM_BW + pu.interDir = 1; +#endif PU::setAllAffineMv( pu, aacMv[0][0], aacMv[0][1], aacMv[0][2], REF_PIC_LIST_0 , changeToHighPrec ); @@ -4947,8 +4957,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, pu.mvdAffi[0][verIdx] = pu.mvdAffi[0][verIdx] - pu.mvdAffi[0][0]; } } - +#if !JVET_N0068_AFFINE_MEM_BW pu.interDir = 1; +#endif pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdx[0][iRefIdx[0]]; pu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdx[0]]; @@ -4957,7 +4968,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, { lastMode = 1; affineCost = uiCost[1]; - +#if JVET_N0068_AFFINE_MEM_BW + pu.interDir = 2; +#endif PU::setAllAffineMv( pu, aacMv[1][0], aacMv[1][1], aacMv[1][2], REF_PIC_LIST_1 , changeToHighPrec ); @@ -4971,8 +4984,9 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, pu.mvdAffi[1][verIdx] = pu.mvdAffi[1][verIdx] - pu.mvdAffi[1][0]; } } - +#if !JVET_N0068_AFFINE_MEM_BW pu.interDir = 2; +#endif pu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdx[1][iRefIdx[1]]; pu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdx[1]];