Newer
Older
16001
16002
16003
16004
16005
16006
16007
16008
16009
16010
16011
16012
16013
16014
16015
16016
16017
16018
16019
16020
16021
16022
16023
16024
16025
16026
16027
16028
16029
16030
16031
16032
16033
16034
16035
16036
16037
16038
16039
16040
16041
16042
16043
16044
16045
16046
16047
16048
16049
16050
16051
16052
16053
16054
16055
16056
16057
16058
16059
16060
16061
16062
16063
16064
16065
16066
16067
16068
16069
16070
16071
16072
16073
16074
16075
16076
16077
16078
16079
16080
16081
16082
16083
16084
16085
16086
16087
16088
16089
16090
16091
16092
16093
16094
16095
16096
16097
16098
16099
16100
16101
16102
16103
16104
16105
16106
16107
16108
16109
16110
16111
16112
16113
16114
16115
16116
16117
16118
16119
16120
16121
16122
16123
16124
16125
16126
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
#if AHG7_LN_TOOLOFF_CFG
void IntraSearch::xGetNextISPMode( ModeInfo& modeInfo, const ModeInfo* lastMode, const Size cuSize, bool lfnstExtFlag, bool nsptFlag )
#else
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
}
#if AHG7_LN_TOOLOFF_CFG
Size tuSize = ( nextISPcandSplitType == HOR_INTRA_SUBPARTITIONS ) ? Size( cuSize.width, CU::getISPSplitDim( cuSize.width, cuSize.height, TU_1D_HORZ_SPLIT ) ) :
Size( CU::getISPSplitDim( cuSize.width, cuSize.height, TU_1D_VERT_SPLIT ), cuSize.height );
int kerCandNum = ( lfnstExtFlag || ( nsptFlag && CU::isNSPTAllowed( tuSize.width, tuSize.height ) ) ) ? 3 : 2;
if( curIspLfnstIdx >= ( kerCandNum + 1 ) )
{
//All lfnst indices have been checked
return;
}
#endif
int maxNumSubPartitions = ispTestedModes.numTotalParts[nextISPcandSplitType - 1];
// We try to break the split here for lfnst > 0 according to the first mode
16185
16186
16187
16188
16189
16190
16191
16192
16193
16194
16195
16196
16197
16198
16199
16200
16201
16202
16203
16204
16205
16206
16207
16208
16209
16210
16211
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
Zheming Fan
committed
#if JVET_W0123_TIMD_FUSION && !JVET_AJ0079_DISABLE_TIMD_COMBINATION
#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)
16435
16436
16437
16438
16439
16440
16441
16442
16443
16444
16445
16446
16447
16448
16449
16450
16451
16452
16453
16454
16455
16456
16457
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);
16472
16473
16474
16475
16476
16477
16478
16479
16480
16481
16482
16483
16484
16485
16486
16487
16488
// 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;
}
16513
16514
16515
16516
16517
16518
16519
16520
16521
16522
16523
16524
16525
16526
16527
16528
16529
16530
16531
16532
16533
16534
16535
16536
// 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;
}
Zheming Fan
committed
#if JVET_W0123_TIMD_FUSION && !JVET_AJ0079_DISABLE_TIMD_COMBINATION
#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
16602
16603
16604
16605
16606
16607
16608
16609
16610
16611
16612
16613
16614
16615
16616
16617
16618
16619
16620
16621
16622
16623
16624
16625
16626
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;
}
Zheming Fan
committed
#if JVET_W0123_TIMD_FUSION && !JVET_AJ0079_DISABLE_TIMD_COMBINATION
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;
}
16645
16646
16647
16648
16649
16650
16651
16652
16653
16654
16655
16656
16657
16658
16659
16660
16661
16662
16663
16664
16665
16666
16667
16668
16669
16670
16671
16672
16673
16674
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
16707
16708
16709
16710
16711
16712
16713
16714
16715
16716
16717
16718
16719
16720
16721
16722
16723
16724
16725
16726
16727
16728
16729
16730
16731
16732
16733
16734
16735
16736
16737
16738
16739
16740
16741
16742
16743
16744
16745
16746
16747
16748
16749
16750
16751
16752
16753
16754
16755
16756
16757
16758
16759
16760
16761
16762
16763
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
16765
16766
16767
16768
16769
16770
16771
16772
16773
16774
16775
16776
16777
16778
16779
16780
16781
16782
16783
16784
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
void IntraSearch::setLumaIntraPredIdx(PredictionUnit& pu)
{
Zexing Sun
committed
#if JVET_AK0061_PDP_MPM
if (pu.cu->plIdx)
{
pu.mpmFlag = true;
pu.secondMpmFlag = false;
pu.ipredIdx = 0;
return;
}
#endif
Fabrice URBAN
committed
16797
16798
16799
16800
16801
16802
16803
16804
16805
16806
16807
16808
16809
16810
16811
16812
16813
16814
16815
16816
16817
16818
16819
16820
16821
16822
16823
16824
16825
#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;
Myungoh Hong
committed
#if JVET_AK0059_MDIP
int num_non_mpm = CU::allowMdip(*pu.cu) ? NUM_NON_MPM_MODES : NUM_NON_MPM_MODES + MDIP_NUM;
pred_idx = num_non_mpm;
for (int idx = 0; idx < num_non_mpm; idx++)
#else
Fabrice URBAN
committed
pred_idx = NUM_NON_MPM_MODES;
for (int idx = 0; idx < NUM_NON_MPM_MODES; idx++)
Myungoh Hong
committed
#endif
Fabrice URBAN
committed
16834
16835
16836
16837
16838
16839
16840
16841
16842
16843
16844
16845
16846
16847
16848
16849
16850
16851
16852
16853
16854
16855
16856
16857
16858
16859
16860
16861
16862
16863
{
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;
}