Newer
Older
tmpRecChroma.copyFrom(piReco);
}
#endif
//===== update distortion =====
#if WCG_EXT
if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcEncCfg->getLmcs()
&& slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD()))))
{
const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
{
if(!(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()))
{
tmpRecLuma.rspSignal(m_pcReshape->getInvLUT());
#if JVET_AF0112_BIF_DYNAMIC_SCALING
bool applyBIF = pps.getUseBIF() && m_bilateralFilter->getApplyBIF(tu, compID);
#else
bool applyBIF = pps.getUseBIF() /*&& (uiAbsSum > 0)*/ && tu.cu->qp > 17 && 128 > std::max(tu.lumaSize().width, tu.lumaSize().height);
#endif
if(applyBIF)
CompArea compArea = tu.blocks[compID];
PelBuf recIPredBuf = cs.slice->getPic()->getRecoBuf(compArea);
if(!(m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled()))
{
m_bilateralFilter->bilateralFilterRDOdiamond5x5( compID, tmpRecLuma, tmpRecLuma, tmpRecLuma, tu.cu->qp, recIPredBuf, cs.slice->clpRng( compID ), tu, true, true, &m_pcReshape->getInvLUT() );
m_bilateralFilter->bilateralFilterRDOdiamond5x5( compID, tmpRecLuma, tmpRecLuma, tmpRecLuma, tu.cu->qp, recIPredBuf, cs.slice->clpRng( compID ), tu, true, false, &invLUT );
ruiDist += m_pcRdCost->getDistPart(piOrg, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
#if JVET_X0071_CHROMA_BILATERAL_FILTER
#if JVET_AF0112_BIF_DYNAMIC_SCALING
bool applyChromaBIF = pps.getUseChromaBIF() && m_bilateralFilter->getApplyBIF(tu, compID);
#else
bool applyChromaBIF = pps.getUseChromaBIF() && tu.cu->qp > 17;
#endif
if(applyChromaBIF)
CompArea compArea = tu.blocks[compID];
PelBuf recIPredBuf = cs.slice->getPic()->getRecoBuf(compArea);
m_bilateralFilter->bilateralFilterRDOdiamond5x5( compID, tmpRecChroma, tmpRecChroma, tmpRecChroma, tu.cu->qp, recIPredBuf, cs.slice->clpRng(compID), tu, true );
ruiDist += m_pcRdCost->getDistPart(piOrg, tmpRecChroma, bitDepth, compID, DF_SSE_WTD, &orgLuma);
#else
ruiDist += m_pcRdCost->getDistPart(piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma);
#endif
if( jointCbCr )
#if JVET_X0071_CHROMA_BILATERAL_FILTER
if(compID == COMPONENT_Cr)
{
ruiDist += m_pcRdCost->getDistPart(crOrg, tmpRecChroma, bitDepth, COMPONENT_Cr, DF_SSE_WTD, &orgLuma);
}
else
{
ruiDist += m_pcRdCost->getDistPart(crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE_WTD, &orgLuma);
}
#else
ruiDist += m_pcRdCost->getDistPart(crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE_WTD, &orgLuma);
#endif
#if JVET_AF0112_BIF_DYNAMIC_SCALING
bool applyBIF = pps.getUseBIF() && m_bilateralFilter->getApplyBIF(tu, compID);
#else
bool applyBIF = pps.getUseBIF() /*&& (uiAbsSum > 0)*/ && tu.cu->qp > 17 && 128 > std::max(tu.lumaSize().width, tu.lumaSize().height);
#endif
if(applyBIF)
{
CompArea compArea = tu.blocks[compID];
PelBuf recIPredBuf = cs.slice->getPic()->getRecoBuf(compArea);
m_bilateralFilter->bilateralFilterRDOdiamond5x5( compID, tmpRecLuma, tmpRecLuma, tmpRecLuma, tu.cu->qp, recIPredBuf, cs.slice->clpRng( compID ), tu, true, false, &invLUT );
ruiDist += m_pcRdCost->getDistPart( piOrg, tmpRecLuma, bitDepth, compID, DF_SSE );
#if JVET_X0071_CHROMA_BILATERAL_FILTER
#if JVET_AF0112_BIF_DYNAMIC_SCALING
bool applyChromaBIF = pps.getUseChromaBIF() && m_bilateralFilter->getApplyBIF(tu, compID);
#else
bool applyChromaBIF = pps.getUseChromaBIF() && isChroma(compID) && (tu.cu->qp > 17);
#endif
if (applyChromaBIF)
CompArea compArea = tu.blocks[compID];
PelBuf recIPredBuf = cs.slice->getPic()->getRecoBuf(compArea);
m_bilateralFilter->bilateralFilterRDOdiamond5x5( compID, tmpRecChroma, tmpRecChroma, tmpRecChroma, tu.cu->qp, recIPredBuf, cs.slice->clpRng(compID), tu, true );
ruiDist += m_pcRdCost->getDistPart( piOrg, tmpRecChroma, bitDepth, compID, DF_SSE );
#else
ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
#endif
if( jointCbCr )
#if JVET_X0071_CHROMA_BILATERAL_FILTER
if(compID == COMPONENT_Cr)
{
ruiDist += m_pcRdCost->getDistPart( crOrg, tmpRecChroma, bitDepth, COMPONENT_Cr, DF_SSE );
}
else
{
ruiDist += m_pcRdCost->getDistPart( crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE );
}
#else
ruiDist += m_pcRdCost->getDistPart( crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE );
#endif

Karsten Suehring
committed
//===== update distortion =====
#if JVET_X0071_CHROMA_BILATERAL_FILTER
CompArea tmpArea2(compID, area.chromaFormat, Position(0, 0), area.size());
PelBuf tmpRecChroma;
if(isChroma(compID))
{
tmpRecChroma = m_tmpStorageLCU.getBuf(tmpArea2);
tmpRecChroma.copyFrom(piReco);
}
#if WCG_EXT
if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcEncCfg->getLmcs() && slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD()))))
{
const CPelBuf orgLuma = cs.getOrgBuf( cs.area.blocks[COMPONENT_Y] );
if(isLuma(compID))
{
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);
tmpRecLuma.rspSignal( piReco, m_pcReshape->getInvLUT() );
ruiDist += m_pcRdCost->getDistPart(piOrg, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
}
else
{
ruiDist += m_pcRdCost->getDistPart(piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma);
if( jointCbCr )
{
ruiDist += m_pcRdCost->getDistPart(crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE_WTD, &orgLuma);
}
}
}
else
{
#if JVET_AF0112_BIF_DYNAMIC_SCALING
bool applyChromaBIF = pps.getUseChromaBIF() && m_bilateralFilter->getApplyBIF(tu, compID);
#else
bool applyChromaBIF = pps.getUseChromaBIF() && tu.cu->qp > 17;
#endif
if (applyChromaBIF)
{
CompArea compArea = tu.blocks[compID];
PelBuf recIPredBuf = cs.slice->getPic()->getRecoBuf(compArea);
m_bilateralFilter->bilateralFilterRDOdiamond5x5( compID, tmpRecChroma, tmpRecChroma, tmpRecChroma, tu.cu->qp, recIPredBuf, cs.slice->clpRng(compID), tu, true );
ruiDist += m_pcRdCost->getDistPart(piOrg, tmpRecChroma, bitDepth, compID, DF_SSE_WTD, &orgLuma);
if( jointCbCr )
{
if(compID == COMPONENT_Cr)
{
ruiDist += m_pcRdCost->getDistPart(crOrg, tmpRecChroma, bitDepth, COMPONENT_Cr, DF_SSE_WTD, &orgLuma);
}
else
{
ruiDist += m_pcRdCost->getDistPart(crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE_WTD, &orgLuma);
}
}
}
}
else
#endif
{
if(isLuma(compID))
{
ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
}
else
{
#if JVET_AF0112_BIF_DYNAMIC_SCALING
bool applyChromaBIF = pps.getUseChromaBIF() && m_bilateralFilter->getApplyBIF(tu, compID);
#else
bool applyChromaBIF = pps.getUseChromaBIF() && tu.cu->qp > 17;
#endif
if (applyChromaBIF)
CompArea compArea = tu.blocks[compID];
PelBuf recIPredBuf = cs.slice->getPic()->getRecoBuf(compArea);
m_bilateralFilter->bilateralFilterRDOdiamond5x5( compID, tmpRecChroma, tmpRecChroma, tmpRecChroma, tu.cu->qp, recIPredBuf, cs.slice->clpRng(compID), tu, true );
ruiDist += m_pcRdCost->getDistPart( piOrg, tmpRecChroma, bitDepth, compID, DF_SSE );
}
if( jointCbCr )
{
if(compID == COMPONENT_Cr)
{
ruiDist += m_pcRdCost->getDistPart( crOrg, tmpRecChroma, bitDepth, COMPONENT_Cr, DF_SSE );
ruiDist += m_pcRdCost->getDistPart( crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE );
}
#else

Karsten Suehring
committed
#if WCG_EXT
if (m_pcEncCfg->getLumaLevelToDeltaQPMapping().isEnabled() || (m_pcEncCfg->getLmcs()
&& slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || (isChroma(compID) && m_pcEncCfg->getReshapeIntraCMD()))))
const CPelBuf orgLuma = cs.getOrgBuf( cs.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);
tmpRecLuma.rspSignal( piReco, m_pcReshape->getInvLUT() );
ruiDist += m_pcRdCost->getDistPart(piOrg, tmpRecLuma, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE_WTD, &orgLuma);
}
else
{
ruiDist += m_pcRdCost->getDistPart(piOrg, piReco, bitDepth, compID, DF_SSE_WTD, &orgLuma);
if( jointCbCr )
{
ruiDist += m_pcRdCost->getDistPart(crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE_WTD, &orgLuma);
}
}
ruiDist += m_pcRdCost->getDistPart( piOrg, piReco, bitDepth, compID, DF_SSE );
if( jointCbCr )
{
ruiDist += m_pcRdCost->getDistPart( crOrg, crReco, bitDepth, COMPONENT_Cr, DF_SSE );
}
}

Karsten Suehring
committed
#endif
ROBERT Antoine
committed
#if INTRA_TRANS_ENC_OPT && SIGN_PREDICTION
#endif

Karsten Suehring
committed
}
12263
12264
12265
12266
12267
12268
12269
12270
12271
12272
12273
12274
12275
12276
12277
12278
12279
12280
12281
12282
12283
12284
12285
void IntraSearch::xIntraCodingACTTUBlock(TransformUnit &tu, const ComponentID &compID, Distortion& ruiDist, std::vector<TrMode>* trModes, const bool loadTr)
{
if (!tu.blocks[compID].valid())
{
CHECK(1, "tu does not exist");
}
CodingStructure &cs = *tu.cs;
const SPS &sps = *cs.sps;
const Slice &slice = *cs.slice;
const CompArea &area = tu.blocks[compID];
const CompArea &crArea = tu.blocks[COMPONENT_Cr];
PelBuf piOrgResi = cs.getOrgResiBuf(area);
PelBuf piResi = cs.getResiBuf(area);
PelBuf crOrgResi = cs.getOrgResiBuf(crArea);
PelBuf crResi = cs.getResiBuf(crArea);
TCoeff uiAbsSum = 0;
CHECK(tu.jointCbCr && compID == COMPONENT_Cr, "wrong combination of compID and jointCbCr");
bool jointCbCr = tu.jointCbCr && compID == COMPONENT_Cb;
m_pcRdCost->setChromaFormat(cs.sps->getChromaFormatIdc());
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
m_pcTrQuant->lambdaAdjustColorTrans(true);
if (jointCbCr)
{
ComponentID compIdCode = (tu.jointCbCr >> 1 ? COMPONENT_Cb : COMPONENT_Cr);
m_pcTrQuant->selectLambda(compIdCode);
}
else
{
m_pcTrQuant->selectLambda(compID);
}
bool flag = slice.getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag())) && (tu.blocks[compID].width*tu.blocks[compID].height > 4);
if (flag && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag())
12301
12302
12303
12304
12305
12306
12307
12308
12309
12310
12311
12312
12313
12314
12315
12316
12317
12318
12319
12320
12321
12322
12323
12324
12325
12326
12327
{
int cResScaleInv = tu.getChromaAdj();
double cResScale = (double)(1 << CSCALE_FP_PREC) / (double)cResScaleInv;
m_pcTrQuant->setLambda(m_pcTrQuant->getLambda() / (cResScale*cResScale));
}
if (jointCbCr)
{
// Lambda is loosened for the joint mode with respect to single modes as the same residual is used for both chroma blocks
const int absIct = abs(TU::getICTMode(tu));
const double lfact = (absIct == 1 || absIct == 3 ? 0.8 : 0.5);
m_pcTrQuant->setLambda(lfact * m_pcTrQuant->getLambda());
}
if (sps.getJointCbCrEnabledFlag() && isChroma(compID) && (slice.getSliceQp() > 18))
{
m_pcTrQuant->setLambda(1.3 * m_pcTrQuant->getLambda());
}
if (isLuma(compID))
{
QpParam cQP(tu, compID);
if (trModes)
{
m_pcTrQuant->transformNxN(tu, compID, cQP, trModes, m_pcEncCfg->getMTSIntraMaxCand());
tu.mtsIdx[compID] = trModes->at(0).first;
}
if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) || tu.cu->bdpcmMode != 0)
{
m_pcTrQuant->transformNxN(tu, compID, cQP, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
}
if ((m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[compID] == 0) && tu.cu->bdpcmMode == 0)
{
uiAbsSum = 0;
tu.getCoeffs(compID).fill(0);
TU::setCbfAtDepth(tu, compID, tu.depth, 0);
}
12338
12339
12340
12341
12342
12343
12344
12345
12346
12347
12348
12349
12350
12351
12352
12353
12354
12355
12356
12357
12358
12359
12360
12361
12362
if (uiAbsSum > 0)
{
m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP);
}
else
{
piResi.fill(0);
}
}
else
{
int codedCbfMask = 0;
ComponentID codeCompId = (tu.jointCbCr ? (tu.jointCbCr >> 1 ? COMPONENT_Cb : COMPONENT_Cr) : compID);
QpParam qpCbCr(tu, codeCompId);
if (tu.jointCbCr)
{
ComponentID otherCompId = (codeCompId == COMPONENT_Cr ? COMPONENT_Cb : COMPONENT_Cr);
tu.getCoeffs(otherCompId).fill(0);
TU::setCbfAtDepth(tu, otherCompId, tu.depth, false);
}
PelBuf& codeResi = (codeCompId == COMPONENT_Cr ? crResi : piResi);
uiAbsSum = 0;
if (trModes)
{
m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, trModes, m_pcEncCfg->getMTSIntraMaxCand());
tu.mtsIdx[codeCompId] = trModes->at(0).first;
if (tu.jointCbCr)
{
tu.mtsIdx[(codeCompId == COMPONENT_Cr) ? COMPONENT_Cb : COMPONENT_Cr] = MTS_DCT2_DCT2;
}
}
if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless() && tu.mtsIdx[codeCompId] == 0) || tu.cu->bdpcmModeChroma != 0)
{
m_pcTrQuant->transformNxN(tu, codeCompId, qpCbCr, uiAbsSum, m_CABACEstimator->getCtx(), loadTr);
}
12376
12377
12378
12379
12380
12381
12382
12383
12384
12385
12386
12387
12388
12389
12390
12391
12392
12393
12394
12395
if (uiAbsSum > 0)
{
m_pcTrQuant->invTransformNxN(tu, codeCompId, codeResi, qpCbCr);
codedCbfMask += (codeCompId == COMPONENT_Cb ? 2 : 1);
}
else
{
codeResi.fill(0);
}
if (tu.jointCbCr)
{
if (tu.jointCbCr == 3 && codedCbfMask == 2)
{
codedCbfMask = 3;
TU::setCbfAtDepth(tu, COMPONENT_Cr, tu.depth, true);
}
if (tu.jointCbCr != codedCbfMask)
{
ruiDist = std::numeric_limits<Distortion>::max();
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
m_pcTrQuant->lambdaAdjustColorTrans(false);
return;
}
m_pcTrQuant->invTransformICT(tu, piResi, crResi);
uiAbsSum = codedCbfMask;
}
}
#if !JVET_S0234_ACT_CRS_FIX
if (flag && uiAbsSum > 0 && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag())
{
piResi.scaleSignal(tu.getChromaAdj(), 0, slice.clpRng(compID));
if (jointCbCr)
{
crResi.scaleSignal(tu.getChromaAdj(), 0, slice.clpRng(COMPONENT_Cr));
}
}
#endif
if (m_pcEncCfg->getCostMode() != COST_LOSSLESS_CODING || !slice.isLossless())
m_pcTrQuant->lambdaAdjustColorTrans(false);
ruiDist += m_pcRdCost->getDistPart(piOrgResi, piResi, sps.getBitDepth(toChannelType(compID)), compID, DF_SSE);
if (jointCbCr)
{
ruiDist += m_pcRdCost->getDistPart(crOrgResi, crResi, sps.getBitDepth(toChannelType(COMPONENT_Cr)), COMPONENT_Cr, DF_SSE);
}
}
bool IntraSearch::xIntraCodingLumaISP(CodingStructure& cs, Partitioner& partitioner, const double bestCostSoFar)
{
int subTuCounter = 0;
const CodingUnit& cu = *cs.getCU(partitioner.currArea().lumaPos(), partitioner.chType);
bool earlySkipISP = false;
const PartSplit ispType = CU::getISPType(cu, COMPONENT_Y);
cs.cost = 0;
partitioner.splitCurrArea(ispType, cs);
CUCtx cuCtx;
cuCtx.isDQPCoded = true;
cuCtx.isChromaQpAdjCoded = true;
do // subpartitions loop
{
uint32_t numSig = 0;
Distortion singleDistTmpLuma = 0;
uint64_t singleTmpFracBits = 0;
double singleCostTmp = 0;
TransformUnit& tu = cs.addTU(CS::getArea(cs, partitioner.currArea(), partitioner.chType), partitioner.chType);
tu.depth = partitioner.currTrDepth;
// Encode TU

Karsten Suehring
committed
xIntraCodingTUBlock(tu, COMPONENT_Y, singleDistTmpLuma, 0, &numSig);
#if JVET_Z0118_GDR
cs.updateReconMotIPM(partitioner.currArea());
#else
cs.picture->getRecoBuf( partitioner.currArea() ).copyFrom( cs.getRecoBuf( partitioner.currArea() ) );
if (singleDistTmpLuma == MAX_INT) // all zero CBF skip
{
earlySkipISP = true;
partitioner.exitCurrSplit();
cs.cost = MAX_DOUBLE;
return false;
}
if (m_pcRdCost->calcRdCost(cs.fracBits, cs.dist + singleDistTmpLuma) > bestCostSoFar)
// The accumulated cost + distortion is already larger than the best cost so far, so it is not necessary to
// calculate the rate
earlySkipISP = true;
}
else
{
singleTmpFracBits = xGetIntraFracBitsQT(cs, partitioner, true, false, subTuCounter, ispType, &cuCtx);
singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
cs.cost += singleCostTmp;
cs.dist += singleDistTmpLuma;
cs.fracBits += singleTmpFracBits;
subTuCounter++;
splitCbfLuma |= TU::getCbfAtDepth(*cs.getTU(partitioner.currArea().lumaPos(), partitioner.chType, subTuCounter - 1), COMPONENT_Y, partitioner.currTrDepth);
int nSubPartitions = m_ispTestedModes[cu.lfnstIdx].numTotalParts[cu.ispMode - 1];
12490
12491
12492
12493
12494
12495
12496
12497
12498
12499
12500
12501
12502
12503
12504
12505
12506
12507
12508
12509
12510
12511
12512
12513
12514
12515
12516
12517
12518
12519
12520
12521
12522
12523
12524
12525
if (subTuCounter < nSubPartitions)
{
// exit condition if the accumulated cost is already larger than the best cost so far (no impact in RD performance)
if (cs.cost > bestCostSoFar)
{
earlySkipISP = true;
break;
}
else if (subTuCounter < nSubPartitions)
{
// more restrictive exit condition
double threshold = nSubPartitions == 2 ? 0.95 : subTuCounter == 1 ? 0.83 : 0.91;
if (subTuCounter < nSubPartitions && cs.cost > bestCostSoFar * threshold)
{
earlySkipISP = true;
break;
}
}
}
} while (partitioner.nextPart(cs)); // subpartitions loop
partitioner.exitCurrSplit();
const UnitArea& currArea = partitioner.currArea();
const uint32_t currDepth = partitioner.currTrDepth;
if (earlySkipISP)
{
cs.cost = MAX_DOUBLE;
}
else
{
cs.cost = m_pcRdCost->calcRdCost(cs.fracBits, cs.dist);
// The cost check is necessary here again to avoid superfluous operations if the maximum number of coded subpartitions was reached and yet ISP did not win
if (cs.cost < bestCostSoFar)
{
cs.setDecomp(cu.Y());
#if JVET_Z0118_GDR
cs.updateReconMotIPM(currArea.Y());
#else
cs.picture->getRecoBuf(currArea.Y()).copyFrom(cs.getRecoBuf(currArea.Y()));
for (auto& ptu : cs.tus)
{
if (currArea.Y().contains(ptu->Y()))
{
TU::setCbfAtDepth(*ptu, COMPONENT_Y, currDepth, splitCbfLuma ? 1 : 0);
}
}
}
else
{
earlySkipISP = true;
}
}
return !earlySkipISP;
}
bool IntraSearch::xRecurIntraCodingLumaQT( CodingStructure &cs, Partitioner &partitioner, const double bestCostSoFar, const int subTuIdx, const PartSplit ispType, const bool ispIsCurrentWinner, bool mtsCheckRangeFlag, int mtsFirstCheckId, int mtsLastCheckId, bool moreProbMTSIdxFirst
#if JVET_AG0136_INTRA_TMP_LIC
, InterPrediction* pcInterPred
#endif
)
{
int subTuCounter = subTuIdx;
const UnitArea &currArea = partitioner.currArea();
const CodingUnit &cu = *cs.getCU( currArea.lumaPos(), partitioner.chType );
bool earlySkipISP = false;
const SPS &sps = *cs.sps;

Karsten Suehring
committed
bool bCheckFull = true;
bool bCheckSplit = false;
Waqas Ahmad
committed
bCheckFull = !partitioner.canSplit( TU_MAX_TR_SPLIT, cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
);
bCheckSplit = partitioner.canSplit( TU_MAX_TR_SPLIT, cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
);
const Slice &slice = *cs.slice;

Karsten Suehring
committed
if( cu.ispMode )
{
Waqas Ahmad
committed
bCheckSplit = partitioner.canSplit( ispType, cs
#if JVET_AI0087_BTCUS_RESTRICTION
, false, false
#endif
);
bCheckFull = !bCheckSplit;
}

Karsten Suehring
committed
uint32_t numSig = 0;
double dSingleCost = MAX_DOUBLE;
Distortion uiSingleDistLuma = 0;
uint64_t singleFracBits = 0;
bool checkTransformSkip = sps.getTransformSkipEnabledFlag();
int bestModeId[ MAX_NUM_COMPONENT ] = { 0, 0, 0 };
uint8_t nNumTransformCands = cu.mtsFlag ? 4 : 1;
uint8_t numTransformIndexCands = nNumTransformCands;

Karsten Suehring
committed
const TempCtx ctxStart ( m_ctxCache, m_CABACEstimator->getCtx() );
TempCtx ctxBest ( m_ctxCache );

Karsten Suehring
committed
CodingStructure *csSplit = nullptr;
CodingStructure *csFull = nullptr;
CUCtx cuCtx;
cuCtx.isDQPCoded = true;
cuCtx.isChromaQpAdjCoded = true;

Karsten Suehring
committed
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

Karsten Suehring
committed
if( bCheckFull )
{
csFull->cost = 0.0;
TransformUnit &tu = csFull->addTU( CS::getArea( *csFull, currArea, partitioner.chType ), partitioner.chType );
tu.depth = currDepth;
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 JVET_Y0142_ADAPT_INTRA_MTS
nNumTransformCands = 1 + (tsAllowed ? 1 : 0) + (mtsAllowed ? 6 : 0); // DCT + TS + 6 MTS = 8 tests
#else
nNumTransformCands = 1 + ( tsAllowed ? 1 : 0 ) + ( mtsAllowed ? 4 : 0 ); // DCT + TS + 4 MTS = 6 tests
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
{
trModes.push_back(TrMode(0, true)); // DCT2
if (tsAllowed)
trModes.push_back(TrMode(1, true));
}
if (mtsAllowed)
{
#if JVET_Y0142_ADAPT_INTRA_MTS
for (int i = 2; i < 8; i++)
#else
for (int i = 2; i < 6; i++)
{
trModes.push_back(TrMode(i, true));
}
}
CHECK( !tu.Y().valid(), "Invalid TU" );

Karsten Suehring
committed
CodingStructure &saveCS = *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;
//we add the MTS candidates to the loop. TransformSkip will still be the last one to be checked (when modeId == lastCheckId) as long as checkTransformSkip is true
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;

Karsten Suehring
committed
//we add the MTS candidates to the loop. TransformSkip will still be the last one to be checked (when modeId == lastCheckId) as long as checkTransformSkip is true
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;

Karsten Suehring
committed
if( isNotOnlyOneMode )
{
saveCS.pcv = cs.pcv;
saveCS.picture = cs.picture;
#if JVET_Z0118_GDR
saveCS.m_pt = cs.m_pt;
#endif

Karsten Suehring
committed
saveCS.area.repositionTo(cs.area);
saveCS.clearTUs();
tmpTU = &saveCS.addTU(currArea, partitioner.chType);
}
bool cbfBestMode = false;
bool cbfBestModeValid = false;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled && cu.mtsFlag )
#else
xSelectAMTForFullRD(tu
#if JVET_AG0136_INTRA_TMP_LIC
, pcInterPred
#endif
);
Santiago de Luxán Hernández
committed
double bestDCT2cost = MAX_DOUBLE;
Santiago de Luxán Hernández
committed
double threshold = m_pcEncCfg->getUseFastISP() && !cu.ispMode && ispIsCurrentWinner && nNumTransformCands > 1 ? 1 + 1.4 / sqrt( cu.lwidth() * cu.lheight() ) : 1;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
for( int modeId = firstCheckId; modeId <= ( spsIntraLfnstEnabled ? lastCheckId : ( nNumTransformCands - 1 ) ); modeId++ )
#else
for( int modeId = firstCheckId; modeId <= ( sps.getUseLFNST() ? lastCheckId : ( nNumTransformCands - 1 ) ); modeId++ )
{
uint8_t transformIndex = modeId;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled && cu.mtsFlag )
#else
if (modeId >= m_numCandAMTForFullRD)
{
continue;
}
transformIndex = m_testAMTForFullRD[modeId];
#if JVET_Y0142_ADAPT_INTRA_MTS
m_validMTSReturn = true;
#endif
#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() && bestModeId[COMPONENT_Y] == MTS_SKIP))
{
break;
}
if (!trModes[modeId].second)
{
continue;
}
// we compare the DCT-II cost against the best ISP cost so far (except for TS)
if (m_pcEncCfg->getUseFastISP() && !cu.ispMode && ispIsCurrentWinner && trModes[modeId].first != MTS_DCT2_DCT2
&& (trModes[modeId].first != MTS_SKIP || !tsAllowed) && bestDCT2cost > bestCostSoFar * threshold)
{
continue;
}
tu.mtsIdx[COMPONENT_Y] = trModes[modeId].first;

Karsten Suehring
committed

Karsten Suehring
committed
if ((modeId != firstCheckId) && isNotOnlyOneMode)
{
m_CABACEstimator->getCtx() = ctxStart;
}
int default0Save1Load2 = 0;
singleDistTmpLuma = 0;
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( modeId == firstCheckId && ( spsIntraLfnstEnabled ? ( modeId != lastCheckId ) : ( nNumTransformCands > 1 ) ) )
#else
if( modeId == firstCheckId && ( sps.getUseLFNST() ? ( modeId != lastCheckId ) : ( nNumTransformCands > 1 ) ) )

Karsten Suehring
committed
{
default0Save1Load2 = 1;
}
else if (modeId != firstCheckId)
{
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled && !cbfBestModeValid )
#else
if( sps.getUseLFNST() && !cbfBestModeValid )
{
default0Save1Load2 = 1;
}
else
{
default0Save1Load2 = 2;
}

Karsten Suehring
committed
}
if( cu.ispMode )
{
default0Save1Load2 = 0;
}
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if( sps.getUseLFNST() )
{
if( cu.mtsFlag )
{
if( moreProbMTSIdxFirst )
{
const ChannelType chType = toChannelType( COMPONENT_Y );
const CompArea& area = tu.blocks[ COMPONENT_Y ];
const PredictionUnit& pu = *cs.getPU( area.pos(), chType );
uint32_t uiIntraMode = pu.intraDir[ chType ];
if( transformIndex == 1 )
{
tu.mtsIdx[COMPONENT_Y] = (uiIntraMode < 34) ? MTS_DST7_DCT8 : MTS_DCT8_DST7;
tu.mtsIdx[COMPONENT_Y] = (uiIntraMode < 34) ? MTS_DCT8_DST7 : MTS_DST7_DCT8;
tu.mtsIdx[COMPONENT_Y] = MTS_DST7_DST7 + transformIndex;
tu.mtsIdx[COMPONENT_Y] = MTS_DST7_DST7 + transformIndex;
}
}
else
{
tu.mtsIdx[COMPONENT_Y] = transformIndex;
}
if( !cu.mtsFlag && checkTransformSkip )
{
xIntraCodingTUBlock( tu, COMPONENT_Y, singleDistTmpLuma, default0Save1Load2, &numSig, modeId == 0 ? &trModes : nullptr, true
#if JVET_AG0136_INTRA_TMP_LIC
, pcInterPred
#endif
);
if( modeId == 0 )
{
for( int i = 0; i < 2; i++ )
{
if( trModes[ i ].second )
{
lastCheckId = trModes[ i ].first;
}
}
}
}
#if JVET_W0103_INTRA_MTS
else if (cu.mtsFlag)
{
xIntraCodingTUBlock(tu, COMPONENT_Y, singleDistTmpLuma, 2, &numSig, nullptr, true
#if JVET_AG0136_INTRA_TMP_LIC
, pcInterPred
#endif
);
xIntraCodingTUBlock( tu, COMPONENT_Y, singleDistTmpLuma, default0Save1Load2, &numSig
#if JVET_AG0136_INTRA_TMP_LIC
, nullptr, false, pcInterPred
#endif
);
}
}
else
{
if( nNumTransformCands > 1 )
{
xIntraCodingTUBlock( tu, COMPONENT_Y, singleDistTmpLuma, default0Save1Load2, &numSig, modeId == 0 ? &trModes : nullptr, true
#if JVET_AG0136_INTRA_TMP_LIC
, pcInterPred
#endif
);
if( modeId == 0 )
{
for( int i = 0; i < nNumTransformCands; i++ )
{
if( trModes[ i ].second )
{
lastCheckId = trModes[ i ].first;
}
}
}
}
else
{
xIntraCodingTUBlock( tu, COMPONENT_Y, singleDistTmpLuma, default0Save1Load2, &numSig
#if JVET_AG0136_INTRA_TMP_LIC
, nullptr, false, pcInterPred
#endif
);
#if JVET_Y0142_ADAPT_INTRA_MTS
cuCtx.mtsCoeffAbsSum = 0;
#endif
cuCtx.mtsLastScanPos = false;
#if INTRA_TRANS_ENC_OPT
cuCtx.lfnstLastScanPos = false;
#endif

Karsten Suehring
committed
//----- 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 ) )

Karsten Suehring
committed
{
//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, subTuCounter, ispType, &cuCtx);
singleCostTmp = m_pcRdCost->calcRdCost(singleTmpFracBits, singleDistTmpLuma);
}

Karsten Suehring
committed
}
else
{
if( cu.ispMode && m_pcRdCost->calcRdCost( csFull->fracBits, csFull->dist + singleDistTmpLuma ) > bestCostSoFar )
{
earlySkipISP = true;
}
else
{
#if JVET_Y0142_ADAPT_INTRA_MTS
if (tu.mtsIdx[COMPONENT_Y] > MTS_SKIP && !m_validMTSReturn)
{
singleTmpFracBits = 0;
}
else
{
singleTmpFracBits = xGetIntraFracBitsQT(*csFull, partitioner, true, false, subTuCounter, ispType, &cuCtx);
}
#else
singleTmpFracBits = xGetIntraFracBitsQT( *csFull, partitioner, true, false, subTuCounter, ispType, &cuCtx );
if (tu.mtsIdx[COMPONENT_Y] > MTS_SKIP)
{
#if JVET_Y0142_ADAPT_INTRA_MTS
if(!m_validMTSReturn)
#else
if (!cuCtx.mtsLastScanPos)
{
singleCostTmp = MAX_DOUBLE;
}