diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 40c4cacf91de61c19291d33559878411f0eef72b..167224a7153bdd0e8f57204c2ddcd9226a4483bb 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,8 @@ #include <assert.h> #include <cassert> +#define JVET_L0090_PAIR_AVG 1 // Add pairwise average candidates, replace HEVC combined candidates + #define JVET_L0392_ALF_INIT_STATE 1 #define JVET_L0664_ALF_REMOVE_LUMA_5x5 1 diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index feb106da69a7e27d1bf3a27f4015b3240c911d77..8497704fb108392a82aa431fb43beec79311e7e2 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -502,11 +502,16 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co const uint32_t maxNumMergeCand = slice.getMaxNumMergeCand(); const bool canFastExit = pu.cs->pps->getLog2ParallelMergeLevelMinus2() == 0; +#if !JVET_L0090_PAIR_AVG + // this variable is unused if remove HEVC combined candidates bool isCandInter[MRG_MAX_NUM_CANDS]; +#endif for (uint32_t ui = 0; ui < maxNumMergeCand; ++ui) { +#if !JVET_L0090_PAIR_AVG isCandInter[ui] = false; +#endif mrgCtx.interDirNeighbours[ui] = 0; mrgCtx.mrgTypeNeighbours [ui] = MRG_TYPE_DEFAULT_N; mrgCtx.mvFieldNeighbours[(ui << 1) ].refIdx = NOT_VALID; @@ -532,7 +537,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co { miLeft = puLeft->getMotionInfo( posLB.offset(-1, 0) ); +#if !JVET_L0090_PAIR_AVG isCandInter[cnt] = true; +#endif // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miLeft.interDir; @@ -570,7 +577,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co if( !isAvailableA1 || ( miAbove != miLeft ) ) { +#if !JVET_L0090_PAIR_AVG isCandInter[cnt] = true; +#endif // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miAbove.interDir; @@ -612,7 +621,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co if( !isAvailableB1 || ( miAbove != miAboveRight ) ) #endif { +#if !JVET_L0090_PAIR_AVG isCandInter[cnt] = true; +#endif // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miAboveRight.interDir; @@ -653,7 +664,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co if( !isAvailableA1 || ( miBelowLeft != miLeft ) ) #endif { +#if !JVET_L0090_PAIR_AVG isCandInter[cnt] = true; +#endif // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miBelowLeft.interDir; @@ -700,7 +713,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co if( isAvailableSubPu ) { +#if !JVET_L0090_PAIR_AVG isCandInter[cnt] = true; +#endif mrgCtx.mrgTypeNeighbours[cnt] = MRG_TYPE_SUBPU_ATMVP; @@ -736,7 +751,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co if( ( !isAvailableA1 || ( miLeft != miAboveLeft ) ) && ( !isAvailableB1 || ( miAbove != miAboveLeft ) ) ) #endif { +#if !JVET_L0090_PAIR_AVG isCandInter[cnt] = true; +#endif // get Inter Dir mrgCtx.interDirNeighbours[cnt] = miAboveLeft.interDir; @@ -867,7 +884,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co if( addTMvp ) { mrgCtx.interDirNeighbours[uiArrayAddr] = dir; +#if !JVET_L0090_PAIR_AVG isCandInter [uiArrayAddr] = true; +#endif if( mrgCandIdx == cnt && canFastExit ) { @@ -885,7 +904,97 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co return; } +#if JVET_L0090_PAIR_AVG + // pairwise-average candidates + { + const int cutoff = std::min( cnt, 4 ); + const int end = cutoff * (cutoff - 1) / 2; + constexpr int PRIORITY_LIST0[] = { 0, 0, 1, 0, 1, 2 }; + constexpr int PRIORITY_LIST1[] = { 1, 2, 2, 3, 3, 3 }; + + for( int idx = 0; idx < end && cnt != maxNumMergeCand; idx++ ) + { + const int i = PRIORITY_LIST0[idx]; + const int j = PRIORITY_LIST1[idx]; + + mrgCtx.mvFieldNeighbours[cnt * 2].setMvField( Mv( 0, 0 ), NOT_VALID ); + mrgCtx.mvFieldNeighbours[cnt * 2 + 1].setMvField( Mv( 0, 0 ), NOT_VALID ); + // calculate average MV for L0 and L1 seperately + unsigned char interDir = 0; + for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ ) + { + const short refIdxI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].refIdx; + const short refIdxJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].refIdx; + + // both MVs are invalid, skip + if( (refIdxI == NOT_VALID) && (refIdxJ == NOT_VALID) ) + { + continue; + } + + interDir += 1 << refListId; + // both MVs are valid, average these two MVs + if( (refIdxI != NOT_VALID) && (refIdxJ != NOT_VALID) ) + { + const Mv& MvI = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv; + const Mv& MvJ = mrgCtx.mvFieldNeighbours[j * 2 + refListId].mv; + + // average two MVs + Mv avgMv = MvI; +#if !REMOVE_MV_ADAPT_PREC + if( pu.cs->sps->getSpsNext().getUseHighPrecMv() ) + { + avgMv.setHighPrec(); + } +#endif + avgMv += MvJ; + avgMv.setHor( avgMv.getHor() / 2 ); + avgMv.setVer( avgMv.getVer() / 2 ); + + mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( avgMv, refIdxI ); + } + // only one MV is valid, take the only one MV + else if( refIdxI != NOT_VALID ) + { + Mv singleMv = mrgCtx.mvFieldNeighbours[i * 2 + refListId].mv; +#if !REMOVE_MV_ADAPT_PREC + if( pu.cs->sps->getSpsNext().getUseHighPrecMv() ) + { + singleMv.setHighPrec(); + } +#endif + mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxI ); + } + else if( refIdxJ != NOT_VALID ) + { + Mv singleMv = mrgCtx.mvFieldNeighbours[j * 2 + refListId].mv; +#if !REMOVE_MV_ADAPT_PREC + if( pu.cs->sps->getSpsNext().getUseHighPrecMv() ) + { + singleMv.setHighPrec(); + } +#endif + mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxJ ); + } + } + + mrgCtx.interDirNeighbours[cnt] = interDir; + if( interDir > 0 ) + { + cnt++; + } + } + + // early termination + if( cnt == maxNumMergeCand ) + { + return; + } + } +#endif + uint32_t uiArrayAddr = cnt; +#if !JVET_L0090_PAIR_AVG uint32_t uiCutoff = std::min( uiArrayAddr, 4u ); if (slice.isInterB()) @@ -928,6 +1037,7 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co { return; } +#endif int iNumRefIdx = slice.isInterB() ? std::min(slice.getNumRefIdx(REF_PIC_LIST_0), slice.getNumRefIdx(REF_PIC_LIST_1)) : slice.getNumRefIdx(REF_PIC_LIST_0); @@ -935,7 +1045,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, co int refcnt = 0; while (uiArrayAddr < maxNumMergeCand) { +#if !JVET_L0090_PAIR_AVG isCandInter [uiArrayAddr ] = true; +#endif mrgCtx.interDirNeighbours [uiArrayAddr ] = 1; mrgCtx.mvFieldNeighbours [uiArrayAddr << 1].setMvField(Mv(0, 0), r);