Newer
Older
Santiago de Luxán Hernández
committed
double bestCurrentCost = bestCostSoFar;
bool ispCanBeUsed = sps.getUseISP() && cu.mtsFlag == 0 && cu.lfnstIdx == 0 && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize());
bool saveDataForISP = ispCanBeUsed && (!colorTransformIsEnabled || isFirstColorSpace);
bool testISP = ispCanBeUsed && (!colorTransformIsEnabled || !cu.colorTransform);
#if JVET_AB0155_SGPM
const bool sgpmAllowed = sps.getUseSgpm() && isLuma(partitioner.chType);
bool testSgpm = sgpmAllowed && cu.lwidth() >= GEO_MIN_CU_SIZE_EX && cu.lheight() >= GEO_MIN_CU_SIZE_EX
&& cu.lwidth() <= GEO_MAX_CU_SIZE_EX && cu.lheight() <= GEO_MAX_CU_SIZE_EX
&& cu.lwidth() < 8 * cu.lheight() && cu.lheight() < 8 * cu.lwidth() && cu.lx() && cu.ly()
&& cu.lwidth() * cu.lheight() >= SGPM_MIN_PIX;
#endif
#if JVET_AG0058_EIP
bool testEip = isLuma(partitioner.chType) && sps.getUseEip() && (getAllowedEip(cu, COMPONENT_Y) || getAllowedEipMerge(cu, COMPONENT_Y));
bool eipSaveFlag = (cu.lfnstIdx == 0 && cu.mtsFlag == 0);
#if JVET_AJ0082_MM_EIP
double eipCost = MAX_DOUBLE;
bool setSkipEipControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
CodedCUInfo *relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfoPtr(partitioner.currArea());
testEip &= !relatedCU->skipEip;
#else
CodedCUInfo &relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfo(partitioner.currArea());
testEip &= !relatedCU.skipEip;
#endif
double eipBestSatdCost = MAX_DOUBLE;
bool isEipModeTested = false;
#endif
#endif
Döne Bugdayci Sansli
committed
#if JVET_AJ0146_TIMDSAD
bool testTimdSad = CU::allowTimdSad(cu) && cu.timdModeSad != INVALID_TIMD_IDX;
bool timdSadSaveFlag = (cu.lfnstIdx == 0 && cu.mtsFlag == 0);
#if !JVET_AJ0061_TIMD_MERGE
bool testTimd = cu.slice->getSPS()->getUseTimd() && !(cu.lwidth() * cu.lheight() > 1024 && cu.slice->getSliceType() == I_SLICE);
bool timdSaveFlag = (cu.lfnstIdx == 0 && cu.mtsFlag == 0);
#endif
#endif
#if JVET_W0103_INTRA_MTS
if (testISP && m_pcEncCfg->getUseFastISP())
{
m_numModesISPRDO = -1;
testISP &= testISPforCurrCU(cu);
}
#endif
//reset the intra modes lists variables
m_ispCandListHor.clear();
m_ispCandListVer.clear();
Santiago de Luxán Hernández
committed
if( testISP )
Yin Zhao
committed
//reset the variables used for the tests
m_regIntraRDListWithCosts.clear();
int numTotalPartsHor = (int)width >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_VERT_SPLIT));
int numTotalPartsVer = (int)height >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_HORZ_SPLIT));
m_ispTestedModes[0].init( numTotalPartsHor, numTotalPartsVer );
//the total number of subpartitions is modified to take into account the cases where LFNST cannot be combined with ISP due to size restrictions
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
numTotalPartsHor = spsIntraLfnstEnabled && CU::canUseLfnstWithISP( cu.Y(), HOR_INTRA_SUBPARTITIONS ) ? numTotalPartsHor : 0;
numTotalPartsVer = spsIntraLfnstEnabled && CU::canUseLfnstWithISP( cu.Y(), VER_INTRA_SUBPARTITIONS ) ? numTotalPartsVer : 0;
#else
numTotalPartsHor = sps.getUseLFNST() && CU::canUseLfnstWithISP(cu.Y(), HOR_INTRA_SUBPARTITIONS) ? numTotalPartsHor : 0;
numTotalPartsVer = sps.getUseLFNST() && CU::canUseLfnstWithISP(cu.Y(), VER_INTRA_SUBPARTITIONS) ? numTotalPartsVer : 0;
for (int j = 1; j < NUM_LFNST_NUM_PER_SET; j++)
{
m_ispTestedModes[j].init(numTotalPartsHor, numTotalPartsVer);
}

Karsten Suehring
committed
#if INTRA_TRANS_ENC_OPT
double regAngCost = MAX_DOUBLE;
bool setSkipTimdControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
double timdAngCost = MAX_DOUBLE;
#endif
#if JVET_AJ0112_REGRESSION_SGPM
double sgpmCost = MAX_DOUBLE;
bool setSkipSgpmControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
#endif
#if JVET_AJ0061_TIMD_MERGE
bool setSkipTimdMrgControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
double timdMrgAngCost[NUM_TIMD_MERGE_MODES];
for (int i = 0; i < NUM_TIMD_MERGE_MODES; i++)
{
timdMrgAngCost[i] = MAX_DOUBLE;
}
bool testTimd = cu.slice->getSPS()->getUseTimd();
if (cu.lwidth() * cu.lheight() > 1024 && cu.slice->getSliceType() == I_SLICE)
{
testTimd = false;
}
bool testTimdMerge = testTimd && PU::canTimdMerge(*cu.firstPU) && cu.timdMrgList[0][0] != INVALID_TIMD_IDX;
bool testTimdMrl = false;
#endif
#if JVET_AH0076_OBIC
double obicAngCost = MAX_DOUBLE, dimdAngCost = MAX_DOUBLE;
bool setSkipDimdControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
Thierry Dumas
committed
#endif
#if JVET_AJ0249_NEURAL_NETWORK_BASED
double regAngCostSupp = MAX_DOUBLE;
const bool setSkipNnControl = m_pcEncCfg->getIntraPeriod() == 1 && !cu.lfnstIdx && !cu.mtsFlag;
double nnAngCost = MAX_DOUBLE;
Alican Nalci
committed
const bool testBDPCM = sps.getBDPCMEnabledFlag() && CU::bdpcmAllowed(cu, ComponentID(partitioner.chType)) && cu.mtsFlag == 0 && cu.lfnstIdx == 0;
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiHadModeList;
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostList;
Bappaditya Ray
committed
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candHadList;

Karsten Suehring
committed
#if JVET_AJ0061_TIMD_MERGE
double mipHadCostStore[MAX_NUM_MIP_MODE] = { MAX_DOUBLE };
#endif

Karsten Suehring
committed
auto &pu = *cu.firstPU;
bool validReturn = false;

Karsten Suehring
committed
{
Bappaditya Ray
committed
candHadList.clear();
candCostList.clear();

Karsten Suehring
committed
uiHadModeList.clear();
Wei Chen
committed
#if JVET_AH0200_INTRA_TMP_BV_REORDER
double tmpBestSatdCost = MAX_DOUBLE;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
CodedCUInfo *relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfoPtr(partitioner.currArea());
#else
Wei Chen
committed
CodedCUInfo &relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfo(partitioner.currArea());
#endif
Wei Chen
committed
bool isTmpModeTestd = false;
#endif

Karsten Suehring
committed
CHECK(pu.cu != &cu, "PU is not contained in the CU");

Karsten Suehring
committed
//===== determine set of modes to be tested (using prediction signal only) =====
int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
const bool fastMip = sps.getUseMIP() && m_pcEncCfg->getUseFastMIP();
const bool mipAllowed = sps.getUseMIP() && isLuma(partitioner.chType) && ((cu.lfnstIdx == 0) || allowLfnstWithMip(cu.firstPU->lumaSize()));
const bool testMip = mipAllowed && !(cu.lwidth() > (8 * cu.lheight()) || cu.lheight() > (8 * cu.lwidth()));
const bool supportedMipBlkSize = pu.lwidth() <= MIP_MAX_WIDTH && pu.lheight() <= MIP_MAX_HEIGHT;
#if JVET_V0130_INTRA_TMP
const bool tpmAllowed = sps.getUseIntraTMP() && isLuma(partitioner.chType) && ((cu.lfnstIdx == 0) || allowLfnstWithTmp());
const bool testTpm = tpmAllowed && (cu.lwidth() <= sps.getIntraTMPMaxSize() && cu.lheight() <= sps.getIntraTMPMaxSize());
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeList;

Karsten Suehring
committed
int numModesForFullRD = 3;
numModesForFullRD = g_aucIntraModeNumFast_UseMPM_2D[uiWidthBit - MIN_CU_LOG2][uiHeightBit - MIN_CU_LOG2];
Döne Bugdayci Sansli
committed
#if JVET_AJ0146_TIMDSAD
bool modList = cu.slice->getSPS()->getUseTimd() && cu.slice->getSliceType() == I_SLICE;
if (modList)
{
numModesForFullRD++;
}
#endif
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
if (m_pcEncCfg->getIBCFastMethod() & IBC_FAST_METHOD_NONSCC)
{
numModesForFullRD = (numModesForFullRD > 1) ? (numModesForFullRD - 1) : numModesForFullRD;
}
#endif

Karsten Suehring
committed
#if INTRA_FULL_SEARCH
numModesForFullRD = numModesAvailable;
#endif
#if JVET_AH0076_OBIC
bool bestObicMode = false;
int bestMipDimd = 0;
#endif
#if JVET_AJ0112_REGRESSION_SGPM
int bestSgpmDimd = 0;
#endif
#if JVET_W0123_TIMD_FUSION
bool bestTimdMode = false;
Döne Bugdayci Sansli
committed
#if JVET_AJ0146_TIMDSAD
bool bestTimdModeSad = false;
#endif
#if JVET_AJ0061_TIMD_MERGE
int bestTimdMrgMode = 0;
int bestTimdTrType[2] = { TransType::DCT2, TransType::DCT2 };
#endif
#if JVET_AC0105_DIRECTIONAL_PLANAR
uint8_t bestPlMode = 0;
#endif
Thierry Dumas
committed
#if JVET_AJ0249_NEURAL_NETWORK_BASED
bool bestLfnstSecFlag = false;
#endif
#if JVET_AB0155_SGPM
bool bestSgpmMode = false;
const CompArea &area = pu.Y();
CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
#endif
#if JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST
int intraTmpDimdMode = 0;
#endif
Bappaditya Ray
committed
Thierry Dumas
committed
#if JVET_AJ0249_NEURAL_NETWORK_BASED
const bool isShapeHandledPnn = isNnIn && IntraPredictionNN::hasPnnPrediction(cu);
int idxShift = 0;
int idxPnnBackwardCompatibility = -MAX_INT;
#endif
if (isSecondColorSpace)
{
uiRdModeList.clear();
if (m_numSavedRdModeFirstColorSpace[m_savedRdModeIdx] > 0)
{
for (int i = 0; i < m_numSavedRdModeFirstColorSpace[m_savedRdModeIdx]; i++)
{
uiRdModeList.push_back(m_savedRdModeFirstColorSpace[m_savedRdModeIdx][i]);
}
}
else
{
return false;
}

Karsten Suehring
committed
{
#if JVET_AH0076_OBIC
if ((testSgpm && SGPMSaveFlag) || obicSaveFlag || dimdSaveFlag)
#else
#endif
#if JVET_AG0152_SGPM_ITMP_IBC
for (int i = 0; i < NUM_LUMA_MODE + SGPM_NUM_BVS; i++)
#else
{
m_intraModeReady[i] = 0;
}
}
#endif
// this should always be true
CHECK(!pu.Y().valid(), "PU is not valid");
#if !JVET_AB0157_TMRL || JVET_AD0082_TMRL_CONFIG
#if JVET_AH0065_RELAX_LINE_BUFFER
bool isFirstLineOfCtu = pu.block(COMPONENT_Y).y == 0;
#else
bool isFirstLineOfCtu = (((pu.block(COMPONENT_Y).y) & ((pu.cs->sps)->getMaxCUWidth() - 1)) == 0);
#if JVET_Y0116_EXTENDED_MRL_LIST
int numOfPassesExtendRef = MRL_NUM_REF_LINES;
if (!sps.getUseMRL() || isFirstLineOfCtu)
{
numOfPassesExtendRef = 1;
}
else
{
bool checkLineOutsideCtu[MRL_NUM_REF_LINES - 1];
for (int mrlIdx = 1; mrlIdx < MRL_NUM_REF_LINES; mrlIdx++)
{
#if JVET_AH0065_RELAX_LINE_BUFFER
bool isLineOutsideCtu = (cu.block(COMPONENT_Y).y <= MULTI_REF_LINE_IDX[mrlIdx]) ? true : false;
#else
bool isLineOutsideCtu =
((cu.block(COMPONENT_Y).y) % ((cu.cs->sps)->getMaxCUWidth()) <= MULTI_REF_LINE_IDX[mrlIdx]) ? true
: false;
#endif
checkLineOutsideCtu[mrlIdx-1] = isLineOutsideCtu;
}
if (checkLineOutsideCtu[0])
{
numOfPassesExtendRef = 1;
}
else
{
for (int mrlIdx = MRL_NUM_REF_LINES - 2; mrlIdx > 0; mrlIdx--)
{
if (checkLineOutsideCtu[mrlIdx] && !checkLineOutsideCtu[mrlIdx - 1])
{
numOfPassesExtendRef = mrlIdx + 1;
break;
}
}
}
}
#else
int numOfPassesExtendRef = ((!sps.getUseMRL() || isFirstLineOfCtu) ? 1 : MRL_NUM_REF_LINES);
#endif
#if JVET_AB0157_TMRL
cu.tmrlFlag = false;
#endif

Karsten Suehring
committed
CHECK(numModesForFullRD >= numModesAvailable, "Too many modes for full RD search");
PelBuf piOrg = cs.getOrgBuf(area);
PelBuf piPred = cs.getPredBuf(area);

Karsten Suehring
committed
DistParam distParamSad;
DistParam distParamHad;
if (cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())

Karsten Suehring
committed
{
CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
PelBuf tmpOrg = m_tmpStorageLCU.getBuf(tmpArea);
m_pcRdCost->setDistParam(distParamSad, tmpOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y,
false); // Use SAD cost
m_pcRdCost->setDistParam(distParamHad, tmpOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y,
true); // Use HAD (SATD) cost

Karsten Suehring
committed
}
m_pcRdCost->setDistParam(distParamSad, piOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y,
false); // Use SAD cost
m_pcRdCost->setDistParam(distParamHad, piOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y,
true); // Use HAD (SATD) cost

Karsten Suehring
committed
distParamSad.applyWeight = false;
distParamHad.applyWeight = false;

Karsten Suehring
committed
if (testMip && supportedMipBlkSize)
{
numModesForFullRD += fastMip
? std::max(numModesForFullRD, floorLog2(std::min(pu.lwidth(), pu.lheight())) - 1)
: numModesForFullRD;
}
#if JVET_AB0130_ITMP_SAMPLING
if (testTpm && !m_pcEncCfg->getUseFastIntraTMP())
#else
{
numModesForFullRD += 1; // testing tpm
}
#if JVET_AG0136_INTRA_TMP_LIC
if( testTpm && m_pcEncCfg->getItmpLicMode())
{
numModesForFullRD += 1; // testing lic itmp
}
Thierry Dumas
committed
#endif
#if JVET_AJ0249_NEURAL_NETWORK_BASED
if (isNnIn)
{
numModesForFullRD += 1;
}
Döne Bugdayci Sansli
committed
#if JVET_AJ0146_TIMDSAD
const int numHadCand = (testMip ? 2 : 1) * 3 + (modList ? 1 : 0) + testTpm;
#else
const int numHadCand = (testMip ? 2 : 1) * 3 + testTpm;
Döne Bugdayci Sansli
committed
#endif
const int numHadCand = (testMip ? 2 : 1) * 3;

Karsten Suehring
committed
#if JVET_AB0155_SGPM
static_vector<SgpmInfo, SGPM_NUM> sgpmInfoList;
static_vector<double, SGPM_NUM> sgpmCostList;
#if JVET_AG0152_SGPM_ITMP_IBC
int sgpmNeededMode[NUM_LUMA_MODE + SGPM_NUM_BVS] = { 0 };
#else
if (testSgpm && SGPMSaveFlag)
{
deriveSgpmModeOrdered(bestCS->picture->getRecoBuf(area), area, cu, sgpmInfoList, sgpmCostList);
Bappaditya Ray
committed
for (int sgpmIdx = 0; sgpmIdx < SGPM_NUM; sgpmIdx++)
{
int sgpmMode[2];
sgpmMode[0] = sgpmInfoList[sgpmIdx].sgpmMode0;
sgpmMode[1] = sgpmInfoList[sgpmIdx].sgpmMode1;
sgpmNeededMode[sgpmMode[0]] = 1;
sgpmNeededMode[sgpmMode[1]] = 1;
}
}
#endif
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
#if JVET_AH0076_OBIC
int dimdNeededMode[NUM_LUMA_MODE] = {0};
if (obicSaveFlag)
{
for (int idx = 0; idx < OBIC_FUSION_NUM; idx++)
{
int iMode = cu.obicMode[idx];
if (iMode < 0)
{
continue;
}
dimdNeededMode[iMode] = 1;
}
}
if (dimdSaveFlag)
{
if (cu.dimdBlending)
{
for (int dimdIdx = 0; dimdIdx < DIMD_FUSION_NUM - 1; dimdIdx++)
{
int dimdMode = (dimdIdx == 0 ? cu.dimdMode : cu.dimdBlendMode[dimdIdx-1]);
if (dimdMode <= 0)
{
break;
}
dimdNeededMode[dimdMode] = 1;
}
dimdNeededMode[PLANAR_IDX] = 1;
}
}
#endif
#if JVET_AB0157_TMRL
double tmrlCostList[MRL_LIST_SIZE]{ MAX_DOUBLE };
#endif
#if JVET_AC0105_DIRECTIONAL_PLANAR
double dirPlanarCostList[2]{ MAX_DOUBLE };
#endif
//*** Derive (regular) candidates using Hadamard
cu.mipFlag = false;

Karsten Suehring
committed
//===== init pattern for luma prediction =====
#if JVET_AB0157_INTRA_FUSION && JVET_AB0155_SGPM
initIntraPatternChType(cu, pu.Y(), true, 0, false);
#elif JVET_AB0157_INTRA_FUSION
initIntraPatternChType(cu, pu.Y(), true, false);
#else
bool bSatdChecked[NUM_INTRA_MODE];
memset(bSatdChecked, 0, sizeof(bSatdChecked));

Karsten Suehring
committed
if (!LFNSTLoadFlag)
{
for (int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++)
{
uint32_t uiMode = modeIdx;
Distortion minSadHad = 0;

Karsten Suehring
committed
// Skip checking extended Angular modes in the first round of SATD
if (uiMode > DC_IDX && (uiMode & 1))
{
continue;

Karsten Suehring
committed
}
#if JVET_AB0157_INTRA_FUSION
predIntraAng(COMPONENT_Y, piPred, pu, false);
#else
Bappaditya Ray
committed
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
#if JVET_AH0209_PDP
bool pdpMode = false;
if( pdpSaveFlag )
{
const int sizeKey = (width << 8) + height;
const int sizeIdx = g_size.find(sizeKey) != g_size.end() ? g_size[sizeKey] : -1;
const int m = sizeIdx > 12 ? 2 : 0;
const int s = sizeIdx > 12 ? 4 : 2;
if (sizeIdx >= 0 && m_refAvailable && pu.cu->cs->sps->getUsePDP() && !(modeIdx > 1 && modeIdx % s != m))
{
PelBuf predBuf(m_pdpIntraPredBuf[uiMode], tmpArea);
predBuf.copyFrom(piPred);
m_pdpIntraPredReady[modeIdx] = true;
pdpMode = true;
}
}
if( !pdpMode )
{
#endif
#if JVET_AB0155_SGPM
if (testSgpm && SGPMSaveFlag && sgpmNeededMode[uiMode])
{
Bappaditya Ray
committed
PelBuf predBuf(m_intraPredBuf[uiMode], tmpArea);
predBuf.copyFrom(piPred);
m_intraModeReady[uiMode] = 1;
}
#endif
#if JVET_AH0076_OBIC
if ((obicSaveFlag || dimdSaveFlag) && dimdNeededMode[uiMode] && !m_intraModeReady[uiMode])
{
Bappaditya Ray
committed
PelBuf predBuf(m_intraPredBuf[uiMode], tmpArea);
predBuf.copyFrom(piPred);
m_intraModeReady[uiMode] = 1;
}
#endif
Bappaditya Ray
committed
#if JVET_AH0209_PDP
}
#endif
// Use the min between SAD and HAD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
Distortion sadCost = distParamSad.distFunc(distParamSad);
minSadHad += std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
#else
minSadHad += std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
#endif
loadStartStates();
uint64_t fracModeBits = xFracModeBitsIntra(pu, uiMode, CHANNEL_TYPE_LUMA);
double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
#endif
DTRACE(g_trace_ctx, D_INTRA_COST, "IntraHAD: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, uiMode);
updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiMode), cost, uiRdModeList,
candCostList, numModesForFullRD);
updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiMode), double(minSadHad),
Bappaditya Ray
committed
uiHadModeList, candHadList, numHadCand);
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
#if JVET_AC0105_DIRECTIONAL_PLANAR
bool testDirPlanar = isLuma(partitioner.chType);
if (testDirPlanar)
{
for (int dirPlanarModeIdx = 0; dirPlanarModeIdx < 2; dirPlanarModeIdx++)
{
cu.sgpm = false;
cu.ispMode = 0;
cu.tmpFlag = false;
cu.tmrlFlag = false;
pu.multiRefIdx = 0;
cu.mipFlag = false;
pu.intraDir[0] = PLANAR_IDX;
cu.plIdx = dirPlanarModeIdx + 1;
initPredIntraParams(pu, pu.Y(), sps);
#if JVET_AB0157_INTRA_FUSION
predIntraAng(COMPONENT_Y, piPred, pu, false);
#else
predIntraAng(COMPONENT_Y, piPred, pu);
#endif
// Use the min between SAD and SATD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
Distortion sadCost = distParamSad.distFunc(distParamSad);
Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
#else
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
#endif
loadStartStates();
uint64_t fracModeBits = xFracModeBitsIntra(pu, PLANAR_IDX, CHANNEL_TYPE_LUMA);
double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
#endif
updateCandList(
ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, dirPlanarModeIdx ? PL_VER_IDX : PL_HOR_IDX), cost,
uiRdModeList, candCostList, numModesForFullRD);
updateCandList(
ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, dirPlanarModeIdx ? PL_VER_IDX : PL_HOR_IDX),
Bappaditya Ray
committed
double(minSadHad), uiHadModeList, candHadList, numHadCand);
dirPlanarCostList[dirPlanarModeIdx] = cost;
}
}
cu.plIdx = 0;
#endif
if (!sps.getUseMIP() && LFNSTSaveFlag)
{
// save found best modes
m_uiSavedNumRdModesLFNST = numModesForFullRD;
m_uiSavedRdModeListLFNST = uiRdModeList;
m_dSavedModeCostLFNST = candCostList;
// PBINTRA fast
m_uiSavedHadModeListLFNST = uiHadModeList;
Bappaditya Ray
committed
m_dSavedHadListLFNST = candHadList;
LFNSTSaveFlag = false;
}
} // NSSTFlag
if (!sps.getUseMIP() && LFNSTLoadFlag)
// restore saved modes
numModesForFullRD = m_uiSavedNumRdModesLFNST;
uiRdModeList = m_uiSavedRdModeListLFNST;
candCostList = m_dSavedModeCostLFNST;
// PBINTRA fast
uiHadModeList = m_uiSavedHadModeListLFNST;
Bappaditya Ray
committed
candHadList = m_dSavedHadListLFNST;
if (!(sps.getUseMIP() && LFNSTLoadFlag))
{
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> parentCandList = uiRdModeList;
// Second round of SATD for extended Angular modes
for (int modeIdx = 0; modeIdx < numModesForFullRD; modeIdx++)
{
unsigned parentMode = parentCandList[modeIdx].modeId;
if (parentMode > (DC_IDX + 1) && parentMode < (NUM_LUMA_MODE - 1))
{
for (int subModeIdx = -1; subModeIdx <= 1; subModeIdx += 2)
{
unsigned mode = parentMode + subModeIdx;
if (!bSatdChecked[mode])
{
pu.intraDir[0] = mode;
initPredIntraParams(pu, pu.Y(), sps);
#if JVET_AB0157_INTRA_FUSION
predIntraAng(COMPONENT_Y, piPred, pu, false);
#else
#if JVET_AB0155_SGPM
if (testSgpm && SGPMSaveFlag && sgpmNeededMode[mode])
{
Bappaditya Ray
committed
PelBuf predBuf(m_intraPredBuf[mode], tmpArea);
predBuf.copyFrom(piPred);
m_intraModeReady[mode] = 1;
}
#endif
#if JVET_AH0076_OBIC
if ((obicSaveFlag || dimdSaveFlag) && dimdNeededMode[mode] && !m_intraModeReady[mode])
{
Bappaditya Ray
committed
PelBuf predBuf(m_intraPredBuf[mode], tmpArea);
predBuf.copyFrom(piPred);
m_intraModeReady[mode] = 1;
}
#endif
// Use the min between SAD and SATD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
Distortion sadCost = distParamSad.distFunc(distParamSad);
Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
#else
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
#endif
loadStartStates();
uint64_t fracModeBits = xFracModeBitsIntra(pu, mode, CHANNEL_TYPE_LUMA);
double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
#endif
updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, mode), cost, uiRdModeList,
candCostList, numModesForFullRD);
updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, mode), double(minSadHad),
Bappaditya Ray
committed
uiHadModeList, candHadList, numHadCand);
bSatdChecked[mode] = true;
}
}
}
}
if (saveDataForISP)
// we save the regular intra modes list
m_ispCandListHor = uiRdModeList;
}
#if !JVET_AB0157_TMRL || JVET_AD0082_TMRL_CONFIG
#if SECONDARY_MPM
const int numMPMs = NUM_PRIMARY_MOST_PROBABLE_MODES;
#else
Fabrice URBAN
committed
uint8_t* multiRefMPM = m_intraMPM;
#if !JVET_AD0082_TMRL_CONFIG
#if JVET_AD0082_TMRL_CONFIG
cu.tmrlFlag = true;
#endif
for (auto multiRefIdx : EXT_REF_LINE_IDX)
{
pu.multiRefIdx = multiRefIdx;
initIntraPatternChType(cu, pu.Y(), true);
for (auto i = 0; i < MRL_LIST_SIZE; i++)
{
if (m_tmrlList[i].multiRefIdx != multiRefIdx)
pu.intraDir[0] = m_tmrlList[i].intraDir;
cu.tmrlListIdx = i;
uint32_t uiMode = i + MAX_REF_LINE_IDX;
initPredIntraParams(pu, pu.Y(), *(pu.cs->sps));
predIntraAng(COMPONENT_Y, piPred, pu);
// Use the min between SAD and SATD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
Distortion sadCost = distParamSad.distFunc(distParamSad);
Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
#else
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
#endif
loadStartStates();
uint64_t fracModeBits = xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA);
double cost = (double)minSadHad + (double)fracModeBits * sqrtLambdaForFirstPass;
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
#endif
updateCandList(ModeInfo(false, false, uiMode, NOT_INTRA_SUBPARTITIONS, 0), cost, uiRdModeList,
candCostList, numModesForFullRD);
updateCandList(ModeInfo(false, false, uiMode, NOT_INTRA_SUBPARTITIONS, 0), double(minSadHad),
Bappaditya Ray
committed
uiHadModeList, candHadList, numHadCand);
#if JVET_AB0157_TMRL
tmrlCostList[i] = cost;
#endif
}
}
#if JVET_AD0082_TMRL_CONFIG
cu.tmrlFlag = false;
#endif
#endif
#if !JVET_AB0157_TMRL || JVET_AD0082_TMRL_CONFIG
#if JVET_AD0082_TMRL_CONFIG
else
{
#endif
for (int mRefNum = 1; mRefNum < numOfPassesExtendRef; mRefNum++)
{
int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
#if JVET_AB0157_INTRA_FUSION && JVET_AB0155_SGPM
initIntraPatternChType(cu, pu.Y(), true, 0, false);
#elif JVET_AB0157_INTRA_FUSION
initIntraPatternChType(cu, pu.Y(), true, false);
#else
}
for (int x = 1; x < numMPMs; x++)
{
uint32_t mode = multiRefMPM[x];
{
pu.intraDir[0] = mode;
initPredIntraParams(pu, pu.Y(), sps);
#if JVET_AB0157_INTRA_FUSION
predIntraAng(COMPONENT_Y, piPred, pu, false);
#else
// Use the min between SAD and SATD as the cost criterion
// SAD is scaled by 2 to align with the scaling of HAD
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
Distortion sadCost = distParamSad.distFunc(distParamSad);
Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
#else
Distortion minSadHad =
std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
loadStartStates();
uint64_t fracModeBits = xFracModeBitsIntra(pu, mode, CHANNEL_TYPE_LUMA);
double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
#endif
updateCandList(ModeInfo(false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, mode), cost, uiRdModeList,
candCostList, numModesForFullRD);
updateCandList(ModeInfo(false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, mode), double(minSadHad),
Bappaditya Ray
committed
uiHadModeList, candHadList, numHadCand);
#if JVET_AD0082_TMRL_CONFIG
}
#endif
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
1830
1831
1832
1833
1834
1835
1836
1837
#if JVET_AJ0061_TIMD_MERGE
const int numTool = 2; // Timd, TimdMrl
bool isTimd, isTimdMrl;
/*-------------*/
/* TIMD */
int numPassTimd = (testTimd ? 1 : 0) + (testTimdMerge ? 1 : 0);
CHECK(!testTimd && testTimdMerge, "something went wrong");
/*-------------*/
/* TIMD-MRL */
bool isFirstLineOfCtu = pu.block(COMPONENT_Y).y == 0;
bool isTimdMrlAllowed = (lfnstIdx == 0 && !cu.mtsFlag) && isTimdValid;
numOfPassesExtendRef = !isTimdMrlAllowed ? 0 : (((!sps.getUseMRL() || isFirstLineOfCtu) ? 1 : 3) - 1);
const int numToolPass[numTool] = { numPassTimd, numOfPassesExtendRef};
// Shared variables
int multiRefIdx;
uint8_t intraDir = 0;
uint32_t modeId = 0;
uint8_t modeRefIdx = 0;
ModeInfo currMode;
for (int tool = 0; tool < numTool; tool++)
{
isTimd = tool == 0;
isTimdMrl = tool == 1;
for (int pass = 0; pass < numToolPass[tool]; pass++)
{
if (isTimd)
{
cu.timd = true;
Döne Bugdayci Sansli
committed
#if JVET_AJ0146_TIMDSAD
cu.timdSad = false;
#endif
cu.timdMrg = pass == 1;
intraDir = !cu.timdMrg ? cu.timdMode : cu.timdMrgList[0][0];
modeId = !cu.timdMrg ? TIMD_IDX : TIMDM_IDX;
modeRefIdx = 0;
multiRefIdx = 0;
}
if (isTimdMrl)
{
multiRefIdx = MULTI_REF_LINE_IDX[pass + 1];
modeRefIdx = multiRefIdx;
intraDir = cu.timdMode;
modeId = TIMD_IDX;
cu.timd = true;
Döne Bugdayci Sansli
committed
#if JVET_AJ0146_TIMDSAD
cu.timdSad = false;
#endif
cu.timdMrg = false;
testTimdMrl = true;
}
// PU/CU init
pu.intraDir[0] = intraDir;
pu.cu->tmrlFlag = false;
pu.multiRefIdx = multiRefIdx;
pu.cu->timd = isTimd || isTimdMrl;
Döne Bugdayci Sansli
committed
#if JVET_AJ0146_TIMDSAD
pu.cu->timdSad = false;
#endif
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
// Init intra pattern
initIntraPatternChType(cu, pu.Y());
// Init IPM parameters
initPredIntraParams(pu, pu.Y(), sps);
// Prediction
predIntraAng(COMPONENT_Y, piPred, pu);
// Cost calculation
Distortion sadCost = distParamSad.distFunc(distParamSad);
Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
loadStartStates();
uint64_t fracModeBits = xFracModeBitsIntra(pu, intraDir, CHANNEL_TYPE_LUMA);
double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
currMode = ModeInfo(false, false, modeRefIdx, NOT_INTRA_SUBPARTITIONS, modeId);
// Update lists
numTimdSatd++;
timdModes.push_back(currMode);
timdCosts.push_back(cost);
timdSadCosts.push_back(static_cast<double>(minSadHad));
TimdMode mode = getTimdMode(cu.timdMrg, multiRefIdx);
PelBuf timdSaveBuf(m_timdPredBuf[mode], pu.Y());
timdSaveBuf.copyFrom(piPred);
m_satdCostTIMD[mode][0] = static_cast<uint64_t>(cost);
m_satdCostTIMD[mode][1] = minSadHad;
}
}
cu.tmrlFlag = false;
cu.timd = false;
cu.timdMrg = false;
#endif
CHECKD(uiRdModeList.size() != numModesForFullRD, "Error: RD mode list size");
#if JVET_V0130_INTRA_TMP && JVET_AB0130_ITMP_SAMPLING
// derive TPM candidate using hadamard
if (testTpm)
{
cu.tmpFlag = true;
cu.mipFlag = false;
pu.multiRefIdx = 0;
#if JVET_AD0086_ENHANCED_INTRA_TMP
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListTmp;
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostListTmp;
int foundCandiNum = 0;
bool bsuccessfull = 0;
Wei Chen
committed
#endif
#if JVET_AH0200_INTRA_TMP_BV_REORDER
int adjustedTMPNonLicBvNum = TMP_REFINE_NONLIC_BV_NUM;
int adjustedTmpLicBvNum = TMP_REFINE_LIC_BV_NUM;
if(m_pcEncCfg->getIntraPeriod() != 1)
{
adjustedTMPNonLicBvNum = 10;
adjustedTmpLicBvNum = 4;
}
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListFracTmp;
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostListFracTmp;
Distortion backupMinSadHad[MTMP_NUM];
Distortion backupSadCost[MTMP_NUM];
Distortion backupLicMinSadHad[MTMP_NUM][4];
Distortion backupLicSadCost[MTMP_NUM][4];
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListLicFracTmp;
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostListLicFracTmp;
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListTmpLic;
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostListTmpLic;
CodingUnit cuCopy = cu;
#if JVET_W0069_TMP_BOUNDARY
RefTemplateType templateType = getRefTemplateType(cuCopy, cuCopy.blocks[COMPONENT_Y]);
if (templateType != NO_TEMPLATE)
#else
if (isRefTemplateAvailable(cuCopy, cuCopy.blocks[COMPONENT_Y]))
#endif
{
#if JVET_AD0086_ENHANCED_INTRA_TMP
cu.tmpIsSubPel = 0;
#if JVET_AG0136_INTRA_TMP_LIC
cu.tmpSubPelIdx = -1;
#else
cu.tmpSubPelIdx = 0;
Wei Chen
committed
#endif
#if JVET_AH0200_INTRA_TMP_BV_REORDER
cu.tmpFracIdx = 0;
int numModesForFracIntraTmp = numModesForFullRD + adjustedTMPNonLicBvNum;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if(relatedCU && relatedCU->skipFracTmp)
#else
Wei Chen
committed
if(relatedCU.skipFracTmp)
#endif
Wei Chen
committed
{
numModesForFracIntraTmp = numModesForFullRD;
}
if(m_tmpNumCand > 0)
{
for(int idxInList=0; idxInList < uiRdModeList.size(); idxInList++)
{
if(cu.lwidth() * cu.lheight() > TMP_SKIP_REFINE_THRESHOLD)
{
break;
}
updateCandList(uiRdModeList[idxInList], candCostList[idxInList], uiRdModeListFracTmp, candCostListFracTmp, numModesForFracIntraTmp);
}
}
int numModesForLicFracIntraTmp = numModesForFullRD + adjustedTmpLicBvNum;
#if JVET_AI0136_ADAPTIVE_DUAL_TREE
if(relatedCU && relatedCU->skipFracTmp)
#else
Wei Chen
committed
if(relatedCU.skipFracTmp)
#endif
Wei Chen
committed
{
numModesForLicFracIntraTmp = numModesForFullRD;
}
if(m_tmpNumCandUseMR > 0)
{
for(int idxInList=0; idxInList < uiRdModeList.size(); idxInList++)
{
if(cu.lwidth() * cu.lheight() > TMP_SKIP_REFINE_THRESHOLD)
{
break;
}
updateCandList(uiRdModeList[idxInList], candCostList[idxInList], uiRdModeListLicFracTmp, candCostListLicFracTmp, numModesForLicFracIntraTmp);
}
}