Newer
Older
else
{
singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
}
}
#if INTRA_TRANS_ENC_OPT
else if (CS::isDualITree(cs) && cu.lfnstIdx && !cu.ispMode)
{
if (!cuCtx.lfnstLastScanPos)
{
singleCostTmp = MAX_DOUBLE;
}
else
{
singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
}
}
#endif
{
singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
}

Karsten Suehring
committed
}
Santiago de Luxán Hernández
committed
if ( !cu.ispMode && nNumTransformCands > 1 && modeId == firstCheckId )
{
bestDCT2cost = singleCostTmp;
}
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled && cu.mtsFlag )
#else
{
if (singleCostTmp != MAX_DOUBLE)
{
const CompArea& area = tu.blocks[COMPONENT_Y];
double skipThreshold = 1.0 + 1.0 / sqrt((double)(area.width*area.height));
skipThreshold = std::max(skipThreshold, !m_pcEncCfg->getUseFastLFNST()? 1.06: 1.03);
#if JVET_Y0142_ADAPT_INTRA_MTS
skipThreshold = (m_coeffAbsSumDCT2 >= MTS_TH_COEFF[1])? std::max(skipThreshold, 1.06) : skipThreshold;
#endif
if (singleCostTmp > skipThreshold * m_globalBestCostStore)
{
m_numCandAMTForFullRD = modeId + 1;
}
}
}
#if JVET_Y0142_ADAPT_INTRA_MTS
if (tu.mtsIdx[0] == 0 && !cu.ispMode && !cu.lfnstIdx)
{
m_coeffAbsSumDCT2 = cuCtx.mtsCoeffAbsSum;
}
#endif

Karsten Suehring
committed
if (singleCostTmp < dSingleCost)
{
dSingleCost = singleCostTmp;
uiSingleDistLuma = singleDistTmpLuma;
singleFracBits = singleTmpFracBits;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if( sps.getUseLFNST() )
bestModeId[ COMPONENT_Y ] = modeId;
cbfBestMode = TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth );
cbfBestModeValid = true;
validReturnFull = true;
else
{
bestModeId[ COMPONENT_Y ] = trModes[ modeId ].first;
if( trModes[ modeId ].first == 0 )
{
cbfDCT2 = TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth );
}
}

Karsten Suehring
committed
if( bestModeId[COMPONENT_Y] != lastCheckId )
{
saveCS.getPredBuf( tu.Y() ).copyFrom( csFull->getPredBuf( tu.Y() ) );
saveCS.getRecoBuf( tu.Y() ).copyFrom( csFull->getRecoBuf( tu.Y() ) );
if( KEEP_PRED_AND_RESI_SIGNALS || JVET_AC0162_ALF_RESIDUAL_SAMPLES_INPUT )

Karsten Suehring
committed
{
saveCS.getResiBuf ( tu.Y() ).copyFrom( csFull->getResiBuf ( tu.Y() ) );
}
if( KEEP_PRED_AND_RESI_SIGNALS )
{

Karsten Suehring
committed
saveCS.getOrgResiBuf( tu.Y() ).copyFrom( csFull->getOrgResiBuf( tu.Y() ) );
}
tmpTU->copyComponentFrom( tu, COMPONENT_Y );
ctxBest = m_CABACEstimator->getCtx();
}
}
}
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled && !validReturnFull )
#else
if( sps.getUseLFNST() && !validReturnFull )

Karsten Suehring
committed
{
csFull->cost = MAX_DOUBLE;

Karsten Suehring
committed
if( bCheckSplit )

Karsten Suehring
committed
{
ctxBest = m_CABACEstimator->getCtx();

Karsten Suehring
committed
}
}
else
{
if( bestModeId[COMPONENT_Y] != lastCheckId )
{
csFull->getPredBuf( tu.Y() ).copyFrom( saveCS.getPredBuf( tu.Y() ) );
csFull->getRecoBuf( tu.Y() ).copyFrom( saveCS.getRecoBuf( tu.Y() ) );

Karsten Suehring
committed
if( KEEP_PRED_AND_RESI_SIGNALS || JVET_AC0162_ALF_RESIDUAL_SAMPLES_INPUT )
{
csFull->getResiBuf ( tu.Y() ).copyFrom( saveCS.getResiBuf ( tu.Y() ) );
}
if( KEEP_PRED_AND_RESI_SIGNALS )
{
csFull->getOrgResiBuf( tu.Y() ).copyFrom( saveCS.getOrgResiBuf( tu.Y() ) );
}

Karsten Suehring
committed
tu.copyComponentFrom( *tmpTU, COMPONENT_Y );
if( !bCheckSplit )
{
m_CABACEstimator->getCtx() = ctxBest;
}
}
else if( bCheckSplit )

Karsten Suehring
committed
{
ctxBest = m_CABACEstimator->getCtx();

Karsten Suehring
committed
}
csFull->cost += dSingleCost;
csFull->dist += uiSingleDistLuma;
csFull->fracBits += singleFracBits;
}

Karsten Suehring
committed
}
bool validReturnSplit = false;

Karsten Suehring
committed
if( bCheckSplit )
{
//----- store full entropy coding status, load original entropy coding status -----
if( bCheckFull )
{
m_CABACEstimator->getCtx() = ctxStart;
}
//----- code splitted block -----
csSplit->cost = 0;
bool uiSplitCbfLuma = false;
bool splitIsSelected = true;
Waqas Ahmad
committed
if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
) )

Karsten Suehring
committed
{
partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
}
if( cu.ispMode )
{
partitioner.splitCurrArea( ispType, *csSplit );
}

Karsten Suehring
committed
do
{
bool tmpValidReturnSplit = xRecurIntraCodingLumaQT( *csSplit, partitioner, bestCostSoFar, subTuCounter, ispType, false, mtsCheckRangeFlag, mtsFirstCheckId, mtsLastCheckId );
#if JVET_Z0118_GDR
cs.updateReconMotIPM(partitioner.currArea());
#else
cs.picture->getRecoBuf( partitioner.currArea() ).copyFrom( cs.getRecoBuf( partitioner.currArea() ) );
subTuCounter += subTuCounter != -1 ? 1 : 0;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled && !tmpValidReturnSplit )
#else
if( sps.getUseLFNST() && !tmpValidReturnSplit )
{
splitIsSelected = false;
break;
}

Karsten Suehring
committed
if( !cu.ispMode )
{
csSplit->setDecomp( partitioner.currArea().Y() );
}
else if( CU::isISPFirst( cu, partitioner.currArea().Y(), COMPONENT_Y ) )
{
csSplit->setDecomp( cu.Y() );
}

Karsten Suehring
committed
uiSplitCbfLuma |= TU::getCbfAtDepth( *csSplit->getTU( partitioner.currArea().lumaPos(), partitioner.chType, subTuCounter - 1 ), COMPONENT_Y, partitioner.currTrDepth );
if( cu.ispMode )
{
//exit condition if the accumulated cost is already larger than the best cost so far (no impact in RD performance)
if( csSplit->cost > bestCostSoFar )
{
earlySkipISP = true;
splitIsSelected = false;
break;
}
else
{
//more restrictive exit condition
bool tuIsDividedInRows = CU::divideTuInRows( cu );
int nSubPartitions = tuIsDividedInRows ? cu.lheight() >> floorLog2(cu.firstTU->lheight()) : cu.lwidth() >> floorLog2(cu.firstTU->lwidth());
Santiago de Luxán Hernández
committed
double threshold = nSubPartitions == 2 ? 0.95 : subTuCounter == 1 ? 0.83 : 0.91;
if( subTuCounter < nSubPartitions && csSplit->cost > bestCostSoFar*threshold )
{
earlySkipISP = true;
splitIsSelected = false;
break;
}
}
}

Karsten Suehring
committed
13231
13232
13233
13234
13235
13236
13237
13238
13239
13240
13241
13242
13243
13244
13245
13246
13247
} while( partitioner.nextPart( *csSplit ) );
partitioner.exitCurrSplit();
if( splitIsSelected )
{
for( auto &ptu : csSplit->tus )
{
if( currArea.Y().contains( ptu->Y() ) )
{
TU::setCbfAtDepth( *ptu, COMPONENT_Y, currDepth, uiSplitCbfLuma ? 1 : 0 );
}
}
//----- restore context states -----
m_CABACEstimator->getCtx() = ctxStart;
cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_LUMA] = false;
cuCtx.violatesLfnstConstrained[CHANNEL_TYPE_CHROMA] = false;
cuCtx.lfnstLastScanPos = false;
cuCtx.violatesMtsCoeffConstraint = false;
cuCtx.mtsLastScanPos = false;
#if JVET_Y0142_ADAPT_INTRA_MTS
cuCtx.mtsCoeffAbsSum = 0;
#endif

Karsten Suehring
committed
//----- determine rate and r-d cost -----
csSplit->fracBits = xGetIntraFracBitsQT( *csSplit, partitioner, true, false, cu.ispMode ? 0 : -1, ispType, &cuCtx );

Karsten Suehring
committed
//--- update cost ---
csSplit->cost = m_pcRdCost->calcRdCost(csSplit->fracBits, csSplit->dist);
validReturnSplit = true;

Karsten Suehring
committed
}
}
bool retVal = false;

Karsten Suehring
committed
if( csFull || csSplit )
{
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( !spsIntraLfnstEnabled || validReturnFull || validReturnSplit )
#else
if( !sps.getUseLFNST() || validReturnFull || validReturnSplit )

Karsten Suehring
committed
{
// otherwise this would've happened in useSubStructure
#if JVET_Z0118_GDR
cs.updateReconMotIPM(currArea.Y());
#else
cs.picture->getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y()));
cs.picture->getPredBuf(currArea.Y()).copyFrom(cs.getPredBuf(currArea.Y()));

Karsten Suehring
committed
if( cu.ispMode && earlySkipISP )
{
cs.cost = MAX_DOUBLE;
}
else
{
cs.cost = m_pcRdCost->calcRdCost( cs.fracBits, cs.dist );
retVal = true;
}

Karsten Suehring
committed
}

Karsten Suehring
committed
}
bool IntraSearch::xRecurIntraCodingACTQT(CodingStructure &cs, Partitioner &partitioner, bool mtsCheckRangeFlag, int mtsFirstCheckId, int mtsLastCheckId, bool moreProbMTSIdxFirst)
{
const UnitArea &currArea = partitioner.currArea();
uint32_t currDepth = partitioner.currTrDepth;
const Slice &slice = *cs.slice;
const SPS &sps = *cs.sps;
Waqas Ahmad
committed
bool bCheckFull = !partitioner.canSplit(TU_MAX_TR_SPLIT, cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
);
bool bCheckSplit = !bCheckFull;
TempCtx ctxStart(m_ctxCache, m_CABACEstimator->getCtx());
TempCtx ctxBest(m_ctxCache);
CodingStructure *csSplit = nullptr;
CodingStructure *csFull = nullptr;
if (bCheckSplit)
{
csSplit = &cs;
}
else if (bCheckFull)
{
csFull = &cs;
}
bool validReturnFull = false;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
bool spsIntraLfnstEnabled = ( ( slice.getSliceType() == I_SLICE && sps.getUseIntraLFNSTISlice() ) ||
( slice.getSliceType() != I_SLICE && sps.getUseIntraLFNSTPBSlice() ) );
#endif
13331
13332
13333
13334
13335
13336
13337
13338
13339
13340
13341
13342
13343
13344
13345
13346
13347
13348
if (bCheckFull)
{
TransformUnit &tu = csFull->addTU(CS::getArea(*csFull, currArea, partitioner.chType), partitioner.chType);
tu.depth = currDepth;
const CodingUnit &cu = *csFull->getCU(tu.Y().pos(), CHANNEL_TYPE_LUMA);
const PredictionUnit &pu = *csFull->getPU(tu.Y().pos(), CHANNEL_TYPE_LUMA);
CHECK(!tu.Y().valid() || !tu.Cb().valid() || !tu.Cr().valid(), "Invalid TU");
CHECK(tu.cu != &cu, "wrong CU fetch");
CHECK(cu.ispMode, "adaptive color transform cannot be applied to ISP");
CHECK(pu.intraDir[CHANNEL_TYPE_CHROMA] != DM_CHROMA_IDX, "chroma should use DM mode for adaptive color transform");
// 1. intra prediction and forward color transform
PelUnitBuf orgBuf = csFull->getOrgBuf(tu);
PelUnitBuf predBuf = csFull->getPredBuf(tu);
PelUnitBuf resiBuf = csFull->getResiBuf(tu);
PelUnitBuf orgResiBuf = csFull->getOrgResiBuf(tu);
#if JVET_S0234_ACT_CRS_FIX
bool doReshaping = (slice.getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (slice.isIntra() || m_pcReshape->getCTUFlag()) && (tu.blocks[COMPONENT_Cb].width * tu.blocks[COMPONENT_Cb].height > 4));
if (doReshaping)
{
const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size()));
const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area);
int adj = m_pcReshape->calculateChromaAdjVpduNei(tu, areaY);
tu.setChromaAdj(adj);
}
#endif
for (int i = 0; i < getNumberValidComponents(tu.chromaFormat); i++)
{
ComponentID compID = (ComponentID)i;
const CompArea &area = tu.blocks[compID];
const ChannelType chType = toChannelType(compID);
PelBuf piOrg = orgBuf.bufs[compID];
PelBuf piPred = predBuf.bufs[compID];
PelBuf piResi = resiBuf.bufs[compID];
initIntraPatternChType(*tu.cu, area);
#if JVET_V0130_INTRA_TMP && !JVET_W0069_TMP_BOUNDARY
if( PU::isTmp( pu, chType ) )
{
int foundCandiNum;
getTargetTemplate( pu.cu, pu.lwidth(), pu.lheight() );
candidateSearchIntra( pu.cu, pu.lwidth(), pu.lheight() );
generateTMPrediction( piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), foundCandiNum );
CHECK( foundCandiNum < 1, "" );
}
else if( PU::isMIP( pu, chType ) )
if (PU::isMIP(pu, chType))
initIntraMip(pu, area);
#if JVET_AB0067_MIP_DIMD_LFNST
#if JVET_AH0076_OBIC
predIntraMip(compID, piPred, pu, true);
#else
predIntraMip(compID, piPred, pu, pu.cu->lfnstIdx > 0 ? true : false);
#endif
predIntraMip(compID, piPred, pu);
}
else
{
predIntraAng(compID, piPred, pu);
}
piResi.copyFrom(piOrg);
if (slice.getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && compID == COMPONENT_Y)
{
CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
PelBuf tmpPred = m_tmpStorageLCU.getBuf(tmpArea);
piResi.subtract(tmpPred);
}
#if JVET_S0234_ACT_CRS_FIX
else if (doReshaping && (compID != COMPONENT_Y))
{
piResi.subtract(piPred);
int cResScaleInv = tu.getChromaAdj();
piResi.scaleSignal(cResScaleInv, 1, slice.clpRng(compID));
}
#endif
piResi.subtract(piPred);
resiBuf.colorSpaceConvert(orgResiBuf, true, cs.slice->clpRng(COMPONENT_Y));
// 2. luma residual optimization
double dSingleCostLuma = MAX_DOUBLE;
bool checkTransformSkip = sps.getTransformSkipEnabledFlag();
int bestLumaModeId = 0;
uint8_t nNumTransformCands = cu.mtsFlag ? 4 : 1;
uint8_t numTransformIndexCands = nNumTransformCands;
const bool tsAllowed = TU::isTSAllowed(tu, COMPONENT_Y);
const bool mtsAllowed = CU::isMTSAllowed(cu, COMPONENT_Y);
std::vector<TrMode> trModes;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if (sps.getUseLFNST())
{
checkTransformSkip &= tsAllowed;
checkTransformSkip &= !cu.mtsFlag;
checkTransformSkip &= !cu.lfnstIdx;
if (!cu.mtsFlag && checkTransformSkip)
{
trModes.push_back(TrMode(0, true)); //DCT2
trModes.push_back(TrMode(1, true)); //TS
}
}
else
{
if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
{
nNumTransformCands = 1;
CHECK(!tsAllowed && !cu.bdpcmMode, "transform skip should be enabled for LS");
if (cu.bdpcmMode)
{
trModes.push_back(TrMode(0, true));
}
else
{
trModes.push_back(TrMode(1, true));
}
}
else
{
nNumTransformCands = 1 + (tsAllowed ? 1 : 0) + (mtsAllowed ? 4 : 0); // DCT + TS + 4 MTS = 6 tests
trModes.push_back(TrMode(0, true)); // DCT2
if (tsAllowed)
trModes.push_back(TrMode(1, true));
}
if (mtsAllowed)
{
for (int i = 2; i < 6; i++)
{
trModes.push_back(TrMode(i, true));
}
}
CodingStructure &saveLumaCS = *m_pSaveCS[0];
TransformUnit *tmpTU = nullptr;
Distortion singleDistTmpLuma = 0;
uint64_t singleTmpFracBits = 0;
double singleCostTmp = 0;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
int firstCheckId = ( spsIntraLfnstEnabled && mtsCheckRangeFlag && cu.mtsFlag ) ? mtsFirstCheckId : 0;
int lastCheckId = spsIntraLfnstEnabled ? ( ( mtsCheckRangeFlag && cu.mtsFlag ) ? ( mtsLastCheckId + ( int ) checkTransformSkip ) : ( numTransformIndexCands - ( firstCheckId + 1 ) + ( int ) checkTransformSkip ) ) : trModes[ nNumTransformCands - 1 ].first;
bool isNotOnlyOneMode = spsIntraLfnstEnabled ? lastCheckId != firstCheckId : nNumTransformCands != 1;
#else
int firstCheckId = (sps.getUseLFNST() && mtsCheckRangeFlag && cu.mtsFlag) ? mtsFirstCheckId : 0;
int lastCheckId = sps.getUseLFNST() ? ((mtsCheckRangeFlag && cu.mtsFlag) ? (mtsLastCheckId + (int)checkTransformSkip) : (numTransformIndexCands - (firstCheckId + 1) + (int)checkTransformSkip)) : trModes[nNumTransformCands - 1].first;
bool isNotOnlyOneMode = sps.getUseLFNST() ? lastCheckId != firstCheckId : nNumTransformCands != 1;
if (isNotOnlyOneMode)
{
saveLumaCS.pcv = csFull->pcv;
saveLumaCS.picture = csFull->picture;
saveLumaCS.area.repositionTo(csFull->area);
saveLumaCS.clearTUs();
tmpTU = &saveLumaCS.addTU(currArea, partitioner.chType);
}
bool cbfBestMode = false;
bool cbfBestModeValid = false;
bool cbfDCT2 = true;
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
m_pcRdCost->lambdaAdjustColorTrans(true, COMPONENT_Y);
for (int modeId = firstCheckId; modeId <= ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()) ? (nNumTransformCands - 1) : lastCheckId); modeId++)
{
uint8_t transformIndex = modeId;
csFull->getResiBuf(tu.Y()).copyFrom(csFull->getOrgResiBuf(tu.Y()));
m_CABACEstimator->getCtx() = ctxStart;
m_CABACEstimator->resetBits();
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if (sps.getUseLFNST())
{
if ((transformIndex < lastCheckId) || ((transformIndex == lastCheckId) && !checkTransformSkip)) //we avoid this if the mode is transformSkip
{
// Skip checking other transform candidates if zero CBF is encountered and it is the best transform so far
if (m_pcEncCfg->getUseFastLFNST() && transformIndex && !cbfBestMode && cbfBestModeValid)
{
continue;
}
}
}
else
{
if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()))
if (!cbfDCT2 || (m_pcEncCfg->getUseTransformSkipFast() && bestLumaModeId == 1))
{
break;
}
if (!trModes[modeId].second)
{
continue;
}
tu.mtsIdx[COMPONENT_Y] = trModes[modeId].first;
}
singleDistTmpLuma = 0;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if (sps.getUseLFNST())
13561
13562
13563
13564
13565
13566
13567
13568
13569
13570
13571
13572
13573
13574
13575
13576
13577
13578
13579
13580
13581
13582
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
13608
13609
13610
13611
13612
13613
13614
13615
13616
13617
13618
13619
13620
13621
13622
13623
13624
13625
13626
13627
13628
13629
13630
13631
{
if (cu.mtsFlag)
{
if (moreProbMTSIdxFirst)
{
uint32_t uiIntraMode = pu.intraDir[CHANNEL_TYPE_LUMA];
if (transformIndex == 1)
{
tu.mtsIdx[COMPONENT_Y] = (uiIntraMode < 34) ? MTS_DST7_DCT8 : MTS_DCT8_DST7;
}
else if (transformIndex == 2)
{
tu.mtsIdx[COMPONENT_Y] = (uiIntraMode < 34) ? MTS_DCT8_DST7 : MTS_DST7_DCT8;
}
else
{
tu.mtsIdx[COMPONENT_Y] = MTS_DST7_DST7 + transformIndex;
}
}
else
{
tu.mtsIdx[COMPONENT_Y] = MTS_DST7_DST7 + transformIndex;
}
}
else
{
tu.mtsIdx[COMPONENT_Y] = transformIndex;
}
if (!cu.mtsFlag && checkTransformSkip)
{
xIntraCodingACTTUBlock(tu, COMPONENT_Y, singleDistTmpLuma, modeId == 0 ? &trModes : nullptr, true);
if (modeId == 0)
{
for (int i = 0; i < 2; i++)
{
if (trModes[i].second)
{
lastCheckId = trModes[i].first;
}
}
}
}
else
{
xIntraCodingACTTUBlock(tu, COMPONENT_Y, singleDistTmpLuma);
}
}
else
{
if (nNumTransformCands > 1)
{
xIntraCodingACTTUBlock(tu, COMPONENT_Y, singleDistTmpLuma, modeId == 0 ? &trModes : nullptr, true);
if (modeId == 0)
{
for (int i = 0; i < nNumTransformCands; i++)
{
if (trModes[i].second)
{
lastCheckId = trModes[i].first;
}
}
}
}
else
{
xIntraCodingACTTUBlock(tu, COMPONENT_Y, singleDistTmpLuma);
}
}
CUCtx cuCtx;
cuCtx.isDQPCoded = true;
cuCtx.isChromaQpAdjCoded = true;
//----- determine rate and r-d cost -----
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( ( spsIntraLfnstEnabled ? ( modeId == lastCheckId && modeId != 0 && checkTransformSkip ) : ( trModes[ modeId ].first != 0 ) ) && !TU::getCbfAtDepth( tu, COMPONENT_Y, currDepth ) )
#else
if ((sps.getUseLFNST() ? (modeId == lastCheckId && modeId != 0 && checkTransformSkip) : (trModes[modeId].first != 0)) && !TU::getCbfAtDepth(tu, COMPONENT_Y, currDepth))
{
//In order not to code TS flag when cbf is zero, the case for TS with cbf being zero is forbidden.
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
singleCostTmp = MAX_DOUBLE;
else
{
singleTmpFracBits = xGetIntraFracBitsQT(*csFull, partitioner, true, false, -1, TU_NO_ISP);
singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma, false);
}
}
else
{
singleTmpFracBits = xGetIntraFracBitsQT(*csFull, partitioner, true, false, -1, TU_NO_ISP, &cuCtx);
if (tu.mtsIdx[COMPONENT_Y] > MTS_SKIP)
{
#if JVET_Y0142_ADAPT_INTRA_MTS
int nCands = (cuCtx.mtsCoeffAbsSum > MTS_TH_COEFF[1]) ? MTS_NCANDS[2] : (cuCtx.mtsCoeffAbsSum > MTS_TH_COEFF[0]) ? MTS_NCANDS[1] : MTS_NCANDS[0];
bool isInvalid = !cuCtx.mtsLastScanPos || ((tu.mtsIdx[COMPONENT_Y] - MTS_DST7_DST7) >= nCands);
if (isInvalid)
#else
if (!cuCtx.mtsLastScanPos)
{
singleCostTmp = MAX_DOUBLE;
}
else
{
singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma, false);
}
}
else
{
singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma, false);
}
}
if (singleCostTmp < dSingleCostLuma)
{
dSingleCostLuma = singleCostTmp;
validReturnFull = true;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if (sps.getUseLFNST())
13688
13689
13690
13691
13692
13693
13694
13695
13696
13697
13698
13699
13700
13701
13702
13703
13704
13705
13706
13707
13708
13709
{
bestLumaModeId = modeId;
cbfBestMode = TU::getCbfAtDepth(tu, COMPONENT_Y, currDepth);
cbfBestModeValid = true;
}
else
{
bestLumaModeId = trModes[modeId].first;
if (trModes[modeId].first == 0)
{
cbfDCT2 = TU::getCbfAtDepth(tu, COMPONENT_Y, currDepth);
}
}
if (bestLumaModeId != lastCheckId)
{
saveLumaCS.getResiBuf(tu.Y()).copyFrom(csFull->getResiBuf(tu.Y()));
tmpTU->copyComponentFrom(tu, COMPONENT_Y);
ctxBest = m_CABACEstimator->getCtx();
}
}
}
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
m_pcRdCost->lambdaAdjustColorTrans(false, COMPONENT_Y);
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if (sps.getUseLFNST())
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
{
if (!validReturnFull)
{
csFull->cost = MAX_DOUBLE;
return false;
}
}
else
{
CHECK(!validReturnFull, "no transform mode was tested for luma");
}
csFull->setDecomp(currArea.Y(), true);
csFull->setDecomp(currArea.Cb(), true);
if (bestLumaModeId != lastCheckId)
{
csFull->getResiBuf(tu.Y()).copyFrom(saveLumaCS.getResiBuf(tu.Y()));
tu.copyComponentFrom(*tmpTU, COMPONENT_Y);
m_CABACEstimator->getCtx() = ctxBest;
}
// 3 chroma residual optimization
CodingStructure &saveChromaCS = *m_pSaveCS[1];
saveChromaCS.pcv = csFull->pcv;
saveChromaCS.picture = csFull->picture;
saveChromaCS.area.repositionTo(csFull->area);
saveChromaCS.initStructData(MAX_INT, true);
tmpTU = &saveChromaCS.addTU(currArea, partitioner.chType);
CompArea& cbArea = tu.blocks[COMPONENT_Cb];
CompArea& crArea = tu.blocks[COMPONENT_Cr];
tu.jointCbCr = 0;
#if !JVET_S0234_ACT_CRS_FIX
bool doReshaping = (slice.getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (slice.isIntra() || m_pcReshape->getCTUFlag()) && (cbArea.width * cbArea.height > 4));
if (doReshaping)
{
#if LMCS_CHROMA_CALC_CU
const Area area = tu.cu->Y().valid() ? tu.cu->Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.cu->blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.cu->blocks[tu.chType].size()));
#else
const Area area = tu.Y().valid() ? tu.Y() : Area(recalcPosition(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].pos()), recalcSize(tu.chromaFormat, tu.chType, CHANNEL_TYPE_LUMA, tu.blocks[tu.chType].size()));
const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area);
int adj = m_pcReshape->calculateChromaAdjVpduNei(tu, areaY);
tu.setChromaAdj(adj);
}
#endif
CompStorage orgResiCb[5], orgResiCr[5]; // 0:std, 1-3:jointCbCr (placeholder at this stage), 4:crossComp
orgResiCb[0].create(cbArea);
orgResiCr[0].create(crArea);
orgResiCb[0].copyFrom(csFull->getOrgResiBuf(cbArea));
orgResiCr[0].copyFrom(csFull->getOrgResiBuf(crArea));
#if !JVET_S0234_ACT_CRS_FIX
if (doReshaping)
{
int cResScaleInv = tu.getChromaAdj();
orgResiCb[0].scaleSignal(cResScaleInv, 1, slice.clpRng(COMPONENT_Cb));
orgResiCr[0].scaleSignal(cResScaleInv, 1, slice.clpRng(COMPONENT_Cr));
}
#endif
// 3.1 regular chroma residual coding
csFull->getResiBuf(cbArea).copyFrom(orgResiCb[0]);
csFull->getResiBuf(crArea).copyFrom(orgResiCr[0]);
for (uint32_t c = COMPONENT_Cb; c < ::getNumberValidTBlocks(*csFull->pcv); c++)
{
const ComponentID compID = ComponentID(c);
double dSingleBestCostChroma = MAX_DOUBLE;
int bestModeId = -1;
bool tsAllowed = TU::isTSAllowed(tu, compID) && (m_pcEncCfg->getUseChromaTS()) && !cu.lfnstIdx;
uint8_t numTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
bool cbfDCT2 = true;
trModes.clear();
if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
13797
13798
13799
13800
13801
13802
13803
13804
13805
13806
13807
13808
13809
13810
13811
13812
13813
13814
13815
13816
{
numTransformCands = 1;
CHECK(!tsAllowed && !cu.bdpcmModeChroma, "transform skip should be enabled for LS");
if (cu.bdpcmModeChroma)
{
trModes.push_back(TrMode(0, true));
}
else
{
trModes.push_back(TrMode(1, true));
}
}
else
{
trModes.push_back(TrMode(0, true)); // DCT
if (tsAllowed)
{
trModes.push_back(TrMode(1, true)); // TS
}
}
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
#if JVET_S0234_ACT_CRS_FIX
{
if (doReshaping)
{
int cResScaleInv = tu.getChromaAdj();
m_pcRdCost->lambdaAdjustColorTrans(true, compID, true, &cResScaleInv);
}
else
{
m_pcRdCost->lambdaAdjustColorTrans(true, compID);
}
}
#else
m_pcRdCost->lambdaAdjustColorTrans(true, compID);
#endif
ctxBegin = m_CABACEstimator->getCtx();
for (int modeId = 0; modeId < numTransformCands; modeId++)
{
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
13842
13843
13844
13845
13846
13847
13848
13849
13850
13851
13852
13853
13854
13855
13856
13857
13858
{
if (modeId && !cbfDCT2)
{
continue;
}
if (!trModes[modeId].second)
{
continue;
}
}
if (modeId > 0)
{
m_CABACEstimator->getCtx() = ctxBegin;
}
tu.mtsIdx[compID] = trModes[modeId].first;
Distortion singleDistChroma = 0;
if (numTransformCands > 1)
13862
13863
13864
13865
13866
13867
13868
13869
13870
13871
13872
13873
13874
13875
13876
13877
13878
13879
13880
13881
13882
13883
xIntraCodingACTTUBlock(tu, compID, singleDistChroma, modeId == 0 ? &trModes : nullptr, true);
}
else
{
xIntraCodingACTTUBlock(tu, compID, singleDistChroma);
}
if (!tu.mtsIdx[compID])
{
cbfDCT2 = TU::getCbfAtDepth(tu, compID, currDepth);
}
uint64_t fracBitChroma = xGetIntraFracBitsQTChroma(tu, compID);
double dSingleCostChroma = m_pcRdCost->calcRdCost(fracBitChroma, singleDistChroma, false);
if (dSingleCostChroma < dSingleBestCostChroma)
{
dSingleBestCostChroma = dSingleCostChroma;
bestModeId = modeId;
if (bestModeId != (numTransformCands - 1))
{
saveChromaCS.getResiBuf(tu.blocks[compID]).copyFrom(csFull->getResiBuf(tu.blocks[compID]));
tmpTU->copyComponentFrom(tu, compID);
ctxBest = m_CABACEstimator->getCtx();
}
}
}
if (bestModeId != (numTransformCands - 1))
{
csFull->getResiBuf(tu.blocks[compID]).copyFrom(saveChromaCS.getResiBuf(tu.blocks[compID]));
tu.copyComponentFrom(*tmpTU, compID);
m_CABACEstimator->getCtx() = ctxBest;
}
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
m_pcRdCost->lambdaAdjustColorTrans(false, compID);
}
Position tuPos = tu.Y();
tuPos.relativeTo(cu.Y());
const UnitArea relativeUnitArea(tu.chromaFormat, Area(tuPos, tu.Y().size()));
PelUnitBuf invColorTransResidual = m_colorTransResiBuf.getBuf(relativeUnitArea);
csFull->getResiBuf(tu).colorSpaceConvert(invColorTransResidual, false, cs.slice->clpRng(COMPONENT_Y));
Distortion totalDist = 0;
for (uint32_t c = COMPONENT_Y; c < ::getNumberValidTBlocks(*csFull->pcv); c++)
{
const ComponentID compID = ComponentID(c);
const CompArea& area = tu.blocks[compID];
PelBuf piOrg = csFull->getOrgBuf(area);
PelBuf piReco = csFull->getRecoBuf(area);
PelBuf piPred = csFull->getPredBuf(area);
PelBuf piResi = invColorTransResidual.bufs[compID];
#if JVET_S0234_ACT_CRS_FIX
if (doReshaping && (compID != COMPONENT_Y))
{
piResi.scaleSignal(tu.getChromaAdj(), 0, slice.clpRng(compID));
}
#endif
piReco.reconstruct(piPred, piResi, cs.slice->clpRng(compID));
if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcEncCfg->getLmcs()
Heiner Kirchhoffer
committed
&& slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD()))))
{
const CPelBuf orgLuma = csFull->getOrgBuf(csFull->area.blocks[COMPONENT_Y]);
if (compID == COMPONENT_Y && !(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()))
{
CompArea tmpArea1(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
PelBuf tmpRecLuma = m_tmpStorageLCU.getBuf(tmpArea1);
13932
13933
13934
13935
13936
13937
13938
13939
13940
13941
13942
13943
13944
13945
13946
13947
13948
13949
13950
13951
13952
13953
13954
13955
13956
13957
13958
13959
13960
13961
13962
13963
13964
13965
13966
13967
13968
13969
13970
13971
13972
totalDist += m_pcRdCost->getDistPart(piOrg, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
}
else
{
totalDist += m_pcRdCost->getDistPart(piOrg, piReco, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
}
}
else
{
totalDist += m_pcRdCost->getDistPart(piOrg, piReco, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE);
}
}
m_CABACEstimator->getCtx() = ctxStart;
uint64_t totalBits = xGetIntraFracBitsQT(*csFull, partitioner, true, true, -1, TU_NO_ISP);
double totalCost = m_pcRdCost->calcRdCost(totalBits, totalDist);
saveChromaCS.getResiBuf(cbArea).copyFrom(csFull->getResiBuf(cbArea));
saveChromaCS.getResiBuf(crArea).copyFrom(csFull->getResiBuf(crArea));
saveChromaCS.getRecoBuf(tu).copyFrom(csFull->getRecoBuf(tu));
tmpTU->copyComponentFrom(tu, COMPONENT_Cb);
tmpTU->copyComponentFrom(tu, COMPONENT_Cr);
ctxBest = m_CABACEstimator->getCtx();
// 3.2 jointCbCr
double bestCostJointCbCr = totalCost;
Distortion bestDistJointCbCr = totalDist;
uint64_t bestBitsJointCbCr = totalBits;
int bestJointCbCr = tu.jointCbCr; assert(!bestJointCbCr);
bool lastIsBest = false;
std::vector<int> jointCbfMasksToTest;
if (sps.getJointCbCrEnabledFlag() && (TU::getCbf(tu, COMPONENT_Cb) || TU::getCbf(tu, COMPONENT_Cr)))
{
jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(tu, orgResiCb, orgResiCr);
}
for (int cbfMask : jointCbfMasksToTest)
{
tu.jointCbCr = (uint8_t)cbfMask;
ComponentID codeCompId = ((cbfMask >> 1) ? COMPONENT_Cb : COMPONENT_Cr);
ComponentID otherCompId = ((codeCompId == COMPONENT_Cb) ? COMPONENT_Cr : COMPONENT_Cb);
bool tsAllowed = TU::isTSAllowed(tu, codeCompId) && (m_pcEncCfg->getUseChromaTS()) && !cu.lfnstIdx;
uint8_t numTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
bool cbfDCT2 = true;
trModes.clear();
trModes.push_back(TrMode(0, true)); // DCT2
13981
13982
13983
13984
13985
13986
13987
13988
13989
13990
13991
13992
13993
13994
13995
13996
13997
13998
13999
if (tsAllowed)
{
trModes.push_back(TrMode(1, true));//TS
}
for (int modeId = 0; modeId < numTransformCands; modeId++)
{
if (modeId && !cbfDCT2)
{
continue;
}
if (!trModes[modeId].second)
{
continue;
}
Distortion distTmp = 0;
tu.mtsIdx[codeCompId] = trModes[modeId].first;
tu.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
m_CABACEstimator->getCtx() = ctxStart;
csFull->getResiBuf(cbArea).copyFrom(orgResiCb[cbfMask]);