Newer
Older
15004
15005
15006
15007
15008
15009
15010
15011
15012
15013
15014
15015
15016
15017
15018
15019
15020
15021
15022
15023
15024
15025
15026
const int modeListSize = int(tempRdModeList.size());
for (int idx = 0; idx < 2; idx++)
{
const uint8_t dirPlanarListIdx = sortedDirPlanarModes[idx];
const ModeInfo dirPlanarMode(false, false, 0, NOT_INTRA_SUBPARTITIONS,
dirPlanarListIdx == 0 ? PL_HOR_IDX : PL_VER_IDX);
bool alreadyIncluded = false;
for (int modeListIdx = 0; modeListIdx < modeListSize; modeListIdx++)
{
if (tempRdModeList[modeListIdx] == dirPlanarMode)
{
alreadyIncluded = true;
break;
}
}
if (!alreadyIncluded)
{
const auto numRd = tempRdModeList.size() + 1;
updateCandList(dirPlanarMode, sortedDirPlanarCost[idx], tempRdModeList, tempCandCostList, numRd);
break;
}
}
Thierry Dumas
committed
#if JVET_AJ0249_NEURAL_NETWORK_BASED
}
#endif
15032
15033
15034
15035
15036
15037
15038
15039
15040
15041
15042
15043
15044
15045
15046
15047
15048
15049
15050
15051
15052
15053
15054
15055
15056
15057
15058
15059
15060
15061
15062
15063
15064
15065
15066
15067
15068
15069
15070
15071
15072
15073
15074
15075
15076
15077
15078
15079
15080
15081
15082
15083
15084
15085
15086
15087
15088
15089
15090
15091
15092
15093
15094
15095
15096
15097
15098
15099
15100
15101
15102
15103
15104
15105
15106
15107
15108
15109
15110
15111
15112
15113
15114
15115
15116
15117
15118
15119
15120
15121
15122
15123
15124
15125
15126
15127
15128
15129
15130
15131
15132
15133
15134
15135
15136
15137
15138
15139
15140
15141
15142
15143
15144
15145
15146
15147
15148
15149
15150
15151
15152
15153
15154
15155
15156
15157
15158
15159
15160
15161
15162
15163
15164
15165
15166
15167
15168
#if JVET_AJ0061_TIMD_MERGE
numModesForFullRD = int(tempRdModeList.size());
CHECK(numModesForFullRD > (int) allModes.size(), "something went wrong");
tempRdModeList.clear();
tempCandCostList.clear();
ModeInfo mode;
double cost, bestCost = MAX_DOUBLE;
bool earlyExist = false;
for (int idx = 0; idx < numModesForFullRD && !earlyExist; idx++)
{
mode = allModes[idx];
cost = allCosts[idx];
updateCandList(mode, cost, tempRdModeList, tempCandCostList, numModesForFullRD);
if (cost < bestCost)
{
bestCost = cost;
}
}
bool testDimd = !m_skipDimdMode && m_satdCostDIMD != MAX_UINT64;
bool testObic = !m_skipObicMode && m_satdCostOBIC != MAX_UINT64;
bool testTimd = !m_skipTimdMode[Timd] && m_satdCostTIMD[Timd][0] != MAX_UINT64;
bool testTimdMerge = !m_skipTimdMode[TimdMrg] && m_satdCostTIMD[TimdMrg][0] != MAX_UINT64;
bool testTimdMrl1 = !m_skipTimdMode[TimdMrl1] && m_satdCostTIMD[TimdMrl1][0] != MAX_UINT64;
bool testTimdMrl3 = !m_skipTimdMode[TimdMrl3] && m_satdCostTIMD[TimdMrl3][0] != MAX_UINT64;
const double timdDimdCostMult = 1.3;
const double angCostMult = 2.0;
const double multMrl = 1.0;
const double bestAngCost = numModesForFullRD ? tempCandCostList[0] : MAX_DOUBLE;
int numTotalRD = !m_skipObicMode + !m_skipDimdMode + !m_skipTimdMode[Timd] + !m_skipTimdMode[TimdMrg];
if (bestAngCost != MAX_DOUBLE)
{
if (testTimdMerge && bestAngCost * angCostMult < m_satdCostTIMD[TimdMrg][0])
{
m_skipTimdMrgLfnstMtsPass = true;
}
if (testTimd && bestAngCost * angCostMult < m_satdCostTIMD[Timd][0])
{
m_skipTimdLfnstMtsPass = true;
}
}
if ((testObic && testTimd && timdDimdCostMult * m_satdCostTIMD[Timd][0] < m_satdCostOBIC) ||
(testObic && testTimdMerge && timdDimdCostMult * m_satdCostTIMD[TimdMrg][0] < m_satdCostOBIC) )
{
m_skipObicMode = true;
testObic = false;
}
if ((testDimd && testTimd && timdDimdCostMult * m_satdCostTIMD[Timd][0] < m_satdCostDIMD) ||
(testDimd && testTimdMerge && timdDimdCostMult * m_satdCostTIMD[TimdMrg][0] < m_satdCostDIMD) )
{
m_skipDimdMode = true;
testDimd = false;
}
if (testTimdMerge &&
( (testDimd && timdDimdCostMult * m_satdCostDIMD < m_satdCostTIMD[TimdMrg][1]) ||
(testObic && timdDimdCostMult * m_satdCostOBIC < m_satdCostTIMD[TimdMrg][1]) ))
{
m_skipTimdMode[TimdMrg] = true;
testTimdMerge = false;
}
if (testTimd &&
( (testDimd && timdDimdCostMult * m_satdCostDIMD < m_satdCostTIMD[Timd][1]) ||
(testObic && timdDimdCostMult * m_satdCostOBIC < m_satdCostTIMD[Timd][1])))
{
m_skipTimdMode[Timd] = true;
testTimd = false;
}
if (testDimd && testObic)
{
if (!m_skipObicMode && timdDimdCostMult * m_satdCostDIMD < m_satdCostOBIC)
{
m_skipObicMode = true;
testObic = false;
}
if (!m_skipDimdMode && timdDimdCostMult * m_satdCostOBIC < m_satdCostDIMD)
{
m_skipDimdMode = true;
testDimd = false;
}
}
if (testTimdMrl1 &&
((testDimd && timdDimdCostMult * m_satdCostDIMD < m_satdCostTIMD[TimdMrl1][1]) ||
(testObic && timdDimdCostMult * m_satdCostOBIC < m_satdCostTIMD[TimdMrl1][1]) ||
(testTimd && multMrl * m_satdCostTIMD[Timd][1] < m_satdCostTIMD[TimdMrl1][1]) ||
(testTimdMerge && multMrl * m_satdCostTIMD[TimdMrg][1] < m_satdCostTIMD[TimdMrl1][1])
))
{
m_skipTimdMode[TimdMrl1] = true;
testTimdMrl1 = false;
}
if (testTimdMrl3 &&
((testDimd && timdDimdCostMult * m_satdCostDIMD < m_satdCostTIMD[TimdMrl3][1]) ||
(testObic && timdDimdCostMult * m_satdCostOBIC < m_satdCostTIMD[TimdMrl3][1]) ||
(testTimd && multMrl * m_satdCostTIMD[Timd][1] < m_satdCostTIMD[TimdMrl3][1]) ||
(testTimdMerge && multMrl * m_satdCostTIMD[TimdMrg][1] < m_satdCostTIMD[TimdMrl3][1])
))
{
m_skipTimdMode[TimdMrl3] = true;
testTimdMrl3 = false;
}
int numTotalRD2 = !m_skipObicMode + !m_skipDimdMode + !m_skipTimdMode[Timd] + !m_skipTimdMode[TimdMrg]; // Don't involve TimdMrl in this
if (numModesForFullRD > 0 && numTotalRD == numTotalRD2 && numTotalRD > 2) // If nothing was decided to be skipped, conditionally pop-back the worse (only one)
{
const double dimdCostMul2 = 2.0;
if (testTimd && tempCandCostList[numModesForFullRD - 1] > timdDimdCostMult * m_satdCostTIMD[Timd][0])
{
tempRdModeList.pop_back();
tempCandCostList.pop_back();
numModesForFullRD--;
}
else if (testTimdMerge && tempCandCostList[numModesForFullRD - 1] > timdDimdCostMult * m_satdCostTIMD[TimdMrg][0])
{
tempRdModeList.pop_back();
tempCandCostList.pop_back();
numModesForFullRD--;
}
else if (testDimd && tempCandCostList[numModesForFullRD - 1] > dimdCostMul2 * m_satdCostDIMD)
{
tempRdModeList.pop_back();
tempCandCostList.pop_back();
numModesForFullRD--;
}
else if (testObic && tempCandCostList[numModesForFullRD - 1] > dimdCostMul2 * m_satdCostOBIC)
{
tempRdModeList.pop_back();
tempCandCostList.pop_back();
numModesForFullRD--;
}
}
CHECK(numModesForFullRD != (int)tempRdModeList.size(), "something went wrong");
candModeList = tempRdModeList;
candCostList = tempCandCostList;
#else
candModeList = tempRdModeList;
candCostList = tempCandCostList;
numModesForFullRD = int(candModeList.size());
// It decides which modes from the ISP lists can be full RD tested
void IntraSearch::xGetNextISPMode(ModeInfo& modeInfo, const ModeInfo* lastMode, const Size cuSize)
{
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM>* rdModeLists[2] = { &m_ispCandListHor, &m_ispCandListVer };
const int curIspLfnstIdx = m_curIspLfnstIdx;
if (curIspLfnstIdx >= NUM_LFNST_NUM_PER_SET)
{
//All lfnst indices have been checked
return;
}
auto& ispTestedModes = m_ispTestedModes[curIspLfnstIdx];
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
{
return; // no more modes will be tested
}
int maxNumSubPartitions = ispTestedModes.numTotalParts[nextISPcandSplitType - 1];
// We try to break the split here for lfnst > 0 according to the first mode
15212
15213
15214
15215
15216
15217
15218
15219
15220
15221
15222
15223
15224
15225
15226
15227
15228
15229
15230
15231
15232
15233
15234
15235
15236
15237
15238
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;
}
}
// 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)
{
// Split stop criteria after checking the performance of previously tested intra modes
const int thresholdSplit1 = maxNumSubPartitions;
bool stopThisSplit = false;
bool stopThisSplitForAllLFNSTs = false;
const int thresholdSplit1ForAllLFNSTs = maxNumSubPartitions - 1;
int mode1 = ispTestedModes.getTestedIntraMode((ISPType)nextISPcandSplitType, 0);
mode1 = ( mode1 == DC_IDX || mode1 == DIMD_IDX ) ? -1 : mode1;
#else
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 || mode2 == DIMD_IDX ) ? -1 : mode2;
#else
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 (curIspLfnstIdx == 0 && numSubPartsBestMode1 < thresholdSplit1ForAllLFNSTs && numSubPartsBestMode2 < thresholdSplit1ForAllLFNSTs)
{
stopThisSplitForAllLFNSTs = true;
}
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;
}
}
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 (numSubPartsBestMode2OtherSplit != -1 && numSubPartsBestMode2 != -1 && ispTestedModes.bestSplitSoFar != nextISPcandSplitType)
if (numSubPartsBestMode2OtherSplit > numSubPartsBestMode2)
{
stopThisSplit = true;
}
// both have the same number of subpartitions
else if (numSubPartsBestMode2OtherSplit == numSubPartsBestMode2)
{
// both have the maximum number of subpartitions, so it compares RD costs to decide
if (numSubPartsBestMode2OtherSplit == maxNumSubPartitions)
{
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;
}
}
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 (stopThisSplitForAllLFNSTs)
{
for (int lfnstIdx = 1; lfnstIdx < NUM_LFNST_NUM_PER_SET; lfnstIdx++)
{
m_ispTestedModes[lfnstIdx].splitIsFinished[nextISPcandSplitType - 1] = true;
}
}
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)
ispTestedModes.splitIsFinished[nextISPcandSplitType - 1] = true;
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
#endif
#if JVET_W0123_TIMD_FUSION
candidate.modeId != TIMD_IDX &&
#endif
#if JVET_AC0105_DIRECTIONAL_PLANAR
candidate.modeId != PL_HOR_IDX && candidate.modeId != PL_VER_IDX &&
#endif
maxNumSubPartitions > 2 && (curIspLfnstIdx > 0 || (candidate.modeId >= DC_IDX && ispTestedModes.numTestedModes[nextISPcandSplitType - 1] >= 2)))
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;
xFindAlreadyTestedNearbyIntraModes(curIspLfnstIdx, (int)candidate.modeId, &refLfnstIdx, &leftIntraMode, &rightIntraMode, (ISPType)candidate.ispMod, windowSize);
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
{
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 (numSubPartsRefMode > 0)
{
// The mode was found. Now we check the condition
testCandidate = numSubPartsRefMode > numSubPartsLimit;
}
}
if (testCandidate)
{
modeInfo = candidate;
}
}
else
{
//the end of the list was reached, so the split is invalidated
ispTestedModes.splitIsFinished[nextISPcandSplitType - 1] = true;
}
void IntraSearch::xFindAlreadyTestedNearbyIntraModes(int lfnstIdx, int currentIntraMode, int* refLfnstIdx, int* leftIntraMode, int* rightIntraMode, ISPType ispOption, int windowSize)
{
bool leftModeFound = false, rightModeFound = false;
*leftIntraMode = -1;
*rightIntraMode = -1;
const unsigned st = ispOption - 1;
//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[st].count(currentIntraMode) )
{
sameIntraModeFound = true;
*refLfnstIdx = 1;
}
else if (m_ispTestedModes[0].modeHasBeenTested[st].count(currentIntraMode) )
{
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
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;
leftModeFound = leftMode != (int)currentIntraMode ? m_ispTestedModes[lfnstIdx].modeHasBeenTested[st].count( leftMode ) > 0 : false;
rightModeFound = rightMode != (int)currentIntraMode ? m_ispTestedModes[lfnstIdx].modeHasBeenTested[st].count( rightMode ) > 0 : false;
if (leftModeFound || rightModeFound)
{
*leftIntraMode = leftModeFound ? leftMode : -1;
*rightIntraMode = rightModeFound ? rightMode : -1;
break;
}
}
}
//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)
15462
15463
15464
15465
15466
15467
15468
15469
15470
15471
15472
15473
15474
15475
15476
15477
15478
15479
15480
15481
15482
15483
15484
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;
}
}
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::stable_sort(m_regIntraRDListWithCosts.begin(), m_regIntraRDListWithCosts.end(), ModeInfoWithCost::compareModeInfoWithCost);
15499
15500
15501
15502
15503
15504
15505
15506
15507
15508
15509
15510
15511
15512
15513
15514
15515
// 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;
#if JVET_AG0058_EIP
bool isAeip = bestISPModeInRelCU >= EIP_IDX && bestISPModeInRelCU < (EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP));
if (m_pcEncCfg->getUseFastISP() && bestISPModeInRelCU != -1 && !isAeip) //RelCU intra mode
#else
if (m_pcEncCfg->getUseFastISP() && bestISPModeInRelCU != -1) //RelCU intra mode
#endif
destListPtr->push_back(
ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, bestISPModeInRelCU));
modeIsInList[bestISPModeInRelCU] = true;
}
// Planar
#if JVET_W0103_INTRA_MTS
// push planar later when FastISP is on.
if (!m_pcEncCfg->getUseFastISP() && !modeIsInList[mode1])
#else
{
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode1));
modeIsInList[mode1] = true;
}
15540
15541
15542
15543
15544
15545
15546
15547
15548
15549
15550
15551
15552
15553
15554
15555
15556
15557
15558
15559
15560
15561
15562
15563
// Best angle in regular intra
if (mode2 != -1 && !modeIsInList[mode2])
{
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode2));
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)
{
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, currentMode));
modeIsInList[currentMode] = true;
}
else if (currentMode == DC_IDX)
{
dcModeIndex = remModeIdx;
}
}
}
#if JVET_W0103_INTRA_MTS
// Planar (after angular modes when FastISP is on)
if (!modeIsInList[mode1])
{
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode1));
modeIsInList[mode1] = true;
}
#endif
// DC is added after the angles from regular intra
if (dcModeIndex != -1 && !modeIsInList[DC_IDX])
{
destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, DC_IDX));
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();
#if JVET_W0103_INTRA_MTS
if (m_pcEncCfg->getUseFastISP() && m_numModesISPRDO != -1 && destListPtr->size() > m_numModesISPRDO)
{
m_ispTestedModes[j].numOrigModesToTest = m_numModesISPRDO;
}
#endif
const int addedModesFromHadList = 3;
int newModesAdded = 0;
for (int k = 0; k < origHadList.size(); k++)
{
if (newModesAdded == addedModesFromHadList)
{
break;
}
#endif
#if JVET_W0123_TIMD_FUSION
origHadList.at(k).modeId == TIMD_IDX ||
#endif
#if JVET_AC0105_DIRECTIONAL_PLANAR
origHadList.at(k).modeId == PL_HOR_IDX || origHadList.at(k).modeId == PL_VER_IDX ||
destListPtr->push_back( ModeInfo( refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, origHadList.at(k).modeId ) );
newModesAdded++;
}
}
if (m_pcEncCfg->getUseFastISP() && bestISPModeInRelCU != -1)
{
destListPtr->resize(1);
}
// 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
15629
15630
15631
15632
15633
15634
15635
15636
15637
15638
15639
15640
15641
15642
15643
15644
15645
15646
15647
15648
15649
15650
15651
15652
15653
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;
}
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++)
{
if( candList[i].modeId == DIMD_IDX )
{
continue;
}
#endif
#if JVET_W0123_TIMD_FUSION
if( candList[i].modeId == TIMD_IDX )
{
continue;
}
#endif
#if JVET_AC0105_DIRECTIONAL_PLANAR
if (candList[i].modeId == PL_HOR_IDX || candList[i].modeId == PL_VER_IDX)
{
continue;
}
15672
15673
15674
15675
15676
15677
15678
15679
15680
15681
15682
15683
15684
15685
15686
15687
15688
15689
15690
15691
15692
15693
15694
15695
15696
15697
15698
15699
15700
15701
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;
}
}
}
}
}
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;
#if JVET_AG0058_EIP
bool bestModeRelCuIsAeip = (m_modeCtrl->getIspPredModeValRelCU() >> 8) & 0x1;
bool bestModeCurrCuIsAeip = (bestNonISPModeCurrCu.modeId >= EIP_IDX) && (bestNonISPModeCurrCu.modeId < EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP));
if (bestModeRelCuIsAeip)
{
relatedCuIntraMode += EIP_IDX;
}
bool isSameTypeOfMode = (bestModeRelCuIsMip && bestModeCurrCuIsMip) // Mip
|| (bestModeRelCuIsAeip && bestModeCurrCuIsAeip) // aeip
|| (!bestModeRelCuIsAeip && !bestModeCurrCuIsAeip && !bestModeRelCuIsMip && !bestModeCurrCuIsMip);
bool bothModesAreAngular = bestNonISPModeCurrCu.modeId > DC_IDX && relatedCuIntraMode > DC_IDX
&& bestNonISPModeCurrCu.modeId < EIP_IDX&& relatedCuIntraMode < EIP_IDX;
bool modesAreComparable = isSameTypeOfMode && (bestModeCurrCuIsMip || bestModeCurrCuIsAeip ||
bestNonISPModeCurrCu.modeId == relatedCuIntraMode || (bothModesAreAngular && abs(relatedCuIntraMode - (int)bestNonISPModeCurrCu.modeId) <= 5));
#else
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));
#endif
15734
15735
15736
15737
15738
15739
15740
15741
15742
15743
15744
15745
15746
15747
15748
15749
15750
15751
15752
15753
15754
15755
15756
15757
15758
15759
15760
15761
15762
15763
15764
15765
15766
15767
15768
15769
15770
15771
15772
15773
15774
15775
15776
15777
15778
15779
15780
15781
15782
15783
15784
15785
15786
15787
15788
15789
15790
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
15792
15793
15794
15795
15796
15797
15798
15799
15800
15801
15802
15803
15804
15805
15806
15807
15808
15809
15810
15811
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();
}
}
}
}
Fabrice URBAN
committed
15812
15813
15814
15815
15816
15817
15818
15819
15820
15821
15822
15823
15824
15825
15826
15827
15828
15829
15830
15831
15832
15833
15834
15835
15836
15837
15838
15839
15840
15841
15842
15843
15844
15845
15846
15847
15848
15849
15850
15851
15852
15853
15854
15855
15856
15857
15858
15859
15860
15861
15862
15863
15864
15865
15866
15867
15868
15869
15870
15871
15872
15873
15874
void IntraSearch::setLumaIntraPredIdx(PredictionUnit& pu)
{
#if SECONDARY_MPM
const int numMPMs = NUM_PRIMARY_MOST_PROBABLE_MODES + NUM_SECONDARY_MOST_PROBABLE_MODES;
#else
const int numMPMs = NUM_MOST_PROBABLE_MODES;
#endif
int pred_idx = numMPMs;
for (int idx = 0; idx < numMPMs; idx++)
{
if (pu.intraDir[0] == m_intraMPM[idx])
{
pred_idx = idx;
break;
}
}
#if SECONDARY_MPM
if (pred_idx < NUM_PRIMARY_MOST_PROBABLE_MODES)
{
pu.mpmFlag = true;
pu.secondMpmFlag = false;
}
else if (pred_idx < numMPMs)
{
pu.mpmFlag = false;
pu.secondMpmFlag = true;
}
else
{
pu.mpmFlag = false;
pu.secondMpmFlag = false;
pred_idx = NUM_NON_MPM_MODES;
for (int idx = 0; idx < NUM_NON_MPM_MODES; idx++)
{
if (pu.intraDir[0] == m_intraNonMPM[idx])
{
pred_idx = idx;
break;
}
}
}
#else
if (mpm_idx < NUM_MOST_PROBABLE_MODES)
{
pu.mpmFlag = true;
}
else
{
std::sort(mpmPred, mpmPred + numMPMs);
int pred_idx = pu.intraDir[0];
for (int idx = numMPMs - 1; idx >= 0; idx--)
{
if (pred_idx > mpmPred[idx])
{
pred_idx--;
}
}
CHECK(pred_idx >= 64, "Incorrect mode");
}
#endif
pu.ipredIdx = pred_idx;
}