Commit 66ab3812 authored by Frank Bossen's avatar Frank Bossen

Merge branch 'Zhang/VVCSoftware_VTM-JVET-L0266-SW-HMVP'

parents 6be52465 371ff39b
Pipeline #221 passed with stage
......@@ -315,6 +315,10 @@ static const int GBI_NUM = 5; ///< the
static const int GBI_DEFAULT = ((uint8_t)(GBI_NUM >> 1)); ///< Default weighting index representing for w=0.5
static const int GBI_SIZE_CONSTRAINT = 256; ///< disabling GBi if cu size is smaller than 256
#endif
#if JVET_L0266_HMVP
static const int MAX_NUM_HMVP_CANDS = 6; ///< maximum number of HMVP candidates to be stored and used in merge list
static const int MAX_NUM_HMVP_AVMPCANDS = 4; ///< maximum number of HMVP candidates to be used in AMVP list
#endif
#if W0038_DB_OPT
static const int MAX_ENCODER_DEBLOCKING_QUALITY_LAYERS = 8 ;
......
......@@ -208,5 +208,11 @@ public:
}
};
#endif
#if JVET_L0266_HMVP
struct LutMotionCand
{
MotionInfo* motionCand;
int currCnt;
};
#endif
#endif // __MOTIONINFO__
......@@ -41,6 +41,9 @@
#include "Picture.h"
#include "dtrace_next.h"
#if JVET_L0266_HMVP
#include "UnitTools.h"
#endif
//! \ingroup CommonLib
//! \{
......@@ -135,6 +138,9 @@ Slice::Slice()
, m_uiMaxTTSizeIChroma ( 0 )
#endif
, m_uiMaxBTSize ( 0 )
#if JVET_L0266_HMVP
, m_MotionCandLut (NULL)
#endif
{
for(uint32_t i=0; i<NUM_REF_PIC_LIST_01; i++)
{
......@@ -171,11 +177,16 @@ Slice::Slice()
m_saoEnabledFlag[ch] = false;
}
#if JVET_L0266_HMVP
initMotionLUTs();
#endif
}
Slice::~Slice()
{
#if JVET_L0266_HMVP
destroyMotionLUTs();
#endif
}
......@@ -207,6 +218,9 @@ void Slice::initSlice()
m_enableTMVPFlag = true;
m_subPuMvpSubBlkSizeSliceEnable = false;
m_subPuMvpSubBlkLog2Size = 2;
#if JVET_L0266_HMVP
resetMotionLUTs();
#endif
}
void Slice::setDefaultClpRng( const SPS& sps )
......@@ -1570,7 +1584,75 @@ void Slice::stopProcessingTimer()
m_dProcessingTime += (double)(clock()-m_iProcessingStartTime) / CLOCKS_PER_SEC;
m_iProcessingStartTime = 0;
}
#if JVET_L0266_HMVP
void Slice::initMotionLUTs()
{
m_MotionCandLut = new LutMotionCand;
m_MotionCandLut->currCnt = 0;
m_MotionCandLut->motionCand = nullptr;
m_MotionCandLut->motionCand = new MotionInfo[MAX_NUM_HMVP_CANDS];
}
void Slice::destroyMotionLUTs()
{
delete[] m_MotionCandLut->motionCand;
m_MotionCandLut->motionCand = nullptr;
delete[] m_MotionCandLut;
m_MotionCandLut = NULL;
}
void Slice::resetMotionLUTs()
{
m_MotionCandLut->currCnt = 0;
}
MotionInfo Slice::getMotionInfoFromLUTs(int MotCandIdx) const
{
return m_MotionCandLut->motionCand[MotCandIdx];
}
void Slice::addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi)
{
int currCnt = lutMC->currCnt ;
bool pruned = false;
int sameCandIdx = -1;
for (int idx = 0; idx < currCnt; idx++)
{
if (lutMC->motionCand[idx] == newMi)
{
sameCandIdx = idx;
pruned = true;
break;
}
}
if (pruned || lutMC->currCnt == MAX_NUM_HMVP_CANDS)
{
int startIdx = pruned ? sameCandIdx : 0;
memmove(&lutMC->motionCand[startIdx], &lutMC->motionCand[startIdx+1], sizeof(MotionInfo)*(currCnt - sameCandIdx - 1));
memcpy(&lutMC->motionCand[lutMC->currCnt-1], &newMi, sizeof(MotionInfo));
}
else
{
memcpy(&lutMC->motionCand[lutMC->currCnt++], &newMi, sizeof(MotionInfo));
}
}
void Slice::updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu)
{
PredictionUnit *selectedPU = cu.firstPU;
if (cu.affine) { return; }
MotionInfo newMi = selectedPU->getMotionInfo();
addMotionInfoToLUTs(lutMC, newMi);
}
void Slice::copyMotionLUTs(LutMotionCand* Src, LutMotionCand* Dst)
{
memcpy(Dst->motionCand, Src->motionCand, sizeof(MotionInfo)*(std::min(Src->currCnt, MAX_NUM_HMVP_CANDS)));
Dst->currCnt = Src->currCnt;
}
#endif
unsigned Slice::getMinPictureDistance() const
{
......
......@@ -49,7 +49,10 @@
//! \ingroup CommonLib
//! \{
#if JVET_L0266_HMVP
#include "CommonLib/MotionInfo.h"
struct MotionInfo;
#endif
struct Picture;
......@@ -1598,6 +1601,9 @@ private:
uint32_t m_uiMaxBTSize;
AlfSliceParam m_alfSliceParam;
#if JVET_L0266_HMVP
LutMotionCand* m_MotionCandLut;
#endif
public:
Slice();
......@@ -1874,6 +1880,20 @@ public:
void setAlfSliceParam( AlfSliceParam& alfSliceParam ) { m_alfSliceParam = alfSliceParam; }
AlfSliceParam& getAlfSliceParam() { return m_alfSliceParam; }
#if JVET_L0266_HMVP
void initMotionLUTs ();
void destroyMotionLUTs ();
void resetMotionLUTs();
int getAvailableLUTMrgNum() const { return m_MotionCandLut->currCnt; }
MotionInfo getMotionInfoFromLUTs(int MotCandIdx) const;
LutMotionCand* getMotionLUTs() { return m_MotionCandLut; }
void addMotionInfoToLUTs(LutMotionCand* lutMC, MotionInfo newMi);
void updateMotionLUTs(LutMotionCand* lutMC, CodingUnit & cu);
void copyMotionLUTs(LutMotionCand* Src, LutMotionCand* Dst);
#endif
protected:
Picture* xGetRefPic (PicList& rcListPic, int poc);
......
......@@ -55,6 +55,7 @@
#define JVET_L0081_VPDU_SPLIT_CONSTRAINTS 1 // VPDU constraints for binary and ternary partitions
#define JVET_L0104_NO_4x4BI_INTER_CU 1 // Prohibit 4x4 bi-prediction for inter CU
#define JVET_L0266_HMVP 1 //History-based MVP
#define JVET_L0553_FIX_INITQP 1
......
......@@ -494,11 +494,95 @@ uint32_t PU::getFinalIntraMode( const PredictionUnit &pu, const ChannelType &chT
return uiIntraMode;
}
#if JVET_L0266_HMVP
bool PU::xCheckSimilarMotion(const int mergeCandIndex, const int prevCnt, const MergeCtx mergeCandList, bool hasPruned[MRG_MAX_NUM_CANDS])
{
for (uint32_t ui = 0; ui < prevCnt; ui++)
{
if (hasPruned[ui])
{
continue;
}
if (mergeCandList.interDirNeighbours[ui] == mergeCandList.interDirNeighbours[mergeCandIndex])
{
if (mergeCandList.interDirNeighbours[ui] == 3)
{
int offset0 = (ui * 2);
int offset1 = (mergeCandIndex * 2);
if (mergeCandList.mvFieldNeighbours[offset0].refIdx == mergeCandList.mvFieldNeighbours[offset1].refIdx &&
mergeCandList.mvFieldNeighbours[offset0 + 1].refIdx == mergeCandList.mvFieldNeighbours[offset1 + 1].refIdx &&
mergeCandList.mvFieldNeighbours[offset0].mv == mergeCandList.mvFieldNeighbours[offset1].mv &&
mergeCandList.mvFieldNeighbours[offset0 + 1].mv == mergeCandList.mvFieldNeighbours[offset1 + 1].mv
)
{
hasPruned[ui] = true;
return true;
}
}
else
{
int offset0 = (ui * 2) + mergeCandList.interDirNeighbours[ui] - 1;
int offset1 = (mergeCandIndex * 2) + mergeCandList.interDirNeighbours[ui] - 1;
if (mergeCandList.mvFieldNeighbours[offset0].refIdx == mergeCandList.mvFieldNeighbours[offset1].refIdx &&
mergeCandList.mvFieldNeighbours[offset0].mv == mergeCandList.mvFieldNeighbours[offset1].mv
)
{
hasPruned[ui] = true;
return true;
}
}
}
}
return false;
}
#if JVET_L0090_PAIR_AVG
bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos)
#else
bool PU::addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter[MRG_MAX_NUM_CANDS], bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos)
#endif
{
MotionInfo miNeighbor;
bool hasPruned[MRG_MAX_NUM_CANDS];
memset(hasPruned, 0, MRG_MAX_NUM_CANDS * sizeof(bool));
if (isAvailableSubPu)
{
hasPruned[subPuMvpPos] = true;
}
int num_avai_candInLUT = slice.getAvailableLUTMrgNum();
for (int mrgIdx = 1; mrgIdx <= num_avai_candInLUT; mrgIdx++)
{
miNeighbor = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx);
mrgCtx.interDirNeighbours[cnt] = miNeighbor.interDir;
mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]);
if (slice.isInterB())
{
mrgCtx.mvFieldNeighbours[(cnt << 1) + 1].setMvField(miNeighbor.mv[1], miNeighbor.refIdx[1]);
}
if (!xCheckSimilarMotion(cnt, prevCnt, mrgCtx, hasPruned))
{
#if !JVET_L0090_PAIR_AVG
isCandInter[cnt] = true;
#endif
if (mrgCandIdx == cnt && canFastExit)
{
return true;
}
cnt ++;
if (cnt == maxNumMergeCandMin1)
{
break;
}
}
}
return false;
}
#endif
void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
#if JVET_L0054_MMVD
int mmvdList,
int mmvdList,
#endif
const int& mrgCandIdx )
const int& mrgCandIdx )
{
const CodingStructure &cs = *pu.cs;
const Slice &slice = *pu.cs->slice;
......@@ -930,7 +1014,21 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
{
return;
}
#if JVET_L0266_HMVP
int maxNumMergeCandMin1 = maxNumMergeCand - 1;
if (cnt != maxNumMergeCandMin1)
{
#if JVET_L0090_PAIR_AVG
bool bFound = addMergeHMVPCand(slice, mrgCtx, canFastExit, mrgCandIdx, maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos);
#else
bool bFound = addMergeHMVPCand(slice, mrgCtx, isCandInter, canFastExit, mrgCandIdx, maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos);
#endif
if (bFound)
{
return;
}
}
#endif
#if JVET_L0090_PAIR_AVG
// pairwise-average candidates
{
......@@ -1022,8 +1120,11 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx,
uint32_t uiArrayAddr = cnt;
#if !JVET_L0090_PAIR_AVG
#if JVET_L0266_HMVP
uint32_t uiCutoff = std::min( uiArrayAddr, 3u );
#else
uint32_t uiCutoff = std::min( uiArrayAddr, 4u );
#endif
if (slice.isInterB())
{
static const uint32_t NUM_PRIORITY_LIST = 12;
......@@ -1469,9 +1570,37 @@ void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const in
if ((C0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdx_Col)) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdx_Col))
{
#if JVET_L0266_HMVP
if (pu.cu->imv != 0)
{
unsigned imvShift = pu.cu->imv << 1;
roundMV(cColMv, imvShift);
}
int i = 0;
for (i = 0; i < pInfo->numCand; i++)
{
if (cColMv == pInfo->mvCand[i])
{
break;
}
}
if (i == pInfo->numCand)
{
pInfo->mvCand[pInfo->numCand++] = cColMv;
}
#else
pInfo->mvCand[pInfo->numCand++] = cColMv;
#endif
}
}
#if JVET_L0266_HMVP
if (pInfo->numCand < AMVP_MAX_NUM_CANDS)
{
const int currRefPOC = cs.slice->getRefPic(eRefPicList, refIdx)->getPOC();
const RefPicList eRefPicList2nd = (eRefPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
addAMVPHMVPCand(pu, eRefPicList, eRefPicList2nd, currRefPOC, *pInfo, pu.cu->imv);
}
#endif
if (pInfo->numCand > AMVP_MAX_NUM_CANDS)
{
pInfo->numCand = AMVP_MAX_NUM_CANDS;
......@@ -2030,6 +2159,58 @@ bool PU::addMVPCandWithScaling( const PredictionUnit &pu, const RefPicList &eRef
return false;
}
#if JVET_L0266_HMVP
void PU::addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, const RefPicList eRefPicList2nd, const int currRefPOC, AMVPInfo &info, uint8_t imv)
{
const Slice &slice = *(*pu.cs).slice;
MotionInfo neibMi;
int i = 0;
unsigned imvShift = imv << 1;
int num_avai_candInLUT = slice.getAvailableLUTMrgNum();
int num_allowedCand = std::min(MAX_NUM_HMVP_AVMPCANDS, num_avai_candInLUT);
for (int mrgIdx = 1; mrgIdx <= num_allowedCand; mrgIdx++)
{
if (info.numCand >= AMVP_MAX_NUM_CANDS)
{
return;
}
neibMi = slice.getMotionInfoFromLUTs(num_avai_candInLUT - mrgIdx);
for (int predictorSource = 0; predictorSource < 2; predictorSource++)
{
const RefPicList eRefPicListIndex = (predictorSource == 0) ? eRefPicList : eRefPicList2nd;
const int neibRefIdx = neibMi.refIdx[eRefPicListIndex];
if (neibRefIdx >= 0 && currRefPOC == slice.getRefPOC(eRefPicListIndex, neibRefIdx))
{
Mv pmv = neibMi.mv[eRefPicListIndex];
if (imv != 0)
{
roundMV(pmv, imvShift);
}
for (i = 0; i < info.numCand; i++)
{
if (pmv == info.mvCand[i])
{
break;
}
}
if (i == info.numCand)
{
info.mvCand[info.numCand++] = pmv;
if (info.numCand >= AMVP_MAX_NUM_CANDS)
{
return;
}
}
}
}
}
}
#endif
bool PU::isBipredRestriction(const PredictionUnit &pu)
{
const SPSNext &spsNext = pu.cs->sps->getSpsNext();
......
......@@ -125,6 +125,15 @@ namespace PU
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] );
#if JVET_L0266_HMVP
bool xCheckSimilarMotion(const int mergeCandIndex, const int prevCnt, const MergeCtx mergeCandList, bool hasPruned[MRG_MAX_NUM_CANDS]);
#if JVET_L0090_PAIR_AVG
bool addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos);
#else
bool addMergeHMVPCand(const Slice &slice, MergeCtx& mrgCtx, bool isCandInter[MRG_MAX_NUM_CANDS], bool canFastExit, const int& mrgCandIdx, const uint32_t maxNumMergeCandMin1, int &cnt, const int prevCnt, bool isAvailableSubPu, unsigned subPuMvpPos);
#endif
void addAMVPHMVPCand(const PredictionUnit &pu, const RefPicList eRefPicList, const RefPicList eRefPicList2nd, const int currRefPOC, AMVPInfo &info, uint8_t imv);
#endif
bool isBipredRestriction (const PredictionUnit &pu);
void spanMotionInfo ( PredictionUnit &pu, const MergeCtx &mrgCtx = MergeCtx() );
void applyImv ( PredictionUnit &pu, MergeCtx &mrgCtx, InterPrediction *interPred = NULL );
......
......@@ -316,6 +316,9 @@ void DecCu::xReconInter(CodingUnit &cu)
{
// inter prediction
m_pcInterPred->motionCompensation( cu );
#if JVET_L0266_HMVP
cu.slice->updateMotionLUTs(cu.slice->getMotionLUTs(), cu);
#endif
DTRACE ( g_trace_ctx, D_TMP, "pred " );
DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getPredBuf( cu ), &cu.Y() );
......
This diff is collapsed.
......@@ -95,6 +95,11 @@ private:
CodingStructure ***m_pTempCS;
CodingStructure ***m_pBestCS;
#if JVET_L0266_HMVP
LutMotionCand ***m_pTempMotLUTs;
LutMotionCand ***m_pBestMotLUTs;
LutMotionCand ***m_pSplitTempMotLUTs;
#endif
// Access channel
EncCfg* m_pcEncCfg;
IntraSearch* m_pcIntraSearch;
......@@ -169,15 +174,31 @@ public:
protected:
void xCompressCU ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm );
void xCompressCU ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm
#if JVET_L0266_HMVP
, LutMotionCand *&tempMotCandLUTs
, LutMotionCand *&bestMotCandLUTs
#endif
);
#if ENABLE_SPLIT_PARALLELISM
void xCompressCUParallel ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm );
void copyState ( EncCu* other, Partitioner& pm, const UnitArea& currArea, const bool isDist );
#endif
void xCheckBestMode ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestmode );
#if JVET_L0266_HMVP
bool
#else
void
#endif
xCheckBestMode ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestmode );
void xCheckModeSplit ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode );
void xCheckModeSplit ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode
#if JVET_L0266_HMVP
, LutMotionCand* &tempMotCandLUTs
, LutMotionCand* &bestMotCandLUTs
, UnitArea parArea
#endif
);
void xCheckRDCostIntra ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode );
void xCheckIntraPCM ( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &pm, const EncTestMode& encTestMode );
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment