Newer
Older

Karsten Suehring
committed
}
}
}
// early termination
if (cnt == maxNumMergeCand)
{
return;
}
int maxNumMergeCandMin1 = maxNumMergeCand - 1;
if (cnt != maxNumMergeCandMin1)
{
bool isAvailableSubPu = false;
unsigned subPuMvpPos = 0;
#if JVET_N0266_SMALL_BLOCKS
bool isShared = false;
#else
bool isShared = ((pu.Y().lumaSize().width != pu.shareParentSize.width) || (pu.Y().lumaSize().height != pu.shareParentSize.height));
#endif
bool bFound = addMergeHMVPCand(cs, mrgCtx, canFastExit
, maxNumMergeCandMin1, cnt
, spatialCandPos
, isAvailableSubPu, subPuMvpPos
);
#else
bool bFound = addMergeHMVPCand(slice, mrgCtx, isCandInter, canFastExit
, (mmvdList != 0 && mrgCandIdx != -1) ? (const int)mrgCandIdxIBC : mrgCandIdx
, maxNumMergeCandMin1, cnt, cnt, isAvailableSubPu, subPuMvpPos
, mmvdList
);
#endif
if (bFound)
{
return;
}
}
Yuling Hsiao
committed
#if JVET_L0090_PAIR_AVG
// pairwise-average candidates
{
Yuling Hsiao
committed
{
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;
Yuling Hsiao
committed
for( int refListId = 0; refListId < (slice.isInterB() ? 2 : 1); refListId++ )
{
Anish Tamse
committed
const short refIdxI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].refIdx;
const short refIdxJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].refIdx;
Yuling Hsiao
committed
// 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) )
{
Anish Tamse
committed
const Mv& MvI = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
const Mv& MvJ = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
Yuling Hsiao
committed
// average two MVs
Mv avgMv = MvI;
avgMv += MvJ;
Yuling Hsiao
committed
mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( avgMv, refIdxI );
}
// only one MV is valid, take the only one MV
else if( refIdxI != NOT_VALID )
{
Anish Tamse
committed
Mv singleMv = mrgCtx.mvFieldNeighbours[0 * 2 + refListId].mv;
Yuling Hsiao
committed
mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxI );
}
else if( refIdxJ != NOT_VALID )
{
Anish Tamse
committed
Mv singleMv = mrgCtx.mvFieldNeighbours[1 * 2 + refListId].mv;
Yuling Hsiao
committed
mrgCtx.mvFieldNeighbours[cnt * 2 + refListId].setMvField( singleMv, refIdxJ );
}
}
mrgCtx.interDirNeighbours[cnt] = interDir;
if( interDir > 0 )
{
cnt++;
}
}
// early termination
if( cnt == maxNumMergeCand )
{
return;
}
}
#endif

Karsten Suehring
committed
uint32_t uiArrayAddr = cnt;
Yuling Hsiao
committed
#if !JVET_L0090_PAIR_AVG
uint32_t uiCutoff = std::min( uiArrayAddr, 3u );

Karsten Suehring
committed
if (slice.isInterB())
{
static const uint32_t NUM_PRIORITY_LIST = 12;
static const uint32_t uiPriorityList0[NUM_PRIORITY_LIST] = { 0 , 1, 0, 2, 1, 2, 0, 3, 1, 3, 2, 3 };
static const uint32_t uiPriorityList1[NUM_PRIORITY_LIST] = { 1 , 0, 2, 0, 2, 1, 3, 0, 3, 1, 3, 2 };
for (int idx = 0; idx < uiCutoff * (uiCutoff - 1) && uiArrayAddr != maxNumMergeCand; idx++)
{
CHECK( idx >= NUM_PRIORITY_LIST, "Invalid priority list number" );
int i = uiPriorityList0[idx];
int j = uiPriorityList1[idx];
if (isCandInter[i] && isCandInter[j] && (mrgCtx.interDirNeighbours[i] & 0x1) && (mrgCtx.interDirNeighbours[j] & 0x2))
{
isCandInter[uiArrayAddr] = true;
mrgCtx.interDirNeighbours[uiArrayAddr] = 3;
mrgCtx.GBiIdx[uiArrayAddr] = ((mrgCtx.interDirNeighbours[uiArrayAddr] == 3)) ? CU::deriveGbiIdx(mrgCtx.GBiIdx[i], mrgCtx.GBiIdx[j]) : GBI_DEFAULT;

Karsten Suehring
committed
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
// get Mv from cand[i] and cand[j]
mrgCtx.mvFieldNeighbours[ uiArrayAddr << 1 ].setMvField(mrgCtx.mvFieldNeighbours[ i << 1 ].mv, mrgCtx.mvFieldNeighbours[ i << 1 ].refIdx);
mrgCtx.mvFieldNeighbours[(uiArrayAddr << 1) + 1].setMvField(mrgCtx.mvFieldNeighbours[(j << 1) + 1].mv, mrgCtx.mvFieldNeighbours[(j << 1) + 1].refIdx);
int iRefPOCL0 = slice.getRefPOC(REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[(uiArrayAddr << 1) ].refIdx);
int iRefPOCL1 = slice.getRefPOC(REF_PIC_LIST_1, mrgCtx.mvFieldNeighbours[(uiArrayAddr << 1) + 1].refIdx);
if( iRefPOCL0 == iRefPOCL1 && mrgCtx.mvFieldNeighbours[( uiArrayAddr << 1 )].mv == mrgCtx.mvFieldNeighbours[( uiArrayAddr << 1 ) + 1].mv )
{
isCandInter[uiArrayAddr] = false;
}
else
{
uiArrayAddr++;
}
}
}
}
// early termination
if (uiArrayAddr == maxNumMergeCand)
{
return;
}
Yuling Hsiao
committed
#endif

Karsten Suehring
committed
int iNumRefIdx = slice.isInterB() ? std::min(slice.getNumRefIdx(REF_PIC_LIST_0), slice.getNumRefIdx(REF_PIC_LIST_1)) : slice.getNumRefIdx(REF_PIC_LIST_0);
int r = 0;
int refcnt = 0;
while (uiArrayAddr < maxNumMergeCand)
{
Yuling Hsiao
committed
#if !JVET_L0090_PAIR_AVG

Karsten Suehring
committed
isCandInter [uiArrayAddr ] = true;
Yuling Hsiao
committed
#endif

Karsten Suehring
committed
mrgCtx.interDirNeighbours [uiArrayAddr ] = 1;
mrgCtx.GBiIdx [uiArrayAddr ] = GBI_DEFAULT;

Karsten Suehring
committed
mrgCtx.mvFieldNeighbours [uiArrayAddr << 1].setMvField(Mv(0, 0), r);
if (slice.isInterB())
{
mrgCtx.interDirNeighbours [ uiArrayAddr ] = 3;
mrgCtx.mvFieldNeighbours [(uiArrayAddr << 1) + 1].setMvField(Mv(0, 0), r);
}
if ( mrgCtx.interDirNeighbours[uiArrayAddr] == 1 && pu.cs->slice->getRefPic(REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[uiArrayAddr << 1].refIdx)->getPOC() == pu.cs->slice->getPOC())
{
mrgCtx.mrgTypeNeighbours[uiArrayAddr] = MRG_TYPE_IBC;

Karsten Suehring
committed
uiArrayAddr++;
if (refcnt == iNumRefIdx - 1)
{
r = 0;
}
else
{
++r;
++refcnt;
}
}
mrgCtx.numValidMergeCand = uiArrayAddr;
}
bool PU::checkDMVRCondition(const PredictionUnit& pu)
{
Takeshi Chujoh
committed
#if JVET_N0146_DMVR_BDOF_CONDITION
WPScalingParam *wp0;
WPScalingParam *wp1;
int refIdx0 = pu.refIdx[REF_PIC_LIST_0];
int refIdx1 = pu.refIdx[REF_PIC_LIST_1];
pu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0, wp0);
pu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1);
#endif
{
return pu.mergeFlag
&& pu.mergeType == MRG_TYPE_DEFAULT_N
&& !pu.cu->affine
&& !pu.mmvdMergeFlag
&& !pu.cu->mmvdSkip
&& PU::isBiPredFromDifferentDirEqDistPoc(pu)
&& (pu.lheight() >= 8)
#if JVET_N0407_DMVR_CU_SIZE_RESTRICTION
&& (pu.lwidth() >= 8)
&& ((pu.lheight() * pu.lwidth()) >= 128)
#else
&& ((pu.lheight() * pu.lwidth()) >= 64)
Takeshi Chujoh
committed
#if JVET_N0146_DMVR_BDOF_CONDITION
&& (pu.cu->GBiIdx == GBI_DEFAULT)
&& ((!wp0[COMPONENT_Y].bPresentFlag) && (!wp1[COMPONENT_Y].bPresentFlag))
;
}
else
{
return false;
}
}
bool PU::isBlockVectorValid(PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xStartInCU, int yStartInCU, int xBv, int yBv, int ctuSize)
{
const int ctuSizeLog2 = g_aucLog2[ctuSize];
int refRightX = xPos + xBv + width - 1;
int refBottomY = yPos + yBv + height - 1;

Karsten Suehring
committed
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250
2251
2252
2253
2254
2255
2256
2257
2258
2259
2260
2261
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
int refLeftX = xPos + xBv;
int refTopY = yPos + yBv;
if ((xPos + xBv) < 0)
{
return false;
}
if (refRightX >= picWidth)
{
return false;
}
if ((yPos + yBv) < 0)
{
return false;
}
if (refBottomY >= picHeight)
{
return false;
}
if ((xBv + width) > 0 && (yBv + height) > 0)
{
return false;
}
// cannot be in the above CTU row
if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2)
return false;
// cannot be in the below CTU row
if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2)
{
return false;
}
// in the same CTU line
#if JVET_N0175_N0251_N0384_IBC_SMALL_CTU
int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0);
if ((refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2) && (refLeftX >> ctuSizeLog2 >= (xPos >> ctuSizeLog2) - numLeftCTUs))
#else
if ((refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2) && (refLeftX >> ctuSizeLog2 >= (xPos >> ctuSizeLog2) - 1))
// in the same CTU, or left CTU
// if part of ref block is in the left CTU, some area can be referred from the not-yet updated local CTU buffer
#if JVET_N0175_N0251_N0384_IBC_SMALL_CTU
if (((refLeftX >> ctuSizeLog2) == ((xPos >> ctuSizeLog2) - 1)) && (ctuSizeLog2 == 7))
#else
if ((refLeftX >> ctuSizeLog2) == ((xPos >> ctuSizeLog2) - 1))
{
// ref block's collocated block in current CTU
const Position refPosCol = pu.Y().topLeft().offset(xBv + ctuSize, yBv);
int offset64x = (refPosCol.x >> (ctuSizeLog2 - 1)) << (ctuSizeLog2 - 1);
int offset64y = (refPosCol.y >> (ctuSizeLog2 - 1)) << (ctuSizeLog2 - 1);
const Position refPosCol64x64 = {offset64x, offset64y};
if (pu.cs->isDecomp(refPosCol64x64, toChannelType(COMPONENT_Y)))
return false;
if (refPosCol64x64 == pu.Y().topLeft())
return false;
#endif
// in the same CTU, or valid area from left CTU. Check if the reference block is already coded
const Position refPosLT = pu.Y().topLeft().offset(xBv, yBv);
const Position refPosBR = pu.Y().bottomRight().offset(xBv, yBv);
const ChannelType chType = toChannelType(COMPONENT_Y);
if (!pu.cs->isDecomp(refPosBR, chType))
return false;
if (!pu.cs->isDecomp(refPosLT, chType))
return false;
return true;

Karsten Suehring
committed
static int xGetDistScaleFactor(const int &iCurrPOC, const int &iCurrRefPOC, const int &iColPOC, const int &iColRefPOC)
{
int iDiffPocD = iColPOC - iColRefPOC;
int iDiffPocB = iCurrPOC - iCurrRefPOC;
if (iDiffPocD == iDiffPocB)
{
return 4096;
}
else
{
int iTDB = Clip3(-128, 127, iDiffPocB);
int iTDD = Clip3(-128, 127, iDiffPocD);
int iX = (0x4000 + abs(iTDD / 2)) / iTDD;
int iScale = Clip3(-4096, 4095, (iTDB * iX + 32) >> 6);
return iScale;
}
}
2335
2336
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
int convertMvFixedToFloat(int32_t val)
{
int sign = val >> 31;
int scale = floorLog2((val ^ sign) | MV_MANTISSA_UPPER_LIMIT) - (MV_MANTISSA_BITCOUNT - 1);
int exponent;
int mantissa;
if (scale >= 0)
{
int round = (1 << scale) >> 1;
int n = (val + round) >> scale;
exponent = scale + ((n ^ sign) >> (MV_MANTISSA_BITCOUNT - 1));
mantissa = (n & MV_MANTISSA_UPPER_LIMIT) | (sign << (MV_MANTISSA_BITCOUNT - 1));
}
else
{
exponent = 0;
mantissa = val;
}
return exponent | (mantissa << MV_EXPONENT_BITCOUNT);
}
int convertMvFloatToFixed(int val)
{
int exponent = val & MV_EXPONENT_MASK;
int mantissa = val >> MV_EXPONENT_BITCOUNT;
return exponent == 0 ? mantissa : (mantissa ^ MV_MANTISSA_LIMIT) << (exponent - 1);
}
int roundMvComp(int x)
{
return convertMvFloatToFixed(convertMvFixedToFloat(x));
}
2371
2372
2373
2374
2375
2376
2377
2378
2379
2380
2381
2382
2383
2384
2385
2386
2387
2388
2389
2390
2391
2392
2393
2394
2395
2396
2397
2398
2399
2400
2401
2402
2403
2404
int PU::getDistScaleFactor(const int &currPOC, const int &currRefPOC, const int &colPOC, const int &colRefPOC)
{
return xGetDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC);
}
void PU::getInterMMVDMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const int& mrgCandIdx)
{
int refIdxList0, refIdxList1;
int k;
int currBaseNum = 0;
const uint16_t maxNumMergeCand = mrgCtx.numValidMergeCand;
for (k = 0; k < maxNumMergeCand; k++)
{
if (mrgCtx.mrgTypeNeighbours[k] == MRG_TYPE_DEFAULT_N)
{
refIdxList0 = mrgCtx.mvFieldNeighbours[(k << 1)].refIdx;
refIdxList1 = mrgCtx.mvFieldNeighbours[(k << 1) + 1].refIdx;
if ((refIdxList0 >= 0) && (refIdxList1 >= 0))
{
mrgCtx.mmvdBaseMv[currBaseNum][0] = mrgCtx.mvFieldNeighbours[(k << 1)];
mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[(k << 1) + 1];
}
else if (refIdxList0 >= 0)
{
mrgCtx.mmvdBaseMv[currBaseNum][0] = mrgCtx.mvFieldNeighbours[(k << 1)];
mrgCtx.mmvdBaseMv[currBaseNum][1] = MvField(Mv(0, 0), -1);
}
else if (refIdxList1 >= 0)
{
mrgCtx.mmvdBaseMv[currBaseNum][0] = MvField(Mv(0, 0), -1);
mrgCtx.mmvdBaseMv[currBaseNum][1] = mrgCtx.mvFieldNeighbours[(k << 1) + 1];
}

Karsten Suehring
committed
currBaseNum++;
if (currBaseNum == MMVD_BASE_MV_NUM)
break;
}
}
if (currBaseNum < MMVD_BASE_MV_NUM)
{
for (k = currBaseNum; k < MMVD_BASE_MV_NUM; k++)
{
mrgCtx.mmvdBaseMv[k][0] = MvField(Mv(0, 0), 0);
const Slice &slice = *pu.cs->slice;
mrgCtx.mmvdBaseMv[k][1] = MvField(Mv(0, 0), (slice.isInterB() ? 0 : -1));
mrgCtx.GBiIdx[k] = GBI_DEFAULT;
mrgCtx.interDirNeighbours[k] = (mrgCtx.mmvdBaseMv[k][0].refIdx >= 0) + (mrgCtx.mmvdBaseMv[k][1].refIdx >= 0) * 2;

Karsten Suehring
committed
bool PU::getColocatedMVP(const PredictionUnit &pu, const RefPicList &eRefPicList, const Position &_pos, Mv& rcMv, const int &refIdx )
{
// don't perform MV compression when generally disabled or subPuMvp is used
const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4);

Karsten Suehring
committed
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
const unsigned mask = ~( scale - 1 );
const Position pos = Position{ PosType( _pos.x & mask ), PosType( _pos.y & mask ) };
const Slice &slice = *pu.cs->slice;
// use coldir.
const Picture* const pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0), slice.getColRefIdx());
if( !pColPic )
{
return false;
}
RefPicList eColRefPicList = slice.getCheckLDC() ? eRefPicList : RefPicList(slice.getColFromL0Flag());
const MotionInfo& mi = pColPic->cs->getMotionInfo( pos );
if( !mi.isInter )
{
return false;
}
if (mi.isIBCmot)
{
return false;
}
if (CU::isIBC(*pu.cu))

Karsten Suehring
committed
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
int iColRefIdx = mi.refIdx[eColRefPicList];
if (iColRefIdx < 0)
{
eColRefPicList = RefPicList(1 - eColRefPicList);
iColRefIdx = mi.refIdx[eColRefPicList];
if (iColRefIdx < 0)
{
return false;
}
}
const Slice *pColSlice = nullptr;
for( const auto s : pColPic->slices )
{
if( s->getIndependentSliceIdx() == mi.sliceIdx )
{
pColSlice = s;
break;
}
}
CHECK( pColSlice == nullptr, "Slice segment not found" );
const Slice &colSlice = *pColSlice;
const bool bIsCurrRefLongTerm = slice.getRefPic(eRefPicList, refIdx)->longTerm;
const bool bIsColRefLongTerm = colSlice.getIsUsedAsLongTerm(eColRefPicList, iColRefIdx);
if (bIsCurrRefLongTerm != bIsColRefLongTerm)
{
return false;
}
// Scale the vector.
Mv cColMv = mi.mv[eColRefPicList];
cColMv.setHor(roundMvComp(cColMv.getHor()));
cColMv.setVer(roundMvComp(cColMv.getVer()));

Karsten Suehring
committed
2501
2502
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
2518
2519
2520
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
if (bIsCurrRefLongTerm /*|| bIsColRefLongTerm*/)
{
rcMv = cColMv;
}
else
{
const int currPOC = slice.getPOC();
const int colPOC = colSlice.getPOC();
const int colRefPOC = colSlice.getRefPOC(eColRefPicList, iColRefIdx);
const int currRefPOC = slice.getRefPic(eRefPicList, refIdx)->getPOC();
const int distscale = xGetDistScaleFactor(currPOC, currRefPOC, colPOC, colRefPOC);
if (distscale == 4096)
{
rcMv = cColMv;
}
else
{
rcMv = cColMv.scaleMv(distscale);
}
}
return true;
}
bool PU::isDiffMER(const PredictionUnit &pu1, const PredictionUnit &pu2)
{
const unsigned xN = pu1.lumaPos().x;
const unsigned yN = pu1.lumaPos().y;
const unsigned xP = pu2.lumaPos().x;
const unsigned yP = pu2.lumaPos().y;
unsigned plevel = pu1.cs->pps->getLog2ParallelMergeLevelMinus2() + 2;
if ((xN >> plevel) != (xP >> plevel))
{
return true;
}
if ((yN >> plevel) != (yP >> plevel))
{
return true;
}
return false;
}
2548
2549
2550
2551
2552
2553
2554
2555
2556
2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
2568
2569
2570
2571
2572
2573
2574
#if JVET_N0329_IBC_SEARCH_IMP
bool PU::isAddNeighborMv(const Mv& currMv, Mv* neighborMvs, int numNeighborMv)
{
bool existed = false;
for (uint32_t cand = 0; cand < numNeighborMv && !existed; cand++)
{
if (currMv == neighborMvs[cand])
{
existed = true;
}
}
if (!existed)
{
return true;
}
else
{
return false;
}
}
#endif
#if JVET_N0329_IBC_SEARCH_IMP
void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* mvPred, int& nbPred)
#else
void PU::getIbcMVPsEncOnly(PredictionUnit &pu, Mv* MvPred, int& nbPred)
#if JVET_N0329_IBC_SEARCH_IMP
const PreCalcValues &pcv = *pu.cs->pcv;
const int cuWidth = pu.blocks[COMPONENT_Y].width;
const int cuHeight = pu.blocks[COMPONENT_Y].height;
const int log2UnitWidth = g_aucLog2[pcv.minCUWidth];
const int log2UnitHeight = g_aucLog2[pcv.minCUHeight];
const int totalAboveUnits = (cuWidth >> log2UnitWidth) + 1;
const int totalLeftUnits = (cuHeight >> log2UnitHeight) + 1;
nbPred = 0;
Position posLT = pu.Y().topLeft();
// above-left
const PredictionUnit *aboveLeftPU = pu.cs->getPURestricted(posLT.offset(-1, -1), pu, CHANNEL_TYPE_LUMA);
if (aboveLeftPU && CU::isIBC(*aboveLeftPU->cu))
{
if (isAddNeighborMv(aboveLeftPU->bv, mvPred, nbPred))
{
mvPred[nbPred++] = aboveLeftPU->bv;
}
}
// above neighbors
for (uint32_t dx = 0; dx < totalAboveUnits && nbPred < IBC_NUM_CANDIDATES; dx++)
{
const PredictionUnit* tmpPU = pu.cs->getPURestricted(posLT.offset((dx << log2UnitWidth), -1), pu, CHANNEL_TYPE_LUMA);
if (tmpPU && CU::isIBC(*tmpPU->cu))
{
if (isAddNeighborMv(tmpPU->bv, mvPred, nbPred))
{
mvPred[nbPred++] = tmpPU->bv;
}
}
}
// left neighbors
for (uint32_t dy = 0; dy < totalLeftUnits && nbPred < IBC_NUM_CANDIDATES; dy++)
{
const PredictionUnit* tmpPU = pu.cs->getPURestricted(posLT.offset(-1, (dy << log2UnitHeight)), pu, CHANNEL_TYPE_LUMA);
if (tmpPU && CU::isIBC(*tmpPU->cu))
{
if (isAddNeighborMv(tmpPU->bv, mvPred, nbPred))
{
mvPred[nbPred++] = tmpPU->bv;
}
}
}
size_t numAvaiCandInLUT = pu.cs->motionLut.lutIbc.size();
for (uint32_t cand = 0; cand < numAvaiCandInLUT && nbPred < IBC_NUM_CANDIDATES; cand++)
{
MotionInfo neibMi = pu.cs->motionLut.lutIbc[cand];
if (isAddNeighborMv(neibMi.bv, mvPred, nbPred))
{
mvPred[nbPred++] = neibMi.bv;
}
}

Karsten Suehring
committed
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
bool isBvCandDerived[IBC_NUM_CANDIDATES];
::memset(isBvCandDerived, false, IBC_NUM_CANDIDATES);
int curNbPred = nbPred;
if (curNbPred < IBC_NUM_CANDIDATES)
{
do
{
curNbPred = nbPred;
for (uint32_t idx = 0; idx < curNbPred && nbPred < IBC_NUM_CANDIDATES; idx++)
{
if (!isBvCandDerived[idx])
{
Mv derivedBv;
if (getDerivedBV(pu, mvPred[idx], derivedBv))
{
if (isAddNeighborMv(derivedBv, mvPred, nbPred))
{
mvPred[nbPred++] = derivedBv;
}
}
isBvCandDerived[idx] = true;
}
}
} while (nbPred > curNbPred && nbPred < IBC_NUM_CANDIDATES);
}
#else
//-- Get Spatial MV
Position posLT = pu.Y().topLeft();
Position posRT = pu.Y().topRight();
Position posLB = pu.Y().bottomLeft();
unsigned int left = 0, above = 0;
//left
const PredictionUnit *neibLeftPU = NULL;
neibLeftPU = pu.cs->getPURestricted(posLB.offset(-1, 0), pu, CHANNEL_TYPE_LUMA);
left = (neibLeftPU) ? CU::isIBC(*neibLeftPU->cu) : 0;
if (left)
{
MvPred[nbPred++] = neibLeftPU->bv;
if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
nbPred++;
}
//above
const PredictionUnit *neibAbovePU = NULL;
neibAbovePU = pu.cs->getPURestricted(posRT.offset(0, -1), pu, CHANNEL_TYPE_LUMA);
above = (neibAbovePU) ? CU::isIBC(*neibAbovePU->cu) : 0;
if (above)
{
MvPred[nbPred++] = neibAbovePU->bv;
if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
nbPred++;
}
// Below Left predictor search
const PredictionUnit *neibBelowLeftPU = NULL;
neibBelowLeftPU = pu.cs->getPURestricted(posLB.offset(-1, 1), pu, CHANNEL_TYPE_LUMA);
unsigned int belowLeft = (neibBelowLeftPU) ? CU::isIBC(*neibBelowLeftPU->cu) : 0;
if (belowLeft)
{
MvPred[nbPred++] = neibBelowLeftPU->bv;
if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
nbPred++;
}
// Above Right predictor search
const PredictionUnit *neibAboveRightPU = NULL;
neibAboveRightPU = pu.cs->getPURestricted(posRT.offset(1, -1), pu, CHANNEL_TYPE_LUMA);
unsigned int aboveRight = (neibAboveRightPU) ? CU::isIBC(*neibAboveRightPU->cu) : 0;
if (aboveRight)
{
MvPred[nbPred++] = neibAboveRightPU->bv;
if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
nbPred++;
}
// Above Left predictor search
const PredictionUnit *neibAboveLeftPU = NULL;
neibAboveLeftPU = pu.cs->getPURestricted(posLT.offset(-1, -1), pu, CHANNEL_TYPE_LUMA);
unsigned int aboveLeft = (neibAboveLeftPU) ? CU::isIBC(*neibAboveLeftPU->cu) : 0;
if (aboveLeft)
{
MvPred[nbPred++] = neibAboveLeftPU->bv;
if (getDerivedBV(pu, MvPred[nbPred - 1], MvPred[nbPred]))
nbPred++;
}
}
bool PU::getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv)
{
int cuPelX = pu.lumaPos().x;
int cuPelY = pu.lumaPos().y;
int rX = cuPelX + currentMv.getHor();
int rY = cuPelY + currentMv.getVer();
int offsetX = currentMv.getHor();
int offsetY = currentMv.getVer();
if (rX < 0 || rY < 0 || rX >= pu.cs->slice->getSPS()->getPicWidthInLumaSamples() || rY >= pu.cs->slice->getSPS()->getPicHeightInLumaSamples())
{
return false;
}
const PredictionUnit *neibRefPU = NULL;
neibRefPU = pu.cs->getPURestricted(pu.lumaPos().offset(offsetX, offsetY), pu, CHANNEL_TYPE_LUMA);
bool isIBC = (neibRefPU) ? CU::isIBC(*neibRefPU->cu) : 0;
{
derivedMv = neibRefPU->bv;
derivedMv += currentMv;
}
* Constructs a list of candidates for IBC AMVP (See specification, section "Derivation process for motion vector predictor candidates")
*/
void PU::fillIBCMvpCand(PredictionUnit &pu, AMVPInfo &amvpInfo)
AMVPInfo *pInfo = &amvpInfo;
pInfo->numCand = 0;
//-- Get Spatial MV
Position posLT = pu.Y().topLeft();
Position posRT = pu.Y().topRight();
Position posLB = pu.Y().bottomLeft();
bool isScaledFlagLX = false; /// variable name from specification; true when the PUs below left or left are available (availableA0 || availableA1).
const PredictionUnit* tmpPU = cs.getPURestricted(posLB.offset(-1, 1), pu, pu.chType); // getPUBelowLeft(idx, partIdxLB);
isScaledFlagLX = tmpPU != NULL && CU::isIBC(*tmpPU->cu);
if (!isScaledFlagLX)
tmpPU = cs.getPURestricted(posLB.offset(-1, 0), pu, pu.chType);
isScaledFlagLX = tmpPU != NULL && CU::isIBC(*tmpPU->cu);
}
// Left predictor search
if (isScaledFlagLX)
{
bool isAdded = addIBCMVPCand(pu, posRT, MD_ABOVE_RIGHT, *pInfo);
if (!isAdded)
pInfo->mvCand[i].roundTransPrecInternal2Amvr(pu.cu->imv);
if (pInfo->numCand == 2)
{
if (pInfo->mvCand[0] == pInfo->mvCand[1])
{
pInfo->numCand = 1;
}
}
if (pInfo->numCand < AMVP_MAX_NUM_CANDS)
{
addAMVPHMVPCand(pu, REF_PIC_LIST_0, REF_PIC_LIST_1, cs.slice->getPOC(), *pInfo, pu.cu->imv);
}
if (pInfo->numCand > AMVP_MAX_NUM_CANDS)
{
pInfo->numCand = AMVP_MAX_NUM_CANDS;
}
while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
{
pInfo->mvCand[pInfo->numCand] = Mv(0, 0);
pInfo->numCand++;
}
#endif
#if JVET_N0843_BVP_SIMPLIFICATION
MergeCtx mergeCtx;
PU::getIBCMergeCandidates(pu, mergeCtx, AMVP_MAX_NUM_CANDS - 1);
int candIdx = 0;
while (pInfo->numCand < AMVP_MAX_NUM_CANDS)
{
pInfo->mvCand[pInfo->numCand] = mergeCtx.mvFieldNeighbours[(candIdx << 1) + 0].mv;;
pInfo->numCand++;
candIdx++;
}
#endif

Karsten Suehring
committed
2865
2866
2867
2868
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884
2885
2886
2887
2888
2889
2890
2891
2892
2893
2894
2895
2896
2897
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
2913
2914
2915
2916
2917
2918
2919
2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
/** Constructs a list of candidates for AMVP (See specification, section "Derivation process for motion vector predictor candidates")
* \param uiPartIdx
* \param uiPartAddr
* \param eRefPicList
* \param iRefIdx
* \param pInfo
*/
void PU::fillMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AMVPInfo &amvpInfo)
{
CodingStructure &cs = *pu.cs;
AMVPInfo *pInfo = &amvpInfo;
pInfo->numCand = 0;
if (refIdx < 0)
{
return;
}
//-- Get Spatial MV
Position posLT = pu.Y().topLeft();
Position posRT = pu.Y().topRight();
Position posLB = pu.Y().bottomLeft();
bool isScaledFlagLX = false; /// variable name from specification; true when the PUs below left or left are available (availableA0 || availableA1).
{
const PredictionUnit* tmpPU = cs.getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType ); // getPUBelowLeft(idx, partIdxLB);
isScaledFlagLX = tmpPU != NULL && CU::isInter( *tmpPU->cu );
if( !isScaledFlagLX )
{
tmpPU = cs.getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType );
isScaledFlagLX = tmpPU != NULL && CU::isInter( *tmpPU->cu );
}
}
// Left predictor search
if( isScaledFlagLX )
{
bool bAdded = addMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_BELOW_LEFT, *pInfo );
if( !bAdded )
{
bAdded = addMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_LEFT, *pInfo );
if( !bAdded )
{
bAdded = addMVPCandWithScaling( pu, eRefPicList, refIdx, posLB, MD_BELOW_LEFT, *pInfo );
if( !bAdded )
{
addMVPCandWithScaling( pu, eRefPicList, refIdx, posLB, MD_LEFT, *pInfo );
}
}
}
}
// Above predictor search
{
bool bAdded = addMVPCandUnscaled( pu, eRefPicList, refIdx, posRT, MD_ABOVE_RIGHT, *pInfo );
if( !bAdded )
{
bAdded = addMVPCandUnscaled( pu, eRefPicList, refIdx, posRT, MD_ABOVE, *pInfo );
if( !bAdded )
{
addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, *pInfo );
}
}
}
if( !isScaledFlagLX )
{
bool bAdded = addMVPCandWithScaling( pu, eRefPicList, refIdx, posRT, MD_ABOVE_RIGHT, *pInfo );
if( !bAdded )
{
bAdded = addMVPCandWithScaling( pu, eRefPicList, refIdx, posRT, MD_ABOVE, *pInfo );
if( !bAdded )
{
addMVPCandWithScaling( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, *pInfo );
}
}
}
for( int i = 0; i < pInfo->numCand; i++ )
{
pInfo->mvCand[i].roundTransPrecInternal2Amvr(pu.cu->imv);
}

Karsten Suehring
committed
if( pInfo->numCand == 2 )
{
if( pInfo->mvCand[0] == pInfo->mvCand[1] )
{
pInfo->numCand = 1;
}
}
#if JVET_N0213_TMVP_REMOVAL
if (cs.slice->getEnableTMVPFlag() && pInfo->numCand < AMVP_MAX_NUM_CANDS && (pu.lumaSize().width + pu.lumaSize().height > 12))
#else
if( cs.slice->getEnableTMVPFlag() && pInfo->numCand < AMVP_MAX_NUM_CANDS )

Karsten Suehring
committed
{
// Get Temporal Motion Predictor
const int refIdx_Col = refIdx;
Position posRB = pu.Y().bottomRight().offset(-3, -3);
const PreCalcValues& pcv = *cs.pcv;
Position posC0;
bool C0Avail = false;
Position posC1 = pu.Y().center();
#if !JVET_N0266_SMALL_BLOCKS
bool C1Avail = ( posC1.x < pcv.lumaWidth ) && ( posC1.y < pcv.lumaHeight ) ;
#endif

Karsten Suehring
committed
Mv cColMv;
if( ( ( posRB.x + pcv.minCUWidth ) < pcv.lumaWidth ) && ( ( posRB.y + pcv.minCUHeight ) < pcv.lumaHeight ) )
{
Position posInCtu( posRB.x & pcv.maxCUWidthMask, posRB.y & pcv.maxCUHeightMask );
if ((posInCtu.x + 4 < pcv.maxCUWidth) && // is not at the last column of CTU
(posInCtu.y + 4 < pcv.maxCUHeight)) // is not at the last row of CTU
{
posC0 = posRB.offset(4, 4);
C0Avail = true;
}
else if (posInCtu.x + 4 < pcv.maxCUWidth) // is not at the last column of CTU But is last row of CTU
{
// in the reference the CTU address is not set - thus probably resulting in no using this C0 possibility