Commit cf726611 authored by Xiang Li's avatar Xiang Li
Browse files

Merge branch 'JVET-N0247' into 'master'

JVET-N0247:  Improvement of Hash Motion Estimation

See merge request jvet/VVCSoftware_VTM!486
parents e72fc404 0921297a
......@@ -109,6 +109,12 @@ TComHash::TComHash()
{
m_lookupTable = NULL;
tableHasContent = false;
#if JVET_N0247_HASH_IMPROVE
for (int i = 0; i < 5; i++)
{
hashPic[i] = NULL;
}
#endif
}
TComHash::~TComHash()
......@@ -120,7 +126,25 @@ TComHash::~TComHash()
m_lookupTable = NULL;
}
}
#if JVET_N0247_HASH_IMPROVE
void TComHash::create(int picWidth, int picHeight)
{
if (m_lookupTable)
{
clearAll();
}
if (!hashPic[0])
{
for (int k = 0; k < 5; k++)
{
hashPic[k] = new uint16_t[picWidth*picHeight];
}
}
if (m_lookupTable)
{
return;
}
#else
void TComHash::create()
{
if (m_lookupTable != NULL)
......@@ -128,6 +152,7 @@ void TComHash::create()
clearAll();
return;
}
#endif
int maxAddr = 1 << (m_CRCBits + m_blockSizeBits);
m_lookupTable = new std::vector<BlockHash>*[maxAddr];
memset(m_lookupTable, 0, sizeof(std::vector<BlockHash>*) * maxAddr);
......@@ -136,6 +161,16 @@ void TComHash::create()
void TComHash::clearAll()
{
#if JVET_N0247_HASH_IMPROVE
if (hashPic[0])
{
for (int k = 0; k < 5; k++)
{
delete[] hashPic[k];
hashPic[k] = NULL;
}
}
#endif
tableHasContent = false;
if (m_lookupTable == NULL)
{
......@@ -251,6 +286,7 @@ void TComHash::generateBlock2x2HashValue(const PelUnitBuf &curPicBuf, int picWid
delete[] p;
}
#if !JVET_N0247_HASH_IMPROVE
void TComHash::generateRectangleHashValue(int picWidth, int picHeight, int width, int height, uint32_t* srcPicBlockHash[2], uint32_t* dstPicBlockHash[2], bool* srcPicBlockSameInfo[3], bool* dstPicBlockSameInfo[3])
{
//at present, only support 1:2(2:1) retangle hash value
......@@ -328,6 +364,7 @@ void TComHash::generateRectangleHashValue(int picWidth, int picHeight, int width
delete[] p;
}
#endif
void TComHash::generateBlockHashValue(int picWidth, int picHeight, int width, int height, uint32_t* srcPicBlockHash[2], uint32_t* dstPicBlockHash[2], bool* srcPicBlockSameInfo[3], bool* dstPicBlockSameInfo[3])
{
......@@ -372,15 +409,21 @@ void TComHash::generateBlockHashValue(int picWidth, int picHeight, int width, in
if (width >= 4)
{
#if !JVET_N0247_HASH_IMPROVE
int widthMinus1 = width - 1;
int heightMinus1 = height - 1;
#endif
pos = 0;
for (int yPos = 0; yPos < yEnd; yPos++)
{
for (int xPos = 0; xPos < xEnd; xPos++)
{
#if JVET_N0247_HASH_IMPROVE
dstPicBlockSameInfo[2][pos] = (!dstPicBlockSameInfo[0][pos] && !dstPicBlockSameInfo[1][pos]);
#else
dstPicBlockSameInfo[2][pos] = (!dstPicBlockSameInfo[0][pos] && !dstPicBlockSameInfo[1][pos]) || (((xPos & widthMinus1) == 0) && ((yPos & heightMinus1) == 0));
#endif
pos++;
}
pos += width - 1;
......@@ -404,12 +447,18 @@ void TComHash::addToHashMapByRowWithPrecalData(uint32_t* picHash[2], bool* picIs
addValue <<= m_CRCBits;
int crcMask = 1 << m_CRCBits;
crcMask -= 1;
#if JVET_N0247_HASH_IMPROVE
int blockIdx = g_aucLog2[width] - 2;
#endif
for (int xPos = 0; xPos < xEnd; xPos++)
{
for (int yPos = 0; yPos < yEnd; yPos++)
{
int pos = yPos * picWidth + xPos;
#if JVET_N0247_HASH_IMPROVE
hashPic[blockIdx][pos] = (uint16_t)(srcHash[1][pos] & crcMask);
#endif
//valid data
if (srcIsAdded[pos])
{
......@@ -557,7 +606,38 @@ bool TComHash::isBlock2x2ColSameValue(unsigned char* p, bool includeAllComponent
return true;
}
#if JVET_N0247_HASH_IMPROVE
bool TComHash::isHorizontalPerfectLuma(const Pel* srcPel, int stride, int width, int height)
{
for (int i = 0; i < height; i++)
{
for (int j = 1; j < width; j++)
{
if (srcPel[j] != srcPel[0])
{
return false;
}
}
srcPel += stride;
}
return true;
}
bool TComHash::isVerticalPerfectLuma(const Pel* srcPel, int stride, int width, int height)
{
for (int i = 0; i < width; i++)
{
for (int j = 1; j < height; j++)
{
if (srcPel[j*stride + i] != srcPel[i])
{
return false;
}
}
}
return true;
}
#endif
bool TComHash::getBlockHashValue(const PelUnitBuf &curPicBuf, int width, int height, int xStart, int yStart, const BitDepths bitDepths, uint32_t& hashValue1, uint32_t& hashValue2)
{
int addValue = m_blockSizeToIndex[width][height];
......@@ -712,8 +792,10 @@ void TComHash::initBlockSizeToIndex()
m_blockSizeToIndex[32][32] = 2;
m_blockSizeToIndex[64][64] = 3;
m_blockSizeToIndex[4][4] = 4;
#if !JVET_N0247_HASH_IMPROVE
m_blockSizeToIndex[4][8] = 5;
m_blockSizeToIndex[8][4] = 6;
#endif
}
uint32_t TComHash::getCRCValue1(unsigned char* p, int length)
......
......@@ -91,7 +91,11 @@ struct TComHash
public:
TComHash();
~TComHash();
#if JVET_N0247_HASH_IMPROVE
void create(int picWidth, int picHeight);
#else
void create();
#endif
void clearAll();
void addToTable(uint32_t hashValue, const BlockHash& blockHash);
int count(uint32_t hashValue);
......@@ -102,11 +106,15 @@ public:
void generateBlock2x2HashValue(const PelUnitBuf &curPicBuf, int picWidth, int picHeight, const BitDepths bitDepths, uint32_t* picBlockHash[2], bool* picBlockSameInfo[3]);
void generateBlockHashValue(int picWidth, int picHeight, int width, int height, uint32_t* srcPicBlockHash[2], uint32_t* dstPicBlockHash[2], bool* srcPicBlockSameInfo[3], bool* dstPicBlockSameInfo[3]);
#if !JVET_N0247_HASH_IMPROVE
void generateRectangleHashValue(int picWidth, int picHeight, int width, int height, uint32_t* srcPicBlockHash[2], uint32_t* dstPicBlockHash[2], bool* srcPicBlockSameInfo[3], bool* dstPicBlockSameInfo[3]);
#endif
void addToHashMapByRowWithPrecalData(uint32_t* srcHash[2], bool* srcIsSame, int picWidth, int picHeight, int width, int height);
bool isInitial() { return tableHasContent; }
void setInitial() { tableHasContent = true; }
#if JVET_N0247_HASH_IMPROVE
uint16_t* getHashPic(int baseSize) const { return hashPic[g_aucLog2[baseSize] - 2]; }
#endif
public:
......@@ -117,10 +125,17 @@ public:
static bool isBlock2x2ColSameValue(unsigned char* p, bool includeAllComponent = true);
static bool getBlockHashValue(const PelUnitBuf &curPicBuf, int width, int height, int xStart, int yStart, const BitDepths bitDepths, uint32_t& hashValue1, uint32_t& hashValue2);
static void initBlockSizeToIndex();
#if JVET_N0247_HASH_IMPROVE
static bool isHorizontalPerfectLuma(const Pel* srcPel, int stride, int width, int height);
static bool isVerticalPerfectLuma(const Pel* srcPel, int stride, int width, int height);
#endif
private:
std::vector<BlockHash>** m_lookupTable;
bool tableHasContent;
#if JVET_N0247_HASH_IMPROVE
uint16_t* hashPic[5];//4x4 ~ 64x64
#endif
private:
static const int m_CRCBits = 16;
......
......@@ -1188,17 +1188,21 @@ void Picture::addPictureToHashMapForInter()
bIsBlockSame[i][j] = new bool[picWidth*picHeight];
}
}
#if JVET_N0247_HASH_IMPROVE
m_hashMap.create(picWidth, picHeight);
#else
m_hashMap.create();
#endif
m_hashMap.generateBlock2x2HashValue(getOrigBuf(), picWidth, picHeight, slices[0]->getSPS()->getBitDepths(), blockHashValues[0], bIsBlockSame[0]);//2x2
m_hashMap.generateBlockHashValue(picWidth, picHeight, 4, 4, blockHashValues[0], blockHashValues[1], bIsBlockSame[0], bIsBlockSame[1]);//4x4
m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[1], bIsBlockSame[1][2], picWidth, picHeight, 4, 4);
#if !JVET_N0247_HASH_IMPROVE
m_hashMap.generateRectangleHashValue(picWidth, picHeight, 8, 4, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//8x4
m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 8, 4);
m_hashMap.generateRectangleHashValue(picWidth, picHeight, 4, 8, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//4x8
m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 4, 8);
#endif
m_hashMap.generateBlockHashValue(picWidth, picHeight, 8, 8, blockHashValues[1], blockHashValues[0], bIsBlockSame[1], bIsBlockSame[0]);//8x8
m_hashMap.addToHashMapByRowWithPrecalData(blockHashValues[0], bIsBlockSame[0][2], picWidth, picHeight, 8, 8);
......
......@@ -1164,6 +1164,9 @@ void Slice::applyReferencePictureSet( PicList& rcListPic, const ReferencePicture
if( ! pcPic->referenced)
{
#if JVET_N0247_HASH_IMPROVE
pcPic->getHashMap()->clearAll();
#endif
continue;
}
......
......@@ -133,6 +133,8 @@
#define JVET_N0325_BDOF 1 // unified right-shifts for BDOF derivation
#define JVET_N0247_HASH_IMPROVE 1 // Improve hash motion estimation
#define JVET_N0449_MMVD_SIMP 1 // Configurable number of mmvd distance entries used
#define JVET_N0363_INTRA_COST_MOD 1 // Modified cost criterion for intra encoder search
......
......@@ -1662,8 +1662,12 @@ void EncCu::xCheckRDCostHashInter( CodingStructure *&tempCS, CodingStructure *&b
}
}
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
#if JVET_N0247_HASH_IMPROVE
int minSize = min(cu.lwidth(), cu.lheight());
if (minSize < 64)
#else
if (cu.lwidth() != 64)
#endif
{
isPerfectMatch = false;
}
......
......@@ -1396,7 +1396,12 @@ void EncModeCtrlMTnoRQT::initCULevel( Partitioner &partitioner, const CodingStru
}
if (m_pcEncCfg->getUseHashME())
{
#if JVET_N0247_HASH_IMPROVE
int minSize = min(cs.area.lwidth(), cs.area.lheight());
if (minSize < 128 && minSize >= 4)
#else
if ((cs.area.lwidth() == cs.area.lheight() && cs.area.lwidth() <= 64 && cs.area.lwidth() >= 4) || (cs.area.lwidth() == 4 && cs.area.lheight() == 8) || (cs.area.lwidth() == 8 && cs.area.lheight() == 4))
#endif
{
m_ComprCUCtxList.back().testModes.push_back({ ETM_HASH_INTER, ETO_STANDARD, qp, lossless });
}
......
......@@ -1799,7 +1799,301 @@ void InterSearch::selectMatchesInter(const MapIterator& itBegin, int count, std:
}
}
}
#if JVET_N0247_HASH_IMPROVE
void InterSearch::selectRectangleMatchesInter(const MapIterator& itBegin, int count, std::list<BlockHash>& listBlockHash, const BlockHash& currBlockHash, int width, int height, int idxNonSimple, unsigned int* &hashValues, int baseNum, int picWidth, int picHeight, bool isHorizontal, uint16_t* curHashPic)
{
const int maxReturnNumber = 5;
int baseSize = min(width, height);
unsigned int crcMask = 1 << 16;
crcMask -= 1;
listBlockHash.clear();
std::list<int> listCost;
listCost.clear();
MapIterator it = itBegin;
for (int i = 0; i < count; i++, it++)
{
if ((*it).hashValue2 != currBlockHash.hashValue2)
{
continue;
}
int xRef = (*it).x;
int yRef = (*it).y;
if (isHorizontal)
{
xRef -= idxNonSimple * baseSize;
}
else
{
yRef -= idxNonSimple * baseSize;
}
if (xRef < 0 || yRef < 0 || xRef + width >= picWidth || yRef + height >= picHeight)
{
continue;
}
//check Other baseSize hash values
uint16_t* refHashValue = curHashPic + yRef * picWidth + xRef;
bool isSame = true;
for (int k = 0; k < baseNum; k++)
{
if ((*refHashValue) != (uint16_t)(hashValues[k] & crcMask))
{
isSame = false;
break;
}
refHashValue += (isHorizontal ? baseSize : (baseSize*picWidth));
}
if (!isSame)
{
continue;
}
int currCost = RdCost::xGetExpGolombNumberOfBits(xRef - currBlockHash.x) +
RdCost::xGetExpGolombNumberOfBits(yRef - currBlockHash.y);
BlockHash refBlockHash;
refBlockHash.hashValue2 = (*it).hashValue2;
refBlockHash.x = xRef;
refBlockHash.y = yRef;
if (listBlockHash.size() < maxReturnNumber)
{
addToSortList(listBlockHash, listCost, currCost, refBlockHash);
}
else if (!listCost.empty() && currCost < listCost.back())
{
listCost.pop_back();
listBlockHash.pop_back();
addToSortList(listBlockHash, listCost, currCost, refBlockHash);
}
}
}
bool InterSearch::xRectHashInterEstimation(PredictionUnit& pu, RefPicList& bestRefPicList, int& bestRefIndex, Mv& bestMv, Mv& bestMvd, int& bestMVPIndex, bool& isPerfectMatch)
{
int width = pu.cu->lumaSize().width;
int height = pu.cu->lumaSize().height;
int baseSize = min(width, height);
bool isHorizontal = true;;
int baseNum = 0;
if (height < width)
{
isHorizontal = true;
baseNum = 1 << (g_aucLog2[width] - g_aucLog2[height]);
}
else
{
isHorizontal = false;
baseNum = 1 << (g_aucLog2[height] - g_aucLog2[width]);
}
int xPos = pu.cu->lumaPos().x;
int yPos = pu.cu->lumaPos().y;
const int currStride = pu.cs->picture->getOrigBuf().get(COMPONENT_Y).stride;
const Pel* curPel = pu.cs->picture->getOrigBuf().get(COMPONENT_Y).buf + yPos * currStride + xPos;
int picWidth = pu.cu->slice->getSPS()->getPicWidthInLumaSamples();
int picHeight = pu.cu->slice->getSPS()->getPicHeightInLumaSamples();
int xBase = xPos;
int yBase = yPos;
const Pel* basePel = curPel;
int idxNonSimple = -1;
unsigned int* hashValue1s = new unsigned int[baseNum];
unsigned int* hashValue2s = new unsigned int[baseNum];
for (int k = 0; k < baseNum; k++)
{
if (isHorizontal)
{
xBase = xPos + k * baseSize;
basePel = curPel + k * baseSize;
}
else
{
yBase = yPos + k * baseSize;
basePel = curPel + k * baseSize * currStride;
}
if (idxNonSimple == -1 && !TComHash::isHorizontalPerfectLuma(basePel, currStride, baseSize, baseSize) && !TComHash::isVerticalPerfectLuma(basePel, currStride, baseSize, baseSize))
{
idxNonSimple = k;
}
TComHash::getBlockHashValue((pu.cs->picture->getOrigBuf()), baseSize, baseSize, xBase, yBase, pu.cu->slice->getSPS()->getBitDepths(), hashValue1s[k], hashValue2s[k]);
}
if (idxNonSimple == -1)
{
idxNonSimple = 0;
}
Distortion bestCost = UINT64_MAX;
BlockHash currBlockHash;
currBlockHash.x = xPos;//still use the first base block location
currBlockHash.y = yPos;
currBlockHash.hashValue2 = hashValue2s[idxNonSimple];
m_pcRdCost->setDistParam(m_cDistParam, pu.cs->getOrgBuf(pu).Y(), 0, 0, m_lumaClpRng.bd, COMPONENT_Y, 0, 1, false);
int imvBest = 0;
int numPredDir = pu.cu->slice->isInterP() ? 1 : 2;
for (int refList = 0; refList < numPredDir; refList++)
{
RefPicList eRefPicList = (refList == 0) ? REF_PIC_LIST_0 : REF_PIC_LIST_1;
int refPicNumber = pu.cu->slice->getNumRefIdx(eRefPicList);
for (int refIdx = 0; refIdx < refPicNumber; refIdx++)
{
int bitsOnRefIdx = 1;
if (refPicNumber > 1)
{
bitsOnRefIdx += refIdx + 1;
if (refIdx == refPicNumber - 1)
{
bitsOnRefIdx--;
}
}
m_numHashMVStoreds[eRefPicList][refIdx] = 0;
if (refList == 0 || pu.cu->slice->getList1IdxToList0Idx(refIdx) < 0)
{
int count = static_cast<int>(pu.cu->slice->getRefPic(eRefPicList, refIdx)->getHashMap()->count(hashValue1s[idxNonSimple]));
if (count == 0)
{
continue;
}
list<BlockHash> listBlockHash;
selectRectangleMatchesInter(pu.cu->slice->getRefPic(eRefPicList, refIdx)->getHashMap()->getFirstIterator(hashValue1s[idxNonSimple]), count, listBlockHash, currBlockHash, width, height, idxNonSimple, hashValue2s, baseNum, picWidth, picHeight, isHorizontal, pu.cu->slice->getRefPic(eRefPicList, refIdx)->getHashMap()->getHashPic(baseSize));
m_numHashMVStoreds[eRefPicList][refIdx] = int(listBlockHash.size());
if (listBlockHash.empty())
{
continue;
}
AMVPInfo currAMVPInfoPel;
AMVPInfo currAMVPInfo4Pel;
AMVPInfo currAMVPInfoQPel;
pu.cu->imv = 2;
PU::fillMvpCand(pu, eRefPicList, refIdx, currAMVPInfo4Pel);
pu.cu->imv = 1;
PU::fillMvpCand(pu, eRefPicList, refIdx, currAMVPInfoPel);
pu.cu->imv = 0;
PU::fillMvpCand(pu, eRefPicList, refIdx, currAMVPInfoQPel);
const Pel* refBufStart = pu.cu->slice->getRefPic(eRefPicList, refIdx)->getRecoBuf().get(COMPONENT_Y).buf;
const int refStride = pu.cu->slice->getRefPic(eRefPicList, refIdx)->getRecoBuf().get(COMPONENT_Y).stride;
m_cDistParam.cur.stride = refStride;
m_pcRdCost->selectMotionLambda(pu.cu->transQuantBypass);
m_pcRdCost->setCostScale(0);
list<BlockHash>::iterator it;
int countMV = 0;
for (it = listBlockHash.begin(); it != listBlockHash.end(); ++it)
{
int curMVPIdx = 0;
unsigned int curMVPbits = MAX_UINT;
Mv cMv((*it).x - currBlockHash.x, (*it).y - currBlockHash.y);
m_hashMVStoreds[eRefPicList][refIdx][countMV++] = cMv;
cMv.changePrecision(MV_PRECISION_INT, MV_PRECISION_QUARTER);
for (int mvpIdxTemp = 0; mvpIdxTemp < 2; mvpIdxTemp++)
{
Mv cMvPredPel = currAMVPInfoQPel.mvCand[mvpIdxTemp];
m_pcRdCost->setPredictor(cMvPredPel);
unsigned int tempMVPbits = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer(), 0);
if (tempMVPbits < curMVPbits)
{
curMVPbits = tempMVPbits;
curMVPIdx = mvpIdxTemp;
pu.cu->imv = 0;
}
if (pu.cu->slice->getSPS()->getAMVREnabledFlag())
{
unsigned int bitsMVP1Pel = MAX_UINT;
Mv mvPred1Pel = currAMVPInfoPel.mvCand[mvpIdxTemp];
m_pcRdCost->setPredictor(mvPred1Pel);
bitsMVP1Pel = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer(), 2);
if (bitsMVP1Pel < curMVPbits)
{
curMVPbits = bitsMVP1Pel;
curMVPIdx = mvpIdxTemp;
pu.cu->imv = 1;
}
if ((cMv.getHor() % 16 == 0) && (cMv.getVer() % 16 == 0))
{
unsigned int bitsMVP4Pel = MAX_UINT;
Mv mvPred4Pel = currAMVPInfo4Pel.mvCand[mvpIdxTemp];
m_pcRdCost->setPredictor(mvPred4Pel);
bitsMVP4Pel = m_pcRdCost->getBitsOfVectorWithPredictor(cMv.getHor(), cMv.getVer(), 4);
if (bitsMVP4Pel < curMVPbits)
{
curMVPbits = bitsMVP4Pel;
curMVPIdx = mvpIdxTemp;
pu.cu->imv = 2;
}
}
}
}
curMVPbits += bitsOnRefIdx;
m_cDistParam.cur.buf = refBufStart + (*it).y*refStride + (*it).x;
Distortion currSad = m_cDistParam.distFunc(m_cDistParam);
Distortion currCost = currSad + m_pcRdCost->getCost(curMVPbits);
if (!isPerfectMatch)
{
if (pu.cu->slice->getRefPic(eRefPicList, refIdx)->slices[0]->getSliceQp() <= pu.cu->slice->getSliceQp())
{
isPerfectMatch = true;
}
}
if (currCost < bestCost)
{
bestCost = currCost;
bestRefPicList = eRefPicList;
bestRefIndex = refIdx;
bestMv = cMv;
bestMVPIndex = curMVPIdx;
imvBest = pu.cu->imv;
if (pu.cu->imv == 2)
{
bestMvd = cMv - currAMVPInfo4Pel.mvCand[curMVPIdx];
}
else if (pu.cu->imv == 1)
{
bestMvd = cMv - currAMVPInfoPel.mvCand[curMVPIdx];
}
else
{
bestMvd = cMv - currAMVPInfoQPel.mvCand[curMVPIdx];
}
}
}
}
}
}
delete[] hashValue1s;
delete[] hashValue2s;
pu.cu->imv = imvBest;
if (bestMvd == Mv(0, 0))
{
pu.cu->imv = 0;
return false;
}
return (bestCost < MAX_INT);
}
#else
int InterSearch::xHashInterPredME(const PredictionUnit& pu, RefPicList currRefPicList, int currRefPicIndex, Mv bestMv[5])
{
int width = pu.cu->lumaSize().width;
......@@ -1843,11 +2137,18 @@ int InterSearch::xHashInterPredME(const PredictionUnit& pu, RefPicList currRefPi
return totalSize;
}
#endif
bool InterSearch::xHashInterEstimation(PredictionUnit& pu, RefPicList& bestRefPicList, int& bestRefIndex, Mv& bestMv, Mv& bestMvd, int& bestMVPIndex, bool& isPerfectMatch)
{
int width = pu.cu->lumaSize().width;
int height = pu.cu->lumaSize().height;
#if JVET_N0247_HASH_IMPROVE
if (width != height)
{
return xRectHashInterEstimation(pu, bestRefPicList, bestRefIndex, bestMv, bestMvd, bestMVPIndex, isPerfectMatch);
}
#endif
int xPos = pu.cu->lumaPos().x;
int yPos = pu.cu->lumaPos().y;
......@@ -1887,6 +2188,9 @@ bool InterSearch::xHashInterEstimation(PredictionUnit& pu, RefPicList& bestRefPi
bitsOnRefIdx--;
}
}
#if JVET_N0247_HASH_IMPROVE
m_numHashMVStoreds[eRefPicList][refIdx] = 0;
#endif
if (refList == 0 || pu.cu->slice->getList1IdxToList0Idx(refIdx) < 0)
{
......@@ -1898,7 +2202,9 @@ bool InterSearch::xHashInterEstimation(PredictionUnit& pu, RefPicList& bestRefPi