Newer
Older
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM>* rdModeLists[2] = { &m_ispCandListHor, &m_ispCandListVer };
#if JVET_P1026_ISP_LFNST_COMBINATION
const int curIspLfnstIdx = m_curIspLfnstIdx;
if (curIspLfnstIdx >= NUM_LFNST_NUM_PER_SET)
{
//All lfnst indices have been checked
return;
}
#endif
#if JVET_P1026_ISP_LFNST_COMBINATION
auto& ispTestedModes = m_ispTestedModes[curIspLfnstIdx];
#else
auto& ispTestedModes = m_ispTestedModes;
const bool horSplitIsTerminated = ispTestedModes.splitIsFinished[HOR_INTRA_SUBPARTITIONS - 1];
const bool verSplitIsTerminated = ispTestedModes.splitIsFinished[VER_INTRA_SUBPARTITIONS - 1];
if (!horSplitIsTerminated && !verSplitIsTerminated)
{
nextISPcandSplitType = !lastMode ? HOR_INTRA_SUBPARTITIONS : lastMode->ispMod == HOR_INTRA_SUBPARTITIONS ? VER_INTRA_SUBPARTITIONS : HOR_INTRA_SUBPARTITIONS;
}
else if (!horSplitIsTerminated && verSplitIsTerminated)
{
nextISPcandSplitType = HOR_INTRA_SUBPARTITIONS;
}
else if (horSplitIsTerminated && !verSplitIsTerminated)
{
nextISPcandSplitType = VER_INTRA_SUBPARTITIONS;
}
else
{
#if JVET_P1026_ISP_LFNST_COMBINATION
xFinishISPModes();
#endif
return; // no more modes will be tested
}
int maxNumSubPartitions = ispTestedModes.numTotalParts[nextISPcandSplitType - 1];
6042
6043
6044
6045
6046
6047
6048
6049
6050
6051
6052
6053
6054
6055
6056
6057
6058
6059
6060
6061
6062
6063
6064
6065
6066
6067
6068
6069
6070
6071
6072
6073
6074
6075
#if JVET_P1026_ISP_LFNST_COMBINATION
// We try to break the split here for lfnst > 0 according to the first mode
if (curIspLfnstIdx > 0 && ispTestedModes.numTestedModes[nextISPcandSplitType - 1] == 1)
{
int firstModeThisSplit = ispTestedModes.getTestedIntraMode(nextISPcandSplitType, 0);
int numSubPartsFirstModeThisSplit = ispTestedModes.getNumCompletedSubParts(nextISPcandSplitType, firstModeThisSplit);
CHECK(numSubPartsFirstModeThisSplit < 0, "wrong number of subpartitions!");
bool stopThisSplit = false;
bool stopThisSplitAllLfnsts = false;
if (numSubPartsFirstModeThisSplit < maxNumSubPartitions)
{
stopThisSplit = true;
if (m_pcEncCfg->getUseFastISP() && curIspLfnstIdx == 1 && numSubPartsFirstModeThisSplit < maxNumSubPartitions - 1)
{
stopThisSplitAllLfnsts = true;
}
}
if (stopThisSplit)
{
ispTestedModes.splitIsFinished[nextISPcandSplitType - 1] = true;
if (curIspLfnstIdx == 1 && stopThisSplitAllLfnsts)
{
m_ispTestedModes[2].splitIsFinished[nextISPcandSplitType - 1] = true;
}
return;
}
}
#endif
#if JVET_P1026_ISP_LFNST_COMBINATION
// We try to break the split here for lfnst = 0 or all lfnst indices according to the first two modes
if (curIspLfnstIdx == 0 && ispTestedModes.numTestedModes[nextISPcandSplitType - 1] == 2)
#else
if (ispTestedModes.numTestedModes[nextISPcandSplitType - 1] >= 2)
{
// Split stop criteria after checking the performance of previously tested intra modes
const int thresholdSplit1 = maxNumSubPartitions;
bool stopThisSplit = false;
#if JVET_P1026_ISP_LFNST_COMBINATION
bool stopThisSplitForAllLFNSTs = false;
const int thresholdSplit1ForAllLFNSTs = maxNumSubPartitions - 1;
#endif
int mode1 = ispTestedModes.getTestedIntraMode((ISPType)nextISPcandSplitType, 0);
mode1 = mode1 == DC_IDX ? -1 : mode1;
int numSubPartsBestMode1 = mode1 != -1 ? ispTestedModes.getNumCompletedSubParts((ISPType)nextISPcandSplitType, mode1) : -1;
int mode2 = ispTestedModes.getTestedIntraMode((ISPType)nextISPcandSplitType, 1);
mode2 = mode2 == DC_IDX ? -1 : mode2;
int numSubPartsBestMode2 = mode2 != -1 ? ispTestedModes.getNumCompletedSubParts((ISPType)nextISPcandSplitType, mode2) : -1;
// 1) The 2 most promising modes do not reach a certain number of sub-partitions
if (numSubPartsBestMode1 != -1 && numSubPartsBestMode2 != -1)
{
if (numSubPartsBestMode1 < thresholdSplit1 && numSubPartsBestMode2 < thresholdSplit1)
{
stopThisSplit = true;
#if JVET_P1026_ISP_LFNST_COMBINATION
if (curIspLfnstIdx == 0 && numSubPartsBestMode1 < thresholdSplit1ForAllLFNSTs && numSubPartsBestMode2 < thresholdSplit1ForAllLFNSTs)
{
stopThisSplitForAllLFNSTs = true;
}
#endif
#if JVET_P1026_ISP_LFNST_COMBINATION
else
{
//we stop also if the cost is MAX_DOUBLE for both modes
double mode1Cost = ispTestedModes.getRDCost(nextISPcandSplitType, mode1);
double mode2Cost = ispTestedModes.getRDCost(nextISPcandSplitType, mode2);
if (!(mode1Cost < MAX_DOUBLE || mode2Cost < MAX_DOUBLE))
{
stopThisSplit = true;
}
}
#endif
if (!stopThisSplit)
// 2) One split type may be discarded by comparing the number of sub-partitions of the best angle modes of both splits
ISPType otherSplit = nextISPcandSplitType == HOR_INTRA_SUBPARTITIONS ? VER_INTRA_SUBPARTITIONS : HOR_INTRA_SUBPARTITIONS;
int numSubPartsBestMode2OtherSplit = mode2 != -1 ? ispTestedModes.getNumCompletedSubParts(otherSplit, mode2) : -1;
#if JVET_P1026_ISP_LFNST_COMBINATION
if (numSubPartsBestMode2OtherSplit != -1 && numSubPartsBestMode2 != -1 && ispTestedModes.bestSplitSoFar != nextISPcandSplitType)
#else
if (numSubPartsBestMode2OtherSplit != -1 && numSubPartsBestMode2 != -1)
if (numSubPartsBestMode2OtherSplit > numSubPartsBestMode2)
{
stopThisSplit = true;
}
#if JVET_P1026_ISP_LFNST_COMBINATION
// both have the same number of subpartitions
else if (numSubPartsBestMode2OtherSplit == numSubPartsBestMode2)
#else
else if (numSubPartsBestMode2OtherSplit == numSubPartsBestMode2 && numSubPartsBestMode2OtherSplit == maxNumSubPartitions)
{
#if JVET_P1026_ISP_LFNST_COMBINATION
// both have the maximum number of subpartitions, so it compares RD costs to decide
if (numSubPartsBestMode2OtherSplit == maxNumSubPartitions)
{
#endif
double rdCostBestMode2ThisSplit = ispTestedModes.getRDCost(nextISPcandSplitType, mode2);
double rdCostBestMode2OtherSplit = ispTestedModes.getRDCost(otherSplit, mode2);
double threshold = 1.3;
if (rdCostBestMode2ThisSplit == MAX_DOUBLE || rdCostBestMode2OtherSplit < rdCostBestMode2ThisSplit * threshold)
{
stopThisSplit = true;
}
#if JVET_P1026_ISP_LFNST_COMBINATION
}
else // none of them reached the maximum number of subpartitions with the best angle modes, so it compares the results with the the planar mode
{
int numSubPartsBestMode1OtherSplit = mode1 != -1 ? ispTestedModes.getNumCompletedSubParts(otherSplit, mode1) : -1;
if (numSubPartsBestMode1OtherSplit != -1 && numSubPartsBestMode1 != -1 && numSubPartsBestMode1OtherSplit > numSubPartsBestMode1)
{
stopThisSplit = true;
}
}
}
}
}
if (stopThisSplit)
{
ispTestedModes.splitIsFinished[nextISPcandSplitType - 1] = true;
#if JVET_P1026_ISP_LFNST_COMBINATION
if (stopThisSplitForAllLFNSTs)
{
for (int lfnstIdx = 1; lfnstIdx < NUM_LFNST_NUM_PER_SET; lfnstIdx++)
{
m_ispTestedModes[lfnstIdx].splitIsFinished[nextISPcandSplitType - 1] = true;
}
}
#endif
return;
}
}
// Now a new mode is retrieved from the list and it has to be decided whether it should be tested or not
if (ispTestedModes.candIndexInList[nextISPcandSplitType - 1] < rdModeLists[nextISPcandSplitType - 1]->size())
ModeInfo candidate = rdModeLists[nextISPcandSplitType - 1]->at(ispTestedModes.candIndexInList[nextISPcandSplitType - 1]);
ispTestedModes.candIndexInList[nextISPcandSplitType - 1]++;
// extra modes are only tested if ISP has won so far
if (ispTestedModes.candIndexInList[nextISPcandSplitType - 1] > ispTestedModes.numOrigModesToTest)
if (ispTestedModes.bestSplitSoFar != candidate.ispMod || ispTestedModes.bestModeSoFar == PLANAR_IDX)
#if JVET_P1026_ISP_LFNST_COMBINATION
ispTestedModes.splitIsFinished[nextISPcandSplitType - 1] = true;
#endif
return;
}
}
bool testCandidate = true;
// we look for a reference mode that has already been tested within the window and decide to test the new one according to the reference mode costs
#if JVET_P1026_ISP_LFNST_COMBINATION
if (maxNumSubPartitions > 2 && (curIspLfnstIdx > 0 || (candidate.modeId >= DC_IDX && ispTestedModes.numTestedModes[nextISPcandSplitType - 1] >= 2)))
#else
if (candidate.modeId >= DC_IDX && maxNumSubPartitions > 2 && ispTestedModes.numTestedModes[nextISPcandSplitType - 1] >= 2)
#if JVET_P1026_ISP_LFNST_COMBINATION
int refLfnstIdx = -1;
#endif
const int angWindowSize = 5;
int numSubPartsLeftMode, numSubPartsRightMode, numSubPartsRefMode, leftIntraMode = -1, rightIntraMode = -1;
int windowSize = candidate.modeId > DC_IDX ? angWindowSize : 1;
int numSamples = cuSize.width << floorLog2(cuSize.height);
int numSubPartsLimit = numSamples >= 256 ? maxNumSubPartitions - 1 : 2;
#if JVET_P1026_ISP_LFNST_COMBINATION
xFindAlreadyTestedNearbyIntraModes(curIspLfnstIdx, (int)candidate.modeId, &refLfnstIdx, &leftIntraMode, &rightIntraMode, (ISPType)candidate.ispMod, windowSize);
#else
xFindAlreadyTestedNearbyIntraModes((int)candidate.modeId, &leftIntraMode, &rightIntraMode, (ISPType)candidate.ispMod, windowSize);
#if JVET_P1026_ISP_LFNST_COMBINATION
if (refLfnstIdx != -1 && refLfnstIdx != curIspLfnstIdx)
{
CHECK(leftIntraMode != candidate.modeId || rightIntraMode != candidate.modeId, "wrong intra mode and lfnstIdx values!");
numSubPartsRefMode = m_ispTestedModes[refLfnstIdx].getNumCompletedSubParts((ISPType)candidate.ispMod, candidate.modeId);
CHECK(numSubPartsRefMode <= 0, "Wrong value of the number of subpartitions completed!");
}
else
{
#endif
numSubPartsLeftMode = leftIntraMode != -1 ? ispTestedModes.getNumCompletedSubParts((ISPType)candidate.ispMod, leftIntraMode) : -1;
numSubPartsRightMode = rightIntraMode != -1 ? ispTestedModes.getNumCompletedSubParts((ISPType)candidate.ispMod, rightIntraMode) : -1;
numSubPartsRefMode = std::max(numSubPartsLeftMode, numSubPartsRightMode);
#if JVET_P1026_ISP_LFNST_COMBINATION
}
#endif
if (numSubPartsRefMode > 0)
{
// The mode was found. Now we check the condition
testCandidate = numSubPartsRefMode > numSubPartsLimit;
}
}
if (testCandidate)
{
modeInfo = candidate;
}
}
#if JVET_P1026_ISP_LFNST_COMBINATION
else
{
//the end of the list was reached, so the split is invalidated
ispTestedModes.splitIsFinished[nextISPcandSplitType - 1] = true;
}
#endif
#if JVET_P1026_ISP_LFNST_COMBINATION
void IntraSearch::xFindAlreadyTestedNearbyIntraModes(int lfnstIdx, int currentIntraMode, int* refLfnstIdx, int* leftIntraMode, int* rightIntraMode, ISPType ispOption, int windowSize)
#else
void IntraSearch::xFindAlreadyTestedNearbyIntraModes(int currentIntraMode, int* leftIntraMode, int* rightIntraMode, ISPType ispOption, int windowSize)
{
bool leftModeFound = false, rightModeFound = false;
*leftIntraMode = -1;
*rightIntraMode = -1;
#if JVET_P1026_ISP_LFNST_COMBINATION
*refLfnstIdx = -1;
#endif
const unsigned st = ispOption - 1;
6280
6281
6282
6283
6284
6285
6286
6287
6288
6289
6290
6291
6292
6293
6294
6295
6296
6297
6298
6299
6300
6301
6302
6303
6304
6305
#if JVET_P1026_ISP_LFNST_COMBINATION
//first we check if the exact intra mode was already tested for another lfnstIdx value
if (lfnstIdx > 0)
{
bool sameIntraModeFound = false;
if (lfnstIdx == 2 && m_ispTestedModes[1].modeHasBeenTested[currentIntraMode][st])
{
sameIntraModeFound = true;
*refLfnstIdx = 1;
}
else if (m_ispTestedModes[0].modeHasBeenTested[currentIntraMode][st])
{
sameIntraModeFound = true;
*refLfnstIdx = 0;
}
if (sameIntraModeFound)
{
*leftIntraMode = currentIntraMode;
*rightIntraMode = currentIntraMode;
return;
}
}
//The mode has not been checked for another lfnstIdx value, so now we look for a similar mode within a window using the same lfnstIdx
#endif
for (int k = 1; k <= windowSize; k++)
{
int off = currentIntraMode - 2 - k;
int leftMode = (off < 0) ? NUM_LUMA_MODE + off : currentIntraMode - k;
int rightMode = currentIntraMode > DC_IDX ? (((int)currentIntraMode - 2 + k) % 65) + 2 : PLANAR_IDX;
#if JVET_P1026_ISP_LFNST_COMBINATION
leftModeFound = leftMode != (int)currentIntraMode ? m_ispTestedModes[lfnstIdx].modeHasBeenTested[leftMode][st] : false;
rightModeFound = rightMode != (int)currentIntraMode ? m_ispTestedModes[lfnstIdx].modeHasBeenTested[rightMode][st] : false;
#else
leftModeFound = leftMode != (int)currentIntraMode ? m_ispTestedModes.modeHasBeenTested[leftMode][st] : false;
rightModeFound = rightMode != (int)currentIntraMode ? m_ispTestedModes.modeHasBeenTested[rightMode][st] : false;
if (leftModeFound || rightModeFound)
{
*leftIntraMode = leftModeFound ? leftMode : -1;
*rightIntraMode = rightModeFound ? rightMode : -1;
#if JVET_P1026_ISP_LFNST_COMBINATION
*refLfnstIdx = lfnstIdx;
#endif
break;
}
}
}
#if JVET_P1026_ISP_LFNST_COMBINATION
//It prepares the list of potential intra modes candidates that will be tested using RD costs
bool IntraSearch::xSortISPCandList(double bestCostSoFar, double bestNonISPCost, ModeInfo bestNonISPMode)
#else
void IntraSearch::xSortISPCandList(double bestCostSoFar, double bestNonISPCost)
6338
6339
6340
6341
6342
6343
6344
6345
6346
6347
6348
6349
6350
6351
6352
6353
6354
6355
6356
6357
6358
6359
6360
6361
6362
#if JVET_P1026_ISP_LFNST_COMBINATION
int bestISPModeInRelCU = -1;
m_modeCtrl->setStopNonDCT2Transforms(false);
if (m_pcEncCfg->getUseFastISP())
{
//we check if the ISP tests can be cancelled
double thSkipISP = 1.4;
if (bestNonISPCost > bestCostSoFar * thSkipISP)
{
for (int splitIdx = 0; splitIdx < NUM_INTRA_SUBPARTITIONS_MODES - 1; splitIdx++)
{
for (int j = 0; j < NUM_LFNST_NUM_PER_SET; j++)
{
m_ispTestedModes[j].splitIsFinished[splitIdx] = true;
}
}
return false;
}
if (!updateISPStatusFromRelCU(bestNonISPCost, bestNonISPMode, bestISPModeInRelCU))
{
return false;
}
}
#else
if (m_pcEncCfg->getUseFastISP())
{
double thSkipISP = 1.4;
if (bestNonISPCost > bestCostSoFar * thSkipISP)
{
for (int splitIdx = 0; splitIdx < NUM_INTRA_SUBPARTITIONS_MODES - 1; splitIdx++)
{
m_ispTestedModes.splitIsFinished[splitIdx] = true;
}
6376
6377
6378
6379
6380
6381
6382
6383
6384
6385
6386
6387
6388
6389
6390
6391
6392
6393
6394
6395
6396
6397
6398
6399
6400
6401
6402
6403
6404
6405
6406
for (int k = 0; k < m_ispCandListHor.size(); k++)
{
m_ispCandListHor.at(k).ispMod = HOR_INTRA_SUBPARTITIONS; //we set the correct ISP split type value
}
auto origHadList = m_ispCandListHor; // save the original hadamard list of regular intra
bool modeIsInList[NUM_LUMA_MODE] = { false };
m_ispCandListHor.clear();
m_ispCandListVer.clear();
// we sort the normal intra modes according to their full RD costs
std::sort(m_regIntraRDListWithCosts.begin(), m_regIntraRDListWithCosts.end(), ModeInfoWithCost::compareModeInfoWithCost);
// we get the best angle from the regular intra list
int bestNormalIntraAngle = -1;
for (int modeIdx = 0; modeIdx < m_regIntraRDListWithCosts.size(); modeIdx++)
{
if (bestNormalIntraAngle == -1 && m_regIntraRDListWithCosts.at(modeIdx).modeId > DC_IDX)
{
bestNormalIntraAngle = m_regIntraRDListWithCosts.at(modeIdx).modeId;
break;
}
}
int mode1 = PLANAR_IDX;
int mode2 = bestNormalIntraAngle;
ModeInfo refMode = origHadList.at(0);
auto* destListPtr = &m_ispCandListHor;
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434
6435
6436
6437
6438
6439
6440
6441
6442
6443
6444
6445
6446
6447
6448
6449
6450
6451
6452
6453
6454
6455
6456
6457
6458
6459
6460
6461
6462
6463
6464
6465
6466
6467
6468
6469
6470
6471
6472
6473
6474
6475
6476
6477
6478
6479
#if JVET_P1026_ISP_LFNST_COMBINATION
//List creation
if (m_pcEncCfg->getUseFastISP() && bestISPModeInRelCU != -1) //RelCU intra mode
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, bestISPModeInRelCU));
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, bestISPModeInRelCU));
#endif
modeIsInList[bestISPModeInRelCU] = true;
}
// Planar
if (!modeIsInList[mode1])
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode1));
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, mode1));
#endif
modeIsInList[mode1] = true;
}
// Best angle in regular intra
if (mode2 != -1 && !modeIsInList[mode2])
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode2));
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, mode2));
#endif
modeIsInList[mode2] = true;
}
// Remaining regular intra modes that were full RD tested (except DC, which is added after the angles from regular intra)
int dcModeIndex = -1;
for (int remModeIdx = 0; remModeIdx < m_regIntraRDListWithCosts.size(); remModeIdx++)
{
int currentMode = m_regIntraRDListWithCosts.at(remModeIdx).modeId;
if (currentMode != mode1 && currentMode != mode2 && !modeIsInList[currentMode])
{
if (currentMode > DC_IDX)
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, currentMode));
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, currentMode));
#endif
modeIsInList[currentMode] = true;
}
else if (currentMode == DC_IDX)
{
dcModeIndex = remModeIdx;
}
}
}
// DC is added after the angles from regular intra
if (dcModeIndex != -1 && !modeIsInList[DC_IDX])
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, DC_IDX));
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, DC_IDX));
#endif
modeIsInList[DC_IDX] = true;
}
// We add extra candidates to the list that will only be tested if ISP is likely to win
for (int j = 0; j < NUM_LFNST_NUM_PER_SET; j++)
{
m_ispTestedModes[j].numOrigModesToTest = (int)destListPtr->size();
}
#else
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back( ModeInfo( refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode1 ) );
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, mode1));
modeIsInList[mode1] = true;
// 2) Best angle in regular intra
if (mode2 != -1)
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back( ModeInfo( refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode2 ) );
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, mode2));
modeIsInList[mode2] = true;
}
// 3) Remaining regular intra modes that were full RD tested (except DC, which is added after the angles from regular intra)
int dcModeIndex = -1;
for (int remModeIdx = 0; remModeIdx < m_regIntraRDListWithCosts.size(); remModeIdx++)
{
int currentMode = m_regIntraRDListWithCosts.at(remModeIdx).modeId;
if (currentMode != mode1 && currentMode != mode2)
{
if (currentMode > DC_IDX)
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back( ModeInfo( refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, currentMode ) );
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, currentMode));
modeIsInList[currentMode] = true;
}
else if (currentMode == DC_IDX)
{
dcModeIndex = remModeIdx;
}
}
}
// 4) DC is added after the angles from regular intra
if (dcModeIndex != -1)
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back( ModeInfo( refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, DC_IDX ) );
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, DC_IDX));
modeIsInList[DC_IDX] = true;
}
// 5) We add extra candidates to the list that will only be tested if ISP is likely to win
m_ispTestedModes.numOrigModesToTest = (int)destListPtr->size();
const int addedModesFromHadList = 3;
int newModesAdded = 0;
for (int k = 0; k < origHadList.size(); k++)
{
if (newModesAdded == addedModesFromHadList)
{
break;
}
if (!modeIsInList[origHadList.at(k).modeId])
{
#if JVET_P0803_COMBINED_MIP_CLEANUP
destListPtr->push_back( ModeInfo( refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, origHadList.at(k).modeId ) );
#else
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mRefId, refMode.ispMod, origHadList.at(k).modeId));
newModesAdded++;
}
}
#if JVET_P1026_ISP_LFNST_COMBINATION
if (m_pcEncCfg->getUseFastISP() && bestISPModeInRelCU != -1)
{
destListPtr->resize(1);
}
#endif
// Copy modes to other split-type list
m_ispCandListVer = m_ispCandListHor;
for (int i = 0; i < m_ispCandListVer.size(); i++)
{
m_ispCandListVer[i].ispMod = VER_INTRA_SUBPARTITIONS;
}
// Reset the tested modes information to 0
#if JVET_P1026_ISP_LFNST_COMBINATION
for (int j = 0; j < NUM_LFNST_NUM_PER_SET; j++)
{
for (int i = 0; i < m_ispCandListHor.size(); i++)
{
m_ispTestedModes[j].clearISPModeInfo(m_ispCandListHor[i].modeId);
}
}
return true;
#else
for (int i = 0; i < m_ispCandListHor.size(); i++)
{
m_ispTestedModes.clearISPModeInfo(m_ispCandListHor[i].modeId);
}
6582
6583
6584
6585
6586
6587
6588
6589
6590
6591
6592
6593
6594
6595
6596
6597
6598
6599
6600
6601
6602
6603
6604
6605
6606
6607
6608
6609
6610
6611
6612
6613
6614
6615
6616
6617
6618
6619
6620
6621
6622
6623
6624
6625
6626
6627
6628
6629
6630
#endif
}
#if JVET_P1026_ISP_LFNST_COMBINATION
void IntraSearch::xSortISPCandListLFNST()
{
//It resorts the list of intra mode candidates for lfnstIdx > 0 by checking the RD costs for lfnstIdx = 0
ISPTestedModesInfo& ispTestedModesRef = m_ispTestedModes[0];
for (int splitIdx = 0; splitIdx < NUM_INTRA_SUBPARTITIONS_MODES - 1; splitIdx++)
{
ISPType ispMode = splitIdx ? VER_INTRA_SUBPARTITIONS : HOR_INTRA_SUBPARTITIONS;
if (!m_ispTestedModes[m_curIspLfnstIdx].splitIsFinished[splitIdx] && ispTestedModesRef.testedModes[splitIdx].size() > 1)
{
auto& candList = ispMode == HOR_INTRA_SUBPARTITIONS ? m_ispCandListHor : m_ispCandListVer;
int bestModeId = candList[1].modeId > DC_IDX ? candList[1].modeId : -1;
int bestSubParts = candList[1].modeId > DC_IDX ? ispTestedModesRef.getNumCompletedSubParts(ispMode, bestModeId) : -1;
double bestCost = candList[1].modeId > DC_IDX ? ispTestedModesRef.getRDCost(ispMode, bestModeId) : MAX_DOUBLE;
for (int i = 0; i < candList.size(); i++)
{
const int candSubParts = ispTestedModesRef.getNumCompletedSubParts(ispMode, candList[i].modeId);
const double candCost = ispTestedModesRef.getRDCost(ispMode, candList[i].modeId);
if (candSubParts > bestSubParts || candCost < bestCost)
{
bestModeId = candList[i].modeId;
bestCost = candCost;
bestSubParts = candSubParts;
}
}
if (bestModeId != -1)
{
if (bestModeId != candList[0].modeId)
{
auto prevMode = candList[0];
candList[0].modeId = bestModeId;
for (int i = 1; i < candList.size(); i++)
{
auto nextMode = candList[i];
candList[i] = prevMode;
if (nextMode.modeId == bestModeId)
{
break;
}
prevMode = nextMode;
}
}
}
}
}
6633
6634
6635
6636
6637
6638
6639
6640
6641
6642
6643
6644
6645
6646
6647
6648
6649
6650
6651
6652
6653
6654
6655
6656
6657
6658
6659
6660
6661
6662
6663
6664
6665
6666
6667
6668
6669
6670
6671
6672
6673
6674
6675
6676
6677
6678
6679
6680
6681
6682
6683
6684
6685
6686
6687
6688
6689
6690
6691
6692
6693
6694
6695
6696
6697
6698
6699
6700
6701
6702
6703
6704
6705
6706
6707
6708
6709
6710
6711
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
bool IntraSearch::updateISPStatusFromRelCU( double bestNonISPCostCurrCu, ModeInfo bestNonISPModeCurrCu, int& bestISPModeInRelCU )
{
//It compares the data of a related CU with the current CU to cancel or reduce the ISP tests
bestISPModeInRelCU = -1;
if (m_modeCtrl->getRelatedCuIsValid())
{
double bestNonISPCostRelCU = m_modeCtrl->getBestDCT2NonISPCostRelCU();
double costRatio = bestNonISPCostCurrCu / bestNonISPCostRelCU;
bool bestModeRelCuIsMip = (m_modeCtrl->getIspPredModeValRelCU() >> 5) & 0x1;
bool bestModeCurrCuIsMip = bestNonISPModeCurrCu.mipFlg;
int relatedCuIntraMode = m_modeCtrl->getIspPredModeValRelCU() >> 9;
bool isSameTypeOfMode = (bestModeRelCuIsMip && bestModeCurrCuIsMip) || (!bestModeRelCuIsMip && !bestModeCurrCuIsMip);
bool bothModesAreAngular = bestNonISPModeCurrCu.modeId > DC_IDX && relatedCuIntraMode > DC_IDX;
bool modesAreComparable = isSameTypeOfMode && (bestModeCurrCuIsMip || bestNonISPModeCurrCu.modeId == relatedCuIntraMode || (bothModesAreAngular && abs(relatedCuIntraMode - (int)bestNonISPModeCurrCu.modeId) <= 5));
int status = m_modeCtrl->getIspPredModeValRelCU();
if ((status & 0x3) == 0x3) //ISP was not selected in the relCU
{
double bestNonDCT2Cost = m_modeCtrl->getBestNonDCT2Cost();
double ratioWithNonDCT2 = bestNonDCT2Cost / bestNonISPCostRelCU;
double margin = ratioWithNonDCT2 < 0.95 ? 0.2 : 0.1;
if (costRatio > 1 - margin && costRatio < 1 + margin && modesAreComparable)
{
for (int lfnstVal = 0; lfnstVal < NUM_LFNST_NUM_PER_SET; lfnstVal++)
{
m_ispTestedModes[lfnstVal].splitIsFinished[HOR_INTRA_SUBPARTITIONS - 1] = true;
m_ispTestedModes[lfnstVal].splitIsFinished[VER_INTRA_SUBPARTITIONS - 1] = true;
}
return false;
}
}
else if ((status & 0x3) == 0x1) //ISP was selected in the relCU
{
double margin = 0.05;
if (costRatio > 1 - margin && costRatio < 1 + margin && modesAreComparable)
{
int ispSplitIdx = (m_modeCtrl->getIspPredModeValRelCU() >> 2) & 0x1;
bool lfnstIdxIsNot0 = (bool)((m_modeCtrl->getIspPredModeValRelCU() >> 3) & 0x1);
bool lfnstIdxIs2 = (bool)((m_modeCtrl->getIspPredModeValRelCU() >> 4) & 0x1);
int lfnstIdx = !lfnstIdxIsNot0 ? 0 : lfnstIdxIs2 ? 2 : 1;
bestISPModeInRelCU = (int)m_modeCtrl->getBestISPIntraModeRelCU();
for (int splitIdx = 0; splitIdx < NUM_INTRA_SUBPARTITIONS_MODES - 1; splitIdx++)
{
for (int lfnstVal = 0; lfnstVal < NUM_LFNST_NUM_PER_SET; lfnstVal++)
{
if (lfnstVal == lfnstIdx && splitIdx == ispSplitIdx)
{
continue;
}
m_ispTestedModes[lfnstVal].splitIsFinished[splitIdx] = true;
}
}
bool stopNonDCT2Transforms = (bool)((m_modeCtrl->getIspPredModeValRelCU() >> 6) & 0x1);
m_modeCtrl->setStopNonDCT2Transforms(stopNonDCT2Transforms);
}
}
else
{
THROW("Wrong ISP relCU status");
}
}
return true;
}
void IntraSearch::xFinishISPModes()
{
//Continue to the next lfnst index
m_curIspLfnstIdx++;
if (m_curIspLfnstIdx < NUM_LFNST_NUM_PER_SET)
{
//Check if LFNST is applicable
if (m_curIspLfnstIdx == 1)
{
bool canTestLFNST = false;
for (int lfnstIdx = 1; lfnstIdx < NUM_LFNST_NUM_PER_SET; lfnstIdx++)
{
canTestLFNST |= !m_ispTestedModes[lfnstIdx].splitIsFinished[HOR_INTRA_SUBPARTITIONS - 1] || !m_ispTestedModes[lfnstIdx].splitIsFinished[VER_INTRA_SUBPARTITIONS - 1];
}
if (canTestLFNST)
{
//Construct the intra modes candidates list for the lfnst > 0 cases
xSortISPCandListLFNST();
}
}
}
}
#endif