Newer
Older

Karsten Suehring
committed
{
// same as for last column but not last row
posC0 = posRB.offset(4, 4);
}
}
#if JVET_M0170_MRG_SHARELIST
if ((C0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdx_Col)) || (C1Avail && getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdx_Col)))
#else

Karsten Suehring
committed
if ((C0Avail && getColocatedMVP(pu, eRefPicList, posC0, cColMv, refIdx_Col)) || getColocatedMVP(pu, eRefPicList, posC1, cColMv, refIdx_Col))

Karsten Suehring
committed
{
if (pu.cu->imv != 0)
{
cColMv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, pu.cu->imv);
}
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;
}

Karsten Suehring
committed
}
}
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);
}

Karsten Suehring
committed
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++;
}

Karsten Suehring
committed
{
mv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, pu.cu->imv);

Karsten Suehring
committed
}
}
bool PU::addAffineMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &refPicList, const int &refIdx, const Position &pos, const MvpDir &dir, AffineAMVPInfo &affiAMVPInfo )
{
CodingStructure &cs = *pu.cs;
const PredictionUnit *neibPU = NULL;
Position neibPos;

Karsten Suehring
committed
switch ( dir )
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
{
case MD_LEFT:
neibPos = pos.offset( -1, 0 );
break;
case MD_ABOVE:
neibPos = pos.offset( 0, -1 );
break;
case MD_ABOVE_RIGHT:
neibPos = pos.offset( 1, -1 );
break;
case MD_BELOW_LEFT:
neibPos = pos.offset( -1, 1 );
break;
case MD_ABOVE_LEFT:
neibPos = pos.offset( -1, -1 );
break;
default:
break;
}
neibPU = cs.getPURestricted( neibPos, pu, pu.chType );
if ( neibPU == NULL || !CU::isInter( *neibPU->cu ) || !neibPU->cu->affine
|| neibPU->mergeType != MRG_TYPE_DEFAULT_N
)
{
return false;
}
Mv outputAffineMv[3];
const MotionInfo& neibMi = neibPU->getMotionInfo( neibPos );
const int currRefPOC = cs.slice->getRefPic( refPicList, refIdx )->getPOC();
const RefPicList refPicList2nd = (refPicList == REF_PIC_LIST_0) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
for ( int predictorSource = 0; predictorSource < 2; predictorSource++ ) // examine the indicated reference picture list, then if not available, examine the other list.
{
const RefPicList eRefPicListIndex = (predictorSource == 0) ? refPicList : refPicList2nd;
const int neibRefIdx = neibMi.refIdx[eRefPicListIndex];
if ( ((neibPU->interDir & (eRefPicListIndex + 1)) == 0) || pu.cu->slice->getRefPOC( eRefPicListIndex, neibRefIdx ) != currRefPOC )
{
continue;
}
xInheritedAffineMv( pu, neibPU, eRefPicListIndex, outputAffineMv );
outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0];
affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1];
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2];
}
affiAMVPInfo.numCand++;
return true;
}
return false;
}

Karsten Suehring
committed
void PU::xInheritedAffineMv( const PredictionUnit &pu, const PredictionUnit* puNeighbour, RefPicList eRefPicList, Mv rcMv[3] )
{
int posNeiX = puNeighbour->Y().pos().x;
int posNeiY = puNeighbour->Y().pos().y;
int posCurX = pu.Y().pos().x;
int posCurY = pu.Y().pos().y;
int neiW = puNeighbour->Y().width;
int curW = pu.Y().width;
int neiH = puNeighbour->Y().height;
int curH = pu.Y().height;
Mv mvLT, mvRT, mvLB;
mvLT = puNeighbour->mvAffi[eRefPicList][0];
mvRT = puNeighbour->mvAffi[eRefPicList][1];
mvLB = puNeighbour->mvAffi[eRefPicList][2];
bool isTopCtuBoundary = false;
if ( (posNeiY + neiH) % pu.cs->sps->getCTUSize() == 0 && (posNeiY + neiH) == posCurY )
{
// use bottom-left and bottom-right sub-block MVs for inheritance
const Position posRB = puNeighbour->Y().bottomRight();
const Position posLB = puNeighbour->Y().bottomLeft();
mvLT = puNeighbour->getMotionInfo( posLB ).mv[eRefPicList];
mvRT = puNeighbour->getMotionInfo( posRB ).mv[eRefPicList];
posNeiY += neiH;
isTopCtuBoundary = true;

Karsten Suehring
committed
int shift = MAX_CU_DEPTH;
int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY;
iDMvHorX = (mvRT - mvLT).getHor() << (shift - g_aucLog2[neiW]);
iDMvHorY = (mvRT - mvLT).getVer() << (shift - g_aucLog2[neiW]);
if ( puNeighbour->cu->affineType == AFFINEMODEL_6PARAM && !isTopCtuBoundary )

Karsten Suehring
committed
{
iDMvVerX = (mvLB - mvLT).getHor() << (shift - g_aucLog2[neiH]);
iDMvVerY = (mvLB - mvLT).getVer() << (shift - g_aucLog2[neiH]);
}
else
{
iDMvVerX = -iDMvHorY;
iDMvVerY = iDMvHorX;
}
int iMvScaleHor = mvLT.getHor() << shift;
int iMvScaleVer = mvLT.getVer() << shift;
int horTmp, verTmp;
// v0
horTmp = iMvScaleHor + iDMvHorX * (posCurX - posNeiX) + iDMvVerX * (posCurY - posNeiY);
verTmp = iMvScaleVer + iDMvHorY * (posCurX - posNeiX) + iDMvVerY * (posCurY - posNeiY);
roundAffineMv( horTmp, verTmp, shift );
rcMv[0].hor = horTmp;
rcMv[0].ver = verTmp;
#if JVET_M0145_AFFINE_MV_CLIP
rcMv[0].clipToStorageBitDepth();
#endif

Karsten Suehring
committed
// v1
horTmp = iMvScaleHor + iDMvHorX * (posCurX + curW - posNeiX) + iDMvVerX * (posCurY - posNeiY);
verTmp = iMvScaleVer + iDMvHorY * (posCurX + curW - posNeiX) + iDMvVerY * (posCurY - posNeiY);
roundAffineMv( horTmp, verTmp, shift );
rcMv[1].hor = horTmp;
rcMv[1].ver = verTmp;
#if JVET_M0145_AFFINE_MV_CLIP
rcMv[1].clipToStorageBitDepth();
#endif

Karsten Suehring
committed
// v2
if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
{
horTmp = iMvScaleHor + iDMvHorX * (posCurX - posNeiX) + iDMvVerX * (posCurY + curH - posNeiY);
verTmp = iMvScaleVer + iDMvHorY * (posCurX - posNeiX) + iDMvVerY * (posCurY + curH - posNeiY);
roundAffineMv( horTmp, verTmp, shift );
rcMv[2].hor = horTmp;
rcMv[2].ver = verTmp;
#if JVET_M0145_AFFINE_MV_CLIP
rcMv[2].clipToStorageBitDepth();
#endif

Karsten Suehring
committed
}
}
void PU::fillAffineMvpCand(PredictionUnit &pu, const RefPicList &eRefPicList, const int &refIdx, AffineAMVPInfo &affiAMVPInfo)
{
affiAMVPInfo.numCand = 0;
if (refIdx < 0)
{
return;
}
// insert inherited affine candidates
Mv outputAffineMv[3];
Position posLT = pu.Y().topLeft();
Position posRT = pu.Y().topRight();
Position posLB = pu.Y().bottomLeft();
// check left neighbor
if ( !addAffineMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_BELOW_LEFT, affiAMVPInfo ) )
{
addAffineMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_LEFT, affiAMVPInfo );
}
// check above neighbor
if ( !addAffineMVPCandUnscaled( pu, eRefPicList, refIdx, posRT, MD_ABOVE_RIGHT, affiAMVPInfo ) )
{
if ( !addAffineMVPCandUnscaled( pu, eRefPicList, refIdx, posRT, MD_ABOVE, affiAMVPInfo ) )
{
addAffineMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, affiAMVPInfo );
}
}

Karsten Suehring
committed
if ( affiAMVPInfo.numCand >= AMVP_MAX_NUM_CANDS )
{
for (int i = 0; i < affiAMVPInfo.numCand; i++)
{
affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);

Karsten Suehring
committed
return;
}
// insert constructed affine candidates
int cornerMVPattern = 0;
//------------------- V0 (START) -------------------//
AMVPInfo amvpInfo0;
amvpInfo0.numCand = 0;
// A->C: Above Left, Above, Left
addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE_LEFT, amvpInfo0 );

Karsten Suehring
committed
if ( amvpInfo0.numCand < 1 )
{
addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_ABOVE, amvpInfo0 );

Karsten Suehring
committed
}
if ( amvpInfo0.numCand < 1 )
{
addMVPCandUnscaled( pu, eRefPicList, refIdx, posLT, MD_LEFT, amvpInfo0 );

Karsten Suehring
committed
}
cornerMVPattern = cornerMVPattern | amvpInfo0.numCand;
//------------------- V1 (START) -------------------//
AMVPInfo amvpInfo1;
amvpInfo1.numCand = 0;
// D->E: Above, Above Right
addMVPCandUnscaled( pu, eRefPicList, refIdx, posRT, MD_ABOVE, amvpInfo1 );

Karsten Suehring
committed
if ( amvpInfo1.numCand < 1 )
{
addMVPCandUnscaled( pu, eRefPicList, refIdx, posRT, MD_ABOVE_RIGHT, amvpInfo1 );

Karsten Suehring
committed
}
cornerMVPattern = cornerMVPattern | (amvpInfo1.numCand << 1);
//------------------- V2 (START) -------------------//
AMVPInfo amvpInfo2;
amvpInfo2.numCand = 0;
// F->G: Left, Below Left
addMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_LEFT, amvpInfo2 );

Karsten Suehring
committed
if ( amvpInfo2.numCand < 1 )
{
addMVPCandUnscaled( pu, eRefPicList, refIdx, posLB, MD_BELOW_LEFT, amvpInfo2 );

Karsten Suehring
committed
}
cornerMVPattern = cornerMVPattern | (amvpInfo2.numCand << 2);
outputAffineMv[0] = amvpInfo0.mvCand[0];
outputAffineMv[1] = amvpInfo1.mvCand[0];
outputAffineMv[2] = amvpInfo2.mvCand[0];
outputAffineMv[0].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[1].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
outputAffineMv[2].roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);

Karsten Suehring
committed
2302
2303
2304
2305
2306
2307
2308
2309
2310
2311
2312
2313
2314
2315
2316
2317
2318
2319
2320
2321
2322
2323
2324
2325
2326
2327
if ( cornerMVPattern == 7 || (cornerMVPattern == 3 && pu.cu->affineType == AFFINEMODEL_4PARAM) )
{
affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[0];
affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[1];
affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[2];
affiAMVPInfo.numCand++;
}
if ( affiAMVPInfo.numCand < 2 )
{
// check corner MVs
for ( int i = 2; i >= 0 && affiAMVPInfo.numCand < AMVP_MAX_NUM_CANDS; i-- )
{
if ( cornerMVPattern & (1 << i) ) // MV i exist
{
affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = outputAffineMv[i];
affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = outputAffineMv[i];
affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = outputAffineMv[i];
affiAMVPInfo.numCand++;
}
}
// Get Temporal Motion Predictor
if ( affiAMVPInfo.numCand < 2 && pu.cs->slice->getEnableTMVPFlag() )
{
const int refIdxCol = refIdx;
Position posRB = pu.Y().bottomRight().offset( -3, -3 );
const PreCalcValues& pcv = *pu.cs->pcv;
Position posC0;
bool C0Avail = false;
Position posC1 = pu.Y().center();
#if JVET_M0170_MRG_SHARELIST
bool C1Avail = ( posC1.x < pcv.lumaWidth ) && ( posC1.y < pcv.lumaHeight ) ;
#endif
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
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
posC0 = posRB.offset( 4, 4 );
}
else if ( posInCtu.y + 4 < pcv.maxCUHeight ) // is not at the last row of CTU But is last column of CTU
{
posC0 = posRB.offset( 4, 4 );
C0Avail = true;
}
else //is the right bottom corner of CTU
{
// same as for last column but not last row
posC0 = posRB.offset( 4, 4 );
}
}
#if JVET_M0170_MRG_SHARELIST
if ( (C0Avail && getColocatedMVP( pu, eRefPicList, posC0, cColMv, refIdxCol )) || (C1Avail && getColocatedMVP( pu, eRefPicList, posC1, cColMv, refIdxCol ) ) )
#else
if ( (C0Avail && getColocatedMVP( pu, eRefPicList, posC0, cColMv, refIdxCol )) || getColocatedMVP( pu, eRefPicList, posC1, cColMv, refIdxCol ) )
cColMv.roundToPrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand] = cColMv;
affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand] = cColMv;
affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand] = cColMv;
affiAMVPInfo.numCand++;
}
}
if ( affiAMVPInfo.numCand < 2 )
{
// add zero MV
for ( int i = affiAMVPInfo.numCand; i < AMVP_MAX_NUM_CANDS; i++ )
{
affiAMVPInfo.mvCandLT[affiAMVPInfo.numCand].setZero();
affiAMVPInfo.mvCandRT[affiAMVPInfo.numCand].setZero();
affiAMVPInfo.mvCandLB[affiAMVPInfo.numCand].setZero();
affiAMVPInfo.numCand++;
}
}
}
for (int i = 0; i < affiAMVPInfo.numCand; i++)
{
affiAMVPInfo.mvCandLT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandRT[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);
affiAMVPInfo.mvCandLB[i].changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_QUARTER);

Karsten Suehring
committed
}
bool PU::addMVPCandUnscaled( const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &info )

Karsten Suehring
committed
2407
2408
2409
2410
2411
2412
2413
2414
2415
2416
2417
2418
2419
2420
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
{
CodingStructure &cs = *pu.cs;
const PredictionUnit *neibPU = NULL;
Position neibPos;
switch (eDir)
{
case MD_LEFT:
neibPos = pos.offset( -1, 0 );
break;
case MD_ABOVE:
neibPos = pos.offset( 0, -1 );
break;
case MD_ABOVE_RIGHT:
neibPos = pos.offset( 1, -1 );
break;
case MD_BELOW_LEFT:
neibPos = pos.offset( -1, 1 );
break;
case MD_ABOVE_LEFT:
neibPos = pos.offset( -1, -1 );
break;
default:
break;
}
neibPU = cs.getPURestricted( neibPos, pu, pu.chType );
if( neibPU == NULL || !CU::isInter( *neibPU->cu ) )
{
return false;
}
const MotionInfo& neibMi = neibPU->getMotionInfo( neibPos );
const int currRefPOC = cs.slice->getRefPic( eRefPicList, iRefIdx )->getPOC();
const RefPicList eRefPicList2nd = ( eRefPicList == REF_PIC_LIST_0 ) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
for( int predictorSource = 0; predictorSource < 2; predictorSource++ ) // examine the indicated reference picture list, then if not available, examine the other list.
{
const RefPicList eRefPicListIndex = ( predictorSource == 0 ) ? eRefPicList : eRefPicList2nd;
const int neibRefIdx = neibMi.refIdx[eRefPicListIndex];
if( neibRefIdx >= 0 && currRefPOC == cs.slice->getRefPOC( eRefPicListIndex, neibRefIdx ) )
{
info.mvCand[info.numCand++] = neibMi.mv[eRefPicListIndex];
return true;

Karsten Suehring
committed
}
}
return false;
}
/**
* \param pInfo
* \param eRefPicList
* \param iRefIdx
* \param uiPartUnitIdx
* \param eDir
* \returns bool
*/
bool PU::addMVPCandWithScaling( const PredictionUnit &pu, const RefPicList &eRefPicList, const int &iRefIdx, const Position &pos, const MvpDir &eDir, AMVPInfo &info )

Karsten Suehring
committed
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
2499
2500
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
{
CodingStructure &cs = *pu.cs;
const Slice &slice = *cs.slice;
const PredictionUnit *neibPU = NULL;
Position neibPos;
switch( eDir )
{
case MD_LEFT:
neibPos = pos.offset( -1, 0 );
break;
case MD_ABOVE:
neibPos = pos.offset( 0, -1 );
break;
case MD_ABOVE_RIGHT:
neibPos = pos.offset( 1, -1 );
break;
case MD_BELOW_LEFT:
neibPos = pos.offset( -1, 1 );
break;
case MD_ABOVE_LEFT:
neibPos = pos.offset( -1, -1 );
break;
default:
break;
}
neibPU = cs.getPURestricted( neibPos, pu, pu.chType );
if( neibPU == NULL || !CU::isInter( *neibPU->cu ) )
{
return false;
}
const MotionInfo& neibMi = neibPU->getMotionInfo( neibPos );
const RefPicList eRefPicList2nd = ( eRefPicList == REF_PIC_LIST_0 ) ? REF_PIC_LIST_1 : REF_PIC_LIST_0;
const int currPOC = slice.getPOC();
const int currRefPOC = slice.getRefPic( eRefPicList, iRefIdx )->poc;
const bool bIsCurrRefLongTerm = slice.getRefPic( eRefPicList, iRefIdx )->longTerm;
const int neibPOC = currPOC;
for( int predictorSource = 0; predictorSource < 2; predictorSource++ ) // examine the indicated reference picture list, then if not available, examine the other list.
{
const RefPicList eRefPicListIndex = (predictorSource == 0) ? eRefPicList : eRefPicList2nd;
const int neibRefIdx = neibMi.refIdx[eRefPicListIndex];
if( neibRefIdx >= 0 )
{
const bool bIsNeibRefLongTerm = slice.getRefPic(eRefPicListIndex, neibRefIdx)->longTerm;
if (bIsCurrRefLongTerm == bIsNeibRefLongTerm)
{
Mv cMv = neibMi.mv[eRefPicListIndex];
if( !( bIsCurrRefLongTerm /* || bIsNeibRefLongTerm*/) )
{
const int neibRefPOC = slice.getRefPOC( eRefPicListIndex, neibRefIdx );
const int scale = xGetDistScaleFactor( currPOC, currRefPOC, neibPOC, neibRefPOC );
if( scale != 4096 )
{
cMv = cMv.scaleMv( scale );
}
}
info.mvCand[info.numCand++] = cMv;
return true;

Karsten Suehring
committed
}
}
}
return false;
}
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;
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)
{
pmv.roundToAmvrSignalPrecision(MV_PRECISION_INTERNAL, imv);
}
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;
}
}
}
}
}
}

Karsten Suehring
committed
bool PU::isBipredRestriction(const PredictionUnit &pu)
{
if(pu.cu->lumaSize().width == 4 && pu.cu->lumaSize().height ==4 )
{
return true;
}

Karsten Suehring
committed
return false;
}
void PU::getAffineControlPointCand( const PredictionUnit &pu, MotionInfo mi[4], bool isAvailable[4], int verIdx[4], int modelIdx, int verNum, AffineMergeCtx& affMrgType )
{
int cuW = pu.Y().width;
int cuH = pu.Y().height;
int vx, vy;
int shift = MAX_CU_DEPTH;
int shiftHtoW = shift + g_aucLog2[cuW] - g_aucLog2[cuH];
// motion info
Mv cMv[2][4];
int refIdx[2] = { -1, -1 };
int dir = 0;
EAffineModel curType = (verNum == 2) ? AFFINEMODEL_4PARAM : AFFINEMODEL_6PARAM;

Karsten Suehring
committed
if ( verNum == 2 )
{
int idx0 = verIdx[0], idx1 = verIdx[1];
if ( !isAvailable[idx0] || !isAvailable[idx1] )
{
return;
}
for ( int l = 0; l < 2; l++ )
{
if ( mi[idx0].refIdx[l] >= 0 && mi[idx1].refIdx[l] >= 0 )
{
// check same refidx and different mv
#if JVET_M0228_REMOVE_CPMV_COMPARE
if ( mi[idx0].refIdx[l] == mi[idx1].refIdx[l])
#else
if ( mi[idx0].refIdx[l] == mi[idx1].refIdx[l] && mi[idx0].mv[l] != mi[idx1].mv[l] )
#endif
{
dir |= (l + 1);
refIdx[l] = mi[idx0].refIdx[l];
}
}
}
}
else if ( verNum == 3 )
{
int idx0 = verIdx[0], idx1 = verIdx[1], idx2 = verIdx[2];
if ( !isAvailable[idx0] || !isAvailable[idx1] || !isAvailable[idx2] )
{
return;
}
for ( int l = 0; l < 2; l++ )
{
if ( mi[idx0].refIdx[l] >= 0 && mi[idx1].refIdx[l] >= 0 && mi[idx2].refIdx[l] >= 0 )
{
// check same refidx and different mv
#if JVET_M0228_REMOVE_CPMV_COMPARE
if ( mi[idx0].refIdx[l] == mi[idx1].refIdx[l] && mi[idx0].refIdx[l] == mi[idx2].refIdx[l])
#else
if ( mi[idx0].refIdx[l] == mi[idx1].refIdx[l] && mi[idx0].refIdx[l] == mi[idx2].refIdx[l] && (mi[idx0].mv[l] != mi[idx1].mv[l] || mi[idx0].mv[l] != mi[idx2].mv[l]) )
#endif
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
2735
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
2756
2757
2758
2759
2760
2761
2762
2763
2764
2765
2766
2767
2768
2769
2770
2771
2772
2773
2774
2775
2776
2777
2778
2779
2780
2781
2782
2783
2784
2785
2786
2787
2788
2789
2790
2791
2792
2793
2794
2795
2796
2797
2798
2799
2800
2801
2802
2803
2804
2805
2806
2807
2808
2809
2810
2811
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824
2825
2826
{
dir |= (l + 1);
refIdx[l] = mi[idx0].refIdx[l];
}
}
}
}
if ( dir == 0 )
{
return;
}
for ( int l = 0; l < 2; l++ )
{
if ( dir & (l + 1) )
{
for ( int i = 0; i < verNum; i++ )
{
cMv[l][verIdx[i]] = mi[verIdx[i]].mv[l];
}
// convert to LT, RT[, [LB]]
switch ( modelIdx )
{
case 0: // 0 : LT, RT, LB
break;
case 1: // 1 : LT, RT, RB
cMv[l][2].hor = cMv[l][3].hor + cMv[l][0].hor - cMv[l][1].hor;
cMv[l][2].ver = cMv[l][3].ver + cMv[l][0].ver - cMv[l][1].ver;
break;
case 2: // 2 : LT, LB, RB
cMv[l][1].hor = cMv[l][3].hor + cMv[l][0].hor - cMv[l][2].hor;
cMv[l][1].ver = cMv[l][3].ver + cMv[l][0].ver - cMv[l][2].ver;
break;
case 3: // 3 : RT, LB, RB
cMv[l][0].hor = cMv[l][1].hor + cMv[l][2].hor - cMv[l][3].hor;
cMv[l][0].ver = cMv[l][1].ver + cMv[l][2].ver - cMv[l][3].ver;
break;
case 4: // 4 : LT, RT
break;
case 5: // 5 : LT, LB
vx = (cMv[l][0].hor << shift) + ((cMv[l][2].ver - cMv[l][0].ver) << shiftHtoW);
vy = (cMv[l][0].ver << shift) - ((cMv[l][2].hor - cMv[l][0].hor) << shiftHtoW);
roundAffineMv( vx, vy, shift );
cMv[l][1].set( vx, vy );
break;
default:
CHECK( 1, "Invalid model index!\n" );
break;
}
}
else
{
for ( int i = 0; i < 4; i++ )
{
cMv[l][i].hor = 0;
cMv[l][i].ver = 0;
}
}
}
for ( int i = 0; i < 3; i++ )
{
affMrgType.mvFieldNeighbours[(affMrgType.numValidMergeCand << 1) + 0][i].mv = cMv[0][i];
affMrgType.mvFieldNeighbours[(affMrgType.numValidMergeCand << 1) + 0][i].refIdx = refIdx[0];
affMrgType.mvFieldNeighbours[(affMrgType.numValidMergeCand << 1) + 1][i].mv = cMv[1][i];
affMrgType.mvFieldNeighbours[(affMrgType.numValidMergeCand << 1) + 1][i].refIdx = refIdx[1];
}
affMrgType.interDirNeighbours[affMrgType.numValidMergeCand] = dir;
affMrgType.affineType[affMrgType.numValidMergeCand] = curType;
affMrgType.numValidMergeCand++;
return;
}
const int getAvailableAffineNeighboursForLeftPredictor( const PredictionUnit &pu, const PredictionUnit* npu[] )
{
const Position posLB = pu.Y().bottomLeft();
int num = 0;
const PredictionUnit *puLeftBottom = pu.cs->getPURestricted( posLB.offset( -1, 1 ), pu, pu.chType );
if ( puLeftBottom && puLeftBottom->cu->affine
&& puLeftBottom->mergeType == MRG_TYPE_DEFAULT_N
)
{
npu[num++] = puLeftBottom;
return num;
}
const PredictionUnit* puLeft = pu.cs->getPURestricted( posLB.offset( -1, 0 ), pu, pu.chType );
if ( puLeft && puLeft->cu->affine
&& puLeft->mergeType == MRG_TYPE_DEFAULT_N
)
{
npu[num++] = puLeft;
return num;
}
return num;
}
const int getAvailableAffineNeighboursForAbovePredictor( const PredictionUnit &pu, const PredictionUnit* npu[], int numAffNeighLeft )
{
const Position posLT = pu.Y().topLeft();
const Position posRT = pu.Y().topRight();
int num = numAffNeighLeft;
const PredictionUnit* puAboveRight = pu.cs->getPURestricted( posRT.offset( 1, -1 ), pu, pu.chType );
if ( puAboveRight && puAboveRight->cu->affine
&& puAboveRight->mergeType == MRG_TYPE_DEFAULT_N
)
{
npu[num++] = puAboveRight;
return num;
}
const PredictionUnit* puAbove = pu.cs->getPURestricted( posRT.offset( 0, -1 ), pu, pu.chType );
if ( puAbove && puAbove->cu->affine
&& puAbove->mergeType == MRG_TYPE_DEFAULT_N
)
{
npu[num++] = puAbove;
return num;
}
const PredictionUnit *puAboveLeft = pu.cs->getPURestricted( posLT.offset( -1, -1 ), pu, pu.chType );
if ( puAboveLeft && puAboveLeft->cu->affine
&& puAboveLeft->mergeType == MRG_TYPE_DEFAULT_N
)
{
npu[num++] = puAboveLeft;
return num;
}
return num;
}
void PU::getAffineMergeCand( const PredictionUnit &pu, AffineMergeCtx& affMrgCtx, const int mrgCandIdx )
{
const CodingStructure &cs = *pu.cs;
const Slice &slice = *pu.cs->slice;
const uint32_t maxNumAffineMergeCand = slice.getMaxNumAffineMergeCand();
for ( int i = 0; i < maxNumAffineMergeCand; i++ )
{
for ( int mvNum = 0; mvNum < 3; mvNum++ )
{
affMrgCtx.mvFieldNeighbours[(i << 1) + 0][mvNum].setMvField( Mv(), -1 );
affMrgCtx.mvFieldNeighbours[(i << 1) + 1][mvNum].setMvField( Mv(), -1 );
}
affMrgCtx.interDirNeighbours[i] = 0;
affMrgCtx.affineType[i] = AFFINEMODEL_4PARAM;
affMrgCtx.mergeType[i] = MRG_TYPE_DEFAULT_N;
affMrgCtx.GBiIdx[i] = GBI_DEFAULT;
}
affMrgCtx.numValidMergeCand = 0;
affMrgCtx.maxNumMergeCand = maxNumAffineMergeCand;
bool enableSubPuMvp = slice.getSPS()->getSBTMVPEnabledFlag() && !(slice.getPOC() == slice.getRefPic(REF_PIC_LIST_0, 0)->getPOC() && slice.isIRAP());
bool isAvailableSubPu = false;
if ( enableSubPuMvp && slice.getEnableTMVPFlag() )
{
MergeCtx mrgCtx = *affMrgCtx.mrgCtx;
bool tmpLICFlag = false;
CHECK( mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized" );
mrgCtx.subPuMvpMiBuf.fill( MotionInfo() );
int pos = 0;
// Get spatial MV
#if JVET_M0116_ATMVP_LEFT_NB_FOR_OFFSET
const Position posCurLB = pu.Y().bottomLeft();
MotionInfo miLeft;
#else
const Position posCurRT = pu.Y().topRight();
const Position posCurLB = pu.Y().bottomLeft();
MotionInfo miAbove, miLeft, miAboveRight, miBelowLeft;
//left
const PredictionUnit* puLeft = cs.getPURestricted( posCurLB.offset( -1, 0 ), pu, pu.chType );
const bool isAvailableA1 = puLeft && isDiffMER( pu, *puLeft ) && pu.cu != puLeft->cu && CU::isInter( *puLeft->cu );
if ( isAvailableA1 )
{
miLeft = puLeft->getMotionInfo( posCurLB.offset( -1, 0 ) );
// get Inter Dir
mrgCtx.interDirNeighbours[pos] = miLeft.interDir;
// get Mv from Left
mrgCtx.mvFieldNeighbours[pos << 1].setMvField( miLeft.mv[0], miLeft.refIdx[0] );
if ( slice.isInterB() )
{
mrgCtx.mvFieldNeighbours[(pos << 1) + 1].setMvField( miLeft.mv[1], miLeft.refIdx[1] );
}
pos++;
}
#if !JVET_M0116_ATMVP_LEFT_NB_FOR_OFFSET
// above
const PredictionUnit *puAbove = cs.getPURestricted( posCurRT.offset( 0, -1 ), pu, pu.chType );
bool isAvailableB1 = puAbove && isDiffMER( pu, *puAbove ) && pu.cu != puAbove->cu && CU::isInter( *puAbove->cu );
if ( isAvailableB1 )
{
miAbove = puAbove->getMotionInfo( posCurRT.offset( 0, -1 ) );
if ( !isAvailableA1 || (miAbove != miLeft) )
{
// get Inter Dir
mrgCtx.interDirNeighbours[pos] = miAbove.interDir;
// get Mv from Left
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
mrgCtx.mvFieldNeighbours[pos << 1].setMvField( miAbove.mv[0], miAbove.refIdx[0] );
if ( slice.isInterB() )
{
mrgCtx.mvFieldNeighbours[(pos << 1) + 1].setMvField( miAbove.mv[1], miAbove.refIdx[1] );
}
pos++;
}
}
// above right
const PredictionUnit *puAboveRight = cs.getPURestricted( posCurRT.offset( 1, -1 ), pu, pu.chType );
bool isAvailableB0 = puAboveRight && isDiffMER( pu, *puAboveRight ) && CU::isInter( *puAboveRight->cu );
if ( isAvailableB0 )
{
miAboveRight = puAboveRight->getMotionInfo( posCurRT.offset( 1, -1 ) );
#if HM_JEM_MERGE_CANDS
if ( (!isAvailableB1 || (miAbove != miAboveRight)) && (!isAvailableA1 || (miLeft != miAboveRight)) )
#else
if ( !isAvailableB1 || (miAbove != miAboveRight) )
#endif
{
// get Inter Dir
mrgCtx.interDirNeighbours[pos] = miAboveRight.interDir;
// get Mv from Left
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
2954
mrgCtx.mvFieldNeighbours[pos << 1].setMvField( miAboveRight.mv[0], miAboveRight.refIdx[0] );
if ( slice.isInterB() )
{
mrgCtx.mvFieldNeighbours[(pos << 1) + 1].setMvField( miAboveRight.mv[1], miAboveRight.refIdx[1] );
}
pos++;
}
}
//left bottom
const PredictionUnit *puLeftBottom = cs.getPURestricted( posCurLB.offset( -1, 1 ), pu, pu.chType );
bool isAvailableA0 = puLeftBottom && isDiffMER( pu, *puLeftBottom ) && CU::isInter( *puLeftBottom->cu );
if ( isAvailableA0 )
{
miBelowLeft = puLeftBottom->getMotionInfo( posCurLB.offset( -1, 1 ) );
#if HM_JEM_MERGE_CANDS
if ( (!isAvailableA1 || (miBelowLeft != miLeft)) && (!isAvailableB1 || (miBelowLeft != miAbove)) && (!isAvailableB0 || (miBelowLeft != miAboveRight)) )
#else
if ( !isAvailableA1 || (miBelowLeft != miLeft) )
#endif
{
// get Inter Dir
mrgCtx.interDirNeighbours[pos] = miBelowLeft.interDir;
// get Mv from Bottom-Left
mrgCtx.mvFieldNeighbours[pos << 1].setMvField( miBelowLeft.mv[0], miBelowLeft.refIdx[0] );
if ( slice.isInterB() )
{
mrgCtx.mvFieldNeighbours[(pos << 1) + 1].setMvField( miBelowLeft.mv[1], miBelowLeft.refIdx[1] );
}
pos++;
}
}
mrgCtx.numValidMergeCand = pos;
isAvailableSubPu = getInterMergeSubPuMvpCand( pu, mrgCtx, tmpLICFlag, pos
, 0
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997
2998
2999
3000
);
if ( isAvailableSubPu )
{
for ( int mvNum = 0; mvNum < 3; mvNum++ )
{
affMrgCtx.mvFieldNeighbours[(affMrgCtx.numValidMergeCand << 1) + 0][mvNum].setMvField( mrgCtx.mvFieldNeighbours[(pos << 1) + 0].mv, mrgCtx.mvFieldNeighbours[(pos << 1) + 0].refIdx );
affMrgCtx.mvFieldNeighbours[(affMrgCtx.numValidMergeCand << 1) + 1][mvNum].setMvField( mrgCtx.mvFieldNeighbours[(pos << 1) + 1].mv, mrgCtx.mvFieldNeighbours[(pos << 1) + 1].refIdx );
}
affMrgCtx.interDirNeighbours[affMrgCtx.numValidMergeCand] = mrgCtx.interDirNeighbours[pos];
affMrgCtx.affineType[affMrgCtx.numValidMergeCand] = AFFINE_MODEL_NUM;
affMrgCtx.mergeType[affMrgCtx.numValidMergeCand] = MRG_TYPE_SUBPU_ATMVP;
if ( affMrgCtx.numValidMergeCand == mrgCandIdx )
{
return;
}
affMrgCtx.numValidMergeCand++;
// early termination
if ( affMrgCtx.numValidMergeCand == maxNumAffineMergeCand )
{
return;