Newer
Older
if( isBestInter && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT && g_GbiSearchOrder[gbiLoopIdx] != bestGBiIdx )
{
continue;
}
}
}
if( !tempCS->slice->getCheckLDC() )
{
if( gbiLoopIdx != 0 && gbiLoopIdx != 3 && gbiLoopIdx != 4 )
{
continue;
}
}
#endif

Karsten Suehring
committed
CodingUnit &cu = tempCS->addCU( tempCS->area, partitioner.chType );
partitioner.setCUData( cu );
cu.slice = tempCS->slice;
#if HEVC_TILES_WPP
cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endif
cu.skip = false;
#if JVET_L0054_MMVD
cu.mmvdSkip = false;
#endif

Karsten Suehring
committed
cu.partSize = encTestMode.partSize;
//cu.affine
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
CU::addPUs( cu );
#if JVET_L0646_GBI
cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx];
uint8_t gbiIdx = cu.GBiIdx;
bool testGbi = (gbiIdx != GBI_DEFAULT);
#endif

Karsten Suehring
committed
m_pcInterSearch->predInterSearch( cu, partitioner );
const unsigned wIdx = gp_sizeIdxInfo->idxFrom( tempCS->area.lwidth () );
#if JVET_L0646_GBI
gbiIdx = CU::getValidGbiIdx(cu);
if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
{
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
continue;
}
CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
bool isEqualUni = false;
if( m_pcEncCfg->getUseGBiFast() )
{
if( cu.firstPU->interDir != 3 && testGbi == 0 )
{
isEqualUni = true;
}
}
#endif
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0
, m_pImvTempCS ? m_pImvTempCS[wIdx][encTestMode.partSize] : NULL
, 1
, 0
#if JVET_L0646_GBI
, &equGBiCost
#endif
);
3074
3075
3076
3077
3078
3079
3080
3081
3082
3083
3084
3085
3086
3087
3088
3089
3090
3091
3092
3093
3094
3095
3096
3097
3098
3099
#if JVET_L0646_GBI
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT )
m_pcInterSearch->setAffineModeSelected((bestCS->cus.front()->affine && !(bestCS->cus.front()->firstPU->mergeFlag)));
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
double skipTH = MAX_DOUBLE;
skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
if( equGBiCost > curBestCost * skipTH )
{
break;
}
if( m_pcEncCfg->getUseGBiFast() )
{
if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
{
break;
}
}
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
{
break;
}
} // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
#endif

Karsten Suehring
committed
}
bool EncCu::xCheckRDCostInterIMV( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
int iIMV = int( ( encTestMode.opts & ETO_IMV ) >> ETO_IMV_SHIFT );
#if JVET_L0646_GBI
m_pcInterSearch->setAffineModeSelected(false);
#endif

Karsten Suehring
committed
3112
3113
3114
3115
3116
3117
3118
3119
3120
3121
3122
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
// Only int-Pel, 4-Pel and fast 4-Pel allowed
CHECK( iIMV != 1 && iIMV != 2 && iIMV != 3, "Unsupported IMV Mode" );
// Fast 4-Pel Mode
EncTestMode encTestModeBase = encTestMode; // copy for clearing non-IMV options
encTestModeBase.opts = EncTestModeOpts( encTestModeBase.opts & ETO_IMV ); // clear non-IMV options (is that intended?)
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
CodingStructure* pcCUInfo2Reuse = nullptr;
if( m_pImvTempCS && encTestMode.partSize != SIZE_2Nx2N && ( ( encTestMode.opts & ETO_FORCE_MERGE ) == 0 ) )
{
pcCUInfo2Reuse = m_pImvTempCS[gp_sizeIdxInfo->idxFrom( tempCS->area.lwidth() )][encTestMode.partSize];
if( pcCUInfo2Reuse != nullptr )
{
CHECK( tempCS->area != pcCUInfo2Reuse->area, " mismatch" );
tempCS->copyStructure( *pcCUInfo2Reuse, partitioner.chType );
tempCS->fracBits = 0;
tempCS->dist = 0;
tempCS->cost = MAX_DOUBLE;
}
}
3137
3138
3139
3140
3141
3142
3143
3144
3145
3146
3147
3148
3149
3150
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
3166
3167
3168
3169
3170
3171
3172
3173
3174
3175
3176
3177
3178
3179
3180
3181
3182
3183
#if JVET_L0646_GBI
m_pcInterSearch->resetBufferedUniMotions();
int gbiLoopNum = (tempCS->slice->isInterB() ? GBI_NUM : 1);
gbiLoopNum = (pcCUInfo2Reuse != NULL ? 1 : gbiLoopNum);
gbiLoopNum = (tempCS->slice->getSPS()->getSpsNext().getUseGBi() ? gbiLoopNum : 1);
if( tempCS->area.lwidth() * tempCS->area.lheight() < GBI_SIZE_CONSTRAINT )
{
gbiLoopNum = 1;
}
double curBestCost = bestCS->cost;
double equGBiCost = MAX_DOUBLE;
for( int gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
{
if( m_pcEncCfg->getUseGBiFast() )
{
auto blkCache = dynamic_cast< CacheBlkInfoCtrl* >(m_modeCtrl);
if( blkCache )
{
bool isBestInter = blkCache->getInter(bestCS->area);
uint8_t bestGBiIdx = blkCache->getGbiIdx(bestCS->area);
if( isBestInter && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT && g_GbiSearchOrder[gbiLoopIdx] != bestGBiIdx )
{
continue;
}
}
}
if( !tempCS->slice->getCheckLDC() )
{
if( gbiLoopIdx != 0 && gbiLoopIdx != 3 && gbiLoopIdx != 4 )
{
continue;
}
}
if( m_pcEncCfg->getUseGBiFast() && tempCS->slice->getCheckLDC() && g_GbiSearchOrder[gbiLoopIdx] != GBI_DEFAULT
&& (m_bestGbiIdx[0] >= 0 && g_GbiSearchOrder[gbiLoopIdx] != m_bestGbiIdx[0])
&& (m_bestGbiIdx[1] >= 0 && g_GbiSearchOrder[gbiLoopIdx] != m_bestGbiIdx[1]))
{
continue;
}
#endif

Karsten Suehring
committed
CodingUnit &cu = ( pcCUInfo2Reuse != nullptr ) ? *tempCS->getCU( partitioner.chType ) : tempCS->addCU( tempCS->area, partitioner.chType );
if( pcCUInfo2Reuse == nullptr )
{
partitioner.setCUData( cu );
cu.slice = tempCS->slice;
#if HEVC_TILES_WPP
cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endif
cu.skip = false;
#if JVET_L0054_MMVD
cu.mmvdSkip = false;
#endif

Karsten Suehring
committed
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
cu.partSize = encTestMode.partSize;
//cu.affine
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
CU::addPUs( cu );
}
else
{
CHECK( cu.partSize != encTestMode.partSize, "Mismatch" );
CHECK( cu.skip, "Mismatch" );
CHECK( cu.qtDepth != partitioner.currQtDepth, "Mismatch" );
CHECK( cu.btDepth != partitioner.currBtDepth, "Mismatch" );
CHECK( cu.mtDepth != partitioner.currMtDepth, "Mismatch" );
CHECK( cu.depth != partitioner.currDepth, "Mismatch" );
}
cu.imv = iIMV > 1 ? 2 : 1;
cu.emtFlag = false;
#if JVET_L0646_GBI
bool testGbi;
uint8_t gbiIdx;
#endif

Karsten Suehring
committed
if( pcCUInfo2Reuse != nullptr )
{
// reuse the motion info from pcCUInfo2Reuse
CU::resetMVDandMV2Int( cu, m_pcInterSearch );
#if JVET_L0646_GBI
CHECK(cu.GBiIdx < 0 || cu.GBiIdx >= GBI_NUM, "cu.GBiIdx < 0 || cu.GBiIdx >= GBI_NUM");
gbiIdx = CU::getValidGbiIdx(cu);
testGbi = (gbiIdx != GBI_DEFAULT);
#endif

Karsten Suehring
committed
if( !CU::hasSubCUNonZeroMVd( cu ) )
{
m_modeCtrl->useModeResult( encTestModeBase, tempCS, partitioner );
return false;
}
else
{
m_pcInterSearch->motionCompensation( cu );
}
}
else
{
#if JVET_L0646_GBI
cu.GBiIdx = g_GbiSearchOrder[gbiLoopIdx];
gbiIdx = cu.GBiIdx;
testGbi = (gbiIdx != GBI_DEFAULT);
#endif

Karsten Suehring
committed
m_pcInterSearch->predInterSearch( cu, partitioner );
#if JVET_L0646_GBI
gbiIdx = CU::getValidGbiIdx(cu);
#endif

Karsten Suehring
committed
}
#if JVET_L0646_GBI
if( testGbi && gbiIdx == GBI_DEFAULT ) // Enabled GBi but the search results is uni.
{
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
continue;
}
CHECK(!(testGbi || (!testGbi && gbiIdx == GBI_DEFAULT)), " !( bTestGbi || (!bTestGbi && gbiIdx == GBI_DEFAULT ) )");
bool isEqualUni = false;
if( m_pcEncCfg->getUseGBiFast() )
{
if( cu.firstPU->interDir != 3 && testGbi == 0 )
{
isEqualUni = true;
}
}
#endif

Karsten Suehring
committed
if( !CU::hasSubCUNonZeroMVd( cu ) )
{
m_modeCtrl->useModeResult( encTestModeBase, tempCS, partitioner );
return false;
}
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0
, NULL
, true
, 0
#if JVET_L0646_GBI
, &equGBiCost
#endif

Karsten Suehring
committed
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
#if JVET_L0646_GBI
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
double skipTH = MAX_DOUBLE;
skipTH = (m_pcEncCfg->getUseGBiFast() ? 1.05 : MAX_DOUBLE);
if( equGBiCost > curBestCost * skipTH )
{
break;
}
if( m_pcEncCfg->getUseGBiFast() )
{
if( isEqualUni == true && m_pcEncCfg->getIntraPeriod() == -1 )
{
break;
}
}
if( g_GbiSearchOrder[gbiLoopIdx] == GBI_DEFAULT && xIsGBiSkip(cu) && m_pcEncCfg->getUseGBiFast() )
{
break;
}
} // for( UChar gbiLoopIdx = 0; gbiLoopIdx < gbiLoopNum; gbiLoopIdx++ )
#endif

Karsten Suehring
committed
return true;
}
void EncCu::xEncodeInterResidual( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode, int residualPass
, CodingStructure* imvCS
, int emtMode
, bool* bestHasNonResi
#if JVET_L0646_GBI
, double* equGBiCost
#endif

Karsten Suehring
committed
{
if( residualPass == 1 && encTestMode.lossless )
{
return;
}
CodingUnit* cu = tempCS->getCU( partitioner.chType );
double bestCostInternal = MAX_DOUBLE;
double bestCost = bestCS->cost;
const SPS& sps = *tempCS->sps;
const int maxSizeEMT = tempCS->pcv->noRQT ? EMT_INTER_MAX_CU_WITH_QTBT : EMT_INTER_MAX_CU;
bool swapped = false; // avoid unwanted data copy
bool reloadCU = false;
const bool considerEmtSecondPass = emtMode && sps.getSpsNext().getUseInterEMT() && partitioner.currArea().lwidth() <= maxSizeEMT && partitioner.currArea().lheight() <= maxSizeEMT;
int minEMTMode = 0;
int maxEMTMode = (considerEmtSecondPass?1:0);

Karsten Suehring
committed
if( emtMode == 2 )
{
minEMTMode = maxEMTMode = (cu->emtFlag?1:0);
}

Karsten Suehring
committed
for( int curEmtMode = minEMTMode; curEmtMode <= maxEMTMode; curEmtMode++ )

Karsten Suehring
committed
{
3354
3355
3356
3357
3358
3359
3360
3361
3362
3363
3364
3365
3366
3367
3368
3369
3370
3371
3372
3373
3374
3375
3376
3377
3378
3379
3380
3381
3382
if( reloadCU )
{
if( bestCost == bestCS->cost ) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
{
tempCS->clearTUs();
}
else if( false == swapped )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
tempCS->copyStructure( *bestCS, partitioner.chType );
tempCS->getPredBuf().copyFrom( bestCS->getPredBuf() );
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
swapped = true;
}
else
{
tempCS->clearTUs();
bestCost = bestCS->cost;
cu = tempCS->getCU( partitioner.chType );
}
//we need to restart the distortion for the new tempCS, the bit count and the cost
tempCS->dist = 0;
tempCS->fracBits = 0;
tempCS->cost = MAX_DOUBLE;
}
reloadCU = true; // enable cu reloading

Karsten Suehring
committed
cu->skip = false;
cu->emtFlag = curEmtMode;

Karsten Suehring
committed
const bool skipResidual = residualPass == 1;
m_pcInterSearch->encodeResAndCalcRdInterCU( *tempCS, partitioner, skipResidual );
xEncodeDontSplit( *tempCS, partitioner );
xCheckDQP( *tempCS, partitioner );
3393
3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
3419
3420
3421
3422
3423
#if JVET_L0646_GBI
if( ETM_INTER_ME == encTestMode.type )
{
if( equGBiCost != NULL )
{
if( tempCS->cost < (*equGBiCost) && cu->GBiIdx == GBI_DEFAULT )
{
(*equGBiCost) = tempCS->cost;
}
}
else
{
CHECK(equGBiCost == NULL, "equGBiCost == NULL");
}
if( tempCS->slice->getCheckLDC() && !cu->imv && cu->GBiIdx != GBI_DEFAULT && tempCS->cost < m_bestGbiCost[1] )
{
if( tempCS->cost < m_bestGbiCost[0] )
{
m_bestGbiCost[1] = m_bestGbiCost[0];
m_bestGbiCost[0] = tempCS->cost;
m_bestGbiIdx[1] = m_bestGbiIdx[0];
m_bestGbiIdx[0] = cu->GBiIdx;
}
else
{
m_bestGbiCost[1] = tempCS->cost;
m_bestGbiIdx[1] = cu->GBiIdx;
}
}
}
#endif
double emtFirstPassCost = tempCS->cost;

Karsten Suehring
committed
if( imvCS && (tempCS->cost < imvCS->cost) )
{
if( imvCS->cost != MAX_DOUBLE )
{
imvCS->initStructData( encTestMode.qp, encTestMode.lossless );
}
imvCS->copyStructure( *tempCS, partitioner.chType );
}
if( NULL != bestHasNonResi && (bestCostInternal > tempCS->cost) )
{
bestCostInternal = tempCS->cost;
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
if (!(tempCS->getPU(partitioner.chType)->mhIntraFlag))

Karsten Suehring
committed
*bestHasNonResi = !cu->rootCbf;
}
#if JVET_L0100_MULTI_HYPOTHESIS_INTRA
if (cu->rootCbf == false)
{
if (tempCS->getPU(partitioner.chType)->mhIntraFlag)
{
tempCS->cost = MAX_DOUBLE;
return;
}
}
#endif

Karsten Suehring
committed
#if WCG_EXT
DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda( true ) );
#else
DTRACE_MODE_COST( *tempCS, m_pcRdCost->getLambda() );
#endif
xCheckBestMode( tempCS, bestCS, partitioner, encTestMode );
//now we check whether the second pass should be skipped or not
if( !curEmtMode && maxEMTMode )
{
const double thresholdToSkipEmtSecondPass = 1.1; // Skip checking EMT transforms
const bool bCond1 = !cu->firstTU->cbf[COMPONENT_Y];

Karsten Suehring
committed
const bool bCond3 = emtFirstPassCost > ( bestCost * thresholdToSkipEmtSecondPass );
if( m_pcEncCfg->getFastInterEMT() && (bCond1 || bCond3 ) )
{
maxEMTMode = 0; // do not test EMT
}
}
} //end emt loop

Karsten Suehring
committed
3475
3476
3477
3478
3479
3480
3481
3482
3483
3484
3485
3486
3487
3488
3489
3490
3491
3492
3493
3494
3495
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
3511
3512
3513
3514
3515
3516
3517
3518
3519
3520
3521
3522
3523
3524
3525
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
3541
3542
3543
3544
3545
3546
3547
3548
3549
3550
3551
3552
3553
3554
3555
3556
3557
3558
3559
3560
3561
3562
3563
3564
3565
3566
3567
3568
3569
3570
3571
}
void EncCu::xEncodeDontSplit( CodingStructure &cs, Partitioner &partitioner )
{
m_CABACEstimator->resetBits();
{
if( partitioner.canSplit( CU_QUAD_SPLIT, cs ) )
{
m_CABACEstimator->split_cu_flag( false, cs, partitioner );
}
if( partitioner.canSplit( CU_MT_SPLIT, cs ) )
{
m_CABACEstimator->split_cu_mode_mt( CU_DONT_SPLIT, cs, partitioner );
}
}
cs.fracBits += m_CABACEstimator->getEstFracBits(); // split bits
cs.cost = m_pcRdCost->calcRdCost( cs.fracBits, cs.dist );
}
#if REUSE_CU_RESULTS
void EncCu::xReuseCachedResult( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner )
{
const SPS &sps = *tempCS->sps;
BestEncInfoCache* bestEncCache = dynamic_cast<BestEncInfoCache*>( m_modeCtrl );
CHECK( !bestEncCache, "If this mode is chosen, mode controller has to implement the mode caching capabilities" );
EncTestMode cachedMode;
if( bestEncCache->setCsFrom( *tempCS, cachedMode, partitioner ) )
{
CodingUnit& cu = *tempCS->cus.front();
partitioner.setCUData( cu );
if( CU::isIntra( cu ) )
{
xReconIntraQT( cu );
}
else
{
xDeriveCUMV( cu );
xReconInter( cu );
}
Distortion finalDistortion = 0;
const int numValidComponents = getNumberValidComponents( tempCS->area.chromaFormat );
for( int comp = 0; comp < numValidComponents; comp++ )
{
const ComponentID compID = ComponentID( comp );
if( CS::isDualITree( *tempCS ) && toChannelType( compID ) != partitioner.chType )
{
continue;
}
CPelBuf reco = tempCS->getRecoBuf( compID );
CPelBuf org = tempCS->getOrgBuf ( compID );
#if WCG_EXT
if( m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() )
{
const CPelBuf orgLuma = tempCS->getOrgBuf(tempCS->area.blocks[COMPONENT_Y]);
finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE_WTD, &orgLuma );
}
else
#endif
finalDistortion += m_pcRdCost->getDistPart( org, reco, sps.getBitDepth( toChannelType( compID ) ), compID, DF_SSE );
}
m_CABACEstimator->getCtx() = m_CurrCtx->start;
m_CABACEstimator->resetBits();
CUCtx cuCtx;
cuCtx.isDQPCoded = true;
cuCtx.isChromaQpAdjCoded = true;
m_CABACEstimator->coding_unit( cu, partitioner, cuCtx );
tempCS->dist = finalDistortion;
tempCS->fracBits = m_CABACEstimator->getEstFracBits();
tempCS->cost = m_pcRdCost->calcRdCost( tempCS->fracBits, tempCS->dist );
xEncodeDontSplit( *tempCS, partitioner );
xCheckDQP ( *tempCS, partitioner );
xCheckBestMode ( tempCS, bestCS, partitioner, cachedMode );
}
else
{
THROW( "Should never happen!" );
}
}
#endif