Newer
Older
}
if ((pu.lwidth() > 8 && pu.lheight() > 8))
{
// Sort MIP candidates by Hadamard cost
const int transpOff = getNumModesMip( pu.Y() );
static_vector<uint8_t, FAST_UDI_MAX_RDMODE_NUM> sortedMipModes(0);
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> sortedMipCost(0);
for( uint8_t mode : { 0, 1, 2 } )
{
uint8_t candMode = mode + uint8_t((mipHadCost[mode + transpOff] < mipHadCost[mode]) ? transpOff : 0);
updateCandList(candMode, mipHadCost[candMode], sortedMipModes, sortedMipCost, 3);
}
// Append MIP mode to RD mode list
const int modeListSize = int(tempRdModeList.size());
for (int idx = 0; idx < 3; idx++)
{
const bool isTransposed = (sortedMipModes[idx] >= transpOff ? true : false);
const uint32_t mipIdx = (isTransposed ? sortedMipModes[idx] - transpOff : sortedMipModes[idx]);
const ModeInfo mipMode( true, isTransposed, 0, NOT_INTRA_SUBPARTITIONS, mipIdx );
for (int modeListIdx = 0; modeListIdx < modeListSize; modeListIdx++)
{
if (tempRdModeList[modeListIdx] == mipMode)
{
alreadyIncluded = true;
break;
}
}
if (!alreadyIncluded)
{
#if JVET_AB0155_SGPM
updateCandList(mipMode, sortedMipCost[idx], tempRdModeList, tempCandCostList, tempRdModeList.size() + 1);
#else
tempRdModeList.push_back(mipMode);
tempCandCostList.push_back(0);
if( fastMip ) break;
}
}
}
if (pu.lwidth() > 8 && pu.lheight() > 8 && CU::allowTmrl(*pu.cu))
{
// Sort TMRL candidates by cost.
static_vector<uint8_t, FAST_UDI_MAX_RDMODE_NUM> sortedTmrlModes(0);
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> sortedTmrlCost(0);
for (uint8_t tmrlListIdx = 0; tmrlListIdx < MRL_LIST_SIZE; tmrlListIdx++)
{
CHECK(tmrlCostList[tmrlListIdx] == MAX_DOUBLE, "tmrlCostList is not filled.");
updateCandList(tmrlListIdx, tmrlCostList[tmrlListIdx], sortedTmrlModes, sortedTmrlCost, 3);
}
// Append TMRL mode to RD mode list
const int modeListSize = int(tempRdModeList.size());
for (int idx = 0; idx < 3; idx++)
{
const uint8_t tmrlListIdx = sortedTmrlModes[idx];
const ModeInfo tmrlMode(false, false, tmrlListIdx + MAX_REF_LINE_IDX, NOT_INTRA_SUBPARTITIONS, 0);
for (int modeListIdx = 0; modeListIdx < modeListSize; modeListIdx++)
{
if (tempRdModeList[modeListIdx] == tmrlMode)
{
alreadyIncluded = true;
break;
}
}
if (!alreadyIncluded)
{
const auto numRd = tempRdModeList.size() + 1;
updateCandList(tmrlMode, sortedTmrlCost[idx], tempRdModeList, tempCandCostList, numRd);
break;
}
}
}
#endif
static_vector<uint8_t, 2> sortedDirPlanarModes(2);
static_vector<double, 2> sortedDirPlanarCost(2);
{
sortedDirPlanarModes[i] = 0;
sortedDirPlanarCost[i] = MAX_DOUBLE;
for (uint8_t idx = 0; idx < 2; idx++)
CHECK(dirPlanarCostList[idx] == MAX_DOUBLE, "dirPlanarCostList is not filled.");
updateCandList(idx, dirPlanarCostList[idx], sortedDirPlanarModes, sortedDirPlanarCost, 2);
13097
13098
13099
13100
13101
13102
13103
13104
13105
13106
13107
13108
13109
13110
13111
13112
13113
13114
13115
13116
13117
13118
13119
13120
13121
13122
13123
}
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;
}
}
#endif
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
13166
13167
13168
13169
13170
13171
13172
13173
13174
13175
13176
13177
13178
13179
13180
13181
13182
13183
13184
13185
13186
13187
13188
13189
13190
13191
13192
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)
13416
13417
13418
13419
13420
13421
13422
13423
13424
13425
13426
13427
13428
13429
13430
13431
13432
13433
13434
13435
13436
13437
13438
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);
13453
13454
13455
13456
13457
13458
13459
13460
13461
13462
13463
13464
13465
13466
13467
13468
13469
// 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;
}
13494
13495
13496
13497
13498
13499
13500
13501
13502
13503
13504
13505
13506
13507
13508
13509
13510
13511
13512
13513
13514
13515
13516
13517
// 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
13583
13584
13585
13586
13587
13588
13589
13590
13591
13592
13593
13594
13595
13596
13597
13598
13599
13600
13601
13602
13603
13604
13605
13606
13607
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;
}
13626
13627
13628
13629
13630
13631
13632
13633
13634
13635
13636
13637
13638
13639
13640
13641
13642
13643
13644
13645
13646
13647
13648
13649
13650
13651
13652
13653
13654
13655
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
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697
13698
13699
13700
13701
13702
13703
13704
13705
13706
13707
13708
13709
13710
13711
13712
13713
13714
13715
13716
13717
13718
13719
13720
13721
13722
13723
13724
13725
13726
13727
13728
13729
13730
13731
13732
13733
13734
13735
13736
13737
13738
13739
13740
13741
13742
13743
13744
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
13746
13747
13748
13749
13750
13751
13752
13753
13754
13755
13756
13757
13758
13759
13760
13761
13762
13763
13764
13765
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
13766
13767
13768
13769
13770
13771
13772
13773
13774
13775
13776
13777
13778
13779
13780
13781
13782
13783
13784
13785
13786
13787
13788
13789
13790
13791
13792
13793
13794
13795
13796
13797
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810
13811
13812
13813
13814
13815
13816
13817
13818
13819
13820
13821
13822
13823
13824
13825
13826
13827
13828
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;
}