Newer
Older
uint8_t candIdx1 = g_triangleCombination[mergeCand][2];
#endif
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;
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
cu.triangle = true;
cu.mmvdSkip = false;
cu.GBiIdx = GBI_DEFAULT;
PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType);
#if JVET_M0883_TRIANGLE_SIGNALING
pu.triangleSplitDir = splitDir;
pu.triangleMergeIdx0 = candIdx0;
pu.triangleMergeIdx1 = candIdx1;
#else
#endif
pu.mergeFlag = true;
#if JVET_M0883_TRIANGLE_SIGNALING
PU::spanTriangleMotionInfo(pu, triangleMrgCtx, splitDir, candIdx0, candIdx1 );
#else
PU::spanTriangleMotionInfo(pu, triangleMrgCtx, mergeCand, splitDir, candIdx0, candIdx1 );
#endif
#if JVET_M0445_MCTS
if( m_pcEncCfg->getMCTSEncConstraint() && ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) )
{
// Do not use this mode
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
return;
}
#endif
tempCS->getPredBuf().copyFrom( triangleWeightedBuffer[mergeCand] );
}
else
{
triangleBuffer[candIdx0] = m_acMergeBuffer[candIdx0].getBuf( localUnitArea );
triangleBuffer[candIdx1] = m_acMergeBuffer[candIdx1].getBuf( localUnitArea );
PelUnitBuf predBuf = tempCS->getPredBuf();
#if JVET_M0328_KEEP_ONE_WEIGHT_GROUP
m_pcInterSearch->weightedTriangleBlk( pu, splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
#else
m_pcInterSearch->weightedTriangleBlk( pu, PU::getTriangleWeights(pu, triangleMrgCtx, candIdx0, candIdx1), splitDir, MAX_NUM_CHANNEL_TYPE, predBuf, triangleBuffer[candIdx0], triangleBuffer[candIdx1] );
#if JVET_M0464_UNI_MTS
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, noResidualPass, NULL, ( noResidualPass == 0 ? &trianglecandHasNoResidual[mergeCand] : NULL ) );
#else
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, noResidualPass, NULL, true, ( (noResidualPass == 0 ) ? &trianglecandHasNoResidual[mergeCand] : NULL ) );
if (m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip)
{
bestIsSkip = bestCS->getCU(partitioner.chType)->rootCbf == 0;
}
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
#if JVET_M0428_ENC_DB_OPT
if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )

Karsten Suehring
committed
void EncCu::xCheckRDCostAffineMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
if( m_modeCtrl->getFastDeltaQp() )
{
return;
}
if ( bestCS->area.lumaSize().width < 8 || bestCS->area.lumaSize().height < 8 )
{
return;
}
#if JVET_M0428_ENC_DB_OPT
m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
#endif
const Slice &slice = *tempCS->slice;
CHECK( slice.getSliceType() == I_SLICE, "Affine Merge modes not available for I-slices" );
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
AffineMergeCtx affineMergeCtx;
const SPS &sps = *tempCS->sps;
MergeCtx mrgCtx;
if ( sps.getSBTMVPEnabledFlag() )
{
Size bufSize = g_miScaling.scale( tempCS->area.lumaSize() );
mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize );
affineMergeCtx.mrgCtx = &mrgCtx;
}
{
// first get merge candidates
CodingUnit cu( tempCS->area );
cu.cs = tempCS;
cu.predMode = MODE_INTER;
cu.slice = tempCS->slice;
#if HEVC_TILES_WPP
cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap( tempCS->area.lumaPos() );
#endif
3123
3124
3125
3126
3127
3128
3129
3130
3131
3132
3133
3134
3135
3136
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
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
3207
3208
3209
3210
3211
3212
3213
3214
3215
3216
3217
3218
3219
3220
3221
3222
3223
3224
3225
3226
3227
3228
3229
3230
PredictionUnit pu( tempCS->area );
pu.cu = &cu;
pu.cs = tempCS;
PU::getAffineMergeCand( pu, affineMergeCtx );
if ( affineMergeCtx.numValidMergeCand <= 0 )
{
return;
}
}
bool candHasNoResidual[AFFINE_MRG_MAX_NUM_CANDS];
for ( uint32_t ui = 0; ui < affineMergeCtx.numValidMergeCand; ui++ )
{
candHasNoResidual[ui] = false;
}
bool bestIsSkip = false;
uint32_t uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;
PelUnitBuf acMergeBuffer[AFFINE_MRG_MAX_NUM_CANDS];
static_vector<uint32_t, AFFINE_MRG_MAX_NUM_CANDS> RdModeList;
bool mrgTempBufSet = false;
for ( uint32_t i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++ )
{
RdModeList.push_back( i );
}
if ( m_pcEncCfg->getUseFastMerge() )
{
uiNumMrgSATDCand = std::min( NUM_AFF_MRG_SATD_CAND, affineMergeCtx.numValidMergeCand );
bestIsSkip = false;
if ( auto blkCache = dynamic_cast<CacheBlkInfoCtrl*>(m_modeCtrl) )
{
bestIsSkip = blkCache->isSkip( tempCS->area );
}
static_vector<double, AFFINE_MRG_MAX_NUM_CANDS> candCostList;
// 1. Pass: get SATD-cost for selected candidates and reduce their count
if ( !bestIsSkip )
{
RdModeList.clear();
mrgTempBufSet = true;
const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda( encTestMode.lossless );
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;
cu.affine = true;
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
PredictionUnit &pu = tempCS->addPU( cu, partitioner.chType );
DistParam distParam;
const bool bUseHadamard = !encTestMode.lossless;
m_pcRdCost->setDistParam( distParam, tempCS->getOrgBuf().Y(), m_acMergeBuffer[0].Y(), sps.getBitDepth( CHANNEL_TYPE_LUMA ), COMPONENT_Y, bUseHadamard );
const UnitArea localUnitArea( tempCS->area.chromaFormat, Area( 0, 0, tempCS->area.Y().width, tempCS->area.Y().height ) );
for ( uint32_t uiMergeCand = 0; uiMergeCand < affineMergeCtx.numValidMergeCand; uiMergeCand++ )
{
acMergeBuffer[uiMergeCand] = m_acMergeBuffer[uiMergeCand].getBuf( localUnitArea );
// set merge information
pu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];
pu.mergeFlag = true;
pu.mergeIdx = uiMergeCand;
cu.affineType = affineMergeCtx.affineType[uiMergeCand];
cu.GBiIdx = affineMergeCtx.GBiIdx[uiMergeCand];
pu.mergeType = affineMergeCtx.mergeType[uiMergeCand];
if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP )
{
pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;
pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;
PU::spanMotionInfo( pu, mrgCtx );
}
else
{
PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0], REF_PIC_LIST_0 );
PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1], REF_PIC_LIST_1 );
PU::spanMotionInfo( pu );
}
distParam.cur = acMergeBuffer[uiMergeCand].Y();
m_pcInterSearch->motionCompensation( pu, acMergeBuffer[uiMergeCand] );
Distortion uiSad = distParam.distFunc( distParam );
uint32_t uiBitsCand = uiMergeCand + 1;
if ( uiMergeCand == tempCS->slice->getMaxNumAffineMergeCand() - 1 )
{
uiBitsCand--;
}
double cost = (double)uiSad + (double)uiBitsCand * sqrtLambdaForFirstPass;
static_vector<int, AFFINE_MRG_MAX_NUM_CANDS> emptyList;
updateCandList( uiMergeCand, cost, RdModeList, candCostList
3235
3236
3237
3238
3239
3240
3241
3242
3243
3244
3245
3246
3247
3248
3249
3250
3251
3252
3253
3254
3255
3256
CHECK( std::min( uiMergeCand + 1, uiNumMrgSATDCand ) != RdModeList.size(), "" );
}
// Try to limit number of candidates using SATD-costs
for ( uint32_t i = 1; i < uiNumMrgSATDCand; i++ )
{
if ( candCostList[i] > MRG_FAST_RATIO * candCostList[0] )
{
uiNumMrgSATDCand = i;
break;
}
}
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
}
else
{
uiNumMrgSATDCand = affineMergeCtx.numValidMergeCand;
}
}
const uint32_t iteration = encTestMode.lossless ? 1 : 2;
// 2. Pass: check candidates using full RD test
for ( uint32_t uiNoResidualPass = 0; uiNoResidualPass < iteration; uiNoResidualPass++ )
#else
uint32_t iteration;
uint32_t iterationBegin = m_modeCtrl->getIsHashPerfectMatch() ? 1 : 0;
if (encTestMode.lossless)
{
iteration = 1;
iterationBegin = 0;
}
else
{
iteration = 2;
}
for (uint32_t uiNoResidualPass = iterationBegin; uiNoResidualPass < iteration; ++uiNoResidualPass)
#endif
3276
3277
3278
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
3298
3299
3300
3301
3302
3303
3304
3305
3306
3307
3308
3309
3310
3311
3312
3313
3314
3315
3316
3317
3318
3319
3320
3321
3322
3323
3324
{
for ( uint32_t uiMrgHADIdx = 0; uiMrgHADIdx < uiNumMrgSATDCand; uiMrgHADIdx++ )
{
uint32_t uiMergeCand = RdModeList[uiMrgHADIdx];
if ( ((uiNoResidualPass != 0) && candHasNoResidual[uiMergeCand])
|| ((uiNoResidualPass == 0) && bestIsSkip) )
{
continue;
}
// first get merge candidates
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;
cu.affine = true;
cu.predMode = MODE_INTER;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
PredictionUnit &pu = tempCS->addPU( cu, partitioner.chType );
// set merge information
pu.mergeFlag = true;
pu.mergeIdx = uiMergeCand;
pu.interDir = affineMergeCtx.interDirNeighbours[uiMergeCand];
cu.affineType = affineMergeCtx.affineType[uiMergeCand];
cu.GBiIdx = affineMergeCtx.GBiIdx[uiMergeCand];
pu.mergeType = affineMergeCtx.mergeType[uiMergeCand];
if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP )
{
pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0][0].refIdx;
pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1][0].refIdx;
PU::spanMotionInfo( pu, mrgCtx );
}
else
{
PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 0], REF_PIC_LIST_0 );
PU::setAllAffineMvField( pu, affineMergeCtx.mvFieldNeighbours[(uiMergeCand << 1) + 1], REF_PIC_LIST_1 );
PU::spanMotionInfo( pu );
}
#if JVET_M0445_MCTS
if( m_pcEncCfg->getMCTSEncConstraint() && ( !( MCTSHelper::checkMvBufferForMCTSConstraint( *cu.firstPU ) ) ) )
{
// Do not use this mode
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
return;
}
#endif
if ( mrgTempBufSet )
{
tempCS->getPredBuf().copyFrom( acMergeBuffer[uiMergeCand] );
}
else
{
m_pcInterSearch->motionCompensation( pu );
}
#if JVET_M0464_UNI_MTS
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, uiNoResidualPass, NULL, ( uiNoResidualPass == 0 ? &candHasNoResidual[uiMergeCand] : NULL ) );
#else
xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, uiNoResidualPass, NULL, true, ((uiNoResidualPass == 0) ? &candHasNoResidual[uiMergeCand] : NULL) );
3347
3348
3349
3350
3351
3352
3353
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
3383
3384
3385
if ( m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip )
{
bestIsSkip = bestCS->getCU( partitioner.chType )->rootCbf == 0;
}
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
}// end loop uiMrgHADIdx
if ( uiNoResidualPass == 0 && m_pcEncCfg->getUseEarlySkipDetection() )
{
const CodingUnit &bestCU = *bestCS->getCU( partitioner.chType );
const PredictionUnit &bestPU = *bestCS->getPU( partitioner.chType );
if ( bestCU.rootCbf == 0 )
{
if ( bestPU.mergeFlag )
{
m_modeCtrl->setEarlySkipDetected();
}
else if ( m_pcEncCfg->getMotionEstimationSearchMethod() != MESEARCH_SELECTIVE )
{
int absolute_MV = 0;
for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ )
{
if ( slice.getNumRefIdx( RefPicList( uiRefListIdx ) ) > 0 )
{
absolute_MV += bestPU.mvd[uiRefListIdx].getAbsHor() + bestPU.mvd[uiRefListIdx].getAbsVer();
}
}
if ( absolute_MV == 0 )
{
m_modeCtrl->setEarlySkipDetected();
}
}
}
}
}
if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
{
xCalDebCost( *bestCS, partitioner );
}

Karsten Suehring
committed
}
//////////////////////////////////////////////////////////////////////////////////////////////
// ibc merge/skip mode check
void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode)
assert(tempCS->chType != CHANNEL_TYPE_CHROMA); // chroma IBC is derived
if (tempCS->area.lwidth() > IBC_MAX_CAND_SIZE || tempCS->area.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip
{
return;
}
const SPS &sps = *tempCS->sps;
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
MergeCtx mergeCtx;
{
Size bufSize = g_miScaling.scale(tempCS->area.lumaSize());
mergeCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize);
}
{
// first get merge candidates
CodingUnit cu(tempCS->area);
cu.cs = tempCS;
cu.slice = tempCS->slice;
#if HEVC_TILES_WPP
cu.tileIdx = tempCS->picture->tileMap->getTileIdxMap(tempCS->area.lumaPos());
#endif
PredictionUnit pu(tempCS->area);
pu.cu = &cu;
pu.cs = tempCS;
cu.mmvdSkip = false;
pu.mmvdMergeFlag = false;
cu.triangle = false;
#if JVET_M0170_MRG_SHARELIST
pu.shareParentPos = tempCS->sharedBndPos;
pu.shareParentSize = tempCS->sharedBndSize;
#endif
PU::getIBCMergeCandidates(pu, mergeCtx);
#else
PU::getInterMergeCandidates(pu, mergeCtx
, 0
);
3446
3447
3448
3449
3450
3451
3452
3453
3454
3455
3456
3457
3458
3459
3460
3461
3462
3463
3464
3465
3466
3467
3468
3469
3470
3471
3472
3473
3474
3475
}
int candHasNoResidual[MRG_MAX_NUM_CANDS];
for (unsigned int ui = 0; ui < mergeCtx.numValidMergeCand; ui++)
{
candHasNoResidual[ui] = 0;
}
bool bestIsSkip = false;
unsigned numMrgSATDCand = mergeCtx.numValidMergeCand;
static_vector<unsigned, MRG_MAX_NUM_CANDS> RdModeList(MRG_MAX_NUM_CANDS);
for (unsigned i = 0; i < MRG_MAX_NUM_CANDS; i++)
{
RdModeList[i] = i;
}
//{
static_vector<double, MRG_MAX_NUM_CANDS> candCostList(MRG_MAX_NUM_CANDS, MAX_DOUBLE);
// 1. Pass: get SATD-cost for selected candidates and reduce their count
{
const double sqrtLambdaForFirstPass = m_pcRdCost->getMotionLambda(encTestMode.lossless);
CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, (const ChannelType)partitioner.chType), (const ChannelType)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;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
cu.mmvdSkip = false;
cu.triangle = false;
DistParam distParam;
const bool bUseHadamard = !encTestMode.lossless;
PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType); //tempCS->addPU(cu);
pu.mmvdMergeFlag = false;
Picture* refPic = pu.cu->slice->getPic();
const CPelBuf refBuf = refPic->getRecoBuf(pu.blocks[COMPONENT_Y]);
const Pel* piRefSrch = refBuf.buf;
#if JVET_M0427_INLOOP_RESHAPER
if (tempCS->slice->getReshapeInfo().getUseSliceReshaper() && m_pcReshape->getCTUFlag())
{
const CompArea &area = cu.blocks[COMPONENT_Y];
CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
PelBuf tmpLuma = m_tmpStorageLCU->getBuf(tmpArea);
tmpLuma.copyFrom(tempCS->getOrgBuf().Y());
tmpLuma.rspSignal(m_pcReshape->getFwdLUT());
m_pcRdCost->setDistParam(distParam, tmpLuma, refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
}
else
#endif
m_pcRdCost->setDistParam(distParam, tempCS->getOrgBuf().Y(), refBuf, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, bUseHadamard);
int refStride = refBuf.stride;
const UnitArea localUnitArea(tempCS->area.chromaFormat, Area(0, 0, tempCS->area.Y().width, tempCS->area.Y().height));
int numValidBv = mergeCtx.numValidMergeCand;
for (unsigned int mergeCand = 0; mergeCand < mergeCtx.numValidMergeCand; mergeCand++)
{
if (mergeCtx.interDirNeighbours[mergeCand] != 1)
{
numValidBv--;
continue;
}
if (tempCS->slice->getRefPic(REF_PIC_LIST_0, mergeCtx.mvFieldNeighbours[mergeCand << 1].refIdx)->getPOC() != tempCS->slice->getPOC())
{
numValidBv--;
continue;
}
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
3572
3573
3574
3575
mergeCtx.setMergeInfo(pu, mergeCand); // set bv info in merge mode
const int cuPelX = pu.Y().x;
const int cuPelY = pu.Y().y;
int roiWidth = pu.lwidth();
int roiHeight = pu.lheight();
const int picWidth = pu.cs->slice->getSPS()->getPicWidthInLumaSamples();
const int picHeight = pu.cs->slice->getSPS()->getPicHeightInLumaSamples();
const unsigned int lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth();
int xPred = pu.bv.getHor();
int yPred = pu.bv.getVer();
if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, xPred, yPred, lcuWidth)) // not valid bv derived
{
numValidBv--;
continue;
}
PU::spanMotionInfo(pu, mergeCtx);
distParam.cur.buf = piRefSrch + refStride * yPred + xPred;
Distortion sad = distParam.distFunc(distParam);
unsigned int bitsCand = mergeCand + 1;
if (mergeCand == tempCS->slice->getMaxNumMergeCand() - 1)
{
bitsCand--;
}
double cost = (double)sad + (double)bitsCand * sqrtLambdaForFirstPass;
static_vector<int, MRG_MAX_NUM_CANDS> * nullList = nullptr;
updateCandList(mergeCand, cost, RdModeList, candCostList
, *nullList, -1
, numMrgSATDCand);
}
// Try to limit number of candidates using SATD-costs
if (numValidBv)
{
numMrgSATDCand = numValidBv;
for (unsigned int i = 1; i < numValidBv; i++)
{
if (candCostList[i] > MRG_FAST_RATIO*candCostList[0])
{
numMrgSATDCand = i;
break;
}
}
}
else
{
tempCS->dist = 0;
tempCS->fracBits = 0;
tempCS->cost = MAX_DOUBLE;
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
return;
}
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
}
//}
const unsigned int iteration = encTestMode.lossless ? 1 : 2;
#if JVET_M0428_ENC_DB_OPT
m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
#endif
// 2. Pass: check candidates using full RD test
for (unsigned int numResidualPass = 0; numResidualPass < iteration; numResidualPass++)
{
for (unsigned int mrgHADIdx = 0; mrgHADIdx < numMrgSATDCand; mrgHADIdx++)
{
unsigned int mergeCand = RdModeList[mrgHADIdx];
if (mergeCtx.interDirNeighbours[mergeCand] != 1)
{
continue;
}
if (tempCS->slice->getRefPic(REF_PIC_LIST_0, mergeCtx.mvFieldNeighbours[mergeCand << 1].refIdx)->getPOC() != tempCS->slice->getPOC())
{
continue;
}
if (!(numResidualPass == 1 && candHasNoResidual[mergeCand] == 1))
{
if (!(bestIsSkip && (numResidualPass == 0)))
{
unsigned char considerEmtSecondPass = 0;
bool skipSecondEmtPass = true;
bool hasResidual[2] = { false, false };
double emtCost[2] = { MAX_DOUBLE, MAX_DOUBLE };
// CU-level optimization
for (unsigned char emtCuFlag = 0; emtCuFlag <= considerEmtSecondPass; emtCuFlag++)
{
if (m_pcEncCfg->getFastInterEMT() && emtCuFlag && skipSecondEmtPass)
{
continue;
}
// first get merge candidates
CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, (const ChannelType)partitioner.chType), (const ChannelType)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;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
Yin Zhao
committed
#if JVET_M0140_SBT
cu.sbtInfo = 0;
#endif
PredictionUnit &pu = tempCS->addPU(cu, partitioner.chType);// tempCS->addPU(cu);
pu.intraDir[0] = DC_IDX; // set intra pred for ibc block
pu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
cu.mmvdSkip = false;
pu.mmvdMergeFlag = false;
cu.triangle = false;
mergeCtx.setMergeInfo(pu, mergeCand);
PU::spanMotionInfo(pu, mergeCtx);
assert(mergeCtx.mrgTypeNeighbours[mergeCand] == MRG_TYPE_IBC); // should be IBC candidate at this round
const bool chroma = !(CS::isDualITree(*tempCS));
// MC
m_pcInterSearch->motionCompensation(pu,REF_PIC_LIST_0, true, chroma);
m_CABACEstimator->getCtx() = m_CurrCtx->start;
m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, (numResidualPass != 0), true, chroma);
xEncodeDontSplit(*tempCS, partitioner);

Christian Helmrich
committed
#if ENABLE_QPA_SUB_CTU
xCheckDQP (*tempCS, partitioner);
#else
// this if-check is redundant
#if JVET_M0113_M0188_QG_SIZE
if (tempCS->pps->getUseDQP() && partitioner.currQgEnable())
#else
if (tempCS->pps->getUseDQP() && (partitioner.currDepth) <= tempCS->pps->getMaxCuDQPDepth())

Christian Helmrich
committed
#endif
hasResidual[emtCuFlag] = cu.rootCbf;
emtCost[emtCuFlag] = tempCS->cost;
DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
}
if (numResidualPass == 0 && (emtCost[0] <= emtCost[1] ? !hasResidual[0] : !hasResidual[1]))
{
// If no residual when allowing for one, then set mark to not try case where residual is forced to 0
candHasNoResidual[mergeCand] = 1;
}
if (m_pcEncCfg->getUseFastDecisionForMerge() && !bestIsSkip)
{
if (bestCS->getCU(partitioner.chType) == NULL)
bestIsSkip = 0;
else
bestIsSkip = bestCS->getCU(partitioner.chType)->rootCbf == 0;
}
}
}
}
}
#if JVET_M0428_ENC_DB_OPT
if ( m_bestModeUpdated && bestCS->cost != MAX_DOUBLE )
void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode)
if (tempCS->area.lwidth() > IBC_MAX_CAND_SIZE || tempCS->area.lheight() > IBC_MAX_CAND_SIZE) // currently only check 32x32 and below block for ibc merge/skip
{
return;
}
tempCS->initStructData(encTestMode.qp, encTestMode.lossless);
#if JVET_M0428_ENC_DB_OPT
m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
#endif
CodingUnit &cu = tempCS->addCU(CS::getArea(*tempCS, tempCS->area, partitioner.chType), 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;
cu.transQuantBypass = encTestMode.lossless;
cu.chromaQpAdj = cu.transQuantBypass ? 0 : m_cuChromaQpOffsetIdxPlus1;
cu.qp = encTestMode.qp;
Yin Zhao
committed
#if JVET_M0140_SBT
cu.sbtInfo = 0;
#endif
#if JVET_M0428_ENC_DB_OPT
m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
#endif
PredictionUnit& pu = *cu.firstPU;
cu.mmvdSkip = false;
pu.mmvdMergeFlag = false;
pu.intraDir[0] = DC_IDX; // set intra pred for ibc block
pu.intraDir[1] = PLANAR_IDX; // set intra pred for ibc block
pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list
pu.refIdx[REF_PIC_LIST_0] = pu.cs->slice->getNumRefIdx(REF_PIC_LIST_0) - 1; // last idx in the list
bool bValid = m_pcInterSearch->predIBCSearch(cu, partitioner, m_ctuIbcSearchRangeX, m_ctuIbcSearchRangeY, m_ibcHashMap);
if (bValid)
{
PU::spanMotionInfo(pu);
const bool chroma = !(CS::isDualITree(*tempCS));
// MC
m_pcInterSearch->motionCompensation(pu, REF_PIC_LIST_0, true, chroma);
double bestCost = bestCS->cost;
unsigned char considerEmtSecondPass = 0;
bool skipSecondEmtPass = true;
double emtFirstPassCost = MAX_DOUBLE;
// CU-level optimization
for (unsigned char emtCuFlag = 0; emtCuFlag <= considerEmtSecondPass; emtCuFlag++)
{
if (m_pcEncCfg->getFastInterEMT() && emtCuFlag && skipSecondEmtPass)
{
continue;
}
tempCS->getCU(tempCS->chType)->emtFlag = emtCuFlag;
m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, false, true, chroma);
if (m_pcEncCfg->getFastInterEMT())
{
emtFirstPassCost = (!emtCuFlag) ? tempCS->cost : emtFirstPassCost;
}

Christian Helmrich
committed
#if ENABLE_QPA_SUB_CTU
xCheckDQP (*tempCS, partitioner);
#else
// this if-check is redundant
#if JVET_M0113_M0188_QG_SIZE
if (tempCS->pps->getUseDQP() && partitioner.currQgEnable())
#else
if (tempCS->pps->getUseDQP() && (partitioner.currDepth) <= tempCS->pps->getMaxCuDQPDepth())

Christian Helmrich
committed
#endif
#if JVET_M0428_ENC_DB_OPT
tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
if ( m_bestModeUpdated )
DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
3849
3850
3851
3852
3853
3854
3855
3856
3857
3858
3859
3860
3861
3862
3863
3864
3865
3866
3867
3868
3869
3870
3871
3872
3873
3874
//now we check whether the second pass should be skipped or not
if (!emtCuFlag && considerEmtSecondPass)
{
static const double thresholdToSkipEmtSecondPass = 1.1; // Skip checking EMT transforms
if (m_pcEncCfg->getFastInterEMT() && (!cu.firstTU->cbf[COMPONENT_Y] || emtFirstPassCost > bestCost * thresholdToSkipEmtSecondPass))
{
skipSecondEmtPass = true;
}
else //EMT will be checked
{
if (bestCost == bestCS->cost) //The first EMT pass didn't become the bestCS, so we clear the TUs generated
{
tempCS->clearTUs();
}
else
{
tempCS->initStructData(bestCS->currQP[bestCS->chType], bestCS->isLossless);
tempCS->copyStructure(*bestCS, partitioner.chType);
tempCS->getPredBuf().copyFrom(bestCS->getPredBuf());
}
//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;
}
} // bValid
else
{
tempCS->dist = 0;
tempCS->fracBits = 0;
tempCS->cost = MAX_DOUBLE;
else
{
bool success = true;
// chroma tree, reuse luma bv at minimal block level
// enabled search only when each chroma sub-block has a BV from its luma sub-block
assert(tempCS->getIbcLumaCoverage(pu.Cb()) == IBC_LUMA_COVERAGE_FULL);
3901
3902
3903
3904
3905
3906
3907
3908
3909
3910
3911
3912
3913
3914
3915
3916
3917
3918
3919
3920
3921
3922
3923
3924
3925
3926
3927
3928
3929
3930
3931
3932
3933
3934
// check if each BV for the chroma sub-block is valid
//static const UInt unitArea = MIN_PU_SIZE * MIN_PU_SIZE;
const CompArea lumaArea = CompArea(COMPONENT_Y, pu.chromaFormat, pu.Cb().lumaPos(), recalcSize(pu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, pu.Cb().size()));
PredictionUnit subPu;
subPu.cs = pu.cs;
subPu.cu = pu.cu;
const ComponentID compID = COMPONENT_Cb; // use Cb to represent both Cb and CR, as their structures are the same
int shiftHor = ::getComponentScaleX(compID, pu.chromaFormat);
int shiftVer = ::getComponentScaleY(compID, pu.chromaFormat);
//const ChromaFormat chFmt = pu.chromaFormat;
for (int y = lumaArea.y; y < lumaArea.y + lumaArea.height; y += MIN_PU_SIZE)
{
for (int x = lumaArea.x; x < lumaArea.x + lumaArea.width; x += MIN_PU_SIZE)
{
const MotionInfo &curMi = pu.cs->picture->cs->getMotionInfo(Position{ x, y });
subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, MIN_PU_SIZE, MIN_PU_SIZE)));
Position offsetRef = subPu.blocks[compID].pos().offset((curMi.bv.getHor() >> shiftHor), (curMi.bv.getVer() >> shiftVer));
Position refEndPos(offsetRef.x + subPu.blocks[compID].size().width - 1, offsetRef.y + subPu.blocks[compID].size().height - 1 );
if (!subPu.cs->isDecomp(refEndPos, toChannelType(compID)) || !subPu.cs->isDecomp(offsetRef, toChannelType(compID))) // ref block is not yet available for this chroma sub-block
{
success = false;
break;
}
}
if (!success)
break;
}
////////////////////////////////////////////////////////////////////////////
if (success)
{
m_pcInterSearch->motionCompensation(pu, REF_PIC_LIST_0, false, true); // luma=0, chroma=1
m_pcInterSearch->encodeResAndCalcRdInterCU(*tempCS, partitioner, false, false, true);
xEncodeDontSplit(*tempCS, partitioner);
xCheckDQP(*tempCS, partitioner);
#if JVET_M0428_ENC_DB_OPT
tempCS->useDbCost = m_pcEncCfg->getUseEncDbOpt();
if ( m_bestModeUpdated )
{
xCalDebCost( *tempCS, partitioner );
}
DTRACE_MODE_COST(*tempCS, m_pcRdCost->getLambda());
xCheckBestMode(tempCS, bestCS, partitioner, encTestMode);
}
else
{
tempCS->dist = 0;
tempCS->fracBits = 0;
tempCS->cost = MAX_DOUBLE;
//////////////////////////////////////////////////////////////////////////////////////////////

Karsten Suehring
committed
void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestCS, Partitioner &partitioner, const EncTestMode& encTestMode )
{
tempCS->initStructData( encTestMode.qp, encTestMode.lossless );
m_pcInterSearch->setAffineModeSelected(false);
if( tempCS->slice->getCheckLDC() )
{
m_bestGbiCost[0] = m_bestGbiCost[1] = std::numeric_limits<double>::max();
m_bestGbiIdx[0] = m_bestGbiIdx[1] = -1;
}
m_pcInterSearch->resetBufferedUniMotions();
int gbiLoopNum = (tempCS->slice->isInterB() ? GBI_NUM : 1);
gbiLoopNum = (tempCS->sps->getUseGBi() ? gbiLoopNum : 1);
if( tempCS->area.lwidth() * tempCS->area.lheight() < GBI_SIZE_CONSTRAINT )
{
gbiLoopNum = 1;
}
double curBestCost = bestCS->cost;
double equGBiCost = MAX_DOUBLE;
#if JVET_M0428_ENC_DB_OPT
m_bestModeUpdated = tempCS->useDbCost = bestCS->useDbCost = false;
#endif