Newer
Older
LFNSTSaveFlag = false;
}
} // NSSTFlag
if (!sps.getUseMIP() && LFNSTLoadFlag)
// restore saved modes
numModesForFullRD = m_uiSavedNumRdModesLFNST;
uiRdModeList = m_uiSavedRdModeListLFNST;
CandCostList = m_dSavedModeCostLFNST;
// PBINTRA fast
uiHadModeList = m_uiSavedHadModeListLFNST;
CandHadList = m_dSavedHadListLFNST;
} // !LFNSTFlag
if (!(sps.getUseMIP() && LFNSTLoadFlag))
{
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> parentCandList = uiRdModeList;
// Second round of SATD for extended Angular modes
for (int modeIdx = 0; modeIdx < numModesForFullRD; modeIdx++)
{
unsigned parentMode = parentCandList[modeIdx].modeId;
if (parentMode > (DC_IDX + 1) && parentMode < (NUM_LUMA_MODE - 1))
{
for (int subModeIdx = -1; subModeIdx <= 1; subModeIdx += 2)
{
unsigned mode = parentMode + subModeIdx;
if (!bSatdChecked[mode])
{
pu.intraDir[0] = mode;
initPredIntraParams(pu, pu.Y(), sps);
#if JVET_AB0157_INTRA_FUSION
predIntraAng(COMPONENT_Y, piPred, pu, false);
#else
#if JVET_AB0155_SGPM
if (testSgpm && SGPMSaveFlag && sgpmNeededMode[mode])
{
PelBuf predBuf(m_intraPredBuf[mode], tmpArea);
predBuf.copyFrom(piPred);
m_intraModeReady[mode] = 1;
}
#endif
// Use the min between SAD and SATD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
// NB xFracModeBitsIntra will not affect the mode for chroma that may have already been
// pre-estimated.
#if JVET_V0130_INTRA_TMP
m_CABACEstimator->getCtx() = SubCtx( Ctx::TmpFlag, ctxStartTpmFlag );
m_CABACEstimator->getCtx() = SubCtx(Ctx::MipFlag, ctxStartMipFlag);
#if JVET_W0123_TIMD_FUSION
m_CABACEstimator->getCtx() = SubCtx( Ctx::TimdFlag, ctxStartTimdFlag );
#endif
#if JVET_AB0155_SGPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::SgpmFlag, ctxStartSgpmFlag);
m_CABACEstimator->getCtx() = SubCtx(Ctx::ISPMode, ctxStartIspMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMPMIdx, ctxStartMPMIdxFlag);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaPlanarFlag, ctxStartPlanarFlag);
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaSecondMpmFlag, ctxStartIntraMode2);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::MultiRefLineIdx, ctxStartMrlIdx);
#if JVET_AB0157_TMRL
m_CABACEstimator->getCtx() = SubCtx(Ctx::TmrlDerive, ctxStartTmrlDerive);
#endif
uint64_t fracModeBits = xFracModeBitsIntra(pu, mode, CHANNEL_TYPE_LUMA);
double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, mode), cost, uiRdModeList,
CandCostList, numModesForFullRD);
updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, mode), double(minSadHad),
uiHadModeList, CandHadList, numHadCand);
bSatdChecked[mode] = true;
}
}
}
}
if (saveDataForISP)
// we save the regular intra modes list
m_ispCandListHor = uiRdModeList;
}
#if SECONDARY_MPM
const int numMPMs = NUM_PRIMARY_MOST_PROBABLE_MODES;
uint8_t* multiRefMPM = m_mpmList;
#else
const int numMPMs = NUM_MOST_PROBABLE_MODES;
unsigned multiRefMPM[numMPMs];
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
#endif
#if JVET_AB0157_TMRL
cu.tmrlFlag = true;
if (CU::allowTmrl(cu))
{
for (auto multiRefIdx : EXT_REF_LINE_IDX)
{
pu.multiRefIdx = multiRefIdx;
initIntraPatternChType(cu, pu.Y(), true);
for (auto i = 0; i < MRL_LIST_SIZE; i++)
{
if (cu.tmrlList[i].multiRefIdx != multiRefIdx)
{
continue;
}
pu.intraDir[0] = cu.tmrlList[i].intraDir;
cu.tmrlListIdx = i;
uint32_t uiMode = i + MAX_REF_LINE_IDX;
initPredIntraParams(pu, pu.Y(), *(pu.cs->sps));
predIntraAng(COMPONENT_Y, piPred, pu);
// Use the min between SAD and SATD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
// NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
#if JVET_V0130_INTRA_TMP
m_CABACEstimator->getCtx() = SubCtx(Ctx::TmpFlag, ctxStartTpmFlag);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::MipFlag, ctxStartMipFlag);
#if JVET_W0123_TIMD_FUSION
m_CABACEstimator->getCtx() = SubCtx(Ctx::TimdFlag, ctxStartTimdFlag);
#endif
#if JVET_AB0155_SGPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::SgpmFlag, ctxStartSgpmFlag);
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::ISPMode, ctxStartIspMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMPMIdx, ctxStartMPMIdxFlag);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaPlanarFlag, ctxStartPlanarFlag);
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaSecondMpmFlag, ctxStartIntraMode2);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::MultiRefLineIdx, ctxStartMrlIdx);
#if JVET_AB0157_TMRL
m_CABACEstimator->getCtx() = SubCtx(Ctx::TmrlDerive, ctxStartTmrlDerive);
#endif
uint64_t fracModeBits = xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA);
double cost = (double)minSadHad + (double)fracModeBits * sqrtLambdaForFirstPass;
updateCandList(ModeInfo(false, false, uiMode, NOT_INTRA_SUBPARTITIONS, 0), cost, uiRdModeList,
CandCostList, numModesForFullRD);
updateCandList(ModeInfo(false, false, uiMode, NOT_INTRA_SUBPARTITIONS, 0), double(minSadHad),
uiHadModeList, CandHadList, numHadCand);
#if JVET_AB0157_TMRL
tmrlCostList[i] = cost;
#endif
}
}
}
#else
for (int mRefNum = 1; mRefNum < numOfPassesExtendRef; mRefNum++)
{
int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
#if JVET_AB0157_INTRA_FUSION && JVET_AB0155_SGPM
initIntraPatternChType(cu, pu.Y(), true, 0, false);
#elif JVET_AB0157_INTRA_FUSION
initIntraPatternChType(cu, pu.Y(), true, false);
#else
}
for (int x = 1; x < numMPMs; x++)
{
uint32_t mode = multiRefMPM[x];
{
pu.intraDir[0] = mode;
initPredIntraParams(pu, pu.Y(), sps);
#if JVET_AB0157_INTRA_FUSION
predIntraAng(COMPONENT_Y, piPred, pu, false);
#else
// Use the min between SAD and SATD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
// NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
#if JVET_V0130_INTRA_TMP
m_CABACEstimator->getCtx() = SubCtx( Ctx::TmpFlag, ctxStartTpmFlag );
m_CABACEstimator->getCtx() = SubCtx(Ctx::MipFlag, ctxStartMipFlag);
#if JVET_W0123_TIMD_FUSION
m_CABACEstimator->getCtx() = SubCtx( Ctx::TimdFlag, ctxStartTimdFlag );
#endif
#if JVET_AB0155_SGPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::SgpmFlag, ctxStartSgpmFlag);
m_CABACEstimator->getCtx() = SubCtx(Ctx::ISPMode, ctxStartIspMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMPMIdx, ctxStartMPMIdxFlag);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaPlanarFlag, ctxStartPlanarFlag);
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaSecondMpmFlag, ctxStartIntraMode2);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::MultiRefLineIdx, ctxStartMrlIdx);
uint64_t fracModeBits = xFracModeBitsIntra(pu, mode, CHANNEL_TYPE_LUMA);
double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
updateCandList(ModeInfo(false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, mode), cost, uiRdModeList,
CandCostList, numModesForFullRD);
updateCandList(ModeInfo(false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, mode), double(minSadHad),
uiHadModeList, CandHadList, numHadCand);
}
}
}
CHECKD(uiRdModeList.size() != numModesForFullRD, "Error: RD mode list size");
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
#if JVET_V0130_INTRA_TMP && JVET_AB0130_ITMP_SAMPLING
// derive TPM candidate using hadamard
if (testTpm)
{
cu.tmpFlag = true;
cu.mipFlag = false;
pu.multiRefIdx = 0;
int foundCandiNum = 0;
bool bsuccessfull = 0;
CodingUnit cuCopy = cu;
#if JVET_W0069_TMP_BOUNDARY
RefTemplateType templateType = getRefTemplateType(cuCopy, cuCopy.blocks[COMPONENT_Y]);
if (templateType != NO_TEMPLATE)
#else
if (isRefTemplateAvailable(cuCopy, cuCopy.blocks[COMPONENT_Y]))
#endif
{
#if JVET_W0069_TMP_BOUNDARY
#if TMP_FAST_ENC
bsuccessfull = generateTMPrediction(piPred.buf, piPred.stride, pu.Y(), foundCandiNum, pu.cu);
#else
getTargetTemplate(&cuCopy, pu.lwidth(), pu.lheight(), templateType);
candidateSearchIntra(&cuCopy, pu.lwidth(), pu.lheight(), templateType);
bsuccessfull = generateTMPrediction(piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), foundCandiNum);
#endif
#else
#if TMP_FAST_ENC
bsuccessfull = generateTMPrediction(piPred.buf, piPred.stride, pu.Y(), foundCandiNum, pu.cu);
#else
getTargetTemplate(&cuCopy, pu.lwidth(), pu.lheight());
candidateSearchIntra(&cuCopy, pu.lwidth(), pu.lheight());
bsuccessfull = generateTMPrediction(piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), foundCandiNum);
#endif
#endif
}
#if JVET_W0069_TMP_BOUNDARY
else
{
foundCandiNum = 1;
bsuccessfull = generateTmDcPrediction(piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), 1 << (cuCopy.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA) - 1));
}
#endif
if (bsuccessfull && foundCandiNum >= 1)
{
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
m_CABACEstimator->getCtx() = SubCtx(Ctx::TmpFlag, ctxStartTpmFlag);
uint64_t fracModeBits = xFracModeBitsIntra(pu, 0, CHANNEL_TYPE_LUMA);
double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass;
DTRACE(g_trace_ctx, D_INTRA_COST, "IntraTPM: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, 0);
updateCandList(ModeInfo(0, 0, 0, NOT_INTRA_SUBPARTITIONS, 0, 1), cost, uiRdModeList, CandCostList, numModesForFullRD);
updateCandList(ModeInfo(0, 0, 0, NOT_INTRA_SUBPARTITIONS, 0, 1), 0.8 * double(minSadHad), uiHadModeList, CandHadList, numHadCand);
}
}
#endif
if (LFNSTSaveFlag && testMip
&& !allowLfnstWithMip(cu.firstPU->lumaSize())) // save a different set for the next run
{
// save found best modes
m_uiSavedRdModeListLFNST = uiRdModeList;
m_dSavedModeCostLFNST = CandCostList;
// PBINTRA fast
m_uiSavedHadModeListLFNST = uiHadModeList;
m_dSavedHadListLFNST = CandHadList;
m_uiSavedNumRdModesLFNST =
g_aucIntraModeNumFast_UseMPM_2D[uiWidthBit - MIN_CU_LOG2][uiHeightBit - MIN_CU_LOG2];
m_uiSavedRdModeListLFNST.resize(m_uiSavedNumRdModesLFNST);
m_dSavedModeCostLFNST.resize(m_uiSavedNumRdModesLFNST);
// PBINTRA fast
m_uiSavedHadModeListLFNST.resize(3);
m_dSavedHadListLFNST.resize(3);
LFNSTSaveFlag = false;
}
#if JVET_V0130_INTRA_TMP && !JVET_AB0130_ITMP_SAMPLING
// derive TPM candidate using hadamard
if( testTpm )
{
cu.tmpFlag = true;
cu.mipFlag = false;
pu.multiRefIdx = 0;
#if JVET_AB0157_TMRL
cu.tmrlFlag = false;
#endif
int foundCandiNum = 0;
bool bsuccessfull = 0;
CodingUnit cu_cpy = cu;
RefTemplateType templateType = getRefTemplateType( cu_cpy, cu_cpy.blocks[COMPONENT_Y] );
if( templateType != NO_TEMPLATE )
if( isRefTemplateAvailable( cu_cpy, cu_cpy.blocks[COMPONENT_Y] ) )
getTargetTemplate( &cu_cpy, pu.lwidth(), pu.lheight(), templateType );
candidateSearchIntra( &cu_cpy, pu.lwidth(), pu.lheight(), templateType );
bsuccessfull = generateTMPrediction( piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), foundCandiNum );
getTargetTemplate( &cu_cpy, pu.lwidth(), pu.lheight() );
candidateSearchIntra( &cu_cpy, pu.lwidth(), pu.lheight() );
bsuccessfull = generateTMPrediction( piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), foundCandiNum );
bsuccessfull = generateTmDcPrediction( piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), 1 << (cu_cpy.cs->sps->getBitDepth( CHANNEL_TYPE_LUMA ) - 1) );
if( bsuccessfull && foundCandiNum >= 1 )
{
Distortion minSadHad =
std::min( distParamSad.distFunc( distParamSad ) * 2, distParamHad.distFunc( distParamHad ) );
m_CABACEstimator->getCtx() = SubCtx( Ctx::TmpFlag, ctxStartTpmFlag );
uint64_t fracModeBits = xFracModeBitsIntra( pu, 0, CHANNEL_TYPE_LUMA );
double cost = double( minSadHad ) + double( fracModeBits ) * sqrtLambdaForFirstPass;
DTRACE( g_trace_ctx, D_INTRA_COST, "IntraTPM: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, 0 );
updateCandList( ModeInfo( 0, 0, 0, NOT_INTRA_SUBPARTITIONS, 0, 1 ), cost, uiRdModeList, CandCostList, numModesForFullRD );
updateCandList( ModeInfo( 0, 0, 0, NOT_INTRA_SUBPARTITIONS, 0, 1 ), 0.8 * double( minSadHad ), uiHadModeList, CandHadList, numHadCand );
}
}
//*** Derive MIP candidates using Hadamard
if (testMip && !supportedMipBlkSize)
{
// avoid estimation for unsupported blk sizes
const int transpOff = getNumModesMip(pu.Y());
const int numModesFull = (transpOff << 1);
for (uint32_t uiModeFull = 0; uiModeFull < numModesFull; uiModeFull++)
{
const bool isTransposed = (uiModeFull >= transpOff ? true : false);
const uint32_t uiMode = (isTransposed ? uiModeFull - transpOff : uiModeFull);
numModesForFullRD++;
uiRdModeList.push_back(ModeInfo(true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, uiMode));
CandCostList.push_back(0);
}
}
else if (testMip)
{
#if JVET_AB0157_TMRL
cu.tmrlFlag = false;
#endif
double mipHadCost[MAX_NUM_MIP_MODE] = { MAX_DOUBLE };
#if JVET_AB0157_INTRA_FUSION && JVET_AB0155_SGPM
initIntraPatternChType(cu, pu.Y(), false, 0, false);
#elif JVET_AB0157_INTRA_FUSION
initIntraPatternChType(cu, pu.Y(), false, false);
#else
const int transpOff = getNumModesMip(pu.Y());
const int numModesFull = (transpOff << 1);
for (uint32_t uiModeFull = 0; uiModeFull < numModesFull; uiModeFull++)
{
const bool isTransposed = (uiModeFull >= transpOff ? true : false);
const uint32_t uiMode = (isTransposed ? uiModeFull - transpOff : uiModeFull);
pu.mipTransposedFlag = isTransposed;
pu.intraDir[CHANNEL_TYPE_LUMA] = uiMode;
predIntraMip(COMPONENT_Y, piPred, pu);
// Use the min between SAD and HAD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));

Karsten Suehring
committed
m_CABACEstimator->getCtx() = SubCtx(Ctx::MipFlag, ctxStartMipFlag);
uint64_t fracModeBits = xFracModeBitsIntra(pu, uiMode, CHANNEL_TYPE_LUMA);

Karsten Suehring
committed
double cost = double(minSadHad) + double(fracModeBits) * sqrtLambdaForFirstPass;
mipHadCost[uiModeFull] = cost;
DTRACE(g_trace_ctx, D_INTRA_COST, "IntraMIP: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost,
uiModeFull);

Karsten Suehring
committed
updateCandList(ModeInfo(true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, uiMode), cost, uiRdModeList,
CandCostList, numModesForFullRD + 1);
updateCandList(ModeInfo(true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, uiMode),
0.8 * double(minSadHad), uiHadModeList, CandHadList, numHadCand);
}

Karsten Suehring
committed
const double thresholdHadCost = 1.0 + 1.4 / sqrt((double) (pu.lwidth() * pu.lheight()));
reduceHadCandList(uiRdModeList, CandCostList, numModesForFullRD, thresholdHadCost, mipHadCost, pu,
fastMip
#if JVET_AB0157_TMRL
, tmrlCostList
#endif
#if JVET_AC0105_DIRECTIONAL_PLANAR
, dirPlanarCostList

Karsten Suehring
committed
}

Karsten Suehring
committed
{
// save found best modes
m_uiSavedNumRdModesLFNST = numModesForFullRD;
m_uiSavedRdModeListLFNST = uiRdModeList;
m_dSavedModeCostLFNST = CandCostList;
// PBINTRA fast
m_uiSavedHadModeListLFNST = uiHadModeList;
m_dSavedHadListLFNST = CandHadList;
LFNSTSaveFlag = false;

Karsten Suehring
committed
}
}
else // if( sps.getUseMIP() && LFNSTLoadFlag)
{
// restore saved modes
numModesForFullRD = m_uiSavedNumRdModesLFNST;
uiRdModeList = m_uiSavedRdModeListLFNST;
CandCostList = m_dSavedModeCostLFNST;
// PBINTRA fast
uiHadModeList = m_uiSavedHadModeListLFNST;
CandHadList = m_dSavedHadListLFNST;
}
#if JVET_AB0155_SGPM
if (testSgpm)
{
if (SGPMSaveFlag)
{
m_uiSavedRdModeListSGPM.clear();
m_dSavedModeCostSGPM.clear();
m_uiSavedHadModeListSGPM.clear();
m_dSavedHadListSGPM.clear();
#if JVET_V0130_INTRA_TMP
#if JVET_AB0157_INTRA_FUSION
initIntraPatternChType(cu, pu.Y(), true, 0, false);
#else
// get single mode predictions
for (int sgpmIdx = 0; sgpmIdx < SGPM_NUM; sgpmIdx++)
{
int sgpmMode[2];
sgpmMode[0] = sgpmInfoList[sgpmIdx].sgpmMode0;
sgpmMode[1] = sgpmInfoList[sgpmIdx].sgpmMode1;
for (int idxIn2 = 0; idxIn2 < 2; idxIn2++)
{
if (!m_intraModeReady[sgpmMode[idxIn2]])
{
pu.intraDir[0] = sgpmMode[idxIn2];
initPredIntraParams(pu, pu.Y(), sps);
#if JVET_AB0157_INTRA_FUSION
predIntraAng(COMPONENT_Y, piPred, pu, false);
#else
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
PelBuf predBuf(m_intraPredBuf[sgpmMode[idxIn2]], tmpArea);
predBuf.copyFrom(piPred);
m_intraModeReady[sgpmMode[idxIn2]] = 1;
}
}
}
cu.sgpm = true;
// frac bits calculate once because all are the same
cu.sgpmIdx = 0;
cu.sgpmSplitDir = sgpmInfoList[0].sgpmSplitDir;
cu.sgpmMode0 = sgpmInfoList[0].sgpmMode0;
cu.sgpmMode1 = sgpmInfoList[0].sgpmMode1;
pu.intraDir[0] = cu.sgpmMode0;
pu.intraDir1[0] = cu.sgpmMode1;
// NB xFracModeBitsIntra will not affect the mode for chroma that may have already been pre-estimated.
#if JVET_V0130_INTRA_TMP
m_CABACEstimator->getCtx() = SubCtx(Ctx::TmpFlag, ctxStartTpmFlag);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::MipFlag, ctxStartMipFlag);
#if JVET_W0123_TIMD_FUSION
m_CABACEstimator->getCtx() = SubCtx(Ctx::TimdFlag, ctxStartTimdFlag);
#endif
#if JVET_AB0155_SGPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::SgpmFlag, ctxStartSgpmFlag);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::ISPMode, ctxStartIspMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMPMIdx, ctxStartMPMIdxFlag);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaPlanarFlag, ctxStartPlanarFlag);
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaSecondMpmFlag, ctxStartIntraMode2);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::MultiRefLineIdx, ctxStartMrlIdx);
#if JVET_AB0157_TMRL
m_CABACEstimator->getCtx() = SubCtx(Ctx::TmrlDerive, ctxStartTmrlDerive);
#endif
uint64_t fracModeBits = xFracModeBitsIntra(pu, 0, CHANNEL_TYPE_LUMA);
for (int sgpmIdx = 0; sgpmIdx < SGPM_NUM; sgpmIdx++)
{
int sgpmMode0 = sgpmInfoList[sgpmIdx].sgpmMode0;
int sgpmMode1 = sgpmInfoList[sgpmIdx].sgpmMode1;
PelBuf src0(m_intraPredBuf[sgpmMode0], tmpArea);
PelBuf src1(m_intraPredBuf[sgpmMode1], tmpArea);
m_if.m_weightedSgpm(pu, width, height, COMPONENT_Y, sgpmInfoList[sgpmIdx].sgpmSplitDir, piPred, src0, src1);
PelBuf predBuf(m_sgpmPredBuf[sgpmIdx], tmpArea);
predBuf.copyFrom(piPred);
Distortion minSadHad = 0;
minSadHad += std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, SGPM_IDX,
#if JVET_V0130_INTRA_TMP
false, //tmpFlag
#endif
true, sgpmInfoList[sgpmIdx].sgpmSplitDir, sgpmInfoList[sgpmIdx].sgpmMode0,
sgpmInfoList[sgpmIdx].sgpmMode1, sgpmIdx),
cost, m_uiSavedRdModeListSGPM, m_dSavedModeCostSGPM, SGPM_NUM);
updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, SGPM_IDX,
#if JVET_V0130_INTRA_TMP
false, //tmpFlag
#endif
true, sgpmInfoList[sgpmIdx].sgpmSplitDir, sgpmInfoList[sgpmIdx].sgpmMode0,
sgpmInfoList[sgpmIdx].sgpmMode1, sgpmIdx),
double(minSadHad), m_uiSavedHadModeListSGPM, m_dSavedHadListSGPM, SGPM_NUM);
}
cu.sgpm = false;
}
int updateNum = std::min<int>( (numModesForFullRD + 1) / 2, (int)m_uiSavedRdModeListSGPM.size() );
for (auto listIdx = 0; listIdx < updateNum; listIdx++)
{
updateCandList(m_uiSavedRdModeListSGPM[listIdx], m_dSavedModeCostSGPM[listIdx], uiRdModeList,
CandCostList, numModesForFullRD);
updateCandList(m_uiSavedHadModeListSGPM[listIdx], m_dSavedHadListSGPM[listIdx], uiHadModeList,
CandHadList, numHadCand);
}
}
#endif
#if SECONDARY_MPM
auto uiPreds = m_mpmList;
#else
const int numMPMs = NUM_MOST_PROBABLE_MODES;
unsigned uiPreds[numMPMs];
#if JVET_AB0157_TMRL
cu.tmrlFlag = false;;
#endif
#if SECONDARY_MPM
int numCand = m_mpmListSize;
numCand = (numCand > 2) ? 2 : numCand;
#else
const int numCand = PU::getIntraMPMs(pu, uiPreds);
for (int j = 0; j < numCand; j++)
{
bool mostProbableModeIncluded = false;
ModeInfo mostProbableMode( false, false, 0, NOT_INTRA_SUBPARTITIONS, uiPreds[j] );
mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]);
}
if (!mostProbableModeIncluded)
{
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
numModesForFullRD++;
uiRdModeList.push_back(mostProbableMode);
CandCostList.push_back(0);
}
}
if (saveDataForISP)
{
// we add the MPMs to the list that contains only regular intra modes
for (int j = 0; j < numCand; j++)
{
bool mostProbableModeIncluded = false;
ModeInfo mostProbableMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiPreds[j]);
for (int i = 0; i < m_ispCandListHor.size(); i++)
{
mostProbableModeIncluded |= (mostProbableMode == m_ispCandListHor[i]);
}
if (!mostProbableModeIncluded)
{
m_ispCandListHor.push_back(mostProbableMode);
}
else
{
THROW("Full search not supported for MIP");
}
if (sps.getUseLFNST() && mtsUsageFlag == 1)
{
// Store the modes to be checked with RD
m_savedNumRdModes[lfnstIdx] = numModesForFullRD;
std::copy_n(uiRdModeList.begin(), numModesForFullRD, m_savedRdModeList[lfnstIdx]);
}

Karsten Suehring
committed
}
else // mtsUsage = 2 (here we potentially reduce the number of modes that will be full-RD checked)
if ((m_pcEncCfg->getUseFastLFNST() || !cu.slice->isIntra()) && m_bestModeCostValid[lfnstIdx])
{
numModesForFullRD = 0;
#if JVET_W0103_INTRA_MTS
double thresholdSkipMode = 1.0 + ((cu.lfnstIdx > 0) ? 0.1 : 0.8) * (1.4 / sqrt((double)(width * height)));
std::vector<std::pair<ModeInfo, double>> modeInfoWithDCT2Cost(m_savedNumRdModes[0]);
for (int i = 0; i < m_savedNumRdModes[0]; i++)
{
modeInfoWithDCT2Cost[i] = { m_savedRdModeList[0][i], m_modeCostStore[0][i] };
std::stable_sort(modeInfoWithDCT2Cost.begin(), modeInfoWithDCT2Cost.end(), [](const std::pair<ModeInfo, double> & l, const std::pair<ModeInfo, double> & r) {return l.second < r.second; });
// **Reorder the modes** and skip checking the modes with much larger R-D cost than the best mode
for (int i = 0; i < m_savedNumRdModes[0]; i++)
{
if (modeInfoWithDCT2Cost[i].second <= thresholdSkipMode * modeInfoWithDCT2Cost[0].second)
uiRdModeList.push_back(modeInfoWithDCT2Cost[i].first);
numModesForFullRD++;
}
}
#else
double thresholdSkipMode = 1.0 + ((cu.lfnstIdx > 0) ? 0.1 : 1.0) * (1.4 / sqrt((double) (width * height)));
// Skip checking the modes with much larger R-D cost than the best mode
for (int i = 0; i < m_savedNumRdModes[lfnstIdx]; i++)
if (m_modeCostStore[lfnstIdx][i] <= thresholdSkipMode * m_bestModeCostStore[lfnstIdx])
{
uiRdModeList.push_back(m_savedRdModeList[lfnstIdx][i]);
numModesForFullRD++;
}
else // this is necessary because we skip the candidates list calculation, since it was already obtained for
// the DCT-II. Now we load it
{
// Restore the modes to be checked with RD
numModesForFullRD = m_savedNumRdModes[lfnstIdx];
uiRdModeList.resize(numModesForFullRD);
std::copy_n(m_savedRdModeList[lfnstIdx], m_savedNumRdModes[lfnstIdx], uiRdModeList.begin());
CandCostList.resize(numModesForFullRD);
}
#if ENABLE_DIMD
bool isDimdValid = cu.slice->getSPS()->getUseDimd();
if (isDimdValid)
{
cu.dimd = false;
ModeInfo m = ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, DIMD_IDX );
uiRdModeList.push_back(m);
if (testISP)
{
m.ispMod = HOR_INTRA_SUBPARTITIONS;
m_ispCandListHor.push_back(m);
m.ispMod = VER_INTRA_SUBPARTITIONS;
m_ispCandListVer.push_back(m);
}
CHECK(numModesForFullRD != uiRdModeList.size(), "Inconsistent state!");
// after this point, don't use numModesForFullRD
// PBINTRA fast
if (m_pcEncCfg->getUsePbIntraFast() && !cs.slice->isIntra() && uiRdModeList.size() < numModesAvailable
&& !cs.slice->getDisableSATDForRD() && (mtsUsageFlag != 2 || lfnstIdx > 0))
double pbintraRatio = (lfnstIdx > 0) ? 1.25 : PBINTRA_RATIO;
int maxSize = -1;
ModeInfo bestMipMode;
int bestMipIdx = -1;
for (int idx = 0; idx < uiRdModeList.size(); idx++)
if (uiRdModeList[idx].mipFlg)
{
bestMipMode = uiRdModeList[idx];
bestMipIdx = idx;
break;
}
const int numHadCand = 3;
for (int k = numHadCand - 1; k >= 0; k--)
if (CandHadList.size() < (k + 1) || CandHadList[k] > cs.interHad * pbintraRatio)
uiRdModeList.resize(std::min<size_t>(uiRdModeList.size(), maxSize));
if (sps.getUseLFNST() && mtsUsageFlag == 1)
{
// Update also the number of stored modes to avoid partial fill of mode storage
m_savedNumRdModes[lfnstIdx] = std::min<int32_t>(int32_t(uiRdModeList.size()), m_savedNumRdModes[lfnstIdx]);
}
if (bestMipIdx >= 0)
{
if (uiRdModeList.size() <= bestMipIdx)
{
uiRdModeList.push_back(bestMipMode);
}
}
if (saveDataForISP)
{
m_ispCandListHor.resize(std::min<size_t>(m_ispCandListHor.size(), maxSize));
}
if (maxSize == 0)
{
cs.dist = std::numeric_limits<Distortion>::max();
cs.interHad = 0;
#if JVET_V0130_INTRA_TMP
m_CABACEstimator->getCtx() = SubCtx( Ctx::TmpFlag, ctxStartTpmFlag );
m_CABACEstimator->getCtx() = SubCtx(Ctx::MipFlag, ctxStartMipFlag);
#if JVET_W0123_TIMD_FUSION
m_CABACEstimator->getCtx() = SubCtx( Ctx::TimdFlag, ctxStartTimdFlag );
#endif
#if JVET_AB0155_SGPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::SgpmFlag, ctxStartSgpmFlag);
m_CABACEstimator->getCtx() = SubCtx(Ctx::ISPMode, ctxStartIspMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMPMIdx, ctxStartMPMIdxFlag);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaPlanarFlag, ctxStartPlanarFlag);
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaMpmFlag, ctxStartIntraMode);
#if SECONDARY_MPM
m_CABACEstimator->getCtx() = SubCtx(Ctx::IntraLumaSecondMpmFlag, ctxStartIntraMode2);
#endif
m_CABACEstimator->getCtx() = SubCtx(Ctx::MultiRefLineIdx, ctxStartMrlIdx);
#if JVET_AB0157_TMRL
m_CABACEstimator->getCtx() = SubCtx(Ctx::TmrlDerive, ctxStartTmrlDerive);
#endif

Karsten Suehring
committed
}
}
#if JVET_Y0142_ADAPT_INTRA_MTS
if (sps.getUseLFNST() && m_modesForMTS.size() == 0 && cu.mtsFlag)
{
return false;
}
#endif
int numNonISPModes = (int)uiRdModeList.size();
#if JVET_W0123_TIMD_FUSION
bool isTimdValid = cu.slice->getSPS()->getUseTimd();
if (cu.lwidth() * cu.lheight() > 1024 && cu.slice->getSliceType() == I_SLICE)
{
isTimdValid = false;
}
if (isTimdValid)
{
cu.timd = false;
uiRdModeList.push_back( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, TIMD_IDX ) );
numNonISPModes++;
if (lfnstIdx == 0 && !cu.mtsFlag)
{
bool isFirstLineOfCtu = (((pu.block(COMPONENT_Y).y) & ((pu.cs->sps)->getMaxCUWidth() - 1)) == 0);
1858
1859
1860
1861
1862
1863
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
#if JVET_Y0116_EXTENDED_MRL_LIST
int numOfPassesExtendRef = 3;
if (!sps.getUseMRL() || isFirstLineOfCtu)
{
numOfPassesExtendRef = 1;
}
else
{
bool checkLineOutsideCtu[2];
for (int mrlIdx = 1; mrlIdx < 3; mrlIdx++)
{
bool isLineOutsideCtu =
((cu.block(COMPONENT_Y).y) % ((cu.cs->sps)->getMaxCUWidth()) <= MULTI_REF_LINE_IDX[mrlIdx]) ? true
: false;
checkLineOutsideCtu[mrlIdx-1] = isLineOutsideCtu;
}
if (checkLineOutsideCtu[0])
{
numOfPassesExtendRef = 1;
}
else
{
if (checkLineOutsideCtu[1] && !checkLineOutsideCtu[0])
{
numOfPassesExtendRef = 2;
}
}
}
#else
int numOfPassesExtendRef = ((!sps.getUseMRL() || isFirstLineOfCtu) ? 1 : MRL_NUM_REF_LINES);
#endif
for (int mRefNum = 1; mRefNum < numOfPassesExtendRef; mRefNum++)
{
int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
uiRdModeList.push_back( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, TIMD_IDX ) );
numNonISPModes++;
}
}
}
#endif
Santiago de Luxán Hernández
committed
if ( testISP )
Santiago de Luxán Hernández
committed
{
// we reserve positions for ISP in the common full RD list
const int maxNumRDModesISP = sps.getUseLFNST() ? 16 * NUM_LFNST_NUM_PER_SET : 16;
m_curIspLfnstIdx = 0;
for (int i = 0; i < maxNumRDModesISP; i++)
uiRdModeList.push_back( ModeInfo( false, false, 0, INTRA_SUBPARTITIONS_RESERVED, 0 ) );
Santiago de Luxán Hernández
committed
}
if (isTimdValid && sps.getUseISP() && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize()) && lfnstIdx == 0 && !cu.mtsFlag)
{
uiRdModeList.push_back( ModeInfo( false, false, 0, HOR_INTRA_SUBPARTITIONS, TIMD_IDX ) );
uiRdModeList.push_back( ModeInfo( false, false, 0, VER_INTRA_SUBPARTITIONS, TIMD_IDX ) );
}
#endif

Karsten Suehring
committed
//===== check modes (using r-d costs) =====
ModeInfo uiBestPUMode;
int bestBDPCMMode = 0;
double bestCostNonBDPCM = MAX_DOUBLE;
#if INTRA_TRANS_ENC_OPT
double bestISPCostTested = MAX_DOUBLE;
ISPType bestISPModeTested = NOT_INTRA_SUBPARTITIONS;
#endif

Karsten Suehring
committed
CodingStructure *csTemp = m_pTempCS[gp_sizeIdxInfo->idxFrom( cu.lwidth() )][gp_sizeIdxInfo->idxFrom( cu.lheight() )];
CodingStructure *csBest = m_pBestCS[gp_sizeIdxInfo->idxFrom( cu.lwidth() )][gp_sizeIdxInfo->idxFrom( cu.lheight() )];
csTemp->slice = cs.slice;
csBest->slice = cs.slice;
csTemp->initStructData();
csBest->initStructData();
csTemp->picture = cs.picture;
csBest->picture = cs.picture;

Karsten Suehring
committed
// just to be sure
numModesForFullRD = ( int ) uiRdModeList.size();
TUIntraSubPartitioner subTuPartitioner( partitioner );
if ( testISP )
{
m_modeCtrl->setIspCost( MAX_DOUBLE );
m_modeCtrl->setMtsFirstPassNoIspCost( MAX_DOUBLE );
}
int bestLfnstIdx = cu.lfnstIdx;
for (int mode = isSecondColorSpace ? 0 : -2 * int(testBDPCM); mode < (int)uiRdModeList.size(); mode++)
{
// set CU/PU to luma prediction mode
ModeInfo uiOrgMode;
if (sps.getUseColorTrans() && !m_pcEncCfg->getRGBFormatFlag() && isSecondColorSpace && mode)
{
continue;
}
if (mode < 0 || (isSecondColorSpace && m_savedBDPCMModeFirstColorSpace[m_savedRdModeIdx][mode]))
cu.bdpcmMode = mode < 0 ? -mode : m_savedBDPCMModeFirstColorSpace[m_savedRdModeIdx][mode];
uiOrgMode = ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, cu.bdpcmMode == 2 ? VER_IDX : HOR_IDX );
}
else
{
cu.bdpcmMode = 0;
uiOrgMode = uiRdModeList[mode];
}
if (!cu.bdpcmMode && uiRdModeList[mode].ispMod == INTRA_SUBPARTITIONS_RESERVED)
{
if (mode == numNonISPModes) // the list needs to be sorted only once
#if JVET_W0123_TIMD_FUSION
if (bestTimdMode)
{
m_modeCtrl->setBestPredModeDCT2(MAP131TO67(uiBestPUMode.modeId));
}
else
{
m_modeCtrl->setBestPredModeDCT2(uiBestPUMode.modeId);
}
#else
m_modeCtrl->setBestPredModeDCT2(uiBestPUMode.modeId);
#if JVET_W0123_TIMD_FUSION
ModeInfo tempBestPUMode = uiBestPUMode;
if (bestTimdMode)
{
tempBestPUMode.modeId = MAP131TO67(tempBestPUMode.modeId);
}
if (!xSortISPCandList(bestCurrentCost, csBest->cost, tempBestPUMode))
#else
if (!xSortISPCandList(bestCurrentCost, csBest->cost, uiBestPUMode))
{
break;
}
}
xGetNextISPMode(uiRdModeList[mode], (mode > 0 ? &uiRdModeList[mode - 1] : nullptr), Size(width, height));
if (uiRdModeList[mode].ispMod == INTRA_SUBPARTITIONS_RESERVED)
{