Newer
Older
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];
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
#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);
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
#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
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");
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
#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 };
initIntraPatternChType(cu, pu.Y());
initIntraMip(pu, pu.Y());
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
);

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();
cu.tmpFlag = false;
pu.multiRefIdx = 0;
cu.mipFlag = false;
#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
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
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
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
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, 0, 1,
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, 0, 1,
sgpmInfoList[sgpmIdx].sgpmSplitDir, sgpmInfoList[sgpmIdx].sgpmMode0,
sgpmInfoList[sgpmIdx].sgpmMode1, sgpmIdx),
double(minSadHad), m_uiSavedHadModeListSGPM, m_dSavedHadListSGPM, SGPM_NUM);
}
cu.sgpm = false;
}
int updateNum = (numModesForFullRD + 1) / 2;
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)
{
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
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);
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775
1776
1777
1778
1779
1780
1781
1782
1783
1784
1785
1786
1787
1788
1789
#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)
{
continue;
cu.lfnstIdx = m_curIspLfnstIdx;
uiOrgMode = uiRdModeList[mode];
}
#if ENABLE_DIMD && INTRA_TRANS_ENC_OPT
if ((m_pcEncCfg->getIntraPeriod() == 1) && cu.slice->getSPS()->getUseDimd() && mode >= 0 && !cu.dimdBlending && uiOrgMode.ispMod == 0 && uiOrgMode.mRefId == 0 && uiOrgMode.modeId != TIMD_IDX && uiOrgMode.modeId != DIMD_IDX)
{
bool modeDuplicated = (uiOrgMode.modeId == cu.dimdMode);
if (modeDuplicated)
{
m_modeCostStore[lfnstIdx][mode] = MAX_DOUBLE / 2.0;
#if ENABLE_DIMD
cu.dimd = false;
if( mode >= 0 && uiOrgMode.modeId == DIMD_IDX ) /*to check*/
{
uiOrgMode.modeId = cu.dimdMode;
cu.dimd = true;
}
#if JVET_AB0155_SGPM
cu.sgpm = uiOrgMode.sgpmFlag;
if (cu.sgpm)
{
uiOrgMode.modeId = uiOrgMode.sgpmMode0;
cu.sgpmSplitDir = uiOrgMode.sgpmSplitDir;
cu.sgpmMode0 = uiOrgMode.sgpmMode0;
cu.sgpmMode1 = uiOrgMode.sgpmMode1;
cu.sgpmIdx = uiOrgMode.sgpmIdx;
pu.intraDir1[CHANNEL_TYPE_LUMA] = uiOrgMode.sgpmMode1;
}
#endif
#if JVET_V0130_INTRA_TMP
cu.tmpFlag = uiOrgMode.tmpFlag;
#if JVET_W0103_INTRA_MTS
if (cu.tmpFlag && cu.mtsFlag) continue;
#endif
cu.mipFlag = uiOrgMode.mipFlg;
pu.mipTransposedFlag = uiOrgMode.mipTrFlg;
cu.ispMode = uiOrgMode.ispMod;
pu.multiRefIdx = uiOrgMode.mRefId;
pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.modeId;
#if JVET_W0123_TIMD_FUSION
cu.timd = false;
if (mode >= 0 && uiOrgMode.modeId == TIMD_IDX)
{
if (cu.ispMode)
{
cu.lfnstIdx = lfnstIdx;
#if INTRA_TRANS_ENC_OPT
if ((m_pcEncCfg->getIntraPeriod() == 1) && ((bestISPModeTested == HOR_INTRA_SUBPARTITIONS) || (bestISPModeTested == VER_INTRA_SUBPARTITIONS)))
{
if (cu.ispMode != bestISPModeTested)
{
continue;
}
}
#endif
if (cu.ispMode == VER_INTRA_SUBPARTITIONS && uiBestPUMode.ispMod == 0 && !bestTimdMode)
{
continue;
}
}
#if INTRA_TRANS_ENC_OPT
else if (m_skipTimdLfnstMtsPass)
{
CHECK(!cu.lfnstIdx && !cu.mtsFlag, "invalid logic");
continue;
}
#endif
uiOrgMode.modeId = cu.timdMode;
pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.modeId;
cu.timd = true;
}
#endif
#if JVET_AB0157_TMRL
cu.tmrlFlag = false;
if (uiOrgMode.mRefId >= MAX_REF_LINE_IDX)
{
int tmrlListIdx = uiOrgMode.mRefId - MAX_REF_LINE_IDX;
cu.tmrlListIdx = tmrlListIdx;
pu.multiRefIdx = cu.tmrlList[tmrlListIdx].multiRefIdx;
pu.intraDir[0] = cu.tmrlList[tmrlListIdx].intraDir;
cu.tmrlFlag = true;
}
#endif
CHECK(cu.mipFlag && pu.multiRefIdx, "Error: combination of MIP and MRL not supported");
#if JVET_W0123_TIMD_FUSION
if (!cu.timd)
{
#endif