diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 4070fcc..54436bb 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -817,7 +817,7 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) ("HighPrecMv", m_highPrecisionMv, false, "High precision motion vectors for temporal merging (0:off, 1:on) [default: off]") ("Affine", m_Affine, false, "Enable affine prediction (0:off, 1:on) [default: off]") #if JVET_K0337_AFFINE_6PARA - ( "AffineType", m_AffineType, true, "Enable affine type prediction (0:off, 1:on) [default: on]" ) + ( "AffineType", m_AffineType, 2, "Enable affine type prediction (0:off, 1:on) [default: on] / [modify] 0:4param, 1:6param, 2:8param" ) #endif #endif ("DisableMotCompression", m_DisableMotionCompression, false, "Disable motion data compression for all modes") diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index 10a0554..10212c0 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -210,7 +210,7 @@ class EncAppCfg #if JVET_K_AFFINE bool m_Affine; #if JVET_K0337_AFFINE_6PARA - bool m_AffineType; + int m_AffineType; #endif #endif #if JVET_K0346 || JVET_K_AFFINE diff --git a/source/Lib/CommonLib/AffineGradientSearch.cpp b/source/Lib/CommonLib/AffineGradientSearch.cpp index 6d56468..b4df0de 100644 --- a/source/Lib/CommonLib/AffineGradientSearch.cpp +++ b/source/Lib/CommonLib/AffineGradientSearch.cpp @@ -129,25 +129,37 @@ void AffineGradientSearch::xVerticalSobelFilter( Pel *const pPred, const int pre } } -void AffineGradientSearch::xEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDerivate, int derivateBufStride, int64_t( *pEqualCoeff )[7], int width, int height, bool b6Param ) +void AffineGradientSearch::xEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDerivate, int derivateBufStride, int64_t( *pEqualCoeff )[9], int width, int height, int i468Param ) { - int affineParamNum = b6Param ? 6 : 4; + int affineParamNum = 0; + if (i468Param == 0) + { + affineParamNum = 4; + } + else if (i468Param == 1) + { + affineParamNum = 6; + } + else if (i468Param == 2) + { + affineParamNum = 8; + } for ( int j = 0; j != height; j++ ) { for ( int k = 0; k != width; k++ ) { - int iC[6]; + int iC[8]; int idx = j * derivateBufStride + k; - if ( !b6Param ) + if (i468Param == 0) { iC[0] = ppDerivate[0][idx]; iC[1] = k * ppDerivate[0][idx] + j * ppDerivate[1][idx]; iC[2] = ppDerivate[1][idx]; iC[3] = j * ppDerivate[0][idx] - k * ppDerivate[1][idx]; } - else + else if (i468Param == 1) { iC[0] = ppDerivate[0][idx]; iC[1] = k * ppDerivate[0][idx]; @@ -156,6 +168,17 @@ void AffineGradientSearch::xEqualCoeffComputer( Pel *pResidue, int residueStride iC[4] = j * ppDerivate[0][idx]; iC[5] = j * ppDerivate[1][idx]; } + else + { + iC[0] = ppDerivate[0][idx]; + iC[1] = k * ppDerivate[0][idx]; + iC[2] = ppDerivate[1][idx]; + iC[3] = k * ppDerivate[1][idx]; + iC[4] = j * ppDerivate[0][idx]; + iC[5] = j * ppDerivate[1][idx]; + iC[6] = k * ppDerivate[0][idx] + j * ppDerivate[0][idx]; + iC[7] = k * ppDerivate[1][idx] + j * ppDerivate[1][idx]; + } for ( int col = 0; col < affineParamNum; col++ ) { for ( int row = 0; row < affineParamNum; row++ ) diff --git a/source/Lib/CommonLib/AffineGradientSearch.h b/source/Lib/CommonLib/AffineGradientSearch.h index b15fef9..f5eb478 100644 --- a/source/Lib/CommonLib/AffineGradientSearch.h +++ b/source/Lib/CommonLib/AffineGradientSearch.h @@ -51,13 +51,13 @@ class AffineGradientSearch void( *m_VerticalSobelFilter ) (Pel *const pPred, const int predStride, int *const pDerivate, const int derivateBufStride, const int width, const int height); - void( *m_EqualCoeffComputer ) (Pel *pResidue, int residueStride, int **ppDerivate, int derivateBufStride, int64_t( *pEqualCoeff )[7], int width, int height, bool b6Param); + void( *m_EqualCoeffComputer ) (Pel *pResidue, int residueStride, int **ppDerivate, int derivateBufStride, int64_t( *pEqualCoeff )[9], int width, int height, int i468Param); static void xHorizontalSobelFilter( Pel *const pPred, const int predStride, int *const pDerivate, const int derivateBufStride, const int width, const int height ); static void xVerticalSobelFilter( Pel *const pPred, const int predStride, int *const pDerivate, const int derivateBufStride, const int width, const int height ); - static void xEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDerivate, int derivateBufStride, int64_t( *pEqualCoeff )[7], int width, int height, bool b6Param ); + static void xEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDerivate, int derivateBufStride, int64_t( *pEqualCoeff )[9], int width, int height, int i468Param); AffineGradientSearch(); ~AffineGradientSearch() {} diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 7c8e0c1..cf4eec3 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -114,6 +114,7 @@ typedef enum { AFFINEMODEL_4PARAM, AFFINEMODEL_6PARAM, + AFFINEMODEL_8PARAM, // [Perspective ME] Perspective Model 8Param AFFINE_MODEL_NUM } EAffineModel; #endif @@ -327,6 +328,7 @@ static const int MAX_GR_ORDER_RESIDUAL = 10; static const int AFFINE_MAX_NUM_V0 = 3; ///< max number of motion candidates in top-left corner static const int AFFINE_MAX_NUM_V1 = 2; ///< max number of motion candidates in top-right corner static const int AFFINE_MAX_NUM_V2 = 2; ///< max number of motion candidates in left-bottom corner +static const int AFFINE_MAX_NUM_V3 = 1; ///< max number of motion candidates in right-bottom corner static const int AFFINE_MAX_NUM_COMB = 12; ///< max number of combined motion candidates static const int AFFINE_MIN_BLOCK_SIZE = 4; ///< Minimum affine MC block size #endif diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index d7d21d2..fd4be0d 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -378,6 +378,7 @@ const CtxSet ContextSetCfg::AffineType = ContextSetCfg::addCtxSet ({ { 92, }, { 77, }, + { 62, }, // [YJC][PerspectiveME] °°Àº °£°ÝÀ¸·Î Çϱä ÇßÀ¸³ª, ¼³Á¤ ¹æ¹ýÀ» Àß ¸ð¸£°ÚÀ½. { CNU, }, }); #endif diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index b5e4bc9..3b0cac5 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -191,7 +191,8 @@ bool checkIdenticalMotion( const PredictionUnit &pu ) #if JVET_K_AFFINE_BUG_FIXES #if JVET_K0337_AFFINE_6PARA if ( (pu.cu->affineType == AFFINEMODEL_4PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1])) - || (pu.cu->affineType == AFFINEMODEL_6PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) && (mb.at( 0, mb.height - 1 ).mv[0] == mb.at( 0, mb.height - 1 ).mv[1])) ) + || (pu.cu->affineType == AFFINEMODEL_6PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) && (mb.at( 0, mb.height - 1 ).mv[0] == mb.at( 0, mb.height - 1 ).mv[1])) + || (pu.cu->affineType == AFFINEMODEL_8PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) && (mb.at( 0, mb.height - 1 ).mv[0] == mb.at( 0, mb.height - 1 ).mv[1])) ) #else if ( (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) ) #endif @@ -243,7 +244,8 @@ bool InterPrediction::xCheckIdenticalMotion( const PredictionUnit &pu ) #if JVET_K_AFFINE_BUG_FIXES #if JVET_K0337_AFFINE_6PARA if ( (pu.cu->affineType == AFFINEMODEL_4PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1])) - || (pu.cu->affineType == AFFINEMODEL_6PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) && (mb.at( 0, mb.height - 1 ).mv[0] == mb.at( 0, mb.height - 1 ).mv[1])) ) + || (pu.cu->affineType == AFFINEMODEL_6PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) && (mb.at( 0, mb.height - 1 ).mv[0] == mb.at( 0, mb.height - 1 ).mv[1])) + || (pu.cu->affineType == AFFINEMODEL_8PARAM && (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) && (mb.at( 0, mb.height - 1 ).mv[0] == mb.at( 0, mb.height - 1 ).mv[1])) ) #else if ( (mb.at( 0, 0 ).mv[0] == mb.at( 0, 0 ).mv[1]) && (mb.at( mb.width - 1, 0 ).mv[0] == mb.at( mb.width - 1, 0 ).mv[1]) ) #endif @@ -370,7 +372,7 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& const SPS &sps = *pu.cs->sps; int iRefIdx = pu.refIdx[eRefPicList]; - Mv mv[3]; + Mv mv[4]; #if JVET_K_AFFINE if( pu.cu->affine ) @@ -381,6 +383,8 @@ void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& mv[0] = mb.at( 0, 0 ).mv[eRefPicList]; mv[1] = mb.at( mb.width - 1, 0 ).mv[eRefPicList]; mv[2] = mb.at( 0, mb.height - 1 ).mv[eRefPicList]; + mv[3] = mb.at( mb.width - 1, mb.height - 1 ).mv[eRefPicList]; + #if !JVET_K_AFFINE_BUG_FIXES clipMv(mv[1], pu.cu->lumaPos(), sps); clipMv(mv[2], pu.cu->lumaPos(), sps); @@ -553,6 +557,7 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio { #if JVET_K0337_AFFINE_6PARA if ( (pu.cu->affineType == AFFINEMODEL_6PARAM && _mv[0] == _mv[1] && _mv[0] == _mv[2]) + || (pu.cu->affineType == AFFINEMODEL_8PARAM && _mv[0] == _mv[1] && _mv[0] == _mv[2] && _mv[0] == _mv[3]) || (pu.cu->affineType == AFFINEMODEL_4PARAM && _mv[0] == _mv[1]) ) #else @@ -577,10 +582,12 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio Mv mvLT =_mv[0]; Mv mvRT =_mv[1]; Mv mvLB =_mv[2]; + Mv mvRB =_mv[3]; mvLT.setHighPrec(); mvRT.setHighPrec(); mvLB.setHighPrec(); + mvRB.setHighPrec(); // get affine sub-block width and height const int width = pu.Y().width; @@ -625,11 +632,18 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio const int iHalfBH = blockHeight >> 1; const int iBit = MAX_CU_DEPTH; - int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY; + int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY; //a, d, b, e + int iDMvHorBottom = 1; //g + int iDMvVerBottom = 1; //h + + //int perspParamX = (int)pu.perspParam[0]; + //int perspParamY = (int)pu.perspParam[1]; + iDMvHorX = (mvRT - mvLT).getHor() << (iBit - g_aucLog2[cxWidth]); iDMvHorY = (mvRT - mvLT).getVer() << (iBit - g_aucLog2[cxWidth]); + #if JVET_K0337_AFFINE_6PARA - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM) { iDMvVerX = (mvLB - mvLT).getHor() << (iBit - g_aucLog2[cxHeight]); iDMvVerY = (mvLB - mvLT).getVer() << (iBit - g_aucLog2[cxHeight]); @@ -639,13 +653,57 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio iDMvVerX = -iDMvHorY; iDMvVerY = iDMvHorX; } + + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + // Full MV Model + if ((((mvRB - mvLB).getVer() * (mvRB - mvRT).getHor()) - ((mvRB - mvLB).getHor() * (mvRB - mvRT).getVer())) != 0) + { + iDMvHorBottom = ((((mvRB - mvLB).getHor() * (2 * mvLT.getVer() - mvRT.getVer())) + ((mvRB - mvLB).getVer() * (mvRT.getHor() - 2 * mvLT.getHor()))) + / (((mvRB - mvLB).getVer() * (mvRB - mvRT).getHor()) - ((mvRB - mvLB).getHor() * (mvRB - mvRT).getVer()))); + } + else + { + iDMvHorBottom = (0) << (iBit - g_aucLog2[cxWidth]); + } + + if ((((mvRB - mvLT).getVer() * (mvRB - mvLB).getHor()) - ((mvRB - mvLT).getHor() * (mvRB - mvLB).getVer())) != 0) + { + iDMvVerBottom = ((((mvRB - mvLT).getHor() * (2 * mvLT.getVer() - mvRT.getVer())) + ((mvRB - mvLT).getVer() * (mvRT.getHor() - 2 * mvLT.getHor()))) + / (((mvRB - mvLT).getVer() * (mvRB - mvLB).getHor()) - ((mvRB - mvLT).getHor() * (mvRB - mvLB).getVer()))); + } + else + { + iDMvVerBottom = (0) << (iBit - g_aucLog2[cxHeight]); + } + + + iDMvHorX = (mvRT.getHor() * (iDMvHorBottom + 1) - mvLT.getHor()) << (iBit - g_aucLog2[cxWidth]); + + iDMvVerX = (mvLB.getHor() * (iDMvVerBottom + 1) - mvLT.getHor()) << (iBit - g_aucLog2[cxHeight]); + + iDMvHorY = (mvRT.getVer() * (iDMvHorBottom + 1) - mvLT.getVer()) << (iBit - g_aucLog2[cxWidth]); + + iDMvVerY = (mvLB.getVer() * (iDMvVerBottom + 1) - mvLT.getVer()) << (iBit - g_aucLog2[cxHeight]); + + + // MV+Param Model + /* + iDMvHorX = (perspParamX * mvRT.getHor() - mvLT.getHor()) << (iBit - g_aucLog2[cxWidth]); + iDMvVerX = (perspParamY * mvLB.getHor() - mvLT.getHor()) << (iBit - g_aucLog2[cxWidth]); + iDMvHorY = (perspParamX * mvRT.getVer() - mvLT.getVer()) << (iBit - g_aucLog2[cxHeight]); + iDMvVerY = (perspParamY * mvLB.getVer() - mvLT.getVer()) << (iBit - g_aucLog2[cxHeight]); + iDMvHorBottom = (perspParamX - 1) << (iBit - g_aucLog2[cxWidth]); + iDMvVerBottom = (perspParamY - 1) << (iBit - g_aucLog2[cxHeight]); + */ + } #else iDMvVerX = -iDMvHorY; iDMvVerY = iDMvHorX; #endif - int iMvScaleHor = mvLT.getHor() << iBit; - int iMvScaleVer = mvLT.getVer() << iBit; + int iMvScaleHor = mvLT.getHor() << iBit; //c + int iMvScaleVer = mvLT.getVer() << iBit; //f const SPS &sps = *pu.cs->sps; const int iMvShift = 4; const int iOffset = 8; @@ -666,6 +724,21 @@ void InterPrediction::xPredAffineBlk( const ComponentID& compID, const Predictio { int iMvScaleTmpHor = iMvScaleHor + iDMvHorX * (iHalfBW + w) + iDMvVerX * (iHalfBH + h); int iMvScaleTmpVer = iMvScaleVer + iDMvHorY * (iHalfBW + w) + iDMvVerY * (iHalfBH + h); + + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + if ((iDMvHorBottom * (iHalfBW + w) + iDMvVerBottom * (iHalfBH + h) + 1) != 0) + { + iMvScaleTmpHor = (iMvScaleHor + iDMvHorX * (iHalfBW + w) + iDMvVerX * (iHalfBH + h)) / (iDMvHorBottom * (iHalfBW + w) + iDMvVerBottom * (iHalfBH + h) + 1); + iMvScaleTmpVer = (iMvScaleVer + iDMvHorY * (iHalfBW + w) + iDMvVerY * (iHalfBH + h)) / (iDMvHorBottom * (iHalfBW + w) + iDMvVerBottom * (iHalfBH + h) + 1); + } + else + { + iMvScaleTmpHor = (iMvScaleHor + iDMvHorX * (iHalfBW + w) + iDMvVerX * (iHalfBH + h)); + iMvScaleTmpVer = (iMvScaleVer + iDMvHorY * (iHalfBW + w) + iDMvVerY * (iHalfBH + h)); + } + } + #if JVET_K_AFFINE_BUG_FIXES roundAffineMv( iMvScaleTmpHor, iMvScaleTmpVer, shift ); #else diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index a895322..1b256b1 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -91,7 +91,7 @@ class InterPrediction : public WeightPrediction void xWeightedAverage ( const PredictionUnit& pu, const CPelUnitBuf& pcYuvSrc0, const CPelUnitBuf& pcYuvSrc1, PelUnitBuf& pcYuvDst, const BitDepths& clipBitDepths, const ClpRngs& clpRngs ); #if JVET_K_AFFINE - void xPredAffineBlk( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng ); + void xPredAffineBlk( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng); #endif static bool xCheckIdenticalMotion( const PredictionUnit& pu ); diff --git a/source/Lib/CommonLib/MotionInfo.h b/source/Lib/CommonLib/MotionInfo.h index 001b84a..e1bc011 100644 --- a/source/Lib/CommonLib/MotionInfo.h +++ b/source/Lib/CommonLib/MotionInfo.h @@ -62,6 +62,7 @@ struct AffineAMVPInfo Mv mvCandLT[ AMVP_MAX_NUM_CANDS_MEM ]; ///< array of affine motion vector predictor candidates for left-top corner Mv mvCandRT[ AMVP_MAX_NUM_CANDS_MEM ]; ///< array of affine motion vector predictor candidates for right-top corner Mv mvCandLB[ AMVP_MAX_NUM_CANDS_MEM ]; ///< array of affine motion vector predictor candidates for left-bottom corner + Mv mvCandRB[ AMVP_MAX_NUM_CANDS_MEM ]; ///< array of affine motion vector predictor candidates for right-bottom corner unsigned numCand; ///< number of motion vector predictor candidates }; #endif diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 7e26fc8..13f8cdf 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -1617,7 +1617,7 @@ SPSNext::SPSNext( SPS& sps ) #if JVET_K_AFFINE , m_Affine ( false ) #if JVET_K0337_AFFINE_6PARA - , m_AffineType ( false ) + , m_AffineType ( 0 ) #endif #endif , m_MTTEnabled ( false ) diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 5164daa..bc79d7b 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -825,7 +825,7 @@ class SPSNext #if JVET_K_AFFINE bool m_Affine; #if JVET_K0337_AFFINE_6PARA - bool m_AffineType; + int m_AffineType; #endif #endif bool m_MTTEnabled; // @@ -887,8 +887,8 @@ class SPSNext void setUseAffine ( bool b ) { m_Affine = b; } bool getUseAffine () const { return m_Affine; } #if JVET_K0337_AFFINE_6PARA - void setUseAffineType ( bool b ) { m_AffineType = b; } - bool getUseAffineType () const { return m_AffineType; } + void setUseAffineType ( int b ) { m_AffineType = b; } + int getUseAffineType () const { return m_AffineType; } #endif #endif #if JVET_K0072 diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 499837a..045c866 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -100,6 +100,10 @@ #if JVET_K0337_AFFINE_6PARA #define JVET_K0185_AFFINE_6PARA_ENC 1 // CE4.1.5 Affine 6-para encoder #endif +#define JVET_YJC_PERSP_8PARA 1 // [YJC] Perspective 8-para encoder +#if JVET_YJC_PERSP_8PARA +#define JVET_YJC_PERSP_8PARA_ENC 1 // [YJC] Perspective 8-para encoder +#endif #endif #define JVET_K0357_AMVR 1 // Adaptive motion vector resolution separated from JEM_TOOLS macro @@ -604,7 +608,7 @@ enum MvpDir MD_ABOVE, ///< MVP of above block MD_ABOVE_RIGHT, ///< MVP of above right block MD_BELOW_LEFT, ///< MVP of below left block - MD_ABOVE_LEFT ///< MVP of above left block + MD_ABOVE_LEFT, ///< MVP of above left block }; enum StoredResidualType diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 9b14f80..8ddbf1c 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -338,12 +338,16 @@ void PredictionUnit::initData() mv[i] .setZero(); mvd[i] .setZero(); #if JVET_K_AFFINE - for( uint32_t j = 0; j < 3; j++ ) + for( uint32_t j = 0; j < 4; j++ ) { mvdAffi[i][j].setZero(); } #endif } + for (uint32_t i = 0; i < 2; i++) + { + perspParam[i] = 0.0; + } } PredictionUnit& PredictionUnit::operator=(const IntraPredictionData& predData) @@ -370,7 +374,7 @@ PredictionUnit& PredictionUnit::operator=(const InterPredictionData& predData) mvd[i] = predData.mvd[i]; refIdx[i] = predData.refIdx[i]; #if JVET_K_AFFINE - for( uint32_t j = 0; j < 3; j++ ) + for( uint32_t j = 0; j < 4; j++ ) { mvdAffi[i][j] = predData.mvdAffi[i][j]; } @@ -399,7 +403,7 @@ PredictionUnit& PredictionUnit::operator=( const PredictionUnit& other ) mvd[i] = other.mvd[i]; refIdx[i] = other.refIdx[i]; #if JVET_K_AFFINE - for( uint32_t j = 0; j < 3; j++ ) + for( uint32_t j = 0; j < 4; j++ ) { mvdAffi[i][j] = other.mvdAffi[i][j]; } diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index 1869401..452f330 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -362,7 +362,9 @@ struct InterPredictionData int16_t refIdx [NUM_REF_PIC_LIST_01]; MergeType mergeType; #if JVET_K_AFFINE - Mv mvdAffi [NUM_REF_PIC_LIST_01][3]; + Mv mvdAffi [NUM_REF_PIC_LIST_01][4]; + + double perspParam[2]; #endif }; diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 9d131a1..c5c77bf 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -1426,6 +1426,7 @@ const int getAvailableAffineNeighbours( const PredictionUnit &pu, const Predicti const Position posLT = pu.Y().topLeft(); const Position posRT = pu.Y().topRight(); const Position posLB = pu.Y().bottomLeft(); + const Position posRB = pu.Y().bottomRight(); int num = 0; const PredictionUnit* puLeft = pu.cs->getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType ); @@ -1458,11 +1459,20 @@ const int getAvailableAffineNeighbours( const PredictionUnit &pu, const Predicti npu[num++] = puAboveLeft; } + const Slice &slice = *pu.cs->slice; + const Picture* const pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0), slice.getColRefIdx()); + + const PredictionUnit *puRightBottom = pColPic->cs->getPURestricted(posRB.offset(0, 0), *pColPic->cs->getPU(pu.chType), pu.chType); + if (puRightBottom && puRightBottom->cu->affine) + { + npu[num++] = puRightBottom; + } + return num; } #endif - -void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puNeighbour, RefPicList eRefPicList, Mv rcMv[3] ) +// in neighbor block, if exist affine coding block, that block's mv(4 control point) return +void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puNeighbour, RefPicList eRefPicList, Mv rcMv[4] ) { int posNeiX = puNeighbour->Y().pos().x; int posNeiY = puNeighbour->Y().pos().y; @@ -1476,22 +1486,29 @@ void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puN int curH = pu.Y().height; #endif - Mv mvLT, mvRT, mvLB; + Mv mvLT, mvRT, mvLB, mvRB; const Position posLT = puNeighbour->Y().topLeft(); const Position posRT = puNeighbour->Y().topRight(); const Position posLB = puNeighbour->Y().bottomLeft(); + const Position posRB = puNeighbour->Y().bottomRight(); mvLT = puNeighbour->getMotionInfo( posLT ).mv[eRefPicList]; mvRT = puNeighbour->getMotionInfo( posRT ).mv[eRefPicList]; mvLB = puNeighbour->getMotionInfo( posLB ).mv[eRefPicList]; + mvRB = puNeighbour->getMotionInfo( posRB ).mv[eRefPicList]; #if JVET_K_AFFINE_BUG_FIXES int shift = MAX_CU_DEPTH; - int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY; + int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY; //a, d, b, e + int iDMvHorBottom = 1; //g + int iDMvVerBottom = 1; //h + + //int perspParamX = (int)pu.perspParam[0]; + //int perspParamY = (int)pu.perspParam[1]; iDMvHorX = (mvRT - mvLT).getHor() << (shift - g_aucLog2[neiW]); iDMvHorY = (mvRT - mvLT).getVer() << (shift - g_aucLog2[neiW]); #if JVET_K0337_AFFINE_6PARA - if ( puNeighbour->cu->affineType == AFFINEMODEL_6PARAM ) + if ( puNeighbour->cu->affineType == AFFINEMODEL_6PARAM || puNeighbour->cu->affineType == AFFINEMODEL_8PARAM) { iDMvVerX = (mvLB - mvLT).getHor() << (shift - g_aucLog2[neiH]); iDMvVerY = (mvLB - mvLT).getVer() << (shift - g_aucLog2[neiH]); @@ -1503,6 +1520,48 @@ void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puN iDMvVerY = iDMvHorX; } + if (puNeighbour->cu->affineType == AFFINEMODEL_8PARAM) + { + // Full MV Model + if ((((mvRB - mvLB).getVer() * (mvRB - mvRT).getHor()) - ((mvRB - mvLB).getHor() * (mvRB - mvRT).getVer())) != 0) + { + iDMvHorBottom = ((((mvRB - mvLB).getHor() * (2 * mvLT.getVer() - mvRT.getVer())) + ((mvRB - mvLB).getVer() * (mvRT.getHor() - 2 * mvLT.getHor()))) + / (((mvRB - mvLB).getVer() * (mvRB - mvRT).getHor()) - ((mvRB - mvLB).getHor() * (mvRB - mvRT).getVer()))); + } + else + { + iDMvHorBottom = (0) << (shift - g_aucLog2[neiW]); + } + + if ((((mvRB - mvLT).getVer() * (mvRB - mvLB).getHor()) - ((mvRB - mvLT).getHor() * (mvRB - mvLB).getVer())) != 0) + { + iDMvVerBottom = ((((mvRB - mvLT).getHor() * (2 * mvLT.getVer() - mvRT.getVer())) + ((mvRB - mvLT).getVer() * (mvRT.getHor() - 2 * mvLT.getHor()))) + / (((mvRB - mvLT).getVer() * (mvRB - mvLB).getHor()) - ((mvRB - mvLT).getHor() * (mvRB - mvLB).getVer()))); + } + else + { + iDMvVerBottom = (0) << (shift - g_aucLog2[neiH]); + } + + iDMvHorX = (mvRT.getHor() * (iDMvHorBottom + 1) - mvLT.getHor()) << (shift - g_aucLog2[neiW]); + + iDMvVerX = (mvLB.getHor() * (iDMvVerBottom + 1) - mvLT.getHor()) << (shift - g_aucLog2[neiH]); + + iDMvHorY = (mvRT.getVer() * (iDMvHorBottom + 1) - mvLT.getVer()) << (shift - g_aucLog2[neiW]); + + iDMvVerY = (mvLB.getVer() * (iDMvVerBottom + 1) - mvLT.getVer()) << (shift - g_aucLog2[neiH]); + + // MV+Param Model + /* + iDMvHorX = (perspParamX * mvRT.getHor() - mvLT.getHor()) << (shift - g_aucLog2[neiW]); + iDMvVerX = (perspParamY * mvLB.getHor() - mvLT.getHor()) << (shift - g_aucLog2[neiW]); + iDMvHorY = (perspParamX * mvRT.getVer() - mvLT.getVer()) << (shift - g_aucLog2[neiH]); + iDMvVerY = (perspParamY * mvLB.getVer() - mvLT.getVer()) << (shift - g_aucLog2[neiH]); + iDMvHorBottom = (perspParamX - 1) << (shift - g_aucLog2[neiW]); + iDMvVerBottom = (perspParamY - 1) << (shift - g_aucLog2[neiH]); + */ + } + int iMvScaleHor = mvLT.getHor() << shift; int iMvScaleVer = mvLT.getVer() << shift; int horTmp, verTmp; @@ -1521,7 +1580,7 @@ void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puN // v2 #if JVET_K0337_AFFINE_6PARA - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM) { horTmp = iMvScaleHor + iDMvHorX * (posCurX - posNeiX) + iDMvVerX * (posCurY + curH - posNeiY); verTmp = iMvScaleVer + iDMvHorY * (posCurX - posNeiX) + iDMvVerY * (posCurY + curH - posNeiY); @@ -1529,6 +1588,29 @@ void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puN rcMv[2] = Mv( horTmp, verTmp, true ); } #endif + + // v3 +#if JVET_YJC_PERSP_8PARA + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + if ((iDMvHorBottom * (posCurX + curW - posNeiX) + iDMvVerBottom * (posCurY + curH - posNeiY)) != 0) + { + horTmp = (iMvScaleHor + iDMvHorX * (posCurX + curW - posNeiX) + iDMvVerX * (posCurY + curH - posNeiY)) / (iDMvHorBottom * (posCurX + curW - posNeiX) + iDMvVerBottom * (posCurY + curH - posNeiY)); + verTmp = (iMvScaleVer + iDMvHorY * (posCurX + curW - posNeiX) + iDMvVerY * (posCurY + curH - posNeiY)) / (iDMvHorBottom * (posCurX + curW - posNeiX) + iDMvVerBottom * (posCurY + curH - posNeiY)); + } + else + { + horTmp = (iMvScaleHor + iDMvHorX * (posCurX + curW - posNeiX) + iDMvVerX * (posCurY + curH - posNeiY)); + verTmp = (iMvScaleVer + iDMvHorY * (posCurX + curW - posNeiX) + iDMvVerY * (posCurY + curH - posNeiY)); + } + + //horTmp = (iMvScaleHor + iDMvHorX * (posCurX + curW - posNeiX) + iDMvVerX * (posCurY + curH - posNeiY)); + //verTmp = (iMvScaleVer + iDMvHorY * (posCurX + curW - posNeiX) + iDMvVerY * (posCurY + curH - posNeiY)); + + roundAffineMv(horTmp, verTmp, shift); + rcMv[3] = Mv(horTmp, verTmp, true); + } +#endif #else rcMv[0].hor = int( mvLT.hor + 1.0 * (mvRT.hor - mvLT.hor) * (posCurX - posNeiX) / neiW + 1.0 * (mvLB.hor - mvLT.hor) * (posCurY - posNeiY) / neiH ); rcMv[0].ver = int( mvLT.ver + 1.0 * (mvRT.ver - mvLT.ver) * (posCurX - posNeiX) / neiW + 1.0 * (mvLB.ver - mvLT.ver) * (posCurY - posNeiY) / neiH ); @@ -1587,7 +1669,7 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co const int curHeight = pu.Y().height; // insert inherited affine candidates - Mv outputAffineMv[3]; + Mv outputAffineMv[4]; const int maxNei = 5; const PredictionUnit* npu[maxNei]; int numAffNeigh = getAvailableAffineNeighbours( pu, npu ); @@ -1606,29 +1688,37 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co continue; } - xInheritedAffineMv( pu, puNeighbour, eTestRefPicList, outputAffineMv ); + xInheritedAffineMv( pu, puNeighbour, eTestRefPicList, outputAffineMv ); // in neighbor block, if exist affine coding block, that block's mv(4 control point) return outputAffineMv[0].roundMV2SignalPrecision(); outputAffineMv[1].roundMV2SignalPrecision(); #if JVET_K0337_AFFINE_6PARA - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM ) { outputAffineMv[2].roundMV2SignalPrecision(); } + if ( pu.cu->affineType == AFFINEMODEL_8PARAM ) + { + outputAffineMv[3].roundMV2SignalPrecision(); + } +#endif - if ( affiAMVPInfo.numCand == 0 - || (pu.cu->affineType == AFFINEMODEL_4PARAM && (outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0])) - || (pu.cu->affineType == AFFINEMODEL_6PARAM && (outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0] || outputAffineMv[2] != affiAMVPInfo.mvCandLB[0])) - ) +#if JVET_YJC_PERSP_8PARA + if (affiAMVPInfo.numCand == 0 + || (pu.cu->affineType == AFFINEMODEL_4PARAM && (outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0])) + || (pu.cu->affineType == AFFINEMODEL_6PARAM && (outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0] || outputAffineMv[2] != affiAMVPInfo.mvCandLB[0])) + || (pu.cu->affineType == AFFINEMODEL_8PARAM && (outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0] || outputAffineMv[2] != affiAMVPInfo.mvCandLB[0] || outputAffineMv[3] != affiAMVPInfo.mvCandRB[0])) + ) #else - if ( affiAMVPInfo.numCand == 0 || outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0] ) + if (affiAMVPInfo.numCand == 0 || outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0]) #endif - { - affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0]; - affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1]; - affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2]; - affiAMVPInfo.numCand++; - } + { + affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0]; + affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1]; + affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2]; + affiAMVPInfo.mvCandRB[affiAMVPInfo.numCand] = outputAffineMv[3]; + affiAMVPInfo.numCand++; + } } } @@ -1642,14 +1732,15 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co Position posLT = pu.Y().topLeft(); Position posRT = pu.Y().topRight(); Position posLB = pu.Y().bottomLeft(); + //Position posRB = pu.Y().bottomRight(); //------------------- V0 (START) -------------------// AMVPInfo amvpInfo0; amvpInfo0.numCand = 0; // A->C: Above Left, Above, Left - addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, amvpInfo0, true ); - if ( amvpInfo0.numCand < 1 ) + addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, amvpInfo0, true ); //°°Àº reference list ¸¦ ÂüÁ¶ÇÏ´Â ÀÌ¿ôºí·ÏÀÇ °æ¿ì¿¡¸¸ addµÊ + if ( amvpInfo0.numCand < 1 ) //°¢ control point À§Ä¡¸¶´Ù 1°³ÀÇ candidate¸¸ Ãß°¡µÊ { addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE, amvpInfo0, true ); } @@ -1686,14 +1777,17 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co outputAffineMv[0] = amvpInfo0.mvCand[0]; outputAffineMv[1] = amvpInfo1.mvCand[0]; outputAffineMv[2] = amvpInfo2.mvCand[0]; + outputAffineMv[3] = amvpInfo2.mvCand[0]; outputAffineMv[0].setHighPrec(); outputAffineMv[1].setHighPrec(); outputAffineMv[2].setHighPrec(); + outputAffineMv[3].setHighPrec(); outputAffineMv[0].roundMV2SignalPrecision(); outputAffineMv[1].roundMV2SignalPrecision(); outputAffineMv[2].roundMV2SignalPrecision(); + outputAffineMv[3].roundMV2SignalPrecision(); if ( cornerMVPattern == 7 || cornerMVPattern == 3 || cornerMVPattern == 5 ) { @@ -1709,7 +1803,7 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co } #endif - if ( cornerMVPattern == 5 ) // V0 V2 are available, derived V1 + if ( cornerMVPattern == 5 && pu.cu->affineType == AFFINEMODEL_6PARAM ) // V0 V2 are available, derived V1 { int shift = MAX_CU_DEPTH; int vx1 = (outputAffineMv[0].getHor() << shift) + ((outputAffineMv[2].getVer() - outputAffineMv[0].getVer()) << (shift + g_aucLog2[curWidth] - g_aucLog2[curHeight])); @@ -1719,10 +1813,55 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co outputAffineMv[1].roundMV2SignalPrecision(); } + if (cornerMVPattern == 3 && pu.cu->affineType == AFFINEMODEL_8PARAM) // V0 V1 are available, derived V2 V3 for 8-para + { + int shift = MAX_CU_DEPTH; + int vx2 = (outputAffineMv[0].getHor() << shift) - ((outputAffineMv[1].getVer() - outputAffineMv[0].getVer()) << (shift + g_aucLog2[curHeight] - g_aucLog2[curWidth])); + int vy2 = (outputAffineMv[0].getVer() << shift) + ((outputAffineMv[1].getHor() - outputAffineMv[0].getHor()) << (shift + g_aucLog2[curHeight] - g_aucLog2[curWidth])); + roundAffineMv(vx2, vy2, shift); + outputAffineMv[2].set(vx2, vy2); + outputAffineMv[2].roundMV2SignalPrecision(); + + int vx3 = ((outputAffineMv[2].getHor() + outputAffineMv[1].getHor() - outputAffineMv[0].getHor()) << (shift + g_aucLog2[curWidth] - g_aucLog2[curHeight])); + int vy3 = ((outputAffineMv[2].getVer() + outputAffineMv[1].getVer() - outputAffineMv[0].getVer()) << (shift + g_aucLog2[curHeight] - g_aucLog2[curWidth])); + roundAffineMv(vx3, vy3, shift); + outputAffineMv[3].set(vx3, vy3); + outputAffineMv[3].roundMV2SignalPrecision(); + } + + if (cornerMVPattern == 5 && pu.cu->affineType == AFFINEMODEL_8PARAM) // V0 V2 are available, derived V1 V3 + { + int shift = MAX_CU_DEPTH; + int vx1 = (outputAffineMv[0].getHor() << shift) + ((outputAffineMv[2].getVer() - outputAffineMv[0].getVer()) << (shift + g_aucLog2[curWidth] - g_aucLog2[curHeight])); + int vy1 = (outputAffineMv[0].getVer() << shift) - ((outputAffineMv[2].getHor() - outputAffineMv[0].getHor()) << (shift + g_aucLog2[curWidth] - g_aucLog2[curHeight])); + roundAffineMv(vx1, vy1, shift); + outputAffineMv[1].set(vx1, vy1); + outputAffineMv[1].roundMV2SignalPrecision(); + + int vx3 = ((outputAffineMv[2].getHor() + outputAffineMv[1].getHor() - outputAffineMv[0].getHor()) << (shift + g_aucLog2[curWidth] - g_aucLog2[curHeight])); + int vy3 = ((outputAffineMv[2].getVer() + outputAffineMv[1].getVer() - outputAffineMv[0].getVer()) << (shift + g_aucLog2[curHeight] - g_aucLog2[curWidth])); + roundAffineMv(vx3, vy3, shift); + outputAffineMv[3].set(vx3, vy3); + outputAffineMv[3].roundMV2SignalPrecision(); + } + + /* + if (cornerMVPattern == 7 && pu.cu->affineType == AFFINEMODEL_8PARAM) // V0 V1 V2 are available, derived V3 + { + int shift = MAX_CU_DEPTH; + int vx3 = ((outputAffineMv[2].getHor() + outputAffineMv[1].getHor() - outputAffineMv[0].getHor()) << (shift + g_aucLog2[curWidth] - g_aucLog2[curHeight])); + int vy3 = ((outputAffineMv[2].getVer() + outputAffineMv[1].getVer() - outputAffineMv[0].getVer()) << (shift + g_aucLog2[curHeight] - g_aucLog2[curWidth])); + roundAffineMv(vx3, vy3, shift); + outputAffineMv[3].set(vx3, vy3); + outputAffineMv[3].roundMV2SignalPrecision(); + } + */ + #if JVET_K0337_AFFINE_6PARA if ( affiAMVPInfo.numCand == 0 || (pu.cu->affineType == AFFINEMODEL_4PARAM && (outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0])) || (pu.cu->affineType == AFFINEMODEL_6PARAM && (outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0] || outputAffineMv[2] != affiAMVPInfo.mvCandLB[0])) + || (pu.cu->affineType == AFFINEMODEL_8PARAM && (outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0] || outputAffineMv[2] != affiAMVPInfo.mvCandLB[0] || outputAffineMv[3] != affiAMVPInfo.mvCandRB[0])) ) #else if ( affiAMVPInfo.numCand == 0 || outputAffineMv[0] != affiAMVPInfo.mvCandLT[0] || outputAffineMv[1] != affiAMVPInfo.mvCandRT[0] ) @@ -1731,6 +1870,7 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0]; affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1]; affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2]; + affiAMVPInfo.mvCandRB[affiAMVPInfo.numCand] = outputAffineMv[3]; affiAMVPInfo.numCand++; } } @@ -1897,6 +2037,7 @@ void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, co affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = amvpInfo.mvCand[i]; affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = amvpInfo.mvCand[i]; affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = amvpInfo.mvCand[i]; + affiAMVPInfo.mvCandRB[affiAMVPInfo.numCand] = amvpInfo.mvCand[i]; affiAMVPInfo.numCand++; } } @@ -2119,38 +2260,48 @@ bool PU::isBipredRestriction(const PredictionUnit &pu) #if JVET_K_AFFINE -const PredictionUnit* getFirstAvailableAffineNeighbour( const PredictionUnit &pu ) -{ - const Position posLT = pu.Y().topLeft(); - const Position posRT = pu.Y().topRight(); - const Position posLB = pu.Y().bottomLeft(); - - const PredictionUnit* puLeft = pu.cs->getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType ); - if( puLeft && puLeft->cu->affine ) - { - return puLeft; - } - const PredictionUnit* puAbove = pu.cs->getPURestricted( posRT.offset( 0, -1 ), pu, pu.chType ); - if( puAbove && puAbove->cu->affine ) - { - return puAbove; - } - const PredictionUnit* puAboveRight = pu.cs->getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType ); - if( puAboveRight && puAboveRight->cu->affine ) - { - return puAboveRight; - } - const PredictionUnit *puLeftBottom = pu.cs->getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); - if( puLeftBottom && puLeftBottom->cu->affine ) - { - return puLeftBottom; - } - const PredictionUnit *puAboveLeft = pu.cs->getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType ); - if( puAboveLeft && puAboveLeft->cu->affine ) - { - return puAboveLeft; - } - return nullptr; +const PredictionUnit* getFirstAvailableAffineNeighbour(const PredictionUnit &pu) +{ + const Position posLT = pu.Y().topLeft(); + const Position posRT = pu.Y().topRight(); + const Position posLB = pu.Y().bottomLeft(); + const Position posRB = pu.Y().bottomRight(); + + const PredictionUnit* puLeft = pu.cs->getPURestricted(posLB.offset(-1, 0), pu, pu.chType); + if (puLeft && puLeft->cu->affine) + { + return puLeft; + } + const PredictionUnit* puAbove = pu.cs->getPURestricted(posRT.offset(0, -1), pu, pu.chType); + if (puAbove && puAbove->cu->affine) + { + return puAbove; + } + const PredictionUnit* puAboveRight = pu.cs->getPURestricted(posRT.offset(1, -1), pu, pu.chType); + if (puAboveRight && puAboveRight->cu->affine) + { + return puAboveRight; + } + const PredictionUnit *puLeftBottom = pu.cs->getPURestricted(posLB.offset(-1, 1), pu, pu.chType); + if (puLeftBottom && puLeftBottom->cu->affine) + { + return puLeftBottom; + } + const PredictionUnit *puAboveLeft = pu.cs->getPURestricted(posLT.offset(-1, -1), pu, pu.chType); + if (puAboveLeft && puAboveLeft->cu->affine) + { + return puAboveLeft; + } + + const Slice &slice = *pu.cs->slice; + const Picture* const pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0), slice.getColRefIdx()); + const PredictionUnit *puRightBottom = pColPic->cs->getPURestricted(posRB.offset(0, 0), *pColPic->cs->getPU(pu.chType), pu.chType); + if (puRightBottom && puRightBottom->cu->affine) + { + return puRightBottom; + } + + return nullptr; } bool PU::isAffineMrgFlagCoded( const PredictionUnit &pu ) @@ -2166,9 +2317,9 @@ bool PU::isAffineMrgFlagCoded( const PredictionUnit &pu ) return getFirstAvailableAffineNeighbour( pu ) != nullptr; } -void PU::getAffineMergeCand( const PredictionUnit &pu, MvField (*mvFieldNeighbours)[3], unsigned char &interDirNeighbours, int &numValidMergeCand ) +void PU::getAffineMergeCand( const PredictionUnit &pu, MvField (*mvFieldNeighbours)[4], unsigned char &interDirNeighbours, int &numValidMergeCand ) { - for ( int mvNum = 0; mvNum < 3; mvNum++ ) + for ( int mvNum = 0; mvNum < 4; mvNum++ ) { mvFieldNeighbours[0][mvNum].setMvField( Mv(), -1 ); mvFieldNeighbours[1][mvNum].setMvField( Mv(), -1 ); @@ -2193,11 +2344,11 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, MvField (*mvFieldNeighbou #endif // derive Mv from neighbor affine block - Mv cMv[3]; + Mv cMv[4]; if ( interDirNeighbours != 2 ) { xInheritedAffineMv( pu, puFirstNeighbour, REF_PIC_LIST_0, cMv ); - for ( int mvNum = 0; mvNum < 3; mvNum++ ) + for ( int mvNum = 0; mvNum < 4; mvNum++ ) { mvFieldNeighbours[0][mvNum].setMvField( cMv[mvNum], puFirstNeighbour->refIdx[0] ); } @@ -2208,7 +2359,7 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, MvField (*mvFieldNeighbou if ( interDirNeighbours != 1 ) { xInheritedAffineMv( pu, puFirstNeighbour, REF_PIC_LIST_1, cMv ); - for ( int mvNum = 0; mvNum < 3; mvNum++ ) + for ( int mvNum = 0; mvNum < 4; mvNum++ ) { mvFieldNeighbours[1][mvNum].setMvField( cMv[mvNum], puFirstNeighbour->refIdx[1] ); } @@ -2219,19 +2370,19 @@ void PU::getAffineMergeCand( const PredictionUnit &pu, MvField (*mvFieldNeighbou void PU::setAllAffineMvField( PredictionUnit &pu, MvField *mvField, RefPicList eRefList ) { // Set Mv - Mv mv[3]; - for ( int i = 0; i < 3; i++ ) + Mv mv[4]; + for ( int i = 0; i < 4; i++ ) { mv[i] = mvField[i].mv; } - setAllAffineMv( pu, mv[0], mv[1], mv[2], eRefList ); + setAllAffineMv( pu, mv[0], mv[1], mv[2], mv[3], eRefList ); // Set RefIdx CHECK( mvField[0].refIdx != mvField[1].refIdx || mvField[0].refIdx != mvField[2].refIdx, "Affine mv corners don't have the same refIdx." ); pu.refIdx[eRefList] = mvField[0].refIdx; } -void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList ) +void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, Mv affRB, RefPicList eRefList ) { int width = pu.Y().width; int shift = MAX_CU_DEPTH; @@ -2239,12 +2390,20 @@ void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPi affLT.setHighPrec(); affRT.setHighPrec(); affLB.setHighPrec(); + affRB.setHighPrec(); + int deltaMvHorX, deltaMvHorY, deltaMvVerX, deltaMvVerY; + int iDMvHorBottom = 1; //g + int iDMvVerBottom = 1; //h + + //int perspParamX = (int)pu.perspParam[0]; + //int perspParamY = (int)pu.perspParam[1]; + deltaMvHorX = (affRT - affLT).getHor() << (shift - g_aucLog2[width]); deltaMvHorY = (affRT - affLT).getVer() << (shift - g_aucLog2[width]); #if JVET_K0337_AFFINE_6PARA int height = pu.Y().height; - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM) { deltaMvVerX = (affLB - affLT).getHor() << (shift - g_aucLog2[height]); deltaMvVerY = (affLB - affLT).getVer() << (shift - g_aucLog2[height]); @@ -2254,6 +2413,47 @@ void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPi deltaMvVerX = -deltaMvHorY; deltaMvVerY = deltaMvHorX; } + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + // Full MV Model + if ((((affRB - affLB).getVer() * (affRB - affRT).getHor()) - ((affRB - affLB).getHor() * (affRB - affRT).getVer())) != 0) + { + iDMvHorBottom = ((((affRB - affLB).getHor() * (2 * affLT.getVer() - affRT.getVer())) + ((affRB - affLB).getVer() * (affRT.getHor() - 2 * affLT.getHor()))) + / (((affRB - affLB).getVer() * (affRB - affRT).getHor()) - ((affRB - affLB).getHor() * (affRB - affRT).getVer()))); + } + else + { + iDMvHorBottom = (0) << (shift - g_aucLog2[width]); + } + + if ((((affRB - affLT).getVer() * (affRB - affLB).getHor()) - ((affRB - affLT).getHor() * (affRB - affLB).getVer())) != 0) + { + iDMvVerBottom = ((((affRB - affLT).getHor() * (2 * affLT.getVer() - affRT.getVer())) + ((affRB - affLT).getVer() * (affRT.getHor() - 2 * affLT.getHor()))) + / (((affRB - affLT).getVer() * (affRB - affLB).getHor()) - ((affRB - affLT).getHor() * (affRB - affLB).getVer()))); + } + else + { + iDMvVerBottom = (0) << (shift - g_aucLog2[height]); + } + + deltaMvHorX = (affRT.getHor() * (iDMvHorBottom + 1) - affLT.getHor()) << (shift - g_aucLog2[width]); + + deltaMvVerX = (affLB.getHor() * (iDMvVerBottom + 1) - affLT.getHor()) << (shift - g_aucLog2[height]); + + deltaMvHorY = (affRT.getVer() * (iDMvHorBottom + 1) - affLT.getVer()) << (shift - g_aucLog2[width]); + + deltaMvVerX = (affLB.getVer() * (iDMvVerBottom + 1) - affLT.getVer()) << (shift - g_aucLog2[height]); + + // MV+Param Model + /* + deltaMvHorX = (perspParamX * affRT.getHor() - affLT.getHor()) << (shift - g_aucLog2[width]); + deltaMvVerX = (perspParamY * affLB.getHor() - affLT.getHor()) << (shift - g_aucLog2[width]); + deltaMvHorY = (perspParamX * affRT.getVer() - affLT.getVer()) << (shift - g_aucLog2[height]); + deltaMvVerY = (perspParamY * affLB.getVer() - affLT.getVer()) << (shift - g_aucLog2[height]); + iDMvHorBottom = (perspParamX - 1) << (shift - g_aucLog2[width]); + iDMvVerBottom = (perspParamY - 1) << (shift - g_aucLog2[height]); + */ + } #else deltaMvVerX = -deltaMvHorY; deltaMvVerY = deltaMvHorX; @@ -2275,6 +2475,20 @@ void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPi { mvScaleTmpHor = mvScaleHor + deltaMvHorX * (halfBW + w) + deltaMvVerX * (halfBH + h); mvScaleTmpVer = mvScaleVer + deltaMvHorY * (halfBW + w) + deltaMvVerY * (halfBH + h); + + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + if ((iDMvHorBottom * (halfBW + w) + iDMvVerBottom * (halfBH + h)) != 0) + { + mvScaleTmpHor = (mvScaleHor + deltaMvHorX * (halfBW + w) + deltaMvVerX * (halfBH + h)) / (iDMvHorBottom * (halfBW + w) + iDMvVerBottom * (halfBH + h)); + mvScaleTmpVer = (mvScaleVer + deltaMvHorY * (halfBW + w) + deltaMvVerY * (halfBH + h)) / (iDMvHorBottom * (halfBW + w) + iDMvVerBottom * (halfBH + h)); + } + else + { + mvScaleTmpHor = (mvScaleHor + deltaMvHorX * (halfBW + w) + deltaMvVerX * (halfBH + h)); + mvScaleTmpVer = (mvScaleVer + deltaMvHorY * (halfBW + w) + deltaMvVerY * (halfBH + h)); + } + } #if JVET_K_AFFINE_BUG_FIXES roundAffineMv( mvScaleTmpHor, mvScaleTmpVer, shift ); #else @@ -2304,11 +2518,17 @@ void PU::setAllAffineMv( PredictionUnit& pu, Mv affLT, Mv affRT, Mv affLB, RefPi #endif #if JVET_K0337_AFFINE_6PARA - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM ) { mb.at( 0, mb.height - 1 ).mv[eRefList] = affLB; } #endif +#if JVET_YJC_PERSP_8PARA + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + mb.at( mb.width - 1, mb.height - 1 ).mv[eRefList] = affRB; + } +#endif } #endif diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index f7640e1..6764336 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -114,7 +114,7 @@ namespace PU void fillAffineMvpCand ( PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AffineAMVPInfo &affiAMVPInfo); bool addMVPCandUnscaled (const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo, bool affine = false); bool addMVPCandWithScaling (const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo, bool affine = false); - void xInheritedAffineMv ( const PredictionUnit &pu, const PredictionUnit* puNeighbour, RefPicList eRefPicList, Mv rcMv[3] ); + void xInheritedAffineMv ( const PredictionUnit &pu, const PredictionUnit* puNeighbour, RefPicList eRefPicList, Mv rcMv[4] ); #else void fillMvpCand ( PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo); bool addMVPCandUnscaled (const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &amvpInfo); @@ -128,9 +128,9 @@ namespace PU #endif #if JVET_K_AFFINE bool isAffineMrgFlagCoded (const PredictionUnit &pu ); - void getAffineMergeCand (const PredictionUnit &pu, MvField (*mvFieldNeighbours)[3], unsigned char &interDirNeighbours, int &numValidMergeCand ); + void getAffineMergeCand (const PredictionUnit &pu, MvField (*mvFieldNeighbours)[4], unsigned char &interDirNeighbours, int &numValidMergeCand ); void setAllAffineMvField ( PredictionUnit &pu, MvField *mvField, RefPicList eRefList ); - void setAllAffineMv ( PredictionUnit &pu, Mv affLT, Mv affRT, Mv affLB, RefPicList eRefList ); + void setAllAffineMv ( PredictionUnit &pu, Mv affLT, Mv affRT, Mv affLB, Mv affRB, RefPicList eRefList ); #endif #if JVET_K0346 bool getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx &mrgCtx, bool& LICFlag, const int count); diff --git a/source/Lib/CommonLib/x86/AffineGradientSearchX86.h b/source/Lib/CommonLib/x86/AffineGradientSearchX86.h index 0ee2b3d..9ceee41 100644 --- a/source/Lib/CommonLib/x86/AffineGradientSearchX86.h +++ b/source/Lib/CommonLib/x86/AffineGradientSearchX86.h @@ -196,14 +196,14 @@ static void simdVerticalSobelFilter( Pel *const pPred, const int predStride, int } template -static void simdEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDerivate, int derivateBufStride, int64_t( *pEqualCoeff )[7], int width, int height, bool b6Param ) +static void simdEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDerivate, int derivateBufStride, int64_t( *pEqualCoeff )[9], int width, int height, int i468Param ) { __m128i mmTwo, mmFour; __m128i mmTmp[4]; __m128i mmIntermediate[4]; __m128i mmIndxK, mmIndxJ[2]; __m128i mmResidue[2]; - __m128i mmC[12]; + __m128i mmC[16]; // Add directly to indexes to get new index mmTwo = _mm_set1_epi32( 2 ); @@ -211,7 +211,19 @@ static void simdEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDe mmIndxJ[0] = _mm_set1_epi32( -2 ); mmIndxJ[1] = _mm_set1_epi32( -1 ); - int n = b6Param ? 6 : 4; + int n = 0; + if (i468Param == 0) + { + n = 4; + } + else if (i468Param == 1) + { + n = 6; + } + else if (i468Param == 2) + { + n = 8; + } int idx1 = 0, idx2 = 0; idx1 = -2 * derivateBufStride - 4; idx2 = -derivateBufStride - 4; @@ -230,7 +242,7 @@ static void simdEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDe idx2 += 4; mmIndxK = _mm_add_epi32( mmIndxK, mmFour ); - if ( b6Param ) + if ( i468Param == 1 ) { // mmC[0-5] for iC[0-5] of 1st row of pixels mmC[0] = _mm_loadu_si128( (const __m128i*)&ppDerivate[0][idx1] ); @@ -248,6 +260,32 @@ static void simdEqualCoeffComputer( Pel *pResidue, int residueStride, int **ppDe mmC[10] = _mm_mullo_epi32( mmIndxJ[1], mmC[6] ); mmC[11] = _mm_mullo_epi32( mmIndxJ[1], mmC[8] ); } + else if (i468Param == 2) + { + // mmC[0-7] for iC[0-7] of 1st row of pixels + mmC[0] = _mm_loadu_si128((const __m128i*)&ppDerivate[0][idx1]); + mmC[2] = _mm_loadu_si128((const __m128i*)&ppDerivate[1][idx1]); + mmC[1] = _mm_mullo_epi32(mmIndxK, mmC[0]); + mmC[3] = _mm_mullo_epi32(mmIndxK, mmC[2]); + mmC[4] = _mm_mullo_epi32(mmIndxJ[0], mmC[0]); + mmC[5] = _mm_mullo_epi32(mmIndxJ[0], mmC[2]); + mmC[6] = _mm_mullo_epi32(mmIndxK, mmC[0]); + mmC[6] = _mm_mullo_epi32(mmIndxJ[0], mmC[6]); + mmC[7] = _mm_mullo_epi32(mmIndxJ[0], mmC[2]); + mmC[7] = _mm_mullo_epi32(mmIndxK, mmC[7]); + + // mmC[8-15] for iC[0-7] of 2nd row of pixels + mmC[8] = _mm_loadu_si128((const __m128i*)&ppDerivate[0][idx2]); + mmC[10] = _mm_loadu_si128((const __m128i*)&ppDerivate[1][idx2]); + mmC[9] = _mm_mullo_epi32(mmIndxK, mmC[6]); + mmC[11] = _mm_mullo_epi32(mmIndxK, mmC[8]); + mmC[12] = _mm_mullo_epi32(mmIndxJ[1], mmC[6]); + mmC[13] = _mm_mullo_epi32(mmIndxJ[1], mmC[8]); + mmC[14] = _mm_mullo_epi32(mmIndxK, mmC[6]); + mmC[14] = _mm_mullo_epi32(mmIndxJ[1], mmC[14]); + mmC[15] = _mm_mullo_epi32(mmIndxJ[1], mmC[8]); + mmC[15] = _mm_mullo_epi32(mmIndxK, mmC[15]); + } else { // mmC[0-3] for iC[0-3] of 1st row of pixels diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index 16908fa..6d28fd7 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -1169,10 +1169,16 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][0] ); mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][1] ); #if JVET_K0337_AFFINE_6PARA - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM) { mvd_coding( pu.mvdAffi[REF_PIC_LIST_0][2] ); } +#endif +#if JVET_YJC_PERSP_8PARA + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][3]); + } #endif } else @@ -1193,6 +1199,7 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) pu.mvdAffi[REF_PIC_LIST_1][0] = Mv(); pu.mvdAffi[REF_PIC_LIST_1][1] = Mv(); pu.mvdAffi[REF_PIC_LIST_1][2] = Mv(); + pu.mvdAffi[REF_PIC_LIST_1][3] = Mv(); #endif } #if JVET_K_AFFINE @@ -1201,10 +1208,16 @@ void CABACReader::prediction_unit( PredictionUnit& pu, MergeCtx& mrgCtx ) mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][0] ); mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][1] ); #if JVET_K0337_AFFINE_6PARA - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM) { mvd_coding( pu.mvdAffi[REF_PIC_LIST_1][2] ); } +#endif +#if JVET_YJC_PERSP_8PARA + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][3]); + } #endif } #endif @@ -1257,7 +1270,7 @@ void CABACReader::affine_flag( CodingUnit& cu ) { ctxId = 0; cu.affineType = m_BinDecoder.decodeBin( Ctx::AffineType( ctxId ) ); - DTRACE( g_trace_ctx, D_SYNTAX, "affine_type() affine_type=%d ctx=%d pos=(%d,%d)\n", cu.affineType ? 1 : 0, ctxId, cu.Y().x, cu.Y().y ); + DTRACE( g_trace_ctx, D_SYNTAX, "affine_type() affine_type=%d ctx=%d pos=(%d,%d)\n", cu.affineType, ctxId, cu.Y().x, cu.Y().y ); } else { diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 370f41f..73cb0a5 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -409,7 +409,7 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) if( pu.cu->affine ) { pu.mergeIdx = 0; - MvField affineMvField[2][3]; + MvField affineMvField[2][4]; unsigned char interDirNeighbours; int numValidMergeCand; PU::getAffineMergeCand( pu, affineMvField, interDirNeighbours, numValidMergeCand ); @@ -514,8 +514,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) #if JVET_K_AFFINE_BUG_FIXES Mv mvLB; + Mv mvRB; #if JVET_K0337_AFFINE_6PARA - if ( cu.affineType == AFFINEMODEL_6PARAM ) + if ( cu.affineType == AFFINEMODEL_6PARAM || cu.affineType == AFFINEMODEL_8PARAM ) { mvLB = affineAMVPInfo.mvCandLB[mvp_idx] + pu.mvdAffi[eRefList][2]; #if JVET_K0337_AFFINE_MVD_PREDICTION @@ -524,6 +525,16 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) CHECK( !mvLB.highPrec, "unexpected lp mv" ); } #endif +#if JVET_YJC_PERSP_8PARA + if (cu.affineType == AFFINEMODEL_8PARAM) + { + mvRB = affineAMVPInfo.mvCandRB[mvp_idx] + pu.mvdAffi[eRefList][3]; +#if JVET_K0337_AFFINE_MVD_PREDICTION + mvRB += pu.mvdAffi[eRefList][0]; +#endif + CHECK(!mvRB.highPrec, "unexpected lp mv"); + } +#endif #else int iWidth = pu.Y().width; int iHeight = pu.Y().height; @@ -536,7 +547,7 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) clipMv(mvRT, pu.cu->lumaPos(), *pu.cs->sps); clipMv(mvLB, pu.cu->lumaPos(), *pu.cs->sps); #endif - PU::setAllAffineMv( pu, mvLT, mvRT, mvLB, eRefList ); + PU::setAllAffineMv( pu, mvLT, mvRT, mvLB, mvRB, eRefList ); } } } diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index b681d5b..25a9d7e 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -823,7 +823,7 @@ void HLSyntaxReader::parseSPSNext( SPSNext& spsNext, const bool usePCM ) #if JVET_K0337_AFFINE_6PARA if ( spsNext.getUseAffine() ) { - READ_FLAG( symbol, "affine_type_flag" ); spsNext.setUseAffineType ( symbol != 0 ); + READ_UVLC( symbol, "affine_type_flag" ); spsNext.setUseAffineType ( symbol ); } #endif #endif diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index d98bd51..54d110d 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -1177,7 +1177,7 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][1]); #endif #if JVET_K0337_AFFINE_6PARA - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM ) { #if JVET_K0357_AMVR mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][2], 0); @@ -1185,6 +1185,16 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][2]); #endif } +#endif +#if JVET_YJC_PERSP_8PARA + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { +#if JVET_K0357_AMVR + mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][3], 0); +#else + mvd_coding(pu.mvdAffi[REF_PIC_LIST_0][3]); +#endif + } #endif } else @@ -1214,7 +1224,7 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][1]); #endif #if JVET_K0337_AFFINE_6PARA - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM ) { #if JVET_K0357_AMVR mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][2], 0); @@ -1222,6 +1232,16 @@ void CABACWriter::prediction_unit( const PredictionUnit& pu ) mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][2]); #endif } +#endif +#if JVET_YJC_PERSP_8PARA + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { +#if JVET_K0357_AMVR + mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][3], 0); +#else + mvd_coding(pu.mvdAffi[REF_PIC_LIST_1][2]); +#endif + } #endif } else @@ -1271,8 +1291,8 @@ void CABACWriter::affine_flag( const CodingUnit& cu ) unsigned ctxId = 0; m_BinEncoder.encodeBin( cu.affineType, Ctx::AffineType( ctxId ) ); - DTRACE( g_trace_ctx, D_COMMON, " (%d) affine_type() affine_type=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_COMMON ), cu.affineType ? 1 : 0 ); - DTRACE( g_trace_ctx, D_SYNTAX, "affine_type() affine_type=%d ctx=%d pos=(%d,%d)\n", cu.affineType ? 1 : 0, ctxId, cu.Y().x, cu.Y().y ); + DTRACE( g_trace_ctx, D_COMMON, " (%d) affine_type() affine_type=%d\n", DTRACE_GET_COUNTER( g_trace_ctx, D_COMMON ), cu.affineType ); + DTRACE( g_trace_ctx, D_SYNTAX, "affine_type() affine_type=%d ctx=%d pos=(%d,%d)\n", cu.affineType, ctxId, cu.Y().x, cu.Y().y ); } #endif } diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 015b7cc..5c23cbf 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -201,7 +201,7 @@ class EncCfg #if JVET_K_AFFINE bool m_Affine; #if JVET_K0337_AFFINE_6PARA - bool m_AffineType; + int m_AffineType; #endif #endif #if JVET_K0346 || JVET_K_AFFINE @@ -635,8 +635,8 @@ class EncCfg void setAffine ( bool b ) { m_Affine = b; } bool getAffine () const { return m_Affine; } #if JVET_K0337_AFFINE_6PARA - void setAffineType( bool b ) { m_AffineType = b; } - bool getAffineType() const { return m_AffineType; } + void setAffineType( int b ) { m_AffineType = b; } + int getAffineType() const { return m_AffineType; } #endif #endif #if JVET_K0346 || JVET_K_AFFINE diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index dadf0bf..5783d2d 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -317,6 +317,46 @@ void EncCu::compressCtu( CodingStructure& cs, const UnitArea& area, const unsign xCompressCU( tempCS, bestCS, *partitioner ); + //print affine type + if (isLuma(partitioner->chType) && !cs.slice->isIntra()) + { + for (int i = 0; i < bestCS->cus.size(); i++) + { + /* + Mv mvLT, mvRT, mvLB, mvRB; + + const Position posLT = bestCS->cus[i]->cs->getPU(partitioner->chType)->Y().topLeft(); + const Position posRT = bestCS->cus[i]->cs->getPU(partitioner->chType)->Y().topRight(); + const Position posLB = bestCS->cus[i]->cs->getPU(partitioner->chType)->Y().bottomLeft(); + const Position posRB = bestCS->cus[i]->cs->getPU(partitioner->chType)->Y().bottomRight(); + + mvLT = bestCS->cus[i]->cs->getPU(partitioner->chType)->getMotionInfo(posLT).mv[0]; + mvRT = bestCS->cus[i]->cs->getPU(partitioner->chType)->getMotionInfo(posRT).mv[0]; + mvLB = bestCS->cus[i]->cs->getPU(partitioner->chType)->getMotionInfo(posLB).mv[0]; + mvRB = bestCS->cus[i]->cs->getPU(partitioner->chType)->getMotionInfo(posRB).mv[0]; + + if (bestCS->cus[i]->affine == true && bestCS->cus[i]->affineType == AFFINEMODEL_6PARAM) { + printf("%d\t%d\t%d\t%d\t%d\t:\t(%d,%d)\t(%d,%d)\t(%d,%d)\n", bestCS->cus[i]->slice->getPOC(), bestCS->cus[i]->lx(), bestCS->cus[i]->ly(), bestCS->cus[i]->lwidth(), bestCS->cus[i]->lheight(), + mvLT.getHor(), mvLT.getVer(), mvRT.getHor(), mvRT.getVer(), mvLB.getHor(), mvLB.getVer()); + } + */ + + if (bestCS->cus[i]->affine == true && bestCS->cus[i]->affineType == AFFINEMODEL_8PARAM) + { + //printf("%d\t%d\t%d\t%d\t%d\n", bestCS->cus[i]->slice->getPOC(), bestCS->cus[i]->lx(), bestCS->cus[i]->ly(), bestCS->cus[i]->lwidth(), bestCS->cus[i]->lheight()); + } + + if (bestCS->cus[i]->affine == true) + { + printf("%d\t%d\t%d\t%d\t%d\n", bestCS->cus[i]->lx(), bestCS->cus[i]->ly(), bestCS->cus[i]->lwidth(), bestCS->cus[i]->lheight(), bestCS->cus[i]->affineType); + } + if (bestCS->cus[i]->affine == false) + { + //printf("%d\t%d\t%d\t%d\t%d\n", bestCS->cus[i]->lx(), bestCS->cus[i]->ly(), bestCS->cus[i]->lwidth(), bestCS->cus[i]->lheight(), 3); + } + + } + } // all signals were already copied during compression if the CTU was split - at this point only the structures are copied to the top level CS const bool copyUnsplitCTUSignals = bestCS->cus.size() == 1 && KEEP_PRED_AND_RESI_SIGNALS; @@ -608,7 +648,12 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par else #endif { - xCheckRDCostInter( tempCS, bestCS, partitioner, currTestMode ); + bool isPerspf = false; + xCheckRDCostInter(tempCS, bestCS, partitioner, currTestMode, isPerspf); + + // 8 parameter perspective ¸¦ À§ÇÑ ¼öÇà ºÎºÐ + bool isPerspt = true; + xCheckRDCostInter(tempCS, bestCS, partitioner, currTestMode, isPerspt); } } @@ -682,6 +727,23 @@ void EncCu::xCompressCU( CodingStructure *&tempCS, CodingStructure *&bestCS, Par CHECK( bestCS->cus[0]->partSize == NUMBER_OF_PART_SIZES , "No possible encoding found" ); CHECK( bestCS->cus[0]->predMode == NUMBER_OF_PREDICTION_MODES, "No possible encoding found" ); CHECK( bestCS->cost == MAX_DOUBLE , "No possible encoding found" ); + /* + if (bestCS->getCU(partitioner.chType)->affine == true && partitioner.chType == CHANNEL_TYPE_LUMA) + { + if (bestCS->getCU(partitioner.chType)->affineType == AFFINEMODEL_4PARAM) + { + printf("%d\t%d\t%d\t%d\t%d\t%d\n", 1, 4, bestCS->area.lx(), bestCS->area.ly(), bestCS->area.lwidth(), bestCS->area.lheight()); + } + else if (bestCS->getCU(partitioner.chType)->affineType == AFFINEMODEL_6PARAM) + { + printf("%d\t%d\t%d\t%d\t%d\t%d\n", 1, 6, bestCS->area.lx(), bestCS->area.ly(), bestCS->area.lwidth(), bestCS->area.lheight()); + } + else if (bestCS->getCU(partitioner.chType)->affineType == AFFINEMODEL_8PARAM) + { + printf("%d\t%d\t%d\t%d\t%d\t%d\n", 1, 8, bestCS->area.lx(), bestCS->area.ly(), bestCS->area.lwidth(), bestCS->area.lheight()); + } + } + */ } #if SHARP_LUMA_DELTA_QP @@ -1717,7 +1779,7 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct return; } - MvField affineMvField[2][3]; + MvField affineMvField[2][4]; unsigned char interDirNeighbours; int numValidMergeCand; bool hasNoResidual = false; @@ -1778,12 +1840,29 @@ void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStruct } #endif -void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ) +void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, bool& isPersp ) { tempCS->initStructData( encTestMode.qp, encTestMode.lossless ); CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType ); + CodingUnit &Bestcu = *bestCS->getCU(partitioner.chType); + auto &Bestpu = *Bestcu.firstPU; + + Mv bestCSMv[2][4]; + int bestCSRefIdx[2] = { -1, -1 }; + const CMotionBuf &Bestmb = Bestpu.getMotionBuf(); + + for (int refList = 0; refList < 2; refList++) + { + bestCSMv[refList][0] = Bestmb.at(0, 0).mv[refList]; + bestCSMv[refList][1] = Bestmb.at(Bestmb.width - 1, 0).mv[refList]; + bestCSMv[refList][2] = Bestmb.at(0, Bestmb.height - 1).mv[refList]; + bestCSMv[refList][3] = Bestmb.at(Bestmb.width - 1, Bestmb.height - 1).mv[refList]; + } + bestCSRefIdx[0] = Bestpu.refIdx[0]; + bestCSRefIdx[1] = Bestpu.refIdx[1]; + partitioner.setCUData( cu ); cu.slice = tempCS->slice; #if HEVC_TILES_WPP @@ -1792,13 +1871,27 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC cu.skip = false; cu.partSize = encTestMode.partSize; //cu.affine +// for perspective + if (isPersp == true) + { + cu.affine = true; + cu.affineType = AFFINEMODEL_8PARAM; + } cu.predMode = MODE_INTER; cu.transQuantBypass = encTestMode.lossless; cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1; cu.qp = encTestMode.qp; CU::addPUs( cu ); - m_pcInterSearch->predInterSearch( cu, partitioner ); + // 8 Parameter perspective¸¦ À§ÇÑ ¼öÇà ºÎºÐ + if (cu.affine == true && cu.affineType == AFFINEMODEL_8PARAM) + { + m_pcInterSearch->predInterSearchPersp(cu, partitioner, bestCSMv, bestCSRefIdx); + } + else + { + m_pcInterSearch->predInterSearch(cu, partitioner); + } #if JVET_K0357_AMVR const unsigned wIdx = gp_sizeIdxInfo->idxFrom( tempCS->area.lwidth () ); diff --git a/source/Lib/EncoderLib/EncCu.h b/source/Lib/EncoderLib/EncCu.h index 560973c..ae17ec7 100644 --- a/source/Lib/EncoderLib/EncCu.h +++ b/source/Lib/EncoderLib/EncCu.h @@ -193,7 +193,7 @@ class EncCu void xCheckRDCostAffineMerge2Nx2N ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode ); #endif - void xCheckRDCostInter ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); + void xCheckRDCostInter ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode, bool& isPersp ); #if JVET_K0357_AMVR bool xCheckRDCostInterIMV ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode ); #endif diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 1b790b6..06b3d86 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -960,8 +960,9 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) } } } - + #if JVET_K0220_ENC_CTRL + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() #if JVET_K0357_AMVR && cu.imv == 0 @@ -977,6 +978,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) { ::memcpy( cMvHevcTemp, cMvTemp, sizeof( cMvTemp ) ); } + #if JVET_K_AFFINE #if JVET_K0220_ENC_CTRL if ( cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() ) @@ -1304,7 +1306,7 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) // do affine ME & Merge #if JVET_K0185_AFFINE_6PARA_ENC cu.affineType = AFFINEMODEL_4PARAM; - Mv acMvAffine4Para[2][33][3]; + Mv acMvAffine4Para[2][33][4]; int refIdx4Para[2] = { -1, -1 }; #if JVET_K0220_ENC_CTRL @@ -1312,75 +1314,75 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) #else xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, bFastSkipBi, acMvAffine4Para, refIdx4Para ); #endif - if ( cu.slice->getSPS()->getSpsNext().getUseAffineType() ) - { - if ( uiAffineCost < uiHevcCost * 1.05 ) ///< condition for 6 parameter affine ME - { - // save 4 parameter results - Mv bestMv[2][3], bestMvd[2][3]; - int bestMvpIdx[2], bestMvpNum[2], bestRefIdx[2]; - uint8_t bestInterDir; - - bestInterDir = pu.interDir; - bestRefIdx[0] = pu.refIdx[0]; - bestRefIdx[1] = pu.refIdx[1]; - bestMvpIdx[0] = pu.mvpIdx[0]; - bestMvpIdx[1] = pu.mvpIdx[1]; - bestMvpNum[0] = pu.mvpNum[0]; - bestMvpNum[1] = pu.mvpNum[1]; - - const CMotionBuf &mb = pu.getMotionBuf(); - for ( int refList = 0; refList < 2; refList++ ) - { - bestMv[refList][0] = mb.at( 0, 0 ).mv[refList]; - bestMv[refList][1] = mb.at( mb.width - 1, 0 ).mv[refList]; - bestMv[refList][2] = mb.at( 0, mb.height - 1 ).mv[refList]; - - bestMvd[refList][0] = pu.mvdAffi[refList][0]; - bestMvd[refList][1] = pu.mvdAffi[refList][1]; - bestMvd[refList][2] = pu.mvdAffi[refList][2]; - } - - refIdx4Para[0] = bestRefIdx[0]; - refIdx4Para[1] = bestRefIdx[1]; - - Distortion uiAffine6Cost = std::numeric_limits::max(); - cu.affineType = AFFINEMODEL_6PARAM; + if (cu.slice->getSPS()->getSpsNext().getUseAffineType()) + { + if (uiAffineCost < uiHevcCost * 1.05) ///< condition for 6 parameter affine ME + { + // save 4 parameter results + Mv bestMv[2][4], bestMvd[2][4]; + int bestMvpIdx[2], bestMvpNum[2], bestRefIdx[2]; + uint8_t bestInterDir; + + bestInterDir = pu.interDir; + bestRefIdx[0] = pu.refIdx[0]; + bestRefIdx[1] = pu.refIdx[1]; + bestMvpIdx[0] = pu.mvpIdx[0]; + bestMvpIdx[1] = pu.mvpIdx[1]; + bestMvpNum[0] = pu.mvpNum[0]; + bestMvpNum[1] = pu.mvpNum[1]; + + const CMotionBuf &mb = pu.getMotionBuf(); + for (int refList = 0; refList < 2; refList++) + { + bestMv[refList][0] = mb.at(0, 0).mv[refList]; + bestMv[refList][1] = mb.at(mb.width - 1, 0).mv[refList]; + bestMv[refList][2] = mb.at(0, mb.height - 1).mv[refList]; + bestMv[refList][3] = mb.at(mb.width - 1, mb.height - 1).mv[refList]; + + bestMvd[refList][0] = pu.mvdAffi[refList][0]; + bestMvd[refList][1] = pu.mvdAffi[refList][1]; + bestMvd[refList][2] = pu.mvdAffi[refList][2]; + bestMvd[refList][3] = pu.mvdAffi[refList][3]; + } + + refIdx4Para[0] = bestRefIdx[0]; + refIdx4Para[1] = bestRefIdx[1]; + + Distortion uiAffine6Cost = std::numeric_limits::max(); + cu.affineType = AFFINEMODEL_6PARAM; #if JVET_K0220_ENC_CTRL - xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, acMvAffine4Para, refIdx4Para ); + xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, acMvAffine4Para, refIdx4Para); #else - xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, bFastSkipBi, acMvAffine4Para, refIdx4Para ); -#endif - - // reset to 4 parameter affine inter mode - if ( uiAffineCost <= uiAffine6Cost ) - { - cu.affineType = AFFINEMODEL_4PARAM; - pu.interDir = bestInterDir; - pu.refIdx[0] = bestRefIdx[0]; - pu.refIdx[1] = bestRefIdx[1]; - pu.mvpIdx[0] = bestMvpIdx[0]; - pu.mvpIdx[1] = bestMvpIdx[1]; - pu.mvpNum[0] = bestMvpNum[0]; - pu.mvpNum[1] = bestMvpNum[1]; - - for ( int verIdx = 0; verIdx < 3; verIdx++ ) - { - pu.mvdAffi[REF_PIC_LIST_0][verIdx] = bestMvd[0][verIdx]; - pu.mvdAffi[REF_PIC_LIST_1][verIdx] = bestMvd[1][verIdx]; - } - - PU::setAllAffineMv( pu, bestMv[0][0], bestMv[0][1], bestMv[0][2], REF_PIC_LIST_0 ); - PU::setAllAffineMv( pu, bestMv[1][0], bestMv[1][1], bestMv[1][2], REF_PIC_LIST_1 ); - } - else - { - uiAffineCost = uiAffine6Cost; - } - } - - uiAffineCost += m_pcRdCost->getCost( 1 ); // add one bit for affine_type - } + xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffine6Cost, cMvHevcTemp, bFastSkipBi, acMvAffine4Para, refIdx4Para); +#endif + // reset to 4 parameter affine inter mode + if (uiAffineCost <= uiAffine6Cost) + { + cu.affineType = AFFINEMODEL_4PARAM; + pu.interDir = bestInterDir; + pu.refIdx[0] = bestRefIdx[0]; + pu.refIdx[1] = bestRefIdx[1]; + pu.mvpIdx[0] = bestMvpIdx[0]; + pu.mvpIdx[1] = bestMvpIdx[1]; + pu.mvpNum[0] = bestMvpNum[0]; + pu.mvpNum[1] = bestMvpNum[1]; + + for (int verIdx = 0; verIdx < 4; verIdx++) + { + pu.mvdAffi[REF_PIC_LIST_0][verIdx] = bestMvd[0][verIdx]; + pu.mvdAffi[REF_PIC_LIST_1][verIdx] = bestMvd[1][verIdx]; + } + + PU::setAllAffineMv(pu, bestMv[0][0], bestMv[0][1], bestMv[0][2], bestMv[0][3], REF_PIC_LIST_0); + PU::setAllAffineMv(pu, bestMv[1][0], bestMv[1][1], bestMv[1][2], bestMv[1][3], REF_PIC_LIST_1); + } + else + { + uiAffineCost = uiAffine6Cost; + } + } + uiAffineCost += m_pcRdCost->getCost(2); // add one bit for affine_type + } #else #if JVET_K0220_ENC_CTRL xPredAffineInterSearch( pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp ); @@ -1431,7 +1433,627 @@ void InterSearch::predInterSearch(CodingUnit& cu, Partitioner& partitioner) return; } +//! [Perspective Prediction] search of the best candidate for inter prediction +void InterSearch::predInterSearchPersp(CodingUnit& cu, Partitioner& partitioner, Mv bestCSMv[2][4], int bestCSRefIdx[2]) +{ + CodingStructure& cs = *cu.cs; + + AMVPInfo amvp[2]; + Mv cMvSrchRngLT; + Mv cMvSrchRngRB; + + Mv cMvZero; + + Mv cMv[2]; + Mv cMvBi[2]; + Mv cMvTemp[2][33]; +#if JVET_K_AFFINE + Mv cMvHevcTemp[2][33]; +#endif + int iNumPredDir = cs.slice->isInterP() ? 1 : 2; + + Mv cMvPred[2][33]; + + Mv cMvPredBi[2][33]; + int aaiMvpIdxBi[2][33]; + + int aaiMvpIdx[2][33]; + int aaiMvpNum[2][33]; + AMVPInfo aacAMVPInfo[2][33]; + + int iRefIdx[2] = { 0,0 }; //If un-initialized, may cause SEGV in bi-directional prediction iterative stage. + int iRefIdxBi[2]; + + uint32_t uiMbBits[3] = { 1, 1, 0 }; + + uint32_t uiLastMode = 0; +#if JVET_K_AFFINE + uint32_t uiLastModeTemp = 0; +#endif + int iRefStart, iRefEnd; + + int bestBiPRefIdxL1 = 0; + int bestBiPMvpL1 = 0; + Distortion biPDistTemp = std::numeric_limits::max(); + + MergeCtx mergeCtx; + + // Loop over Prediction Units + CHECK(!cu.firstPU, "CU does not contain any PUs"); + uint32_t puIdx = 0; + auto &pu = *cu.firstPU; + + { + // motion estimation only evaluates luma component + m_maxCompIDToPred = MAX_NUM_COMPONENT; + // m_maxCompIDToPred = COMPONENT_Y; + + CHECK(pu.cu != &cu, "PU is contained in another CU"); + +#if JVET_K0346 + if (cu.cs->sps->getSpsNext().getUseSubPuMvp()) + { + Size bufSize = g_miScaling.scale(pu.lumaSize()); + mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); + } +#endif + + PU::spanMotionInfo(pu); +#if JVET_K_AFFINE + Distortion uiHevcCost = std::numeric_limits::max(); + Distortion uiAffineCost = std::numeric_limits::max(); +#endif + Distortion uiCost[2] = { std::numeric_limits::max(), std::numeric_limits::max() }; + Distortion uiCostBi = std::numeric_limits::max(); + Distortion uiCostTemp; + + uint32_t uiBits[3]; + uint32_t uiBitsTemp; + Distortion bestBiPDist = std::numeric_limits::max(); + + Distortion uiCostTempL0[MAX_NUM_REF]; + for (int iNumRef = 0; iNumRef < MAX_NUM_REF; iNumRef++) + { + uiCostTempL0[iNumRef] = std::numeric_limits::max(); + } + uint32_t uiBitsTempL0[MAX_NUM_REF]; + + Mv mvValidList1; + int refIdxValidList1 = 0; + uint32_t bitsValidList1 = MAX_UINT; + Distortion costValidList1 = std::numeric_limits::max(); + + PelUnitBuf origBuf = pu.cs->getOrgBuf(pu); + + xGetBlkBits(cu.partSize, cs.slice->isInterP(), puIdx, uiLastMode, uiMbBits); + + m_pcRdCost->selectMotionLambda(cu.transQuantBypass); + +#if !JVET_K0220_ENC_CTRL + bool bFastSkipBi = false; + if (auto slsCtrl = dynamic_cast< SaveLoadEncInfoCtrl* >(m_modeCtrl)) + { + bFastSkipBi = (LOAD_ENC_INFO == slsCtrl->getSaveLoadTag(pu) && 3 != slsCtrl->getSaveLoadInterDir(pu)); + } + +#endif +#if JVET_K_AFFINE +#if !JVET_K0220_ENC_CTRL + bool bFastSkipAffine = false; + if (pu.cs->sps->getSpsNext().getUseQTBT() && m_pcEncCfg->getUseSaveLoadEncInfo()) + { + SaveLoadEncInfoCtrl* modeCtrl = dynamic_cast(m_modeCtrl); + bFastSkipAffine = modeCtrl && LOAD_ENC_INFO == modeCtrl->getSaveLoadTag(pu) && !modeCtrl->getSaveLoadAffineFlag(pu); + } +#endif +#endif +#if JVET_K0357_AMVR + unsigned imvShift = pu.cu->imv << 1; +#endif + // Uni-directional prediction + for (int iRefList = 0; iRefList < iNumPredDir; iRefList++) + { + RefPicList eRefPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + + for (int iRefIdxTemp = 0; iRefIdxTemp < cs.slice->getNumRefIdx(eRefPicList); iRefIdxTemp++) + { + uiBitsTemp = uiMbBits[iRefList]; + if (cs.slice->getNumRefIdx(eRefPicList) > 1) + { + uiBitsTemp += iRefIdxTemp + 1; + if (iRefIdxTemp == cs.slice->getNumRefIdx(eRefPicList) - 1) + { + uiBitsTemp--; + } + } + xEstimateMvPredAMVP(pu, origBuf, eRefPicList, iRefIdxTemp, cMvPred[iRefList][iRefIdxTemp], amvp[eRefPicList], false, &biPDistTemp); + + aaiMvpIdx[iRefList][iRefIdxTemp] = pu.mvpIdx[eRefPicList]; + aaiMvpNum[iRefList][iRefIdxTemp] = pu.mvpNum[eRefPicList]; + + if (cs.slice->getMvdL1ZeroFlag() && iRefList == 1 && biPDistTemp < bestBiPDist) + { + bestBiPDist = biPDistTemp; + bestBiPMvpL1 = aaiMvpIdx[iRefList][iRefIdxTemp]; + bestBiPRefIdxL1 = iRefIdxTemp; + } + + uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdx[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS]; + + if (m_pcEncCfg->getFastMEForGenBLowDelayEnabled() && iRefList == 1) // list 1 + { + if (cs.slice->getList1IdxToList0Idx(iRefIdxTemp) >= 0) + { + cMvTemp[1][iRefIdxTemp] = cMvTemp[0][cs.slice->getList1IdxToList0Idx(iRefIdxTemp)]; + uiCostTemp = uiCostTempL0[cs.slice->getList1IdxToList0Idx(iRefIdxTemp)]; + /*first subtract the bit-rate part of the cost of the other list*/ + uiCostTemp -= m_pcRdCost->getCost(uiBitsTempL0[cs.slice->getList1IdxToList0Idx(iRefIdxTemp)]); + /*correct the bit-rate part of the current ref*/ + m_pcRdCost->setPredictor(cMvPred[iRefList][iRefIdxTemp]); +#if JVET_K0357_AMVR + uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor(cMvTemp[1][iRefIdxTemp].getHor(), cMvTemp[1][iRefIdxTemp].getVer(), imvShift); +#else + uiBitsTemp += m_pcRdCost->getBitsOfVectorWithPredictor(cMvTemp[1][iRefIdxTemp].getHor(), cMvTemp[1][iRefIdxTemp].getVer()); +#endif + /*calculate the correct cost*/ + uiCostTemp += m_pcRdCost->getCost(uiBitsTemp); + } + else + { + xMotionEstimation(pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[eRefPicList]); + } + } + else + { + xMotionEstimation(pu, origBuf, eRefPicList, cMvPred[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[eRefPicList]); + } + xCopyAMVPInfo(&amvp[eRefPicList], &aacAMVPInfo[iRefList][iRefIdxTemp]); // must always be done ( also when AMVP_MODE = AM_NONE ) +#if JVET_K0357_AMVR + xCheckBestMVP(eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], amvp[eRefPicList], uiBitsTemp, uiCostTemp, pu.cu->imv); +#else + xCheckBestMVP(eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], aaiMvpIdx[iRefList][iRefIdxTemp], amvp[eRefPicList], uiBitsTemp, uiCostTemp); +#endif + + if (iRefList == 0) + { + uiCostTempL0[iRefIdxTemp] = uiCostTemp; + uiBitsTempL0[iRefIdxTemp] = uiBitsTemp; + } + if (uiCostTemp < uiCost[iRefList]) + { + uiCost[iRefList] = uiCostTemp; + uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction + + // set motion + cMv[iRefList] = cMvTemp[iRefList][iRefIdxTemp]; + iRefIdx[iRefList] = iRefIdxTemp; + } + + if (iRefList == 1 && uiCostTemp < costValidList1 && cs.slice->getList1IdxToList0Idx(iRefIdxTemp) < 0) + { + costValidList1 = uiCostTemp; + bitsValidList1 = uiBitsTemp; + + // set motion + mvValidList1 = cMvTemp[iRefList][iRefIdxTemp]; + refIdxValidList1 = iRefIdxTemp; + } + } + } + +#if JVET_K0220_ENC_CTRL + + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() +#if JVET_K0357_AMVR + && cu.imv == 0 +#endif + ) +#else + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() +#if JVET_K0357_AMVR + && cu.imv == 0 +#endif + && !bFastSkipAffine) +#endif + { + ::memcpy(cMvHevcTemp, cMvTemp, sizeof(cMvTemp)); + } + +#if JVET_K_AFFINE +#if JVET_K0220_ENC_CTRL + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine()) +#else + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && !bFastSkipAffine) +#endif + { + ::memcpy(cMvHevcTemp, cMvTemp, sizeof(cMvTemp)); + } +#endif + // Bi-predictive Motion estimation +#if JVET_K0220_ENC_CTRL + if ((cs.slice->isInterB()) && (PU::isBipredRestriction(pu) == false)) +#else + if ((cs.slice->isInterB()) && (PU::isBipredRestriction(pu) == false) && !bFastSkipBi) +#endif + { + cMvBi[0] = cMv[0]; + cMvBi[1] = cMv[1]; + iRefIdxBi[0] = iRefIdx[0]; + iRefIdxBi[1] = iRefIdx[1]; + + ::memcpy(cMvPredBi, cMvPred, sizeof(cMvPred)); + ::memcpy(aaiMvpIdxBi, aaiMvpIdx, sizeof(aaiMvpIdx)); + + uint32_t uiMotBits[2]; + + if (cs.slice->getMvdL1ZeroFlag()) + { + xCopyAMVPInfo(&aacAMVPInfo[1][bestBiPRefIdxL1], &amvp[REF_PIC_LIST_1]); + aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1; + cMvPredBi[1][bestBiPRefIdxL1] = amvp[REF_PIC_LIST_1].mvCand[bestBiPMvpL1]; + + cMvBi[1] = cMvPredBi[1][bestBiPRefIdxL1]; + iRefIdxBi[1] = bestBiPRefIdxL1; + pu.mv[REF_PIC_LIST_1] = cMvBi[1]; + pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1]; + pu.mvpIdx[REF_PIC_LIST_1] = bestBiPMvpL1; + + PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_1].getBuf(UnitAreaRelative(cu, pu)); + motionCompensation(pu, predBufTmp, REF_PIC_LIST_1); + + uiMotBits[0] = uiBits[0] - uiMbBits[0]; + uiMotBits[1] = uiMbBits[1]; + + if (cs.slice->getNumRefIdx(REF_PIC_LIST_1) > 1) + { + uiMotBits[1] += bestBiPRefIdxL1 + 1; + if (bestBiPRefIdxL1 == cs.slice->getNumRefIdx(REF_PIC_LIST_1) - 1) + { + uiMotBits[1]--; + } + } + + uiMotBits[1] += m_auiMVPIdxCost[aaiMvpIdxBi[1][bestBiPRefIdxL1]][AMVP_MAX_NUM_CANDS]; + + uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1]; + + cMvTemp[1][bestBiPRefIdxL1] = cMvBi[1]; + } + else + { + uiMotBits[0] = uiBits[0] - uiMbBits[0]; + uiMotBits[1] = uiBits[1] - uiMbBits[1]; + uiBits[2] = uiMbBits[2] + uiMotBits[0] + uiMotBits[1]; + } + + // 4-times iteration (default) + int iNumIter = 4; + + // fast encoder setting: only one iteration + if (m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE2 || cs.slice->getMvdL1ZeroFlag()) + { + iNumIter = 1; + } + + for (int iIter = 0; iIter < iNumIter; iIter++) + { + int iRefList = iIter % 2; + + if (m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE1 || m_pcEncCfg->getFastInterSearchMode() == FASTINTERSEARCH_MODE2) + { + if (uiCost[0] <= uiCost[1]) + { + iRefList = 1; + } + else + { + iRefList = 0; + } + } + else if (iIter == 0) + { + iRefList = 0; + } + if (iIter == 0 && !cs.slice->getMvdL1ZeroFlag()) + { + pu.mv[1 - iRefList] = cMv[1 - iRefList]; + pu.refIdx[1 - iRefList] = iRefIdx[1 - iRefList]; + + PelUnitBuf predBufTmp = m_tmpPredStorage[1 - iRefList].getBuf(UnitAreaRelative(cu, pu)); + motionCompensation(pu, predBufTmp, RefPicList(1 - iRefList)); + } + + RefPicList eRefPicList = (iRefList ? REF_PIC_LIST_1 : REF_PIC_LIST_0); + + if (cs.slice->getMvdL1ZeroFlag()) + { + iRefList = 0; + eRefPicList = REF_PIC_LIST_0; + } + + bool bChanged = false; + + iRefStart = 0; + iRefEnd = cs.slice->getNumRefIdx(eRefPicList) - 1; + + for (int iRefIdxTemp = iRefStart; iRefIdxTemp <= iRefEnd; iRefIdxTemp++) + { + uiBitsTemp = uiMbBits[2] + uiMotBits[1 - iRefList]; + if (cs.slice->getNumRefIdx(eRefPicList) > 1) + { + uiBitsTemp += iRefIdxTemp + 1; + if (iRefIdxTemp == cs.slice->getNumRefIdx(eRefPicList) - 1) + { + uiBitsTemp--; + } + } + uiBitsTemp += m_auiMVPIdxCost[aaiMvpIdxBi[iRefList][iRefIdxTemp]][AMVP_MAX_NUM_CANDS]; + + // call ME + xCopyAMVPInfo(&aacAMVPInfo[iRefList][iRefIdxTemp], &amvp[eRefPicList]); + xMotionEstimation(pu, origBuf, eRefPicList, cMvPredBi[iRefList][iRefIdxTemp], iRefIdxTemp, cMvTemp[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], uiBitsTemp, uiCostTemp, amvp[eRefPicList], true); +#if JVET_K0357_AMVR + xCheckBestMVP(eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], amvp[eRefPicList], uiBitsTemp, uiCostTemp, pu.cu->imv); +#else + xCheckBestMVP(eRefPicList, cMvTemp[iRefList][iRefIdxTemp], cMvPredBi[iRefList][iRefIdxTemp], aaiMvpIdxBi[iRefList][iRefIdxTemp], amvp[eRefPicList], uiBitsTemp, uiCostTemp); +#endif + if (uiCostTemp < uiCostBi) + { + bChanged = true; + + cMvBi[iRefList] = cMvTemp[iRefList][iRefIdxTemp]; + iRefIdxBi[iRefList] = iRefIdxTemp; + + uiCostBi = uiCostTemp; + uiMotBits[iRefList] = uiBitsTemp - uiMbBits[2] - uiMotBits[1 - iRefList]; + uiBits[2] = uiBitsTemp; + + if (iNumIter != 1) + { + // Set motion + pu.mv[eRefPicList] = cMvBi[iRefList]; + pu.refIdx[eRefPicList] = iRefIdxBi[iRefList]; + + PelUnitBuf predBufTmp = m_tmpPredStorage[iRefList].getBuf(UnitAreaRelative(cu, pu)); + motionCompensation(pu, predBufTmp, eRefPicList); + } + } + } // for loop-iRefIdxTemp + + if (!bChanged) + { + if (uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) + { + xCopyAMVPInfo(&aacAMVPInfo[0][iRefIdxBi[0]], &amvp[REF_PIC_LIST_0]); +#if JVET_K0357_AMVR + xCheckBestMVP(REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], amvp[eRefPicList], uiBits[2], uiCostBi, pu.cu->imv); +#else + xCheckBestMVP(REF_PIC_LIST_0, cMvBi[0], cMvPredBi[0][iRefIdxBi[0]], aaiMvpIdxBi[0][iRefIdxBi[0]], amvp[eRefPicList], uiBits[2], uiCostBi); +#endif + if (!cs.slice->getMvdL1ZeroFlag()) + { + xCopyAMVPInfo(&aacAMVPInfo[1][iRefIdxBi[1]], &amvp[REF_PIC_LIST_1]); +#if JVET_K0357_AMVR + xCheckBestMVP(REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], amvp[eRefPicList], uiBits[2], uiCostBi, pu.cu->imv); +#else + xCheckBestMVP(REF_PIC_LIST_1, cMvBi[1], cMvPredBi[1][iRefIdxBi[1]], aaiMvpIdxBi[1][iRefIdxBi[1]], amvp[eRefPicList], uiBits[2], uiCostBi); +#endif + } + } + break; + } + } // for loop-iter + } // if (B_SLICE) + + + + // Clear Motion Field + pu.mv[REF_PIC_LIST_0] = Mv(); + pu.mv[REF_PIC_LIST_1] = Mv(); + pu.mvd[REF_PIC_LIST_0] = cMvZero; + pu.mvd[REF_PIC_LIST_1] = cMvZero; + pu.refIdx[REF_PIC_LIST_0] = NOT_VALID; + pu.refIdx[REF_PIC_LIST_1] = NOT_VALID; + pu.mvpIdx[REF_PIC_LIST_0] = NOT_VALID; + pu.mvpIdx[REF_PIC_LIST_1] = NOT_VALID; + pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; + pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; + + + uint32_t uiMEBits = 0; + + // Set Motion Field + + cMv[1] = mvValidList1; + iRefIdx[1] = refIdxValidList1; + uiBits[1] = bitsValidList1; + uiCost[1] = costValidList1; + +#if JVET_K_AFFINE + uiLastModeTemp = uiLastMode; +#endif + if (uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) + { + uiLastMode = 2; + pu.mv[REF_PIC_LIST_0] = cMvBi[0]; + pu.mv[REF_PIC_LIST_1] = cMvBi[1]; + pu.mvd[REF_PIC_LIST_0] = cMvBi[0] - cMvPredBi[0][iRefIdxBi[0]]; + pu.mvd[REF_PIC_LIST_1] = cMvBi[1] - cMvPredBi[1][iRefIdxBi[1]]; + pu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0]; + pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1]; + pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdxBi[0][iRefIdxBi[0]]; + pu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdxBi[1][iRefIdxBi[1]]; + pu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdxBi[0]]; + pu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdxBi[1]]; + pu.interDir = 3; + + uiMEBits = uiBits[2]; + } + else if (uiCost[0] <= uiCost[1]) + { + uiLastMode = 0; + pu.mv[REF_PIC_LIST_0] = cMv[0]; + pu.mvd[REF_PIC_LIST_0] = cMv[0] - cMvPred[0][iRefIdx[0]]; + pu.refIdx[REF_PIC_LIST_0] = iRefIdx[0]; + pu.mvpIdx[REF_PIC_LIST_0] = aaiMvpIdx[0][iRefIdx[0]]; + pu.mvpNum[REF_PIC_LIST_0] = aaiMvpNum[0][iRefIdx[0]]; + pu.interDir = 1; + + uiMEBits = uiBits[0]; + } + else + { + uiLastMode = 1; + pu.mv[REF_PIC_LIST_1] = cMv[1]; + pu.mvd[REF_PIC_LIST_1] = cMv[1] - cMvPred[1][iRefIdx[1]]; + pu.refIdx[REF_PIC_LIST_1] = iRefIdx[1]; + pu.mvpIdx[REF_PIC_LIST_1] = aaiMvpIdx[1][iRefIdx[1]]; + pu.mvpNum[REF_PIC_LIST_1] = aaiMvpNum[1][iRefIdx[1]]; + pu.interDir = 2; + + uiMEBits = uiBits[1]; + } + + if (cu.partSize != SIZE_2Nx2N) + { + uint32_t uiMRGIndex = 0; + + // calculate ME cost + Distortion uiMEError = xGetInterPredictionError(pu, origBuf); + Distortion uiMECost = uiMEError + m_pcRdCost->getCost(uiMEBits); + // save ME result. + InterPredictionData savedPU = pu; + + // find Merge result + Distortion uiMRGCost = std::numeric_limits::max(); + + pu.initData(); + xMergeEstimation(pu, origBuf, puIdx, uiMRGIndex, uiMRGCost, mergeCtx); + + if (uiMRGCost < uiMECost) + { + // set Merge result + mergeCtx.setMergeInfo(pu, uiMRGIndex); + } + else + { + pu = savedPU; + } +#if JVET_K_AFFINE + uiHevcCost = (uiMRGCost < uiMECost) ? uiMRGCost : uiMECost; +#endif + } +#if JVET_K_AFFINE + if (cu.cs->pcv->only2Nx2N || cu.partSize == SIZE_2Nx2N) + { + uiHevcCost = (uiCostBi <= uiCost[0] && uiCostBi <= uiCost[1]) ? uiCostBi : ((uiCost[0] <= uiCost[1]) ? uiCost[0] : uiCost[1]); + } +#endif + CHECK(!(!cu.cs->pcv->only2Nx2N || cu.partSize == SIZE_2Nx2N), "Unexpected part size for QTBT."); +#if JVET_K_AFFINE +#if JVET_K0220_ENC_CTRL +#if JVET_K0357_AMVR + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && cu.imv == 0) +#else + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine()) +#endif +#else +#if JVET_K0357_AMVR + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && cu.imv == 0 && !bFastSkipAffine) +#else + if (cu.Y().width > 8 && cu.Y().height > 8 && cu.partSize == SIZE_2Nx2N && cu.slice->getSPS()->getSpsNext().getUseAffine() && !bFastSkipAffine) +#endif +#endif + { + // save normal hevc result + uint32_t uiMRGIndex = pu.mergeIdx; + bool bMergeFlag = pu.mergeFlag; + uint32_t uiInterDir = pu.interDir; + + Mv cMvd[2]; + uint32_t uiMvpIdx[2], uiMvpNum[2]; + uiMvpIdx[0] = pu.mvpIdx[REF_PIC_LIST_0]; + uiMvpIdx[1] = pu.mvpIdx[REF_PIC_LIST_1]; + uiMvpNum[0] = pu.mvpNum[REF_PIC_LIST_0]; + uiMvpNum[1] = pu.mvpNum[REF_PIC_LIST_1]; + cMvd[0] = pu.mvd[REF_PIC_LIST_0]; + cMvd[1] = pu.mvd[REF_PIC_LIST_1]; + + MvField cHevcMvField[2]; + cHevcMvField[0].setMvField(pu.mv[REF_PIC_LIST_0], pu.refIdx[REF_PIC_LIST_0]); + cHevcMvField[1].setMvField(pu.mv[REF_PIC_LIST_1], pu.refIdx[REF_PIC_LIST_1]); + + // do affine ME & Merge +#if JVET_K0185_AFFINE_6PARA_ENC + if (cu.slice->getSPS()->getSpsNext().getUseAffineType()) + { + cu.affineType = AFFINEMODEL_8PARAM; + Mv acMvAffine4Para[2][33][4]; + int refIdx4Para[2] = { -1, -1 }; + + for (int refList = 0; refList < 2; refList++) + { + ::memcpy(acMvAffine4Para[refList][iRefIdx[refList]], bestCSMv[refList], sizeof(Mv) * 4); + refIdx4Para[refList] = bestCSRefIdx[refList]; + } + + +#if JVET_K0220_ENC_CTRL + xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, acMvAffine4Para, refIdx4Para); +#else + xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, bFastSkipBi, acMvAffine4Para, refIdx4Para); +#endif + uiAffineCost += m_pcRdCost->getCost(2); // add one bit for affine_type + } +#else +#if JVET_K0220_ENC_CTRL + xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp); +#else + xPredAffineInterSearch(pu, origBuf, puIdx, uiLastModeTemp, uiAffineCost, cMvHevcTemp, bFastSkipBi); +#endif +#endif + if (uiHevcCost <= uiAffineCost) + { + // set hevc me result + cu.affine = false; + pu.mergeFlag = bMergeFlag; + pu.mergeIdx = uiMRGIndex; + pu.interDir = uiInterDir; + pu.mv[REF_PIC_LIST_0] = cHevcMvField[0].mv; + pu.refIdx[REF_PIC_LIST_0] = cHevcMvField[0].refIdx; + pu.mv[REF_PIC_LIST_1] = cHevcMvField[1].mv; + pu.refIdx[REF_PIC_LIST_1] = cHevcMvField[1].refIdx; + pu.mvpIdx[REF_PIC_LIST_0] = uiMvpIdx[0]; + pu.mvpIdx[REF_PIC_LIST_1] = uiMvpIdx[1]; + pu.mvpNum[REF_PIC_LIST_0] = uiMvpNum[0]; + pu.mvpNum[REF_PIC_LIST_1] = uiMvpNum[1]; + pu.mvd[REF_PIC_LIST_0] = cMvd[0]; + pu.mvd[REF_PIC_LIST_1] = cMvd[1]; + } + else + { + CHECK(!cu.affine, "Wrong."); + uiLastMode = uiLastModeTemp; + } + } +#endif + m_maxCompIDToPred = MAX_NUM_COMPONENT; + + { + PU::spanMotionInfo(pu, mergeCtx); + } + + // MC + PelUnitBuf predBuf = pu.cs->getPredBuf(pu); + motionCompensation(pu, predBuf, REF_PIC_LIST_X); + puIdx++; + } + + setWpScalingDistParam(-1, REF_PIC_LIST_X, cu.cs->slice); + + return; +} // AMVP @@ -1637,7 +2259,7 @@ Distortion InterSearch::xGetTemplateCost( const PredictionUnit& pu, } #if JVET_K_AFFINE -Distortion InterSearch::xGetAffineTemplateCost( PredictionUnit& pu, PelUnitBuf& origBuf, PelUnitBuf& predBuf, Mv acMvCand[3], int iMVPIdx, int iMVPNum, RefPicList eRefPicList, int iRefIdx ) +Distortion InterSearch::xGetAffineTemplateCost( PredictionUnit& pu, PelUnitBuf& origBuf, PelUnitBuf& predBuf, Mv acMvCand[4], int iMVPIdx, int iMVPNum, RefPicList eRefPicList, int iRefIdx ) { Distortion uiCost = std::numeric_limits::max(); @@ -1776,7 +2398,7 @@ void InterSearch::xMotionEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Ref rcMv += ( cMvHalf <<= 1 ); rcMv += cMvQter; #if JVET_K0357_AMVR - uint32_t uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor( rcMv.getHor(), rcMv.getVer(), cStruct.imvShift ); + uint32_t uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor(rcMv.getHor(), rcMv.getVer(), cStruct.imvShift); #else uint32_t uiMvBits = m_pcRdCost->getBitsOfVectorWithPredictor( rcMv.getHor(), rcMv.getVer() ); #endif @@ -2499,7 +3121,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, bool bFastSkipBi #endif #if JVET_K0185_AFFINE_6PARA_ENC - , Mv mvAffine4Para[2][33][3] + , Mv mvAffine4Para[2][33][4] , int refIdx4Para[2] #endif ) @@ -2509,20 +3131,31 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, affineCost = std::numeric_limits::max(); Mv cMvZero; - Mv aacMv[2][3]; - Mv cMvBi[2][3]; - Mv cMvTemp[2][33][3]; + Mv aacMv[2][4]; + Mv cMvBi[2][4]; + Mv cMvTemp[2][33][4]; int iNumPredDir = slice.isInterP() ? 1 : 2; int mvNum = 2; #if JVET_K0185_AFFINE_6PARA_ENC - mvNum = pu.cu->affineType ? 3 : 2; + if (pu.cu->affineType == 0) + { + mvNum = 2; + } + else if (pu.cu->affineType == 1) + { + mvNum = 3; + } + else if (pu.cu->affineType == 2) + { + mvNum = 4; + } #endif // Mvp - Mv cMvPred[2][33][3]; - Mv cMvPredBi[2][33][3]; + Mv cMvPred[2][33][4]; + Mv cMvPredBi[2][33][4]; int aaiMvpIdxBi[2][33]; int aaiMvpIdx[2][33]; int aaiMvpNum[2][33]; @@ -2574,7 +3207,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, #else uint32_t costValidList1 = MAX_UINT; #endif - Mv mvHevc[3]; + Mv mvHevc[4]; xGetBlkBits( ePartSize, slice.isInterP(), puIdx, lastMode, uiMbBits); @@ -2612,7 +3245,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, #endif // set hevc ME result as start search position when it is best than mvp - for ( int i=0; i<3; i++ ) + for ( int i=0; i<4; i++ ) { mvHevc[i] = hevcMv[iRefList][iRefIdxTemp]; } @@ -2627,7 +3260,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, #if JVET_K0185_AFFINE_6PARA_ENC // use 4-parameter results as start point if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) { - Mv mvFour[3]; + Mv mvFour[4]; mvFour[0] = mvAffine4Para[iRefList][iRefIdxTemp][0]; mvFour[1] = mvAffine4Para[iRefList][iRefIdxTemp][1]; @@ -2643,21 +3276,76 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, if ( uiCandCostInherit < uiCandCost ) { uiCandCost = uiCandCostInherit; - for ( int i = 0; i < 3; i++ ) + for ( int i = 0; i < 4; i++ ) { mvHevc[i] = mvFour[i]; } } } -#endif + else if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + Mv mvFour[4]; + int shift = MAX_CU_DEPTH; + + int vx0 = (mvAffine4Para[iRefList][iRefIdxTemp][0].getHor()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]); + int vy0 = (mvAffine4Para[iRefList][iRefIdxTemp][0].getVer()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]); + vx0 >>= shift; + vy0 >>= shift; + mvFour[0] = Mv(vx0, vy0, true); + mvFour[0].roundMV2SignalPrecision(); + + int vx1 = (mvAffine4Para[iRefList][iRefIdxTemp][1].getHor()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]); + int vy1 = (mvAffine4Para[iRefList][iRefIdxTemp][1].getVer()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]); + vx1 >>= shift; + vy1 >>= shift; + mvFour[1] = Mv(vx1, vy1, true); + mvFour[1].roundMV2SignalPrecision(); + + int vx2 = (mvAffine4Para[iRefList][iRefIdxTemp][2].getHor()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]); + int vy2 = (mvAffine4Para[iRefList][iRefIdxTemp][2].getVer()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]); + vx2 >>= shift; + vy2 >>= shift; + mvFour[2] = Mv(vx2, vy2, true); + mvFour[2].roundMV2SignalPrecision(); + + int vx3 = (mvAffine4Para[iRefList][iRefIdxTemp][3].getHor()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]); + int vy3 = (mvAffine4Para[iRefList][iRefIdxTemp][3].getVer()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()]); + vx3 >>= shift; + vy3 >>= shift; + mvFour[3] = Mv(vx3, vy3, true); + mvFour[3].roundMV2SignalPrecision(); + + //¿©±â ´Ü¶ô ÁÖ¼® + //int shift = MAX_CU_DEPTH; + //int vx3 = (mvFour[0].getHor() << shift) + ((mvFour[2].getVer() - mvFour[0].getVer()) << (shift + g_aucLog2[pu.lwidth()] - g_aucLog2[pu.lheight()])); + //int vy3 = (mvFour[0].getVer() << shift) + ((mvFour[1].getHor() - mvFour[0].getHor()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()])); + //int vx3 = ((mvFour[1].getHor() + mvFour[2].getHor() - mvFour[0].getHor()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()])); + //int vy3 = ((mvFour[1].getVer() + mvFour[2].getVer() - mvFour[0].getVer()) << (shift + g_aucLog2[pu.lheight()] - g_aucLog2[pu.lwidth()])); + //vx3 >>= shift; + //vy3 >>= shift; + //mvFour[3] = Mv(vx3, vy3, true); + //mvFour[3].roundMV2SignalPrecision(); + + Distortion uiCandCostInherit = xGetAffineTemplateCost(pu, origBuf, predBuf, mvFour, aaiMvpIdx[iRefList][iRefIdxTemp], AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdxTemp); + + if (uiCandCostInherit < uiCandCost) + { + uiCandCost = uiCandCostInherit; + for (int i = 0; i < 4; i++) + { + mvHevc[i] = mvFour[i]; + } + } + } +#endif if ( uiCandCost < biPDistTemp ) { - ::memcpy( cMvTemp[iRefList][iRefIdxTemp], mvHevc, sizeof(Mv)*3 ); + ::memcpy( cMvTemp[iRefList][iRefIdxTemp], mvHevc, sizeof(Mv)*4 ); } else { - ::memcpy( cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], sizeof(Mv)*3 ); + ::memcpy( cMvTemp[iRefList][iRefIdxTemp], cMvPred[iRefList][iRefIdxTemp], sizeof(Mv)*4 ); } // GPB list 1, save the best MvpIdx, RefIdx and Cost @@ -2674,13 +3362,13 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, if ( m_pcEncCfg->getFastMEForGenBLowDelayEnabled() && iRefList == 1 ) // list 1 { #if JVET_K0185_AFFINE_6PARA_ENC - if ( slice.getList1IdxToList0Idx( iRefIdxTemp ) >= 0 && (pu.cu->affineType != AFFINEMODEL_6PARAM || slice.getList1IdxToList0Idx( iRefIdxTemp ) == refIdx4Para[0]) ) + if ( slice.getList1IdxToList0Idx( iRefIdxTemp ) >= 0 && (pu.cu->affineType == AFFINEMODEL_4PARAM || slice.getList1IdxToList0Idx( iRefIdxTemp ) == refIdx4Para[0]) ) #else if ( slice.getList1IdxToList0Idx( iRefIdxTemp ) >= 0 ) #endif { int iList1ToList0Idx = slice.getList1IdxToList0Idx( iRefIdxTemp ); - ::memcpy( cMvTemp[1][iRefIdxTemp], cMvTemp[0][iList1ToList0Idx], sizeof(Mv)*3 ); + ::memcpy( cMvTemp[1][iRefIdxTemp], cMvTemp[0][iList1ToList0Idx], sizeof(Mv)*4 ); uiCostTemp = uiCostTempL0[iList1ToList0Idx]; uiCostTemp -= m_pcRdCost->getCost( uiBitsTempL0[iList1ToList0Idx] ); @@ -2732,7 +3420,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, uiBits[iRefList] = uiBitsTemp; // storing for bi-prediction // set best motion - ::memcpy( aacMv[iRefList], cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv) * 3 ); + ::memcpy( aacMv[iRefList], cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv) * 4 ); iRefIdx[iRefList] = iRefIdxTemp; } @@ -2742,14 +3430,14 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, bitsValidList1 = uiBitsTemp; // set motion - memcpy( mvValidList1, cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv)*3 ); + memcpy( mvValidList1, cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv)*4 ); refIdxValidList1 = iRefIdxTemp; } } // End refIdx loop } // end Uni-prediction #if JVET_K0185_AFFINE_6PARA_ENC // save 4-parameter UNI-ME results - if ( pu.cu->affineType == AFFINEMODEL_4PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_4PARAM || pu.cu->affineType == AFFINEMODEL_6PARAM ) { ::memcpy( mvAffine4Para, cMvTemp, sizeof( cMvTemp ) ); } @@ -2779,16 +3467,17 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, aaiMvpIdxBi[1][bestBiPRefIdxL1] = bestBiPMvpL1; // Set Mv for list1 - Mv pcMvTemp[3] = { affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLT[bestBiPMvpL1], + Mv pcMvTemp[4] = { affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLT[bestBiPMvpL1], affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandRT[bestBiPMvpL1], - affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLB[bestBiPMvpL1] }; - ::memcpy( cMvPredBi[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv)*3 ); - ::memcpy( cMvBi[1], pcMvTemp, sizeof(Mv)*3 ); - ::memcpy( cMvTemp[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv)*3 ); + affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandLB[bestBiPMvpL1], + affiAMVPInfoTemp[REF_PIC_LIST_1].mvCandRB[bestBiPMvpL1] }; + ::memcpy( cMvPredBi[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv)*4 ); + ::memcpy( cMvBi[1], pcMvTemp, sizeof(Mv)*4 ); + ::memcpy( cMvTemp[1][bestBiPRefIdxL1], pcMvTemp, sizeof(Mv)*4 ); iRefIdxBi[1] = bestBiPRefIdxL1; // Get list1 prediction block - PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1 ); + PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], cMvBi[1][3], REF_PIC_LIST_1 ); pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1]; PelUnitBuf predBufTmp = m_tmpPredStorage[REF_PIC_LIST_1].getBuf( UnitAreaRelative(*pu.cu, pu) ); @@ -2847,7 +3536,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, // First iterate, get prediction block of opposite direction if( iIter == 0 && !slice.getMvdL1ZeroFlag() ) { - PU::setAllAffineMv( pu, aacMv[1-iRefList][0], aacMv[1-iRefList][1], aacMv[1-iRefList][2], RefPicList(1-iRefList) ); + PU::setAllAffineMv( pu, aacMv[1-iRefList][0], aacMv[1-iRefList][1], aacMv[1-iRefList][2], aacMv[1 - iRefList][3], RefPicList(1-iRefList) ); pu.refIdx[1-iRefList] = iRefIdx[1-iRefList]; PelUnitBuf predBufTmp = m_tmpPredStorage[1 - iRefList].getBuf( UnitAreaRelative(*pu.cu, pu) ); @@ -2896,7 +3585,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, if ( uiCostTemp < uiCostBi ) { bChanged = true; - ::memcpy( cMvBi[iRefList], cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv)*3 ); + ::memcpy( cMvBi[iRefList], cMvTemp[iRefList][iRefIdxTemp], sizeof(Mv)*4 ); iRefIdxBi[iRefList] = iRefIdxTemp; uiCostBi = uiCostTemp; @@ -2906,7 +3595,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, if ( iNumIter != 1 ) // MC for next iter { // Set motion - PU::setAllAffineMv( pu, cMvBi[iRefList][0], cMvBi[iRefList][1], cMvBi[iRefList][2], eRefPicList ); + PU::setAllAffineMv( pu, cMvBi[iRefList][0], cMvBi[iRefList][1], cMvBi[iRefList][2], cMvBi[iRefList][3], eRefPicList ); pu.refIdx[eRefPicList] = iRefIdxBi[eRefPicList]; PelUnitBuf predBufTmp = m_tmpPredStorage[iRefList].getBuf( UnitAreaRelative(*pu.cu, pu) ); motionCompensation( pu, predBufTmp, eRefPicList ); @@ -2943,14 +3632,14 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, pu.mvpNum[REF_PIC_LIST_0] = NOT_VALID; pu.mvpNum[REF_PIC_LIST_1] = NOT_VALID; - for ( int verIdx = 0; verIdx < 3; verIdx++ ) + for ( int verIdx = 0; verIdx < 4; verIdx++ ) { pu.mvdAffi[REF_PIC_LIST_0][verIdx] = cMvZero; pu.mvdAffi[REF_PIC_LIST_1][verIdx] = cMvZero; } // Set Motion Field - memcpy( aacMv[1], mvValidList1, sizeof(Mv)*3 ); + memcpy( aacMv[1], mvValidList1, sizeof(Mv)*4 ); iRefIdx[1] = refIdxValidList1; uiBits[1] = bitsValidList1; uiCost[1] = costValidList1; @@ -2961,8 +3650,8 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, lastMode = 2; affineCost = uiCostBi; - PU::setAllAffineMv( pu, cMvBi[0][0], cMvBi[0][1], cMvBi[0][2], REF_PIC_LIST_0 ); - PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], REF_PIC_LIST_1 ); + PU::setAllAffineMv( pu, cMvBi[0][0], cMvBi[0][1], cMvBi[0][2], cMvBi[0][3], REF_PIC_LIST_0 ); + PU::setAllAffineMv( pu, cMvBi[1][0], cMvBi[1][1], cMvBi[1][2], cMvBi[1][3], REF_PIC_LIST_1 ); pu.refIdx[REF_PIC_LIST_0] = iRefIdxBi[0]; pu.refIdx[REF_PIC_LIST_1] = iRefIdxBi[1]; @@ -2991,7 +3680,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, lastMode = 0; affineCost = uiCost[0]; - PU::setAllAffineMv( pu, aacMv[0][0], aacMv[0][1], aacMv[0][2], REF_PIC_LIST_0 ); + PU::setAllAffineMv( pu, aacMv[0][0], aacMv[0][1], aacMv[0][2], aacMv[0][3], REF_PIC_LIST_0 ); pu.refIdx[REF_PIC_LIST_0] = iRefIdx[0]; for ( int verIdx = 0; verIdx < mvNum; verIdx++ ) @@ -3014,7 +3703,7 @@ void InterSearch::xPredAffineInterSearch( PredictionUnit& pu, lastMode = 1; affineCost = uiCost[1]; - PU::setAllAffineMv( pu, aacMv[1][0], aacMv[1][1], aacMv[1][2], REF_PIC_LIST_1 ); + PU::setAllAffineMv( pu, aacMv[1][0], aacMv[1][1], aacMv[1][2], aacMv[1][3], REF_PIC_LIST_1 ); pu.refIdx[REF_PIC_LIST_1] = iRefIdx[1]; for ( int verIdx = 0; verIdx < mvNum; verIdx++ ) @@ -3113,7 +3802,7 @@ void solveEqual( double** dEqualCoeff, int iOrder, double* dAffinePara ) } } -void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affineAMVPInfo, RefPicList eRefPicList, Mv acMv[3], Mv acMvPred[3], int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost ) +void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affineAMVPInfo, RefPicList eRefPicList, Mv acMv[4], Mv acMvPred[4], int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost ) { if ( affineAMVPInfo.numCand < 2 ) { @@ -3121,7 +3810,20 @@ void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affin } #if JVET_K0185_AFFINE_6PARA_ENC - int mvNum = pu.cu->affineType ? 3 : 2; + //int mvNum = pu.cu->affineType ? 3 : 2; + int mvNum = 0; + if (pu.cu->affineType == AFFINEMODEL_4PARAM) + { + mvNum = 2; + } + else if (pu.cu->affineType == AFFINEMODEL_6PARAM) + { + mvNum = 3; + } + else if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + mvNum = 4; + } #endif m_pcRdCost->selectMotionLambda( pu.cu->transQuantBypass ); @@ -3172,8 +3874,8 @@ void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affin #endif { #if JVET_K0185_AFFINE_6PARA_ENC - m_pcRdCost->setPredictor( iVerIdx == 2 ? affineAMVPInfo.mvCandLB[iMVPIdx] : - (iVerIdx == 1 ? affineAMVPInfo.mvCandRT[iMVPIdx] : affineAMVPInfo.mvCandLT[iMVPIdx]) ); + m_pcRdCost->setPredictor( iVerIdx == 3 ? affineAMVPInfo.mvCandRB[iMVPIdx] : (iVerIdx == 2 ? affineAMVPInfo.mvCandLB[iMVPIdx] : + (iVerIdx == 1 ? affineAMVPInfo.mvCandRT[iMVPIdx] : affineAMVPInfo.mvCandLT[iMVPIdx]) )); #else m_pcRdCost->setPredictor ( iVerIdx ? affineAMVPInfo.mvCandRT[iMVPIdx] : affineAMVPInfo.mvCandLT[iMVPIdx] ); #endif @@ -3211,6 +3913,7 @@ void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affin acMvPred[0] = affineAMVPInfo.mvCandLT[iBestMVPIdx]; acMvPred[1] = affineAMVPInfo.mvCandRT[iBestMVPIdx]; acMvPred[2] = affineAMVPInfo.mvCandLB[iBestMVPIdx]; + acMvPred[3] = affineAMVPInfo.mvCandRB[iBestMVPIdx]; riMVPIdx = iBestMVPIdx; uint32_t uiOrgBits = ruiBits; ruiBits = uiOrgBits - iOrgMvBits + iBestMvBits; @@ -3221,9 +3924,9 @@ void InterSearch::xCheckBestAffineMVP( PredictionUnit &pu, AffineAMVPInfo &affin void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eRefPicList, - Mv acMvPred[3], + Mv acMvPred[4], int iRefIdxPred, - Mv acMv[3], + Mv acMv[4], uint32_t& ruiBits, Distortion& ruiCost, bool bBi ) @@ -3255,18 +3958,43 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, PelUnitBuf predBuf = m_tmpAffiStorage.getBuf( UnitAreaRelative(*pu.cu, pu) ); // Set start Mv position, use input mv as started search mv - Mv acMvTemp[3]; - ::memcpy( acMvTemp, acMv, sizeof(Mv)*3 ); + Mv acMvTemp[4]; + ::memcpy( acMvTemp, acMv, sizeof(Mv)*4 ); acMvTemp[0].setHighPrec(); acMvTemp[1].setHighPrec(); acMvTemp[2].setHighPrec(); + acMvTemp[3].setHighPrec(); // Set delta mv // malloc buffer #if JVET_K0185_AFFINE_6PARA_ENC - int iParaNum = pu.cu->affineType ? 7 : 5; + int iParaNum = 0; + if (pu.cu->affineType == 0) + { + iParaNum = 5; + } + else if (pu.cu->affineType == 1) + { + iParaNum = 7; + } + else if (pu.cu->affineType == 2) + { + iParaNum = 9; + } int affineParaNum = iParaNum - 1; - int mvNum = pu.cu->affineType ? 3 : 2; + int mvNum = 0; + if (pu.cu->affineType == 0) + { + mvNum = 2; + } + else if (pu.cu->affineType == 1) + { + mvNum = 3; + } + else if (pu.cu->affineType == 2) + { + mvNum = 4; + } #else static const int iParaNum = 5; #endif @@ -3278,7 +4006,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, } #if JVET_K0367_AFFINE_FIX_POINT - int64_t i64EqualCoeff[7][7]; + int64_t i64EqualCoeff[9][9]; Pel *piError = m_tmpAffiError; int *pdDerivate[2]; #else @@ -3295,11 +4023,17 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, clipMv( acMvTemp[0], pu.cu->lumaPos(), *pu.cs->sps ); clipMv( acMvTemp[1], pu.cu->lumaPos(), *pu.cs->sps ); #if JVET_K0185_AFFINE_6PARA_ENC - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM) { clipMv( acMvTemp[2], pu.cu->lumaPos(), *pu.cs->sps ); } #endif +#if JVET_YJC_PERSP_8PARA_ENC + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + clipMv(acMvTemp[3], pu.cu->lumaPos(), *pu.cs->sps); + } +#endif #if !JVET_K_AFFINE_BUG_FIXES int vx2 = - ( acMvTemp[1].getVer() - acMvTemp[0].getVer() ) * height / width + acMvTemp[0].getHor(); int vy2 = ( acMvTemp[1].getHor() - acMvTemp[0].getHor() ) * height / width + acMvTemp[0].getVer(); @@ -3345,14 +4079,14 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, DTRACE( g_trace_ctx, D_COMMON, " (%d) uiBitsBest=%d, uiCostBest=%d\n", DTRACE_GET_COUNTER(g_trace_ctx,D_COMMON), uiBitsBest, uiCostBest ); - ::memcpy( acMv, acMvTemp, sizeof(Mv) * 3 ); + ::memcpy( acMv, acMvTemp, sizeof(Mv) * 4 ); const int bufStride = pBuf->Y().stride; const int predBufStride = predBuf.Y().stride; #if JVET_K0185_AFFINE_6PARA_ENC int iIterTime; - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM ) { iIterTime = bBi ? 3 : 4; } @@ -3460,7 +4194,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, m_EqualCoeffComputer( piError, width, pdDerivate, width, i64EqualCoeff, width, height #if JVET_K0185_AFFINE_6PARA_ENC - , (pu.cu->affineType == AFFINEMODEL_6PARAM) + , pu.cu->affineType #else , false #endif @@ -3535,22 +4269,44 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, #endif #if JVET_K0185_AFFINE_6PARA_ENC - double dAffinePara[6]; - double dDeltaMv[6]; - Mv acDeltaMv[3]; + double dAffinePara[8]; + double dDeltaMv[8]; + Mv acDeltaMv[4]; + + dDeltaMv[0] = 0.0; + dDeltaMv[1] = 0.0; + dDeltaMv[2] = 0.0; + dDeltaMv[3] = 0.0; + dDeltaMv[4] = 0.0; + dDeltaMv[5] = 0.0; + dDeltaMv[6] = 0.0; + dDeltaMv[7] = 0.0; solveEqual( pdEqualCoeff, affineParaNum, dAffinePara ); + //pu.perspParam[0] = dAffinePara[6] * width + 1; + //pu.perspParam[1] = dAffinePara[7] * height + 1; + // convert to delta mv dDeltaMv[0] = dAffinePara[0]; dDeltaMv[2] = dAffinePara[2]; - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM) { dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0]; dDeltaMv[3] = dAffinePara[3] * width + dAffinePara[2]; dDeltaMv[4] = dAffinePara[4] * height + dAffinePara[0]; dDeltaMv[5] = dAffinePara[5] * height + dAffinePara[2]; } + else if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + //¿©±â À¯µµÇÒ¶© ±×´ë·Î + dDeltaMv[1] = (dAffinePara[1] * width + dAffinePara[0]) / (dAffinePara[6] * width + 1); + dDeltaMv[3] = (dAffinePara[3] * width + dAffinePara[2]) / (dAffinePara[6] * width + 1); + dDeltaMv[4] = (dAffinePara[4] * height + dAffinePara[0]) / (dAffinePara[7] * height + 1); + dDeltaMv[5] = (dAffinePara[5] * height + dAffinePara[2]) / (dAffinePara[7] * height + 1); + dDeltaMv[6] = (dAffinePara[1] * width + dAffinePara[4] * height + dAffinePara[0]) / (dAffinePara[6] * width + dAffinePara[7] * height + 1); + dDeltaMv[7] = (dAffinePara[3] * width + dAffinePara[5] * height + dAffinePara[0]) / (dAffinePara[6] * width + dAffinePara[7] * height + 1); + } else { dDeltaMv[1] = dAffinePara[1] * width + dAffinePara[0]; @@ -3560,10 +4316,14 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, acDeltaMv[0] = Mv( (int)(dDeltaMv[0] * 4 + SIGN( dDeltaMv[0] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[2] * 4 + SIGN( dDeltaMv[2] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true ); acDeltaMv[1] = Mv( (int)(dDeltaMv[1] * 4 + SIGN( dDeltaMv[1] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[3] * 4 + SIGN( dDeltaMv[3] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true ); - if ( pu.cu->affineType == AFFINEMODEL_6PARAM ) + if ( pu.cu->affineType == AFFINEMODEL_6PARAM || pu.cu->affineType == AFFINEMODEL_8PARAM) { acDeltaMv[2] = Mv( (int)(dDeltaMv[4] * 4 + SIGN( dDeltaMv[4] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[5] * 4 + SIGN( dDeltaMv[5] ) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true ); } + if (pu.cu->affineType == AFFINEMODEL_8PARAM) + { + acDeltaMv[3] = Mv((int)(dDeltaMv[6] * 4 + SIGN(dDeltaMv[6]) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, (int)(dDeltaMv[7] * 4 + SIGN(dDeltaMv[7]) * 0.5) << VCEG_AZ07_MV_ADD_PRECISION_BIT_FOR_STORE, true); + } #else double dAffinePara[4]; solveEqual( pdEqualCoeff, 4, dAffinePara ); @@ -3621,7 +4381,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, acMvTemp[2].set( vx2, vy2 ); clipMv(acMvTemp[2], pu.cu->lumaPos(), *pu.cs->sps); #endif - xPredAffineBlk( COMPONENT_Y, pu, refPic, acMvTemp, predBuf, false, pu.cu->slice->clpRng( COMPONENT_Y ) ); + xPredAffineBlk( COMPONENT_Y, pu, refPic, acMvTemp, predBuf, false, pu.cu->slice->clpRng( COMPONENT_Y )); // get error Distortion uiCostTemp = m_pcRdCost->getDistPart( predBuf.Y(), pBuf->Y(), pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, DF_HAD ); @@ -3660,7 +4420,7 @@ void InterSearch::xAffineMotionEstimation( PredictionUnit& pu, { uiCostBest = uiCostTemp; uiBitsBest = uiBitsTemp; - memcpy( acMv, acMvTemp, sizeof(Mv) * 3 ); + memcpy( acMv, acMvTemp, sizeof(Mv) * 4 ); } } @@ -3680,10 +4440,10 @@ void InterSearch::xEstimateAffineAMVP( PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eRefPicList, int iRefIdx, - Mv acMvPred[3], + Mv acMvPred[4], Distortion* puiDistBiP ) { - Mv bestMvLT, bestMvRT, bestMvLB; + Mv bestMvLT, bestMvRT, bestMvLB, bestMvRB; int iBestIdx = 0; Distortion uiBestCost = std::numeric_limits::max(); @@ -3697,11 +4457,12 @@ void InterSearch::xEstimateAffineAMVP( PredictionUnit& pu, iBestIdx = 0; for( int i = 0 ; i < affineAMVPInfo.numCand; i++ ) { - Mv mv[3] = { affineAMVPInfo.mvCandLT[i], affineAMVPInfo.mvCandRT[i], affineAMVPInfo.mvCandLB[i] }; - Mv mvTrace[3] = { affineAMVPInfo.mvCandLT[i], affineAMVPInfo.mvCandRT[i], affineAMVPInfo.mvCandLB[i] }; + Mv mv[4] = { affineAMVPInfo.mvCandLT[i], affineAMVPInfo.mvCandRT[i], affineAMVPInfo.mvCandLB[i], affineAMVPInfo.mvCandRB[i] }; + Mv mvTrace[4] = { affineAMVPInfo.mvCandLT[i], affineAMVPInfo.mvCandRT[i], affineAMVPInfo.mvCandLB[i], affineAMVPInfo.mvCandRB[i] }; mvTrace[0].setHighPrec(); mvTrace[1].setHighPrec(); mvTrace[2].setHighPrec(); + mvTrace[3].setHighPrec(); Distortion uiTmpCost = xGetAffineTemplateCost( pu, origBuf, predBuf, mv, i, AMVP_MAX_NUM_CANDS, eRefPicList, iRefIdx ); @@ -3711,6 +4472,7 @@ void InterSearch::xEstimateAffineAMVP( PredictionUnit& pu, bestMvLT = affineAMVPInfo.mvCandLT[i]; bestMvRT = affineAMVPInfo.mvCandRT[i]; bestMvLB = affineAMVPInfo.mvCandLB[i]; + bestMvRB = affineAMVPInfo.mvCandRB[i]; iBestIdx = i; *puiDistBiP = uiTmpCost; } @@ -3720,6 +4482,7 @@ void InterSearch::xEstimateAffineAMVP( PredictionUnit& pu, acMvPred[0] = bestMvLT; acMvPred[1] = bestMvRT; acMvPred[2] = bestMvLB; + acMvPred[3] = bestMvRB; pu.mvpIdx[eRefPicList] = iBestIdx; pu.mvpNum[eRefPicList] = affineAMVPInfo.numCand; @@ -3733,6 +4496,7 @@ void InterSearch::xCopyAffineAMVPInfo (AffineAMVPInfo& src, AffineAMVPInfo& dst) ::memcpy( dst.mvCandLT, src.mvCandLT, sizeof(Mv)*src.numCand ); ::memcpy( dst.mvCandRT, src.mvCandRT, sizeof(Mv)*src.numCand ); ::memcpy( dst.mvCandLB, src.mvCandLB, sizeof(Mv)*src.numCand ); + ::memcpy( dst.mvCandRB, src.mvCandRB, sizeof(Mv)*src.numCand); } #endif diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h index 6cf72e3..ac48dcf 100644 --- a/source/Lib/EncoderLib/InterSearch.h +++ b/source/Lib/EncoderLib/InterSearch.h @@ -196,6 +196,8 @@ class InterSearch : public InterPrediction, CrossComponentPrediction void predInterSearch(CodingUnit& cu, Partitioner& partitioner ); + void predInterSearchPersp(CodingUnit& cu, Partitioner& partitioner, Mv bestCSMv[2][4], int bestCSRefIdx[2]); + /// set ME search range void setAdaptiveSearchRange ( int iDir, int iRefIdx, int iSearchRange) { CHECK(iDir >= MAX_NUM_REF_LIST_ADAPT_SR || iRefIdx>=int(MAX_IDX_ADAPT_SR), "Invalid index"); m_aaiAdaptSR[iDir][iRefIdx] = iSearchRange; } @@ -339,7 +341,7 @@ class InterSearch : public InterPrediction, CrossComponentPrediction bool bFastSkipBi #endif #if JVET_K0185_AFFINE_6PARA_ENC - , Mv mvAffine4Para[2][33][3] + , Mv mvAffine4Para[2][33][4] , int refIdx4Para[2] #endif ); @@ -347,9 +349,9 @@ class InterSearch : public InterPrediction, CrossComponentPrediction void xAffineMotionEstimation ( PredictionUnit& pu, PelUnitBuf& origBuf, RefPicList eRefPicList, - Mv acMvPred[3], + Mv acMvPred[4], int iRefIdxPred, - Mv acMv[3], + Mv acMv[4], uint32_t& ruiBits, Distortion& ruiCost, bool bBi = false @@ -360,14 +362,14 @@ class InterSearch : public InterPrediction, CrossComponentPrediction PelUnitBuf& origBuf, RefPicList eRefPicList, int iRefIdx, - Mv acMvPred[3], + Mv acMvPred[4], Distortion* puiDistBiP ); - Distortion xGetAffineTemplateCost( PredictionUnit& pu, PelUnitBuf& origBuf, PelUnitBuf& predBuf, Mv acMvCand[3], int iMVPIdx, int iMVPNum, RefPicList eRefPicList, int iRefIdx ); + Distortion xGetAffineTemplateCost( PredictionUnit& pu, PelUnitBuf& origBuf, PelUnitBuf& predBuf, Mv acMvCand[4], int iMVPIdx, int iMVPNum, RefPicList eRefPicList, int iRefIdx ); void xCopyAffineAMVPInfo ( AffineAMVPInfo& src, AffineAMVPInfo& dst ); - void xCheckBestAffineMVP ( PredictionUnit &pu, AffineAMVPInfo &affineAMVPInfo, RefPicList eRefPicList, Mv acMv[3], Mv acMvPred[3], int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost ); + void xCheckBestAffineMVP ( PredictionUnit &pu, AffineAMVPInfo &affineAMVPInfo, RefPicList eRefPicList, Mv acMv[4], Mv acMvPred[4], int& riMVPIdx, uint32_t& ruiBits, Distortion& ruiCost ); #endif void xExtDIFUpSamplingH ( CPelBuf* pcPattern ); void xExtDIFUpSamplingQ ( CPelBuf* pcPatternKey, Mv halfPelRef ); diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index 62d3f33..ed47237 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -563,7 +563,7 @@ void HLSWriter::codeSPSNext( const SPSNext& spsNext, const bool usePCM ) #if JVET_K0337_AFFINE_6PARA if ( spsNext.getUseAffine() ) { - WRITE_FLAG( spsNext.getUseAffineType() ? 1 : 0, "affine_type_flag" ); + WRITE_UVLC( spsNext.getUseAffineType(), "affine_type_flag" ); } #endif #endif