Newer
Older

Karsten Suehring
committed
}
}
pu.mvAffi[eRefList][0] = affLT;
pu.mvAffi[eRefList][1] = affRT;
pu.mvAffi[eRefList][2] = affLB;

Karsten Suehring
committed
}
void clipColPos(int& posX, int& posY, const PredictionUnit& pu)
{
Position puPos = pu.lumaPos();
int log2CtuSize = floorLog2(pu.cs->sps->getCTUSize());
int ctuX = ((puPos.x >> log2CtuSize) << log2CtuSize);
int ctuY = ((puPos.y >> log2CtuSize) << log2CtuSize);
int horMax;
const SubPic &curSubPic = pu.cu->slice->getPPS()->getSubPicFromPos(puPos);
if (curSubPic.getTreatedAsPicFlag())
{
horMax = std::min((int)curSubPic.getSubPicRight(), ctuX + (int)pu.cs->sps->getCTUSize() + 3);
}
else
{
horMax = std::min((int)pu.cs->pps->getPicWidthInLumaSamples() - 1, ctuX + (int)pu.cs->sps->getCTUSize() + 3);
}
int horMin = std::max((int)0, ctuX);
int verMax = std::min( (int)pu.cs->pps->getPicHeightInLumaSamples() - 1, ctuY + (int)pu.cs->sps->getCTUSize() - 1 );
int verMin = std::max((int)0, ctuY);
posX = std::min(horMax, std::max(horMin, posX));
posY = std::min(verMax, std::max(verMin, posY));
}

Karsten Suehring
committed
bool PU::getInterMergeSubPuMvpCand(const PredictionUnit &pu, MergeCtx& mrgCtx, bool& LICFlag, const int count
, int mmvdList

Karsten Suehring
committed
{
const Slice &slice = *pu.cs->slice;
const unsigned scale = 4 * std::max<int>(1, 4 * AMVP_DECIMATION_FACTOR / 4);
const unsigned mask = ~(scale - 1);

Karsten Suehring
committed
const Picture *pColPic = slice.getRefPic(RefPicList(slice.isInterB() ? 1 - slice.getColFromL0Flag() : 0), slice.getColRefIdx());
Mv cTMv;
if ( count )
{
if ( (mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_0)) && slice.getRefPic( REF_PIC_LIST_0, mrgCtx.mvFieldNeighbours[REF_PIC_LIST_0].refIdx ) == pColPic )
{
cTMv = mrgCtx.mvFieldNeighbours[REF_PIC_LIST_0].mv;
}
else if ( slice.isInterB() && (mrgCtx.interDirNeighbours[0] & (1 << REF_PIC_LIST_1)) && slice.getRefPic( REF_PIC_LIST_1, mrgCtx.mvFieldNeighbours[REF_PIC_LIST_1].refIdx ) == pColPic )
{
cTMv = mrgCtx.mvFieldNeighbours[REF_PIC_LIST_1].mv;
}
}

Karsten Suehring
committed
///////////////////////////////////////////////////////////////////////
//////// GET Initial Temporal Vector ////////
///////////////////////////////////////////////////////////////////////
Mv cTempVector = cTMv;
bool tempLICFlag = false;
// compute the location of the current PU
Position puPos = pu.lumaPos();
Size puSize = pu.lumaSize();
int numPartLine = std::max(puSize.width >> ATMVP_SUB_BLOCK_SIZE, 1u);
int numPartCol = std::max(puSize.height >> ATMVP_SUB_BLOCK_SIZE, 1u);
int puHeight = numPartCol == 1 ? puSize.height : 1 << ATMVP_SUB_BLOCK_SIZE;
int puWidth = numPartLine == 1 ? puSize.width : 1 << ATMVP_SUB_BLOCK_SIZE;

Karsten Suehring
committed
Mv cColMv;

Karsten Suehring
committed
// use coldir.
bool bBSlice = slice.isInterB();
Position centerPos;
bool found = false;
cTempVector = cTMv;
cTempVector.changePrecision(MV_PRECISION_SIXTEENTH, MV_PRECISION_INT);
int tempX = cTempVector.getHor();
int tempY = cTempVector.getVer();
centerPos.x = puPos.x + (puSize.width >> 1) + tempX;
centerPos.y = puPos.y + (puSize.height >> 1) + tempY;
clipColPos(centerPos.x, centerPos.y, pu);

Karsten Suehring
committed
centerPos = Position{ PosType(centerPos.x & mask), PosType(centerPos.y & mask) };
// derivation of center motion parameters from the collocated CU
const MotionInfo &mi = pColPic->cs->getMotionInfo(centerPos);

Karsten Suehring
committed
{
mrgCtx.interDirNeighbours[count] = 0;

Karsten Suehring
committed
for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)
{
RefPicList currRefPicList = RefPicList(currRefListId);
if (getColocatedMVP(pu, currRefPicList, centerPos, cColMv, refIdx, true))

Karsten Suehring
committed
{
// set as default, for further motion vector field spanning
mrgCtx.mvFieldNeighbours[(count << 1) + currRefListId].setMvField(cColMv, 0);
mrgCtx.interDirNeighbours[count] |= (1 << currRefListId);
LICFlag = tempLICFlag;
mrgCtx.BcwIdx[count] = BCW_DEFAULT;

Karsten Suehring
committed
found = true;
}
else
{
mrgCtx.mvFieldNeighbours[(count << 1) + currRefListId].setMvField(Mv(), NOT_VALID);
mrgCtx.interDirNeighbours[count] &= ~(1 << currRefListId);
}
}
}
if (!found)
{
return false;
}
if (mmvdList != 1)
{
int xOff = (puWidth >> 1) + tempX;
int yOff = (puHeight >> 1) + tempY;

Karsten Suehring
committed
MotionBuf &mb = mrgCtx.subPuMvpMiBuf;

Karsten Suehring
committed
const bool isBiPred = isBipredRestriction(pu);

Karsten Suehring
committed
for (int y = puPos.y; y < puPos.y + puSize.height; y += puHeight)

Karsten Suehring
committed
{
for (int x = puPos.x; x < puPos.x + puSize.width; x += puWidth)
{
Position colPos{ x + xOff, y + yOff };

Karsten Suehring
committed
clipColPos(colPos.x, colPos.y, pu);

Karsten Suehring
committed
colPos = Position{ PosType(colPos.x & mask), PosType(colPos.y & mask) };

Karsten Suehring
committed
const MotionInfo &colMi = pColPic->cs->getMotionInfo(colPos);

Karsten Suehring
committed

Karsten Suehring
committed
found = false;
mi.isInter = true;
mi.sliceIdx = slice.getIndependentSliceIdx();
mi.isIBCmot = false;
if (colMi.isInter && colMi.isIBCmot == false)

Karsten Suehring
committed
{
for (unsigned currRefListId = 0; currRefListId < (bBSlice ? 2 : 1); currRefListId++)

Karsten Suehring
committed
{
RefPicList currRefPicList = RefPicList(currRefListId);
if (getColocatedMVP(pu, currRefPicList, colPos, cColMv, refIdx, true))
{
mi.refIdx[currRefListId] = 0;
mi.mv[currRefListId] = cColMv;
found = true;
}

Karsten Suehring
committed
}
}
if (!found)
{
mi.mv[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].mv;
mi.mv[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].mv;
mi.refIdx[0] = mrgCtx.mvFieldNeighbours[(count << 1) + 0].refIdx;
mi.refIdx[1] = mrgCtx.mvFieldNeighbours[(count << 1) + 1].refIdx;
}

Karsten Suehring
committed
mi.interDir = (mi.refIdx[0] != -1 ? 1 : 0) + (mi.refIdx[1] != -1 ? 2 : 0);

Karsten Suehring
committed
if (isBiPred && mi.interDir == 3)
{
mi.interDir = 1;
mi.mv[1] = Mv();
mi.refIdx[1] = NOT_VALID;
}

Karsten Suehring
committed
mb.subBuf(g_miScaling.scale(Position{ x, y } - pu.lumaPos()), g_miScaling.scale(Size(puWidth, puHeight)))
.fill(mi);

Karsten Suehring
committed
}
}

Karsten Suehring
committed
return true;

Karsten Suehring
committed
#if MULTI_PASS_DMVR
void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx, Mv* bdmvrSubPuMv0, Mv* bdmvrSubPuMv1, Mv* bdofSubPuMvOffset)
#else

Karsten Suehring
committed
void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx )

Karsten Suehring
committed
{

Karsten Suehring
committed
MotionBuf mb = pu.getMotionBuf();

Karsten Suehring
committed
if (!pu.mergeFlag || pu.mergeType == MRG_TYPE_DEFAULT_N || pu.mergeType == MRG_TYPE_IBC)

Karsten Suehring
committed
{
MotionInfo mi;
mi.isInter = !CU::isIntra(*pu.cu);
mi.isIBCmot = CU::isIBC(*pu.cu);

Karsten Suehring
committed
mi.sliceIdx = pu.cu->slice->getIndependentSliceIdx();
#if INTER_LIC
mi.usesLIC = pu.cu->LICFlag;
#endif

Karsten Suehring
committed
if( mi.isInter )
{
mi.interDir = pu.interDir;

Karsten Suehring
committed
for( int i = 0; i < NUM_REF_PIC_LIST_01; i++ )
{
mi.mv[i] = pu.mv[i];
mi.refIdx[i] = pu.refIdx[i];
}

Karsten Suehring
committed
}

Karsten Suehring
committed
{
CHECK(bdmvrSubPuMv0 == nullptr, "this is not possible");
const int dx = std::min<int>(pu.lwidth (), BDOF_SUBPU_DIM);
const int dy = std::min<int>(pu.lheight(), BDOF_SUBPU_DIM);
int subPuIdx = 0;
const int bioSubPuIdxStrideIncr = BDOF_SUBPU_STRIDE - std::max(1, (int)(pu.lwidth() >> BDOF_SUBPU_DIM_LOG2));
for (int yStart = 0; yStart < pu.lheight(); yStart += dy)

Karsten Suehring
committed
{

Karsten Suehring
committed
{
const int bdmvrSubPuIdx = (yStart >> DMVR_SUBCU_HEIGHT_LOG2) * DMVR_SUBPU_STRIDE + (xStart >> DMVR_SUBCU_WIDTH_LOG2);
mi.mv[0] = bdmvrSubPuMv0[bdmvrSubPuIdx] + bdofSubPuMvOffset[subPuIdx];
mi.mv[1] = bdmvrSubPuMv1[bdmvrSubPuIdx] - bdofSubPuMvOffset[subPuIdx];
subPuIdx++;
MotionBuf mb = pu.cs->getMotionBuf(Area(pu.lx() + xStart, pu.ly() + yStart, dx, dy));
mb.fill(mi);

Karsten Suehring
committed
}
subPuIdx += bioSubPuIdxStrideIncr;
}
return;
}
MotionBuf mb = pu.getMotionBuf();
#endif
if (pu.cu->affine)
{
mi.mv[0].setZero(); // to make sure filling of MV in unused reference list
mi.mv[1].setZero();
mb.fill(mi);
if (pu.refIdx[0] >= 0)
{
PU::setAllAffineMv(pu, pu.mvAffi[0][0], pu.mvAffi[0][1], pu.mvAffi[0][2], REF_PIC_LIST_0);
}
if (pu.refIdx[1] >= 0)
{
PU::setAllAffineMv(pu, pu.mvAffi[1][0], pu.mvAffi[1][1], pu.mvAffi[1][2], REF_PIC_LIST_1);

Karsten Suehring
committed
}
}
else
{

Karsten Suehring
committed
}
}
else if (pu.mergeType == MRG_TYPE_SUBPU_ATMVP)
{
CHECK(mrgCtx.subPuMvpMiBuf.area() == 0 || !mrgCtx.subPuMvpMiBuf.buf, "Buffer not initialized");
#if MULTI_PASS_DMVR
MotionBuf mb = pu.getMotionBuf();
#endif

Karsten Suehring
committed
mb.copyFrom(mrgCtx.subPuMvpMiBuf);
}
}
void PU::applyImv( PredictionUnit& pu, MergeCtx &mrgCtx, InterPrediction *interPred )
{
if( !pu.mergeFlag )
{
if( pu.interDir != 2 /* PRED_L1 */ )
{
pu.mvd[0].changeTransPrecAmvr2Internal(pu.cu->imv);

Karsten Suehring
committed
unsigned mvp_idx = pu.mvpIdx[0];
AMVPInfo amvpInfo;
PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo
#if TM_AMVP
, interPred
#endif
);

Karsten Suehring
committed
pu.mvpNum[0] = amvpInfo.numCand;
pu.mvpIdx[0] = mvp_idx;
pu.mv [0] = amvpInfo.mvCand[mvp_idx] + pu.mvd[0];

Karsten Suehring
committed
}
if (pu.interDir != 1 /* PRED_L0 */)
{
if( !( pu.cu->cs->picHeader->getMvdL1ZeroFlag() && pu.interDir == 3 ) && pu.cu->imv )/* PRED_BI */

Karsten Suehring
committed
{
pu.mvd[1].changeTransPrecAmvr2Internal(pu.cu->imv);

Karsten Suehring
committed
}
unsigned mvp_idx = pu.mvpIdx[1];
AMVPInfo amvpInfo;
PU::fillMvpCand(pu, REF_PIC_LIST_1, pu.refIdx[1], amvpInfo
#if TM_AMVP
, interPred
#endif
);

Karsten Suehring
committed
pu.mvpNum[1] = amvpInfo.numCand;
pu.mvpIdx[1] = mvp_idx;
pu.mv [1] = amvpInfo.mvCand[mvp_idx] + pu.mvd[1];

Karsten Suehring
committed
}
}
else
{
// this function is never called for merge
THROW("unexpected");
PU::getInterMergeCandidates(pu, mrgCtx, 0);

Karsten Suehring
committed
mrgCtx.setMergeInfo( pu, pu.mergeIdx );
}
PU::spanMotionInfo( pu, mrgCtx );
}
bool PU::isBiPredFromDifferentDirEqDistPoc(const PredictionUnit& pu)
{
if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
{
if (pu.cu->slice->getRefPic(REF_PIC_LIST_0, pu.refIdx[0])->longTerm
|| pu.cu->slice->getRefPic(REF_PIC_LIST_1, pu.refIdx[1])->longTerm)
{
return false;
}
const int poc0 = pu.cu->slice->getRefPOC(REF_PIC_LIST_0, pu.refIdx[0]);
const int poc1 = pu.cu->slice->getRefPOC(REF_PIC_LIST_1, pu.refIdx[1]);
const int poc = pu.cu->slice->getPOC();
if ((poc - poc0)*(poc - poc1) < 0)
{
return true;
}
}
}
return false;
}

Karsten Suehring
committed
void PU::restrictBiPredMergeCandsOne(PredictionUnit &pu)
{
if (PU::isBipredRestriction(pu))
{
if (pu.interDir == 3)
{
pu.interDir = 1;
pu.refIdx[1] = -1;
pu.mv[1] = Mv(0, 0);
pu.cu->BcwIdx = BCW_DEFAULT;
#if MULTI_HYP_PRED
pu.addHypData.clear();
pu.numMergedAddHyps = 0;
#endif
void PU::getGeoMergeCandidates( const PredictionUnit &pu, MergeCtx& geoMrgCtx )
{
MergeCtx tmpMergeCtx;
const uint32_t maxNumMergeCand = pu.cs->sps->getMaxNumMergeCand();
geoMrgCtx.numValidMergeCand = 0;
for (int32_t i = 0; i < GEO_MAX_NUM_UNI_CANDS; i++)
{
geoMrgCtx.BcwIdx[i] = BCW_DEFAULT;
geoMrgCtx.interDirNeighbours[i] = 0;
geoMrgCtx.mvFieldNeighbours[(i << 1)].refIdx = NOT_VALID;
geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].refIdx = NOT_VALID;
geoMrgCtx.mvFieldNeighbours[(i << 1)].mv = Mv();
geoMrgCtx.mvFieldNeighbours[(i << 1) + 1].mv = Mv();
geoMrgCtx.useAltHpelIf[i] = false;
#if INTER_LIC
geoMrgCtx.LICFlags[i] = false;
#endif
4400
4401
4402
4403
4404
4405
4406
4407
4408
4409
4410
4411
4412
4413
4414
4415
4416
4417
4418
4419
4420
4421
4422
4423
4424
4425
4426
4427
4428
4429
4430
4431
4432
4433
4434
4435
4436
4437
4438
4439
4440
4441
4442
4443
4444
4445
4446
4447
4448
4449
4450
4451
4452
4453
4454
4455
4456
4457
4458
4459
4460
4461
4462
4463
4464
4465
4466
4467
4468
4469
4470
4471
4472
4473
4474
4475
4476
4477
4478
4479
4480
4481
4482
4483
4484
4485
}
PU::getInterMergeCandidates(pu, tmpMergeCtx, 0);
for (int32_t i = 0; i < maxNumMergeCand; i++)
{
int parity = i & 1;
if( tmpMergeCtx.interDirNeighbours[i] & (0x01 + parity) )
{
geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 1 + parity;
geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = Mv(0, 0);
geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].mv;
geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].refIdx = -1;
geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + parity].refIdx;
geoMrgCtx.numValidMergeCand++;
if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS)
{
return;
}
continue;
}
if (tmpMergeCtx.interDirNeighbours[i] & (0x02 - parity))
{
geoMrgCtx.interDirNeighbours[geoMrgCtx.numValidMergeCand] = 2 - parity;
geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].mv = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].mv;
geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].mv = Mv(0, 0);
geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + !parity].refIdx = tmpMergeCtx.mvFieldNeighbours[(i << 1) + !parity].refIdx;
geoMrgCtx.mvFieldNeighbours[(geoMrgCtx.numValidMergeCand << 1) + parity].refIdx = -1;
geoMrgCtx.numValidMergeCand++;
if (geoMrgCtx.numValidMergeCand == GEO_MAX_NUM_UNI_CANDS)
{
return;
}
}
}
}
void PU::spanGeoMotionInfo( PredictionUnit &pu, MergeCtx &geoMrgCtx, const uint8_t splitDir, const uint8_t candIdx0, const uint8_t candIdx1)
{
pu.geoSplitDir = splitDir;
pu.geoMergeIdx0 = candIdx0;
pu.geoMergeIdx1 = candIdx1;
MotionBuf mb = pu.getMotionBuf();
MotionInfo biMv;
biMv.isInter = true;
biMv.sliceIdx = pu.cs->slice->getIndependentSliceIdx();
if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 )
{
biMv.interDir = 3;
biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].mv;
biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].refIdx;
biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
}
else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 )
{
biMv.interDir = 3;
biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].mv;
biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].refIdx;
biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
}
else if( geoMrgCtx.interDirNeighbours[candIdx0] == 1 && geoMrgCtx.interDirNeighbours[candIdx1] == 1 )
{
biMv.interDir = 1;
biMv.mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
biMv.mv[1] = Mv(0, 0);
biMv.refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx;
biMv.refIdx[1] = -1;
}
else if( geoMrgCtx.interDirNeighbours[candIdx0] == 2 && geoMrgCtx.interDirNeighbours[candIdx1] == 2 )
{
biMv.interDir = 2;
biMv.mv[0] = Mv(0, 0);
biMv.mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
biMv.refIdx[0] = -1;
biMv.refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
}
int16_t angle = g_GeoParams[splitDir][0];
int tpmMask = 0;
int lookUpY = 0, motionIdx = 0;
bool isFlip = angle >= 13 && angle <= 27;
int distanceIdx = g_GeoParams[splitDir][1];
int distanceX = angle;
int distanceY = (distanceX + (GEO_NUM_ANGLES >> 2)) % GEO_NUM_ANGLES;
int offsetX = (-(int)pu.lwidth()) >> 1;
int offsetY = (-(int)pu.lheight()) >> 1;
if (distanceIdx > 0)
{
if( angle % 16 == 8 || ( angle % 16 != 0 && pu.lheight() >= pu.lwidth() ) )
offsetY += angle < 16 ? ( ( distanceIdx * pu.lheight() ) >> 3 ) : -( int ) ( ( distanceIdx * pu.lheight() ) >> 3 );
offsetX += angle < 16 ? ( ( distanceIdx * pu.lwidth() ) >> 3 ) : -( int ) ( ( distanceIdx * pu.lwidth() ) >> 3 );
for (int y = 0; y < mb.height; y++)
{
lookUpY = (((4 * y + offsetY) << 1) + 5) * g_Dis[distanceY];
for (int x = 0; x < mb.width; x++)
{
motionIdx = (((4 * x + offsetX) << 1) + 5) * g_Dis[distanceX] + lookUpY;
tpmMask = abs(motionIdx) < 32 ? 2 : (motionIdx <= 0 ? (1 - isFlip) : isFlip);
if (tpmMask == 2)
{
motionInfo[x].isInter = true;
motionInfo[x].interDir = biMv.interDir;
motionInfo[x].refIdx[0] = biMv.refIdx[0];
motionInfo[x].refIdx[1] = biMv.refIdx[1];
motionInfo[x].mv[0] = biMv.mv[0];
motionInfo[x].mv[1] = biMv.mv[1];
motionInfo[x].sliceIdx = biMv.sliceIdx;
}
else if (tpmMask == 0)
{
motionInfo[x].isInter = true;
motionInfo[x].interDir = geoMrgCtx.interDirNeighbours[candIdx0];
motionInfo[x].refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx;
motionInfo[x].refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
motionInfo[x].mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv;
motionInfo[x].mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
motionInfo[x].sliceIdx = biMv.sliceIdx;
}
else
{
motionInfo[x].isInter = true;
motionInfo[x].interDir = geoMrgCtx.interDirNeighbours[candIdx1];
motionInfo[x].refIdx[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx;
motionInfo[x].refIdx[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
motionInfo[x].mv[0] = geoMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
motionInfo[x].mv[1] = geoMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
motionInfo[x].sliceIdx = biMv.sliceIdx;
}
}
}
}

Karsten Suehring
committed
bool CU::hasSubCUNonZeroMVd( const CodingUnit& cu )
{
bool bNonZeroMvd = false;
for( const auto &pu : CU::traversePUs( cu ) )
{
if( ( !pu.mergeFlag ) && ( !cu.skip ) )
{
if( pu.interDir != 2 /* PRED_L1 */ )
{
bNonZeroMvd |= pu.mvd[REF_PIC_LIST_0].getHor() != 0;
bNonZeroMvd |= pu.mvd[REF_PIC_LIST_0].getVer() != 0;
}
if( pu.interDir != 1 /* PRED_L0 */ )
{
if( !pu.cu->cs->picHeader->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )

Karsten Suehring
committed
{
bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getHor() != 0;
bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getVer() != 0;
}
}
}
}
return bNonZeroMvd;
}
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
bool CU::hasSubCUNonZeroAffineMVd( const CodingUnit& cu )
{
bool nonZeroAffineMvd = false;
if ( !cu.affine || cu.firstPU->mergeFlag )
{
return false;
}
for ( const auto &pu : CU::traversePUs( cu ) )
{
if ( ( !pu.mergeFlag ) && ( !cu.skip ) )
{
if ( pu.interDir != 2 /* PRED_L1 */ )
{
for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
{
nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getHor() != 0;
nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_0][i].getVer() != 0;
}
}
if ( pu.interDir != 1 /* PRED_L0 */ )
{
if ( !pu.cu->cs->picHeader->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
{
for ( int i = 0; i < ( cu.affineType == AFFINEMODEL_6PARAM ? 3 : 2 ); i++ )
{
nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getHor() != 0;
nonZeroAffineMvd |= pu.mvdAffi[REF_PIC_LIST_1][i].getVer() != 0;
}
}
}
}
}
return nonZeroAffineMvd;
}
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625
4626
4627
4628
4629
4630
4631
4632
4633
4634
4635
4636
4637
4638
4639
4640
4641
4642
4643
4644
4645
4646
4647
uint8_t CU::getSbtInfo( uint8_t idx, uint8_t pos )
{
return ( pos << 4 ) + ( idx << 0 );
}
uint8_t CU::getSbtIdx( const uint8_t sbtInfo )
{
return ( sbtInfo >> 0 ) & 0xf;
}
uint8_t CU::getSbtPos( const uint8_t sbtInfo )
{
return ( sbtInfo >> 4 ) & 0x3;
}
uint8_t CU::getSbtMode( uint8_t sbtIdx, uint8_t sbtPos )
{
uint8_t sbtMode = 0;
switch( sbtIdx )
{
case SBT_VER_HALF: sbtMode = sbtPos + SBT_VER_H0; break;
case SBT_HOR_HALF: sbtMode = sbtPos + SBT_HOR_H0; break;
case SBT_VER_QUAD: sbtMode = sbtPos + SBT_VER_Q0; break;
case SBT_HOR_QUAD: sbtMode = sbtPos + SBT_HOR_Q0; break;
default: assert( 0 );
}
assert( sbtMode < NUMBER_SBT_MODE );
return sbtMode;
}
uint8_t CU::getSbtIdxFromSbtMode( uint8_t sbtMode )
{
if( sbtMode <= SBT_VER_H1 )
else if( sbtMode <= SBT_HOR_H1 )
else if( sbtMode <= SBT_VER_Q1 )
else if( sbtMode <= SBT_HOR_Q1 )
else
{
assert( 0 );
return 0;
}
}
uint8_t CU::getSbtPosFromSbtMode( uint8_t sbtMode )
{
if( sbtMode <= SBT_VER_H1 )
return sbtMode - SBT_VER_H0;
else if( sbtMode <= SBT_HOR_H1 )
return sbtMode - SBT_HOR_H0;
else if( sbtMode <= SBT_VER_Q1 )
return sbtMode - SBT_VER_Q0;
else if( sbtMode <= SBT_HOR_Q1 )
return sbtMode - SBT_HOR_Q0;
4688
4689
4690
4691
4692
4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
4709
4710
4711
4712
4713
4714
4715
4716
4717
4718
4719
4720
4721
4722
4723
4724
4725
4726
4727
4728
4729
4730
else
{
assert( 0 );
return 0;
}
}
uint8_t CU::targetSbtAllowed( uint8_t sbtIdx, uint8_t sbtAllowed )
{
uint8_t val = 0;
switch( sbtIdx )
{
case SBT_VER_HALF: val = ( ( sbtAllowed >> SBT_VER_HALF ) & 0x1 ); break;
case SBT_HOR_HALF: val = ( ( sbtAllowed >> SBT_HOR_HALF ) & 0x1 ); break;
case SBT_VER_QUAD: val = ( ( sbtAllowed >> SBT_VER_QUAD ) & 0x1 ); break;
case SBT_HOR_QUAD: val = ( ( sbtAllowed >> SBT_HOR_QUAD ) & 0x1 ); break;
default: CHECK( 1, "unknown SBT type" );
}
return val;
}
uint8_t CU::numSbtModeRdo( uint8_t sbtAllowed )
{
uint8_t num = 0;
uint8_t sum = 0;
num = targetSbtAllowed( SBT_VER_HALF, sbtAllowed ) + targetSbtAllowed( SBT_HOR_HALF, sbtAllowed );
sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
num = targetSbtAllowed( SBT_VER_QUAD, sbtAllowed ) + targetSbtAllowed( SBT_HOR_QUAD, sbtAllowed );
sum += std::min( SBT_NUM_RDO, ( num << 1 ) );
return sum;
}
bool CU::isSbtMode( const uint8_t sbtInfo )
{
uint8_t sbtIdx = getSbtIdx( sbtInfo );
return sbtIdx >= SBT_VER_HALF && sbtIdx <= SBT_HOR_QUAD;
}
bool CU::isSameSbtSize( const uint8_t sbtInfo1, const uint8_t sbtInfo2 )
{
uint8_t sbtIdx1 = getSbtIdxFromSbtMode( sbtInfo1 );
uint8_t sbtIdx2 = getSbtIdxFromSbtMode( sbtInfo2 );
if( sbtIdx1 == SBT_HOR_HALF || sbtIdx1 == SBT_VER_HALF )
return sbtIdx2 == SBT_HOR_HALF || sbtIdx2 == SBT_VER_HALF;
else if( sbtIdx1 == SBT_HOR_QUAD || sbtIdx1 == SBT_VER_QUAD )
return sbtIdx2 == SBT_HOR_QUAD || sbtIdx2 == SBT_VER_QUAD;
Adarsh Krishnan Ramasubramonian
committed
bool CU::isPredRegDiffFromTB(const CodingUnit &cu, const ComponentID compID)
{
return (compID == COMPONENT_Y)
&& (cu.ispMode == VER_INTRA_SUBPARTITIONS
&& CU::isMinWidthPredEnabledForBlkSize(cu.blocks[compID].width, cu.blocks[compID].height));
Adarsh Krishnan Ramasubramonian
committed
}
Adarsh Krishnan Ramasubramonian
committed
bool CU::isMinWidthPredEnabledForBlkSize(const int w, const int h)
{
return ((w == 8 && h > 4) || w == 4);
}
Adarsh Krishnan Ramasubramonian
committed
bool CU::isFirstTBInPredReg(const CodingUnit& cu, const ComponentID compID, const CompArea &area)
{
return (compID == COMPONENT_Y) && cu.ispMode && ((area.topLeft().x - cu.Y().topLeft().x) % PRED_REG_MIN_WIDTH == 0);
}
Adarsh Krishnan Ramasubramonian
committed
void CU::adjustPredArea(CompArea &area)
{
area.width = std::max<int>(PRED_REG_MIN_WIDTH, area.width);
}
4766
4767
4768
4769
4770
4771
4772
4773
4774
4775
4776
4777
4778
4779
4780
4781
4782
4783
4784
4785
4786
4787
4788
4789
4790
4791
4792
4793
4794
4795
4796
4797
4798
4799
4800
4801
4802
4803
4804
4805
4806
4807
4808
4809
4810
4811
4812
4813
4814
4815
4816
4817
4818
4819
4820
4821
4822
4823
#if MULTI_HYP_PRED
AMVPInfo PU::getMultiHypMVPCandsMerge(PredictionUnit &pu, const RefPicList eRefPicList, const int refIdx)
{
CHECK(!pu.mergeFlag, "this function is only for merge");
AMVPInfo amvpInfo;
PU::fillMvpCand(pu, eRefPicList, refIdx, amvpInfo);
return amvpInfo;
}
AMVPInfo PU::getMultiHypMVPCandsAMVP(PredictionUnit &pu, const RefPicList eRefPicList, const int refIdx)
{
CHECK(pu.mergeFlag, "this function is only for AMVP");
CHECK(pu.interDir != 3, "Multi-Hyp is only allowed for bi-predictive AMVP mode")
const int refListForAMVP = eRefPicList;
const int refIdxForAMVP = refIdx;
AMVPInfo amvpInfo;
if (pu.cu->affine) // TODO: check performance impact
{
AffineAMVPInfo affineAMVPInfo;
PU::fillAffineMvpCand(pu, RefPicList(refListForAMVP), refIdxForAMVP, affineAMVPInfo);
amvpInfo.numCand = affineAMVPInfo.numCand;
memcpy(amvpInfo.mvCand, affineAMVPInfo.mvCandLT, sizeof(amvpInfo.mvCand));
}
else
{
PU::fillMvpCand(pu, RefPicList(refListForAMVP), refIdxForAMVP, amvpInfo);
}
return amvpInfo;
}
AMVPInfo PU::getMultiHypMVPCands(PredictionUnit &pu, const MultiHypPredictionData &mhData)
{
const auto &mhDataForAMVPList = !pu.mergeFlag || pu.addHypData.size() == pu.numMergedAddHyps ? mhData : pu.addHypData[pu.numMergedAddHyps];
const auto mhRefIdxForAMVPList = mhDataForAMVPList.refIdx;
const auto &MHRefPics = pu.cs->slice->getMultiHypRefPicList();
CHECK(MHRefPics.empty(), "Multi Hyp: MHRefPics.empty()");
CHECK(mhRefIdxForAMVPList >= MHRefPics.size(), "Multi Hyp: mhRefIdxForAMVPList >= MHRefPics.size()");
const auto eRefPicList = RefPicList(MHRefPics[mhRefIdxForAMVPList].refList);
const int iRefIdx = MHRefPics[mhRefIdxForAMVPList].refIdx;
return (pu.mergeFlag ? PU::getMultiHypMVPCandsMerge : PU::getMultiHypMVPCandsAMVP)(pu, eRefPicList, iRefIdx);
}
Mv PU::getMultiHypMVP(PredictionUnit &pu, const MultiHypPredictionData &mhData)
{
const auto amvpInfo = getMultiHypMVPCands(pu, mhData);
CHECK(mhData.mvpIdx < 0, "Multi Hyp: mhData.mvpIdx < 0");
CHECK(mhData.mvpIdx >= amvpInfo.numCand, "Multi Hyp: mhData.mvpIdx >= amvpInfo.numCand");
const Mv mvp = amvpInfo.mvCand[mhData.mvpIdx];
return mvp;
}
#endif
bool CU::isBcwIdxCoded( const CodingUnit &cu )
if( cu.cs->sps->getUseBcw() == false )
CHECK(cu.BcwIdx != BCW_DEFAULT, "Error: cu.BcwIdx != BCW_DEFAULT");
if (cu.predMode == MODE_IBC)
{
return false;
}
if( cu.predMode == MODE_INTRA || cu.cs->slice->isInterP() )
{
return false;
}

Karsten Suehring
committed
if( cu.lwidth() * cu.lheight() < BCW_SIZE_CONSTRAINT )

Karsten Suehring
committed
if( !cu.firstPU->mergeFlag )
if( cu.firstPU->interDir == 3 )
{
const int refIdx0 = cu.firstPU->refIdx[REF_PIC_LIST_0];
const int refIdx1 = cu.firstPU->refIdx[REF_PIC_LIST_1];
const WPScalingParam *wp0 = cu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0);
const WPScalingParam *wp1 = cu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1);
return !(WPScalingParam::isWeighted(wp0) || WPScalingParam::isWeighted(wp1));

Karsten Suehring
committed
uint8_t CU::getValidBcwIdx( const CodingUnit &cu )
{
if( cu.firstPU->interDir == 3 && !cu.firstPU->mergeFlag )
{
return cu.BcwIdx;
}
else if( cu.firstPU->interDir == 3 && cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_DEFAULT_N )
{
// This is intended to do nothing here.
}
else if( cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP )
{
CHECK(cu.BcwIdx != BCW_DEFAULT, " cu.BcwIdx != BCW_DEFAULT ");
CHECK(cu.BcwIdx != BCW_DEFAULT, " cu.BcwIdx != BCW_DEFAULT ");
return BCW_DEFAULT;
void CU::setBcwIdx( CodingUnit &cu, uint8_t uh )
{
int8_t uhCnt = 0;
if( cu.firstPU->interDir == 3 && !cu.firstPU->mergeFlag )
{
++uhCnt;
}
else if( cu.firstPU->interDir == 3 && cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_DEFAULT_N )
{
// This is intended to do nothing here.
}
else if( cu.firstPU->mergeFlag && cu.firstPU->mergeType == MRG_TYPE_SUBPU_ATMVP )
{
cu.BcwIdx = BCW_DEFAULT;
cu.BcwIdx = BCW_DEFAULT;
}
CHECK(uhCnt <= 0, " uhCnt <= 0 ");
}
uint8_t CU::deriveBcwIdx( uint8_t bcwLO, uint8_t bcwL1 )
if( bcwLO == bcwL1 )
const int8_t w0 = getBcwWeight(bcwLO, REF_PIC_LIST_0);
const int8_t w1 = getBcwWeight(bcwL1, REF_PIC_LIST_1);
const int8_t th = g_BcwWeightBase >> 1;
const int8_t off = 1;
if( w0 == w1 || (w0 < (th - off) && w1 < (th - off)) || (w0 >(th + off) && w1 >(th + off)) )
{
return BCW_DEFAULT;
}
else
{
if( w0 > w1 )
{
return ( w0 >= th ? bcwLO : bcwL1 );
return ( w1 >= th ? bcwL1 : bcwLO );

Karsten Suehring
committed
bool CU::bdpcmAllowed( const CodingUnit& cu, const ComponentID compID )
{
Shih-Ta Hsiang
committed
SizeType transformSkipMaxSize = 1 << cu.cs->sps->getLog2MaxTransformSkipBlockSize();
Alican Nalci
committed
bool bdpcmAllowed = cu.cs->sps->getBDPCMEnabledFlag();
bdpcmAllowed &= CU::isIntra( cu );
{
bdpcmAllowed &= (cu.lwidth() <= transformSkipMaxSize && cu.lheight() <= transformSkipMaxSize);
{
bdpcmAllowed &=
(cu.chromaSize().width <= transformSkipMaxSize && cu.chromaSize().height <= transformSkipMaxSize)
&& !cu.colorTransform;
}
bool CU::isMTSAllowed(const CodingUnit &cu, const ComponentID compID)
{
Shih-Ta Hsiang
committed
SizeType tsMaxSize = 1 << cu.cs->sps->getLog2MaxTransformSkipBlockSize();
const int maxSize = CU::isIntra( cu ) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE;
const int cuWidth = cu.blocks[0].lumaSize().width;
const int cuHeight = cu.blocks[0].lumaSize().height;
bool mtsAllowed = cu.chType == CHANNEL_TYPE_LUMA && compID == COMPONENT_Y;
mtsAllowed &= CU::isIntra( cu ) ? cu.cs->sps->getUseIntraMTS() : cu.cs->sps->getUseInterMTS() && CU::isInter( cu );
mtsAllowed &= cuWidth <= maxSize && cuHeight <= maxSize;
mtsAllowed &= !cu.ispMode;
mtsAllowed &= !cu.sbtInfo;
mtsAllowed &= !(cu.bdpcmMode && cuWidth <= tsMaxSize && cuHeight <= tsMaxSize);
return mtsAllowed;
}
4977
4978
4979
4980
4981
4982
4983
4984
4985
4986
4987
4988
4989
4990
4991
4992
4993
4994
4995
4996
4997
4998
4999
5000
#if ENABLE_OBMC
unsigned int PU::getSameNeigMotion(PredictionUnit &pu, MotionInfo& mi, Position off, int iDir, int& iLength, int iMaxLength)
{
PredictionUnit* tmpPu = nullptr;
Position posNeighborMotion = Position(0, 0);
const Position posSubBlock(pu.lumaPos().offset(off));
const unsigned int uiMinCUW = pu.cs->pcv->minCUWidth;
if (iDir == 0)
{
posNeighborMotion = posSubBlock.offset(0, -1);
}
else if (iDir == 1)
{
posNeighborMotion = posSubBlock.offset(-1, 0);
}
else
{
THROW("iDir not supported");
}
tmpPu = pu.cs->getPU(posNeighborMotion, pu.chType);
//if neighbor pu is not available, return.