Newer
Older
{
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]];

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]];

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
5283
5284
5285
5286
5287
5288
5289
5290
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
5308
5309
5310
5311
5312
5313
5314
5315
5316
5317
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;
}
5318
5319
5320
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337
5338
5339
5340
5341
5342
5343
5344
5345
5346
5347
5348
5349
5350
5351
5352
5353
5354
5355
5356
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
#if JVET_N0150_ONE_CTU_DELAY_WPP
const CodingUnit *cuLeft = cs.getCURestricted( pos.offset( -1, 0 ), pos, cs.slice->getIndependentSliceIdx(), cs.picture->brickMap->getBrickIdxRsMap( pos ), CH_L );
#else
const CodingUnit *cuLeft = cs.getCURestricted( pos.offset( -1, 0 ), cs.slice->getIndependentSliceIdx(), cs.picture->brickMap->getBrickIdxRsMap( pos ), CH_L );
#endif
#else
#if JVET_N0150_ONE_CTU_DELAY_WPP
const CodingUnit *cuLeft = cs.getCURestricted( pos.offset( -1, 0 ), pos, cs.slice->getIndependentSliceIdx(), cs.picture->tileMap->getTileIdxMap( pos ), CH_L );

Karsten Suehring
committed
const CodingUnit *cuLeft = cs.getCURestricted( pos.offset( -1, 0 ), cs.slice->getIndependentSliceIdx(), cs.picture->tileMap->getTileIdxMap( pos ), CH_L );

Karsten Suehring
committed
maxImvNumCand = ( cuLeft ) ? cuLeft->imvNumCand : numDefault;
// Get BCBP of above PU
#if JVET_N0150_ONE_CTU_DELAY_WPP
const CodingUnit *cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), pos, cs.slice->getIndependentSliceIdx(), cs.picture->brickMap->getBrickIdxRsMap( pos ), CH_L );
#else
const CodingUnit *cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), cs.slice->getIndependentSliceIdx(), cs.picture->brickMap->getBrickIdxRsMap( pos ), CH_L );
#endif
#else
#if JVET_N0150_ONE_CTU_DELAY_WPP
const CodingUnit *cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), pos, cs.slice->getIndependentSliceIdx(), cs.picture->tileMap->getTileIdxMap( pos ), CH_L );

Karsten Suehring
committed
const CodingUnit *cuAbove = cs.getCURestricted( pos.offset( 0, -1 ), cs.slice->getIndependentSliceIdx(), cs.picture->tileMap->getTileIdxMap( pos ), CH_L );

Karsten Suehring
committed
maxImvNumCand = std::max( maxImvNumCand, ( cuAbove ) ? cuAbove->imvNumCand : numDefault );
return maxImvNumCand;
}
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
5424
5425
5426
5427
5428
5429
5430
5431
5432
5433
5434
5435
5436
5437
5438
5439
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
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
5554
5555
5556
5557
5558
5559
5560
5561
5562
5563
5564
5565
5566
5567
5568
5569
5570
5571
5572
5573
5574
5575
5576
5577
5578
5579
5580
5581
5582
5583
5584
5585
5586
5587
5588
5589
5590
5591
5592
5593
5594
5595
5596
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
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
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
// 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)
{
const bool transformSkip = tu.mtsIdx==MTS_SKIP;

Karsten Suehring
committed
5703
5704
5705
5706
5707
5708
5709
5710
5711
5712
5713
5714
5715
5716
5717
5718
5719
5720
5721
5722
5723
5724
5725
5726
5727
5728
5729
5730
5731
5732
5733
5734
5735
5736
5737
5738
5739
5740
5741
5742
5743
5744
5745
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
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 JVET_N0193_LFNST
if( tu.blocks[ i ].valid() && tu.mtsIdx != MTS_SKIP && TU::getCbf( tu, ComponentID( i ) ) )
if( tu.blocks[i].valid() && ( isLuma(ComponentID(i)) ? tu.mtsIdx !=MTS_SKIP : 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;
}
#if JVET_N0193_LFNST
uint32_t TU::getNumNonZeroCoeffsNonTSCorner8x8( const TransformUnit& tu, const bool lumaFlag, const bool chromaFlag )
{
const uint32_t lumaWidth = tu.blocks[ 0 ].width, chromaWidth = tu.blocks[ 1 ].width;
const uint32_t lumaHeight = tu.blocks[ 0 ].height, chromaHeight = tu.blocks[ 1 ].height;
bool luma4x4TUFlag = lumaWidth == 4 && lumaHeight == 4;
bool chroma4x4TUFlag = chromaWidth == 4 && chromaHeight == 4;
bool luma8x8TUFlag = lumaWidth == 8 && lumaHeight == 8;
bool chroma8x8TUFlag = chromaWidth == 8 && chromaHeight == 8;
bool lumaCountFlag = ( lumaWidth >= 8 && lumaHeight >= 8 ) || luma4x4TUFlag;
bool chromaCountFlag = ( chromaWidth >= 8 && chromaHeight >= 8 ) || chroma4x4TUFlag;
uint32_t count = 0;
for( uint32_t i = 0; i < ::getNumberValidTBlocks( *tu.cs->pcv ); i++ )
{
if( tu.blocks[ i ].valid() && tu.mtsIdx != MTS_SKIP && TU::getCbf( tu, ComponentID( i ) ) )
5820
5821
5822
5823
5824
5825
5826
5827
5828
5829
5830
5831
5832
5833
5834
5835
5836
5837
5838
5839
5840
5841
5842
5843
5844
5845
5846
5847
{
if( isLuma( tu.blocks[ i ].compID ) && ( !lumaFlag || !lumaCountFlag ) ) continue;
if( isChroma( tu.blocks[ i ].compID ) && ( !chromaFlag || !chromaCountFlag ) ) continue;
const ScanElement * scan = g_coefTopLeftDiagScan8x8[ gp_sizeIdxInfo->idxFrom( tu.blocks[ i ].width ) ];
const TCoeff* coeff = tu.getCoeffs( ComponentID( i ) ).buf;
int startPos = MAX_LFNST_COEF_NUM, endPos = 47;
if( ( isLuma( tu.blocks[ i ].compID ) && luma4x4TUFlag ) || ( isChroma( tu.blocks[ i ].compID ) && chroma4x4TUFlag ) )
{
startPos = 8; endPos = 15;
}
else if( ( isLuma( tu.blocks[ i ].compID ) && luma8x8TUFlag ) || ( isChroma( tu.blocks[ i ].compID ) && chroma8x8TUFlag ) )
{
startPos = 8; endPos = 47;
}
const ScanElement *scanPtr = scan + startPos;
for( uint32_t j = startPos; j <= endPos; j++ )
{
count += coeff[ scanPtr->idx ] != 0;
scanPtr++;
}
}
}
return count;
}
#endif
bool TU::needsSqrt2Scale( const TransformUnit &tu, const ComponentID &compID )
{
const Size &size=tu.blocks[compID];
const bool isTransformSkip = tu.mtsIdx==MTS_SKIP && 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
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
5918
5919
5920
5921
5922
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;
}
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
5962
5963
5964
5965
5966
#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