Newer
Older
#if JVET_N0266_SMALL_BLOCKS
existMV = getColocatedMVP( pu, REF_PIC_LIST_0, posC1, cColMv, refIdx );
#else
existMV = isAvailableC1 && getColocatedMVP(pu, REF_PIC_LIST_0, posC1, cColMv, refIdx );
#endif
temporalMv.isInter = true;
temporalMv.interDir |= 1;
temporalMv.mv[0] = cColMv;
temporalMv.refIdx[0] = refIdx;
#if JVET_N0266_SMALL_BLOCKS
existMV = getColocatedMVP( pu, REF_PIC_LIST_1, posC1, cColMv, refIdx );
#else
existMV = isAvailableC1 && getColocatedMVP(pu, REF_PIC_LIST_1, posC1, cColMv, refIdx );
#endif
temporalMv.interDir |= 2;
temporalMv.mv[1] = cColMv;
temporalMv.refIdx[1] = refIdx;
candidate[candCount].isInter = true;
candidate[candCount].interDir = temporalMv.interDir;
candidate[candCount].mv[0] = temporalMv.mv[0];
candidate[candCount].mv[1] = temporalMv.mv[1];
candidate[candCount].refIdx[0] = temporalMv.refIdx[0];
candidate[candCount].refIdx[1] = temporalMv.refIdx[1];
candCount++;
}
// put uni-prediction candidate to the triangle candidate list
for( int32_t i = 0; i < candCount; i++ )
if( candidate[i].interDir != 3 )
{
triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = candidate[i].interDir;
triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) ].mv = candidate[i].mv[0];
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = candidate[i].mv[1];
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) ].refIdx = candidate[i].refIdx[0];
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = candidate[i].refIdx[1];
triangleMrgCtx.numValidMergeCand += isUniqueTriangleCandidates(pu, triangleMrgCtx);
if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
{
return;
}
}
}
// put L0 mv of bi-prediction candidate to the triangle candidate list
for( int32_t i = 0; i < candCount; i++ )
triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1;
triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) ].mv = candidate[i].mv[0];
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = Mv(0, 0);
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) ].refIdx = candidate[i].refIdx[0];
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = -1;
triangleMrgCtx.numValidMergeCand += isUniqueTriangleCandidates(pu, triangleMrgCtx);
if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
{
return;
}
}
}
// put L1 mv of bi-prediction candidate to the triangle candidate list
for( int32_t i = 0; i < candCount; i++ )
triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 2;
triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) ].mv = Mv(0, 0);
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = candidate[i].mv[1];
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) ].refIdx = -1;
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = candidate[i].refIdx[1];
triangleMrgCtx.numValidMergeCand += isUniqueTriangleCandidates(pu, triangleMrgCtx);
if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
{
return;
}
}
}
// put average of L0 and L1 mvs of bi-prediction candidate to the triangle candidate list
for( int32_t i = 0; i < candCount; i++ )
int32_t curPicPoc = slice.getPOC();
int32_t refPicPocL0 = slice.getRefPOC(REF_PIC_LIST_0, candidate[i].refIdx[0]);
int32_t refPicPocL1 = slice.getRefPOC(REF_PIC_LIST_1, candidate[i].refIdx[1]);
Mv aveMv = candidate[i].mv[1];
int32_t distscale = xGetDistScaleFactor( curPicPoc, refPicPocL0, curPicPoc, refPicPocL1 );
if( distscale != 4096 )
{
aveMv = aveMv.scaleMv( distscale ); // scaling to L0
}
aveMv = aveMv + candidate[i].mv[0];
roundAffineMv(aveMv.hor, aveMv.ver, 1);
triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1;
triangleMrgCtx.mrgTypeNeighbours [triangleMrgCtx.numValidMergeCand] = MRG_TYPE_DEFAULT_N;
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) ].mv = aveMv;
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = Mv(0, 0);
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) ].refIdx = candidate[i].refIdx[0];
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = -1;
triangleMrgCtx.numValidMergeCand += isUniqueTriangleCandidates(pu, triangleMrgCtx);
if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
{
return;
}
}
// fill with Mv(0, 0)
int32_t numRefIdx = std::min( slice.getNumRefIdx(REF_PIC_LIST_0), slice.getNumRefIdx(REF_PIC_LIST_1) );
int32_t cnt = 0;
while( triangleMrgCtx.numValidMergeCand < TRIANGLE_MAX_NUM_UNI_CANDS )
triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 1;
triangleMrgCtx.mvFieldNeighbours[triangleMrgCtx.numValidMergeCand << 1].setMvField(Mv(0, 0), cnt);
triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + 1].refIdx = NOT_VALID;
triangleMrgCtx.mvFieldNeighbours[(triangleMrgCtx.numValidMergeCand << 1) + 1].mv = Mv();
if( triangleMrgCtx.numValidMergeCand == TRIANGLE_MAX_NUM_UNI_CANDS )
{
return;
}
triangleMrgCtx.interDirNeighbours[triangleMrgCtx.numValidMergeCand] = 2;
triangleMrgCtx.mvFieldNeighbours [(triangleMrgCtx.numValidMergeCand << 1) + 1 ].setMvField(Mv(0, 0), cnt);
triangleMrgCtx.mvFieldNeighbours[triangleMrgCtx.numValidMergeCand << 1].refIdx = NOT_VALID;
triangleMrgCtx.mvFieldNeighbours[triangleMrgCtx.numValidMergeCand << 1].mv = Mv();
bool PU::isUniqueTriangleCandidates( const PredictionUnit &pu, MergeCtx& triangleMrgCtx )
int newCand = triangleMrgCtx.numValidMergeCand;
for( int32_t i = 0; i < newCand; i++ )
{
int32_t predFlagCur = triangleMrgCtx.interDirNeighbours[i] == 1 ? 0 : 1;
int32_t predFlagNew = triangleMrgCtx.interDirNeighbours[newCand] == 1 ? 0 : 1;
int32_t refPicPocCur = pu.cs->slice->getRefPOC( (RefPicList)predFlagCur, triangleMrgCtx.mvFieldNeighbours[(i << 1) + predFlagCur].refIdx );
int32_t refPicPocNew = pu.cs->slice->getRefPOC( (RefPicList)predFlagNew, triangleMrgCtx.mvFieldNeighbours[(newCand << 1) + predFlagNew].refIdx);
if( refPicPocCur == refPicPocNew && triangleMrgCtx.mvFieldNeighbours[(i << 1) + predFlagCur].mv == triangleMrgCtx.mvFieldNeighbours[(newCand << 1) + predFlagNew].mv )
{
return false;
}
}
void PU::spanTriangleMotionInfo( PredictionUnit &pu, MergeCtx &triangleMrgCtx, const bool splitDir, const uint8_t candIdx0, const uint8_t candIdx1 )
pu.triangleSplitDir = splitDir;
pu.triangleMergeIdx0 = candIdx0;
pu.triangleMergeIdx1 = candIdx1;
MotionBuf mb = pu.getMotionBuf();
biMv.sliceIdx = pu.cs->slice->getIndependentSliceIdx();
if( triangleMrgCtx.interDirNeighbours[candIdx0] == 1 && triangleMrgCtx.interDirNeighbours[candIdx1] == 2 )
biMv.interDir = 3;
biMv.mv[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].mv;
biMv.mv[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
biMv.refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].refIdx;
biMv.refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
else if( triangleMrgCtx.interDirNeighbours[candIdx0] == 2 && triangleMrgCtx.interDirNeighbours[candIdx1] == 1 )
biMv.interDir = 3;
biMv.mv[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].mv;
biMv.mv[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
biMv.refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].refIdx;
biMv.refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
else if( triangleMrgCtx.interDirNeighbours[candIdx0] == 1 && triangleMrgCtx.interDirNeighbours[candIdx1] == 1 )
int32_t refIdx = mappingRefPic( pu, pu.cs->slice->getRefPOC( REF_PIC_LIST_0, triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx ), REF_PIC_LIST_1 );
if( refIdx != -1 )
{
biMv.interDir = 3;
biMv.mv[0] = triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv;
biMv.mv[1] = triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv;
biMv.refIdx[0] = triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx;
biMv.refIdx[1] = refIdx;
}
else
{
refIdx = mappingRefPic( pu, pu.cs->slice->getRefPOC( REF_PIC_LIST_0, triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx), REF_PIC_LIST_1 );
biMv.interDir = ( refIdx != -1 ) ? 3 : 1;
biMv.mv[0] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].mv : triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv;
biMv.mv[1] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].mv : Mv(0, 0);
biMv.refIdx[0] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[candIdx1 << 1].refIdx : triangleMrgCtx.mvFieldNeighbours[candIdx0 << 1].refIdx;
biMv.refIdx[1] = ( refIdx != -1 ) ? refIdx : -1;
else if( triangleMrgCtx.interDirNeighbours[candIdx0] == 2 && triangleMrgCtx.interDirNeighbours[candIdx1] == 2 )
int32_t refIdx = mappingRefPic( pu, pu.cs->slice->getRefPOC( REF_PIC_LIST_1, triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx ), REF_PIC_LIST_0 );
if( refIdx != -1 )
{
biMv.interDir = 3;
biMv.mv[0] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
biMv.mv[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
biMv.refIdx[0] = refIdx;
biMv.refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
}
else
{
refIdx = mappingRefPic( pu, pu.cs->slice->getRefPOC( REF_PIC_LIST_1, triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx ), REF_PIC_LIST_0 );
biMv.interDir = ( refIdx != -1 ) ? 3 : 2;
biMv.mv[0] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv : Mv(0, 0);
biMv.mv[1] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv : triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
biMv.refIdx[0] = ( refIdx != -1 ) ? refIdx : -1;
biMv.refIdx[1] = ( refIdx != -1 ) ? triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx : triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
int32_t idxW = (int32_t)(g_aucLog2[pu.lwidth() ] - MIN_CU_LOG2);
int32_t idxH = (int32_t)(g_aucLog2[pu.lheight()] - MIN_CU_LOG2);
for( int32_t y = 0; y < mb.height; y++ )
{
for( int32_t x = 0; x < mb.width; x++ )
{
if( g_triangleMvStorage[splitDir][idxH][idxW][y][x] == 2 )
{
mb.at( x, y ).isInter = true;
mb.at( x, y ).interDir = biMv.interDir;
mb.at( x, y ).refIdx[0] = biMv.refIdx[0];
mb.at( x, y ).refIdx[1] = biMv.refIdx[1];
mb.at( x, y ).mv [0] = biMv.mv [0];
mb.at( x, y ).mv [1] = biMv.mv [1];
mb.at( x, y ).sliceIdx = biMv.sliceIdx;
else if( g_triangleMvStorage[splitDir][idxH][idxW][y][x] == 0 )
{
mb.at( x, y ).isInter = true;
mb.at( x, y ).interDir = triangleMrgCtx.interDirNeighbours[candIdx0];
mb.at( x, y ).refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].refIdx;
mb.at( x, y ).refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].refIdx;
mb.at( x, y ).mv [0] = triangleMrgCtx.mvFieldNeighbours[ candIdx0 << 1 ].mv;
mb.at( x, y ).mv [1] = triangleMrgCtx.mvFieldNeighbours[(candIdx0 << 1) + 1].mv;
mb.at( x, y ).sliceIdx = biMv.sliceIdx;
}
else
{
mb.at( x, y ).isInter = true;
mb.at( x, y ).interDir = triangleMrgCtx.interDirNeighbours[candIdx1];
mb.at( x, y ).refIdx[0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].refIdx;
mb.at( x, y ).refIdx[1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].refIdx;
mb.at( x, y ).mv [0] = triangleMrgCtx.mvFieldNeighbours[ candIdx1 << 1 ].mv;
mb.at( x, y ).mv [1] = triangleMrgCtx.mvFieldNeighbours[(candIdx1 << 1) + 1].mv;
mb.at( x, y ).sliceIdx = biMv.sliceIdx;
}
}
}
}
int32_t PU::mappingRefPic( const PredictionUnit &pu, int32_t refPicPoc, bool targetRefPicList )
{
int32_t numRefIdx = pu.cs->slice->getNumRefIdx( (RefPicList)targetRefPicList );
for( int32_t i = 0; i < numRefIdx; i++ )
{
if( pu.cs->slice->getRefPOC( (RefPicList)targetRefPicList, i ) == refPicPoc )
{
return i;
}
}
return -1;
}

Karsten Suehring
committed
void CU::resetMVDandMV2Int( CodingUnit& cu, InterPrediction *interPred )
{
for( auto &pu : CU::traversePUs( cu ) )
{
MergeCtx mrgCtx;
if( !pu.mergeFlag )
{
if( pu.interDir != 2 /* PRED_L1 */ )
{
Mv mv = pu.mv[0];
Mv mvPred;
AMVPInfo amvpInfo;

Karsten Suehring
committed
PU::fillMvpCand(pu, REF_PIC_LIST_0, pu.refIdx[0], amvpInfo);
pu.mvpNum[0] = amvpInfo.numCand;
mvPred = amvpInfo.mvCand[pu.mvpIdx[0]];
mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, cu.imv);

Karsten Suehring
committed
pu.mv[0] = mv;
Mv mvDiff = mv - mvPred;
pu.mvd[0] = mvDiff;
}
if( pu.interDir != 1 /* PRED_L0 */ )
{
Mv mv = pu.mv[1];
Mv mvPred;
AMVPInfo amvpInfo;
PU::fillMvpCand(pu, REF_PIC_LIST_1, pu.refIdx[1], amvpInfo);
pu.mvpNum[1] = amvpInfo.numCand;
mvPred = amvpInfo.mvCand[pu.mvpIdx[1]];
mv.roundToAmvrSignalPrecision(MV_PRECISION_QUARTER, cu.imv);

Karsten Suehring
committed
Mv mvDiff = mv - mvPred;
if( pu.cu->cs->slice->getMvdL1ZeroFlag() && pu.interDir == 3 /* PRED_BI */ )
{
pu.mvd[1] = Mv();
mv = mvPred;
}
else
{
pu.mvd[1] = mvDiff;
}
pu.mv[1] = mv;
}
}
else
{
PU::getInterMergeCandidates ( pu, mrgCtx

Karsten Suehring
committed
5350
5351
5352
5353
5354
5355
5356
5357
5358
5359
5360
5361
5362
5363
5364
5365
5366
5367
5368
5369
5370
5371
5372
5373
5374
5375
5376
5377
5378
5379
5380
5381
5382
5383
5384
mrgCtx.setMergeInfo( pu, pu.mergeIdx );
}
PU::spanMotionInfo( pu, mrgCtx );
}
}
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->slice->getMvdL1ZeroFlag() || pu.interDir != 3 /* PRED_BI */ )
{
bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getHor() != 0;
bNonZeroMvd |= pu.mvd[REF_PIC_LIST_1].getVer() != 0;
}
}
}
}
return bNonZeroMvd;
}
5385
5386
5387
5388
5389
5390
5391
5392
5393
5394
5395
5396
5397
5398
5399
5400
5401
5402
5403
5404
5405
5406
5407
5408
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
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->slice->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;
}

Karsten Suehring
committed
int CU::getMaxNeighboriMVCandNum( const CodingStructure& cs, const Position& pos )
{
const int numDefault = 0;
int maxImvNumCand = 0;
// Get BCBP of left PU
const CodingUnit *cuLeft = cs.getCURestricted( pos.offset( -1, 0 ), cs.slice->getIndependentSliceIdx(), cs.picture->tileMap->getTileIdxMap( pos ), CH_L );
maxImvNumCand = ( cuLeft ) ? cuLeft->imvNumCand : numDefault;
// Get BCBP of above PU
const CodingUnit *cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), cs.slice->getIndependentSliceIdx(), cs.picture->tileMap->getTileIdxMap( pos ), CH_L );
maxImvNumCand = std::max( maxImvNumCand, ( cuAbove ) ? cuAbove->imvNumCand : numDefault );
return maxImvNumCand;
}
5440
5441
5442
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
5493
5494
5495
5496
5497
5498
5499
5500
5501
5502
5503
5504
5505
5506
5507
5508
5509
5510
5511
5512
5513
5514
5515
5516
5517
5518
5519
5520
5521
5522
5523
5524
5525
5526
5527
5528
5529
5530
5531
5532
5533
5534
5535
5536
5537
5538
5539
5540
5541
5542
5543
5544
5545
5546
5547
5548
5549
5550
5551
5552
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 )
return SBT_VER_HALF;
else if( sbtMode <= SBT_HOR_H1 )
return SBT_HOR_HALF;
else if( sbtMode <= SBT_VER_Q1 )
return SBT_VER_QUAD;
else if( sbtMode <= SBT_HOR_Q1 )
return SBT_HOR_QUAD;
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;
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::isMtsMode( const uint8_t sbtInfo )
{
return getSbtIdx( sbtInfo ) == SBT_OFF_MTS;
}
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;
else
return false;
}
bool CU::isGBiIdxCoded( const CodingUnit &cu )
{
if( cu.cs->sps->getUseGBi() == false )
{
CHECK(cu.GBiIdx != GBI_DEFAULT, "Error: cu.GBiIdx != GBI_DEFAULT");
return false;
}
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() < GBI_SIZE_CONSTRAINT )
{
return false;
}

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

Karsten Suehring
committed
5597
5598
5599
5600
5601
5602
5603
5604
5605
5606
5607
5608
5609
5610
5611
5612
5613
5614
5615
5616
5617
5618
5619
5620
5621
5622
5623
5624
5625
5626
5627
5628
5629
5630
5631
5632
5633
5634
5635
5636
5637
5638
5639
5640
5641
5642
5643
5644
5645
5646
5647
5648
5649
5650
5651
5652
5653
5654
5655
5656
5657
5658
5659
5660
5661
5662
5663
5664
5665
5666
5667
5668
5669
5670
5671
5672
5673
return false;
}
uint8_t CU::getValidGbiIdx( const CodingUnit &cu )
{
if( cu.firstPU->interDir == 3 && !cu.firstPU->mergeFlag )
{
return cu.GBiIdx;
}
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.GBiIdx != GBI_DEFAULT, " cu.GBiIdx != GBI_DEFAULT ");
}
else
{
CHECK(cu.GBiIdx != GBI_DEFAULT, " cu.GBiIdx != GBI_DEFAULT ");
}
return GBI_DEFAULT;
}
void CU::setGbiIdx( CodingUnit &cu, uint8_t uh )
{
int8_t uhCnt = 0;
if( cu.firstPU->interDir == 3 && !cu.firstPU->mergeFlag )
{
cu.GBiIdx = uh;
++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.GBiIdx = GBI_DEFAULT;
}
else
{
cu.GBiIdx = GBI_DEFAULT;
}
CHECK(uhCnt <= 0, " uhCnt <= 0 ");
}
uint8_t CU::deriveGbiIdx( uint8_t gbiLO, uint8_t gbiL1 )
{
if( gbiLO == gbiL1 )
{
return gbiLO;
}
const int8_t w0 = getGbiWeight(gbiLO, REF_PIC_LIST_0);
const int8_t w1 = getGbiWeight(gbiL1, REF_PIC_LIST_1);
const int8_t th = g_GbiWeightBase >> 1;
const int8_t off = 1;
if( w0 == w1 || (w0 < (th - off) && w1 < (th - off)) || (w0 >(th + off) && w1 >(th + off)) )
{
return GBI_DEFAULT;
}
else
{
if( w0 > w1 )
{
return ( w0 >= th ? gbiLO : gbiL1 );
}
else
{
return ( w1 >= th ? gbiL1 : gbiLO );
}
}
}

Karsten Suehring
committed
#if JVET_N0413_RDPCM
bool CU::bdpcmAllowed( const CodingUnit& cu, const ComponentID compID )
{
bool bdpcmAllowed = compID == COMPONENT_Y;
bdpcmAllowed &= CU::isIntra( cu );
bdpcmAllowed &= ( cu.lwidth() <= 32 && cu.lheight() <= 32 );
return bdpcmAllowed;
}
#endif

Karsten Suehring
committed
5685
5686
5687
5688
5689
5690
5691
5692
5693
5694
5695
5696
5697
5698
5699
5700
5701
5702
5703
5704
5705
5706
5707
5708
5709
// TU tools
bool TU::isNonTransformedResidualRotated(const TransformUnit &tu, const ComponentID &compID)
{
return tu.cs->sps->getSpsRangeExtension().getTransformSkipRotationEnabledFlag() && tu.blocks[compID].width == 4 && tu.cu->predMode == MODE_INTRA;
}
bool TU::getCbf( const TransformUnit &tu, const ComponentID &compID )
{
return getCbfAtDepth( tu, compID, tu.depth );
}
bool TU::getCbfAtDepth(const TransformUnit &tu, const ComponentID &compID, const unsigned &depth)
{
return ((tu.cbf[compID] >> depth) & 1) == 1;
}
void TU::setCbfAtDepth(TransformUnit &tu, const ComponentID &compID, const unsigned &depth, const bool &cbf)
{
// first clear the CBF at the depth
tu.cbf[compID] &= ~(1 << depth);
// then set the CBF
tu.cbf[compID] |= ((cbf ? 1 : 0) << depth);
}
bool TU::isTSAllowed(const TransformUnit &tu, const ComponentID compID)
{
bool tsAllowed = compID == COMPONENT_Y;
const int maxSize = tu.cs->pps->getPpsRangeExtension().getLog2MaxTransformSkipBlockSize();
tsAllowed &= tu.cs->pps->getUseTransformSkip();
tsAllowed &= !tu.cu->transQuantBypass;
tsAllowed &= ( !tu.cu->ispMode || !isLuma(compID) );
#if JVET_N0413_RDPCM
tsAllowed &= !( tu.cu->bdpcmMode && tu.lwidth() <= BDPCM_MAX_CU_SIZE && tu.lheight() <= BDPCM_MAX_CU_SIZE );
#endif
SizeType transformSkipMaxSize = 1 << maxSize;
tsAllowed &= tu.lwidth() <= transformSkipMaxSize && tu.lheight() <= transformSkipMaxSize;
tsAllowed &= !tu.cu->sbtInfo;
return tsAllowed;
}
bool TU::isMTSAllowed(const TransformUnit &tu, const ComponentID compID)
{
bool mtsAllowed = compID == COMPONENT_Y;
const int maxSize = CU::isIntra( *tu.cu ) ? MTS_INTRA_MAX_CU_SIZE : MTS_INTER_MAX_CU_SIZE;
mtsAllowed &= CU::isIntra( *tu.cu ) ? tu.cs->sps->getUseIntraMTS() : tu.cs->sps->getUseInterMTS() && CU::isInter( *tu.cu );
mtsAllowed &= ( tu.lwidth() <= maxSize && tu.lheight() <= maxSize );
mtsAllowed &= !tu.cu->ispMode;
mtsAllowed &= !tu.cu->sbtInfo;
#if JVET_N0413_RDPCM
mtsAllowed &= !( tu.cu->bdpcmMode && tu.lwidth() <= BDPCM_MAX_CU_SIZE && tu.lheight() <= BDPCM_MAX_CU_SIZE );
#endif

Karsten Suehring
committed
uint32_t TU::getGolombRiceStatisticsIndex(const TransformUnit &tu, const ComponentID &compID)
{

Karsten Suehring
committed
5746
5747
5748
5749
5750
5751
5752
5753
5754
5755
5756
5757
5758
5759
5760
5761
5762
5763
5764
5765
5766
5767
5768
5769
5770
5771
5772
5773
5774
5775
5776
5777
5778
5779
5780
5781
5782
5783
5784
5785
5786
5787
5788
5789
5790
5791
5792
5793
5794
5795
5796
5797
5798
5799
5800
5801
5802
5803
5804
5805
5806
5807
5808
5809
5810
5811
5812
5813
5814
5815
5816
5817
const bool transquantBypass = tu.cu->transQuantBypass;
//--------
const uint32_t channelTypeOffset = isChroma(compID) ? 2 : 0;
const uint32_t nonTransformedOffset = (transformSkip || transquantBypass) ? 1 : 0;
//--------
const uint32_t selectedIndex = channelTypeOffset + nonTransformedOffset;
CHECK( selectedIndex >= RExt__GOLOMB_RICE_ADAPTATION_STATISTICS_SETS, "Invalid golomb rice adaptation statistics set" );
return selectedIndex;
}
#if HEVC_USE_MDCS
uint32_t TU::getCoefScanIdx(const TransformUnit &tu, const ComponentID &compID)
{
//------------------------------------------------
//this mechanism is available for intra only
if( !CU::isIntra( *tu.cu ) )
{
return SCAN_DIAG;
}
//------------------------------------------------
//check that MDCS can be used for this TU
const CompArea &area = tu.blocks[compID];
const SPS &sps = *tu.cs->sps;
const ChromaFormat format = sps.getChromaFormatIdc();
const uint32_t maximumWidth = MDCS_MAXIMUM_WIDTH >> getComponentScaleX(compID, format);
const uint32_t maximumHeight = MDCS_MAXIMUM_HEIGHT >> getComponentScaleY(compID, format);
if ((area.width > maximumWidth) || (area.height > maximumHeight))
{
return SCAN_DIAG;
}
//------------------------------------------------
//otherwise, select the appropriate mode
const PredictionUnit &pu = *tu.cs->getPU( area.pos(), toChannelType( compID ) );
uint32_t uiDirMode = PU::getFinalIntraMode(pu, toChannelType(compID));
//------------------
if (abs((int) uiDirMode - VER_IDX) <= MDCS_ANGLE_LIMIT)
{
return SCAN_HOR;
}
else if (abs((int) uiDirMode - HOR_IDX) <= MDCS_ANGLE_LIMIT)
{
return SCAN_VER;
}
else
{
return SCAN_DIAG;
}
}
#endif
bool TU::hasCrossCompPredInfo( const TransformUnit &tu, const ComponentID &compID )
{
return (isChroma(compID) && tu.cs->pps->getPpsRangeExtension().getCrossComponentPredictionEnabledFlag() && TU::getCbf(tu, COMPONENT_Y) &&
(!CU::isIntra(*tu.cu) || PU::isChromaIntraModeCrossCheckMode(*tu.cs->getPU(tu.blocks[compID].pos(), toChannelType(compID)))));

Karsten Suehring
committed
}
uint32_t TU::getNumNonZeroCoeffsNonTS( const TransformUnit& tu, const bool bLuma, const bool bChroma )
{
uint32_t count = 0;
for( uint32_t i = 0; i < ::getNumberValidTBlocks( *tu.cs->pcv ); i++ )
{
if( tu.blocks[i].valid() && ( isLuma(ComponentID(i)) ? tu.mtsIdx !=1 : true ) && TU::getCbf( tu, ComponentID( i ) ) )

Karsten Suehring
committed
{
if( isLuma ( tu.blocks[i].compID ) && !bLuma ) continue;
if( isChroma( tu.blocks[i].compID ) && !bChroma ) continue;
uint32_t area = tu.blocks[i].area();
const TCoeff* coeff = tu.getCoeffs( ComponentID( i ) ).buf;
for( uint32_t j = 0; j < area; j++ )
{
count += coeff[j] != 0;
}
}
}
return count;
}
bool TU::needsSqrt2Scale( const TransformUnit &tu, const ComponentID &compID )
{
const Size &size=tu.blocks[compID];
const bool isTransformSkip = tu.mtsIdx==1 && isLuma(compID);
return (!isTransformSkip) && (((g_aucLog2[size.width] + g_aucLog2[size.height]) & 1) == 1);

Karsten Suehring
committed
#if HM_QTBT_AS_IN_JEM_QUANT
bool TU::needsBlockSizeTrafoScale( const TransformUnit &tu, const ComponentID &compID )
{
return needsSqrt2Scale( tu, compID ) || isNonLog2BlockSize( tu.blocks[compID] );
}
#else

Karsten Suehring
committed
bool TU::needsQP3Offset(const TransformUnit &tu, const ComponentID &compID)
{

Karsten Suehring
committed
{
return ( ( ( g_aucLog2[tu.blocks[compID].width] + g_aucLog2[tu.blocks[compID].height] ) & 1 ) == 1 );
}
return false;
}
#endif
TransformUnit* TU::getPrevTU( const TransformUnit &tu, const ComponentID compID )
{
TransformUnit* prevTU = tu.prev;

Karsten Suehring
committed
if( prevTU != nullptr && ( prevTU->cu != tu.cu || !prevTU->blocks[compID].valid() ) )
{
prevTU = nullptr;
}
return prevTU;
}
bool TU::getPrevTuCbfAtDepth( const TransformUnit ¤tTu, const ComponentID compID, const int trDepth )
{
const TransformUnit* prevTU = getPrevTU( currentTu, compID );
return ( prevTU != nullptr ) ? TU::getCbfAtDepth( *prevTU, compID, trDepth ) : false;
}
#if !JVET_N0866_UNIF_TRFM_SEL_IMPL_MTS_ISP
5887
5888
5889
5890
5891
5892
5893
5894
5895
5896
5897
5898
5899
5900
5901
5902
5903
5904
5905
5906
5907
5908
5909
5910
5911
5912
5913
5914
5915
5916
5917
void TU::getTransformTypeISP( const TransformUnit &tu, const ComponentID compID, int &typeH, int &typeV )
{
typeH = DCT2, typeV = DCT2;
const int uiChFinalMode = PU::getFinalIntraMode( *tu.cu->firstPU, toChannelType( compID ) );
bool intraModeIsEven = uiChFinalMode % 2 == 0;
if( uiChFinalMode == DC_IDX || uiChFinalMode == 33 || uiChFinalMode == 35 )
{
typeH = DCT2;
typeV = typeH;
}
else if( uiChFinalMode == PLANAR_IDX || ( uiChFinalMode >= 31 && uiChFinalMode <= 37 ) )
{
typeH = DST7;
typeV = typeH;
}
else if( ( intraModeIsEven && uiChFinalMode >= 2 && uiChFinalMode <= 30 ) || ( !intraModeIsEven && uiChFinalMode >= 39 && uiChFinalMode <= 65 ) )
{
typeH = DST7;
typeV = DCT2;
}
else if( ( !intraModeIsEven && uiChFinalMode >= 3 && uiChFinalMode <= 29 ) || ( intraModeIsEven && uiChFinalMode >= 38 && uiChFinalMode <= 66 ) )
{
typeH = DCT2;
typeV = DST7;
}
//Size restriction for non-DCT-II transforms
Area tuArea = tu.blocks[compID];
typeH = tuArea.width <= 2 || tuArea.width >= 32 ? DCT2 : typeH;
typeV = tuArea.height <= 2 || tuArea.height >= 32 ? DCT2 : typeV;
}

Karsten Suehring
committed
#endif

Karsten Suehring
committed
// other tools
uint32_t getCtuAddr( const Position& pos, const PreCalcValues& pcv )
{
return ( pos.x >> pcv.maxCUWidthLog2 ) + ( pos.y >> pcv.maxCUHeightLog2 ) * pcv.widthInCtus;
}
5928
5929
5930
5931
5932
5933
5934
5935
5936
5937
5938
5939
5940
5941
5942
5943
5944
5945
5946
5947
5948
5949
5950
5951
5952
5953
5954
5955
5956
5957
5958
5959
5960
5961
#if JVET_N0217_MATRIX_INTRAPRED
int getNumModesMip(const Size& block)
{
if (block.width > (4 * block.height) || block.height > (4 * block.width))
{
return 0;
}
if( block.width == 4 && block.height == 4 )
{
return 35;
}
else if (block.width <= 8 && block.height <= 8)
{
return 19;
}
else
{
return 11;
}
}
int getNumEpBinsMip(const Size& block)
{
int numModes = getNumModesMip(block);
return int(std::ceil((std::log2(numModes - NUM_MPM_MIP - 1))));
}
bool mipModesAvailable(const Size& block)
{
return (getNumModesMip(block));
}
#endif