Newer
Older
ctxBest = m_CABACEstimator->getCtx();
}
}
if (!lastIsBest)
{
csFull->getResiBuf(cbArea).copyFrom(saveChromaCS.getResiBuf(cbArea));
csFull->getResiBuf(crArea).copyFrom(saveChromaCS.getResiBuf(crArea));
csFull->getRecoBuf(tu).copyFrom(saveChromaCS.getRecoBuf(tu));
tu.copyComponentFrom(*tmpTU, COMPONENT_Cb);
tu.copyComponentFrom(*tmpTU, COMPONENT_Cr);
m_CABACEstimator->getCtx() = ctxBest;
}
tu.jointCbCr = bestJointCbCr;
#if JVET_Z0118_GDR
csFull->updateReconMotIPM(tu);
#else
csFull->picture->getRecoBuf(tu).copyFrom(csFull->getRecoBuf(tu));
12023
12024
12025
12026
12027
12028
12029
12030
12031
12032
12033
12034
12035
12036
12037
12038
12039
12040
csFull->dist += bestDistJointCbCr;
csFull->fracBits += bestBitsJointCbCr;
csFull->cost = m_pcRdCost->calcRdCost(csFull->fracBits, csFull->dist);
}
bool validReturnSplit = false;
if (bCheckSplit)
{
if (partitioner.canSplit(TU_MAX_TR_SPLIT, *csSplit))
{
partitioner.splitCurrArea(TU_MAX_TR_SPLIT, *csSplit);
}
bool splitIsSelected = true;
do
{
bool tmpValidReturnSplit = xRecurIntraCodingACTQT(*csSplit, partitioner, mtsCheckRangeFlag, mtsFirstCheckId, mtsLastCheckId, moreProbMTSIdxFirst);
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if (sps.getUseLFNST())
12046
12047
12048
12049
12050
12051
12052
12053
12054
12055
12056
12057
12058
12059
12060
12061
12062
12063
12064
12065
12066
12067
12068
12069
12070
12071
12072
12073
12074
12075
12076
12077
12078
12079
12080
12081
12082
12083
12084
12085
12086
12087
12088
12089
{
if (!tmpValidReturnSplit)
{
splitIsSelected = false;
break;
}
}
else
{
CHECK(!tmpValidReturnSplit, "invalid RD of sub-TU partitions for ACT");
}
} while (partitioner.nextPart(*csSplit));
partitioner.exitCurrSplit();
if (splitIsSelected)
{
unsigned compCbf[3] = { 0, 0, 0 };
for (auto &currTU : csSplit->traverseTUs(currArea, partitioner.chType))
{
for (unsigned ch = 0; ch < getNumberValidTBlocks(*csSplit->pcv); ch++)
{
compCbf[ch] |= (TU::getCbfAtDepth(currTU, ComponentID(ch), currDepth + 1) ? 1 : 0);
}
}
for (auto &currTU : csSplit->traverseTUs(currArea, partitioner.chType))
{
TU::setCbfAtDepth(currTU, COMPONENT_Y, currDepth, compCbf[COMPONENT_Y]);
TU::setCbfAtDepth(currTU, COMPONENT_Cb, currDepth, compCbf[COMPONENT_Cb]);
TU::setCbfAtDepth(currTU, COMPONENT_Cr, currDepth, compCbf[COMPONENT_Cr]);
}
m_CABACEstimator->getCtx() = ctxStart;
csSplit->fracBits = xGetIntraFracBitsQT(*csSplit, partitioner, true, true, -1, TU_NO_ISP);
csSplit->cost = m_pcRdCost->calcRdCost(csSplit->fracBits, csSplit->dist);
validReturnSplit = true;
}
}
bool retVal = false;
if (csFull || csSplit)
{
#if JVET_AH0103_LOW_DELAY_LFNST_NSPT
if( spsIntraLfnstEnabled )
#else
if (sps.getUseLFNST())
{
if (validReturnFull || validReturnSplit)
{
retVal = true;
}
}
else
{
CHECK(!validReturnFull && !validReturnSplit, "illegal TU optimization");
retVal = true;
}
}
return retVal;
}
ChromaCbfs IntraSearch::xRecurIntraChromaCodingQT( CodingStructure &cs, Partitioner& partitioner, const double bestCostSoFar, const PartSplit ispType
#if JVET_AB0143_CCCM_TS || JVET_AC0119_LM_CHROMA_FUSION
, const PelUnitBuf& predStorage
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, InterPrediction* pcInterPred
#endif

Karsten Suehring
committed
{
UnitArea currArea = partitioner.currArea();
const bool keepResi = cs.sps->getUseLMChroma() || KEEP_PRED_AND_RESI_SIGNALS;

Karsten Suehring
committed
if( !currArea.Cb().valid() ) return ChromaCbfs( false );
const Slice &slice = *cs.slice;

Karsten Suehring
committed
TransformUnit &currTU = *cs.getTU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
#if JVET_AD0188_CCP_MERGE
PredictionUnit &pu = *cs.getPU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );
#else

Karsten Suehring
committed
const PredictionUnit &pu = *cs.getPU( currArea.chromaPos(), CHANNEL_TYPE_CHROMA );

Karsten Suehring
committed
bool lumaUsesISP = false;

Karsten Suehring
committed
uint32_t currDepth = partitioner.currTrDepth;
ChromaCbfs cbfs ( false );
if (currDepth == currTU.depth)
{
if (!currArea.Cb().valid() || !currArea.Cr().valid())
{
return cbfs;
}
CodingStructure &saveCS = *m_pSaveCS[1];
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.initStructData( MAX_INT, true );
if( !currTU.cu->isSepTree() && currTU.cu->ispMode )
#else
if (!CS::isDualITree(cs) && currTU.cu->ispMode)
#endif
{
saveCS.clearCUs();
CodingUnit& auxCU = saveCS.addCU( *currTU.cu, partitioner.chType );
auxCU.ispMode = currTU.cu->ispMode;
saveCS.sps = currTU.cs->sps;
saveCS.clearPUs();
saveCS.addPU( *currTU.cu->firstPU, partitioner.chType );
}

Karsten Suehring
committed
TransformUnit &tmpTU = saveCS.addTU(currArea, partitioner.chType);
#if !(JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS && JVET_AC0071_DBV)

Karsten Suehring
committed
cs.setDecomp(currArea.Cb(), true); // set in advance (required for Cb2/Cr2 in 4:2:2 video)
#endif

Karsten Suehring
committed
const unsigned numTBlocks = ::getNumberValidTBlocks( *cs.pcv );
CompArea& cbArea = currTU.blocks[COMPONENT_Cb];
CompArea& crArea = currTU.blocks[COMPONENT_Cr];
double bestCostCb = MAX_DOUBLE;
double bestCostCr = MAX_DOUBLE;
Distortion bestDistCb = 0;
Distortion bestDistCr = 0;
int maxModesTested = 0;
bool earlyExitISP = false;
TempCtx ctxStartTU( m_ctxCache );
TempCtx ctxStart ( m_ctxCache );
TempCtx ctxBest ( m_ctxCache );
ctxStartTU = m_CABACEstimator->getCtx();
currTU.jointCbCr = 0;
// Do predictions here to avoid repeating the "default0Save1Load2" stuff
int predMode = pu.cu->bdpcmModeChroma ? BDPCM_IDX : PU::getFinalIntraMode(pu, CHANNEL_TYPE_CHROMA);
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS && JVET_AC0071_DBV
#if JVET_AH0136_CHROMA_REORDERING
if (!PU::isDbvMode(predMode) || pu.isChromaFusion > 0)
#else
if (predMode != DBV_CHROMA_IDX)
{
cs.setDecomp(currArea.Cb(), true); // set in advance (required for Cb2/Cr2 in 4:2:2 video)
}
#endif
#if JVET_AH0136_CHROMA_REORDERING && JVET_AC0071_DBV
if (pu.cs->sps->getUseChromaReordering() && PU::isDbvMode(predMode) && CS::isDualITree(cs))
{
pu.bv = pu.cu->bvs[predMode - DBV_CHROMA_IDX];
pu.mv[0] = pu.cu->mvs[predMode - DBV_CHROMA_IDX];
pu.cu->rribcFlipType = pu.cu->rribcTypes[predMode - DBV_CHROMA_IDX];
}
#endif
PelBuf piPredCb = cs.getPredBuf(cbArea);
PelBuf piPredCr = cs.getPredBuf(crArea);
Alexey Filippov
committed
initIntraPatternChType( *currTU.cu, cbArea);
initIntraPatternChType( *currTU.cu, crArea);
12214
12215
12216
12217
12218
12219
12220
12221
12222
12223
12224
12225
12226
12227
12228
12229
12230
12231
12232
12233
12234
12235
12236
12237
12238
12239
12240
12241
12242
12243
12244
12245
#if JVET_AG0154_DECODER_DERIVED_CCP_FUSION
if (pu.decoderDerivedCcpMode)
{
if (!predStorage.bufs.empty())
{
piPredCb.copyFrom(predStorage.Cb());
piPredCr.copyFrom(predStorage.Cr());
}
else
{
if (pu.cccmFlag)
{
predIntraCCCM(pu, piPredCb, piPredCr, predMode);
}
else
{
CclmModel modelsCb, modelsCr;
PU::ccpParamsToCclmModel(COMPONENT_Cb, pu.curCand, modelsCb);
PU::ccpParamsToCclmModel(COMPONENT_Cr, pu.curCand, modelsCr);
predIntraChromaLM(COMPONENT_Cb, piPredCb, pu, cbArea, predMode, false, &modelsCb);
predIntraChromaLM(COMPONENT_Cr, piPredCr, pu, crArea, predMode, false, &modelsCr);
}
predDecoderDerivedIntraCCCMFusions(pu, piPredCb, piPredCr, m_decoderDerivedCcpList);
PelBuf predCb = m_ddCcpStorageTemp.Cb();
PelBuf predCr = m_ddCcpStorageTemp.Cr();
predCb.copyFrom(piPredCb);
predCr.copyFrom(piPredCr);
firstTransformDdccp = false;
}
}
else
#endif
Chia-Ming Tsai
committed
#if JVET_AD0188_CCP_MERGE
if (pu.idxNonLocalCCP)
{
#if JVET_AG0154_DECODER_DERIVED_CCP_FUSION
if (pu.ddNonLocalCCPFusion > 0)
{
piPredCb.copyFrom(predStorage.Cb());
piPredCr.copyFrom(predStorage.Cr());
}
else
{
#endif
Chia-Ming Tsai
committed
if (!predStorage.bufs.empty())
{
piPredCb.copyFrom(predStorage.Cb());
piPredCr.copyFrom(predStorage.Cr());
}
else
{
predCCPCandidate(pu, piPredCb, piPredCr);
}
#if JVET_AG0154_DECODER_DERIVED_CCP_FUSION
}
#endif
Chia-Ming Tsai
committed
}
else
#endif
#if JVET_AD0120_LBCCP
if (pu.ccInsideFilter && PU::isLMCMode( predMode ) && !predStorage.bufs.empty())
{
piPredCb.copyFrom(predStorage.Cb());
piPredCr.copyFrom(predStorage.Cr());
}
else
#endif
#if JVET_AE0100_BVGCCCM
if (pu.bvgCccmFlag)
{
xGetLumaRecPixels( pu, cbArea );
predIntraCCCM( pu, piPredCb, piPredCr, predMode );
}
else
#endif
Alexey Filippov
committed
if (pu.cs->slice->isIntra() && !predStorage.bufs.empty())
piPredCb.copyFrom(predStorage.Cb());
piPredCr.copyFrom(predStorage.Cr());
}
else
{
predIntraCCCM(pu, piPredCb, piPredCr, predMode);
}
#else
xGetLumaRecPixels( pu, cbArea );
predIntraCCCM( pu, piPredCb, piPredCr, predMode );
if( PU::isLMCMode( predMode ) )
{
xGetLumaRecPixels( pu, cbArea );
predIntraChromaLM( COMPONENT_Cb, piPredCb, pu, cbArea, predMode );
#if JVET_AA0126_GLM && !JVET_AB0092_GLM_WITH_LUMA
xGetLumaRecPixels( pu, crArea ); // generate GLM luma samples for Cr prediction
#endif
predIntraChromaLM( COMPONENT_Cr, piPredCr, pu, crArea, predMode );
}
else if (PU::isMIP(pu, CHANNEL_TYPE_CHROMA))
{
initIntraMip(pu, cbArea);
predIntraMip(COMPONENT_Cb, piPredCb, pu);
initIntraMip(pu, crArea);
predIntraMip(COMPONENT_Cr, piPredCr, pu);
}
#if JVET_AC0119_LM_CHROMA_FUSION
Alexey Filippov
committed
if (pu.cs->slice->isIntra() && pu.isChromaFusion && !predStorage.bufs.empty())
{
piPredCb.copyFrom(predStorage.Cb());
piPredCr.copyFrom(predStorage.Cr());
}
else
{
#endif
#if JVET_AC0071_DBV
#if JVET_AH0136_CHROMA_REORDERING
if (PU::isDbvMode(predMode))
#else
if (predMode == DBV_CHROMA_IDX)
predIntraDbv(COMPONENT_Cb, piPredCb, pu
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, pcInterPred
#endif
);
predIntraDbv(COMPONENT_Cr, piPredCr, pu
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, pcInterPred
#endif
);
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS && JVET_AC0071_DBV
#if JVET_AH0136_CHROMA_REORDERING
if (pu.isChromaFusion == 0)
#endif
cs.setDecomp(currArea.Cb(), true); // set in advance (required for Cb2/Cr2 in 4:2:2 video)
#endif
}
else
{
#endif
Alexey Filippov
committed
predIntraAng( COMPONENT_Cb, piPredCb, pu);
predIntraAng( COMPONENT_Cr, piPredCr, pu);
#if JVET_AC0071_DBV
}
#endif
#if JVET_Z0050_DIMD_CHROMA_FUSION
if (pu.isChromaFusion)
{
geneChromaFusionPred(COMPONENT_Cb, piPredCb, pu
#if JVET_AH0136_CHROMA_REORDERING
, pcInterPred
#endif
);
geneChromaFusionPred(COMPONENT_Cr, piPredCr, pu
#if JVET_AH0136_CHROMA_REORDERING
, pcInterPred
#endif
);
#if JVET_AC0119_LM_CHROMA_FUSION
}
#endif
}

Karsten Suehring
committed
// determination of chroma residuals including reshaping and cross-component prediction
//----- get chroma residuals -----
PelBuf resiCb = cs.getResiBuf(cbArea);
PelBuf resiCr = cs.getResiBuf(crArea);
#if JVET_AC0071_DBV && JVET_AA0070_RRIBC
#if JVET_AH0136_CHROMA_REORDERING
if (PU::isDbvMode(predMode) && currTU.cu->rribcFlipType)
#else
if (predMode == DBV_CHROMA_IDX && currTU.cu->rribcFlipType)
{
resiCb.copyFrom(cs.getOrgBuf(cbArea));
resiCr.copyFrom(cs.getOrgBuf(crArea));
resiCb.flipSignal(currTU.cu->rribcFlipType == 1);
resiCr.flipSignal(currTU.cu->rribcFlipType == 1);
resiCb.subtract(piPredCb);
resiCr.subtract(piPredCr);
}
else
{
#endif
resiCb.copyFrom( cs.getOrgBuf (cbArea) );
resiCr.copyFrom( cs.getOrgBuf (crArea) );
resiCb.subtract( piPredCb );
resiCr.subtract( piPredCr );
#if JVET_AC0071_DBV && JVET_AA0070_RRIBC
}
#endif
//----- get reshape parameter ----
bool doReshaping = ( cs.slice->getLmcsEnabledFlag() && cs.picHeader->getLmcsChromaResidualScaleFlag()
&& (cs.slice->isIntra() || m_pcReshape->getCTUFlag()) && (cbArea.width * cbArea.height > 4) );
if( doReshaping )
{
#if LMCS_CHROMA_CALC_CU
const Area area = currTU.cu->Y().valid() ? currTU.cu->Y() : Area(recalcPosition(currTU.chromaFormat, currTU.chType, CHANNEL_TYPE_LUMA, currTU.cu->blocks[currTU.chType].pos()), recalcSize(currTU.chromaFormat, currTU.chType, CHANNEL_TYPE_LUMA, currTU.cu->blocks[currTU.chType].size()));
#else
const Area area = currTU.Y().valid() ? currTU.Y() : Area(recalcPosition(currTU.chromaFormat, currTU.chType, CHANNEL_TYPE_LUMA, currTU.blocks[currTU.chType].pos()), recalcSize(currTU.chromaFormat, currTU.chType, CHANNEL_TYPE_LUMA, currTU.blocks[currTU.chType].size()));
const CompArea &areaY = CompArea(COMPONENT_Y, currTU.chromaFormat, area);
int adj = m_pcReshape->calculateChromaAdjVpduNei(currTU, areaY);
currTU.setChromaAdj(adj);
}
//----- get cross component prediction parameters -----

Karsten Suehring
committed
//===== store original residual signals =====
CompStorage orgResiCb[4], orgResiCr[4]; // 0:std, 1-3:jointCbCr (placeholder at this stage)
orgResiCb[0].create( cbArea );
orgResiCr[0].create( crArea );
orgResiCb[0].copyFrom( resiCb );
orgResiCr[0].copyFrom( resiCr );
if( doReshaping )
{
int cResScaleInv = currTU.getChromaAdj();
orgResiCb[0].scaleSignal( cResScaleInv, 1, currTU.cu->cs->slice->clpRng(COMPONENT_Cb) );
orgResiCr[0].scaleSignal( cResScaleInv, 1, currTU.cu->cs->slice->clpRng(COMPONENT_Cr) );
}

Karsten Suehring
committed
for( uint32_t c = COMPONENT_Cb; c < numTBlocks; c++)
{
const ComponentID compID = ComponentID(c);
const CompArea& area = currTU.blocks[compID];
double dSingleCost = MAX_DOUBLE;
int bestModeId = 0;
Distortion singleDistCTmp = 0;
double singleCostTmp = 0;
Hilmi Egilmez
committed
const bool tsAllowed = TU::isTSAllowed(currTU, compID) && m_pcEncCfg->getUseChromaTS() && !currTU.cu->lfnstIdx;
uint8_t nNumTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
std::vector<TrMode> trModes;
if (m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless())
{
nNumTransformCands = 1;
CHECK(!tsAllowed && !currTU.cu->bdpcmModeChroma, "transform skip should be enabled for LS");
if (currTU.cu->bdpcmModeChroma)
{
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)); // TS
}
CHECK(!currTU.Cb().valid(), "Invalid TU");

Karsten Suehring
committed
const int totalModesToTest = nNumTransformCands;
const bool isOneMode = false;
maxModesTested = totalModesToTest > maxModesTested ? totalModesToTest : maxModesTested;

Karsten Suehring
committed
int currModeId = 0;
int default0Save1Load2 = 0;
if (!isOneMode)
{
ctxStart = m_CABACEstimator->getCtx();
}
for (int modeId = 0; modeId < nNumTransformCands; modeId++)

Karsten Suehring
committed
{
resiCb.copyFrom(orgResiCb[0]);
resiCr.copyFrom(orgResiCr[0]);
currTU.mtsIdx[compID] = currTU.cu->bdpcmModeChroma ? MTS_SKIP : trModes[modeId].first;

Karsten Suehring
committed
const bool isFirstMode = (currModeId == 1);
const bool isLastMode = false; // Always store output to saveCS and tmpTU
if (!(m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()))
{
// if DCT2's cbf==0, skip ts search
if (!cbfDCT2 && trModes[modeId].first == MTS_SKIP)
{
break;
}
if (!trModes[modeId].second)
{
continue;
}
if (!isFirstMode) // if not first mode to be tested
{
m_CABACEstimator->getCtx() = ctxStart;
}

Karsten Suehring
committed

Karsten Suehring
committed
if (nNumTransformCands > 1)
{
xIntraCodingTUBlock(currTU, compID, singleDistCTmp, default0Save1Load2, nullptr,
modeId == 0 ? &trModes : nullptr, true);
}
else
{
xIntraCodingTUBlock(currTU, compID, singleDistCTmp, default0Save1Load2);
}
if (((currTU.mtsIdx[compID] == MTS_SKIP && !currTU.cu->bdpcmModeChroma)
&& !TU::getCbf(currTU, compID))) // 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;
uint64_t fracBitsTmp = xGetIntraFracBitsQTChroma(currTU, compID);
singleCostTmp = m_pcRdCost->calcRdCost(fracBitsTmp, singleDistCTmp);
}
else if (lumaUsesISP && bestCostSoFar != MAX_DOUBLE && c == COMPONENT_Cb)
{
uint64_t fracBitsTmp = xGetIntraFracBitsQTSingleChromaComponent(cs, partitioner, ComponentID(c));
singleCostTmp = m_pcRdCost->calcRdCost(fracBitsTmp, singleDistCTmp);
if (isOneMode || (!isOneMode && !isLastMode))

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

Karsten Suehring
committed
}
}
else if (!isOneMode)
{
uint64_t fracBitsTmp = xGetIntraFracBitsQTChroma(currTU, compID);
singleCostTmp = m_pcRdCost->calcRdCost(fracBitsTmp, singleDistCTmp);
}
if (singleCostTmp < dSingleCost)
{
dSingleCost = singleCostTmp;
bestModeId = currModeId;
if (c == COMPONENT_Cb)
bestCostCb = singleCostTmp;
bestDistCb = singleDistCTmp;

Karsten Suehring
committed
{
bestCostCr = singleCostTmp;
bestDistCr = singleDistCTmp;

Karsten Suehring
committed
}
if (currTU.mtsIdx[compID] == MTS_DCT2_DCT2)

Karsten Suehring
committed
{
cbfDCT2 = TU::getCbfAtDepth(currTU, compID, currDepth);
}

Karsten Suehring
committed
#if KEEP_PRED_AND_RESI_SIGNALS
saveCS.getPredBuf(area).copyFrom(cs.getPredBuf(area));
saveCS.getOrgResiBuf(area).copyFrom(cs.getOrgResiBuf(area));
saveCS.getPredBuf(area).copyFrom(cs.getPredBuf(area));
if (keepResi)
{
saveCS.getResiBuf(area).copyFrom(cs.getResiBuf(area));
}
saveCS.getRecoBuf(area).copyFrom(cs.getRecoBuf(area));

Karsten Suehring
committed
tmpTU.copyComponentFrom(currTU, compID);

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

Karsten Suehring
committed
}

Karsten Suehring
committed
}
if( lumaUsesISP && dSingleCost > bestCostSoFar && c == COMPONENT_Cb )
{
//Luma + Cb cost is already larger than the best cost, so we don't need to test Cr
cs.dist = MAX_UINT;
m_CABACEstimator->getCtx() = ctxStart;
break;
//return cbfs;
}
// Done with one component of separate coding of Cr and Cb, just switch to the best Cb contexts if Cr coding is still to be done
if ((c == COMPONENT_Cb && bestModeId < totalModesToTest) || (c == COMPONENT_Cb && m_pcEncCfg->getCostMode() == COST_LOSSLESS_CODING && slice.isLossless()))
{
m_CABACEstimator->getCtx() = ctxBest;
currTU.copyComponentFrom(tmpTU, COMPONENT_Cb); // Cbf of Cb is needed to estimate cost for Cr Cbf
}
}
if ( !earlyExitISP )
{
// Test using joint chroma residual coding
double bestCostCbCr = bestCostCb + bestCostCr;
Distortion bestDistCbCr = bestDistCb + bestDistCr;
int bestJointCbCr = 0;
std::vector<int> jointCbfMasksToTest;
if ( cs.sps->getJointCbCrEnabledFlag() && (TU::getCbf(tmpTU, COMPONENT_Cb) || TU::getCbf(tmpTU, COMPONENT_Cr)))
jointCbfMasksToTest = m_pcTrQuant->selectICTCandidates(currTU, orgResiCb, orgResiCr);

Xiaoyu Xiu
committed
bool checkDCTOnly = (TU::getCbf(tmpTU, COMPONENT_Cb) && tmpTU.mtsIdx[COMPONENT_Cb] == MTS_DCT2_DCT2 && !TU::getCbf(tmpTU, COMPONENT_Cr)) ||
(TU::getCbf(tmpTU, COMPONENT_Cr) && tmpTU.mtsIdx[COMPONENT_Cr] == MTS_DCT2_DCT2 && !TU::getCbf(tmpTU, COMPONENT_Cb)) ||
(TU::getCbf(tmpTU, COMPONENT_Cb) && tmpTU.mtsIdx[COMPONENT_Cb] == MTS_DCT2_DCT2 && TU::getCbf(tmpTU, COMPONENT_Cr) && tmpTU.mtsIdx[COMPONENT_Cr] == MTS_DCT2_DCT2);
bool checkTSOnly = (TU::getCbf(tmpTU, COMPONENT_Cb) && tmpTU.mtsIdx[COMPONENT_Cb] == MTS_SKIP && !TU::getCbf(tmpTU, COMPONENT_Cr)) ||
(TU::getCbf(tmpTU, COMPONENT_Cr) && tmpTU.mtsIdx[COMPONENT_Cr] == MTS_SKIP && !TU::getCbf(tmpTU, COMPONENT_Cb)) ||
(TU::getCbf(tmpTU, COMPONENT_Cb) && tmpTU.mtsIdx[COMPONENT_Cb] == MTS_SKIP && TU::getCbf(tmpTU, COMPONENT_Cr) && tmpTU.mtsIdx[COMPONENT_Cr] == MTS_SKIP);
if (jointCbfMasksToTest.size() && currTU.cu->bdpcmModeChroma)
{
CHECK(!checkTSOnly || checkDCTOnly, "bdpcm only allows transform skip");
}
for( int cbfMask : jointCbfMasksToTest )
currTU.jointCbCr = (uint8_t)cbfMask;

Xiaoyu Xiu
committed
ComponentID codeCompId = ((currTU.jointCbCr >> 1) ? COMPONENT_Cb : COMPONENT_Cr);
ComponentID otherCompId = ((codeCompId == COMPONENT_Cb) ? COMPONENT_Cr : COMPONENT_Cb);
bool tsAllowed = TU::isTSAllowed(currTU, codeCompId) && (m_pcEncCfg->getUseChromaTS()) && !currTU.cu->lfnstIdx;

Xiaoyu Xiu
committed
uint8_t numTransformCands = 1 + (tsAllowed ? 1 : 0); // DCT + TS = 2 tests
bool cbfDCT2 = true;
std::vector<TrMode> trModes;
if (checkDCTOnly || checkTSOnly)
{
numTransformCands = 1;
}
if (!checkTSOnly || currTU.cu->bdpcmModeChroma)
{
trModes.push_back(TrMode(0, true)); // DCT2

Xiaoyu Xiu
committed
12667
12668
12669
12670
12671
12672
12673
12674
12675
12676
12677
12678
12679
12680
12681
12682
12683
12684
}
if (tsAllowed && !checkDCTOnly)
{
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;
currTU.mtsIdx[codeCompId] = currTU.cu->bdpcmModeChroma ? MTS_SKIP : trModes[modeId].first;
currTU.mtsIdx[otherCompId] = MTS_DCT2_DCT2;
m_CABACEstimator->getCtx() = ctxStartTU;
resiCb.copyFrom(orgResiCb[cbfMask]);
resiCr.copyFrom(orgResiCr[cbfMask]);
if (numTransformCands > 1)

Xiaoyu Xiu
committed
{
12691
12692
12693
12694
12695
12696
12697
12698
12699
12700
12701
12702
12703
12704
12705
12706
12707
12708
12709
xIntraCodingTUBlock(currTU, COMPONENT_Cb, distTmp, 0, nullptr, modeId == 0 ? &trModes : nullptr, true);
}
else
{
xIntraCodingTUBlock(currTU, COMPONENT_Cb, distTmp, 0);
}
double costTmp = std::numeric_limits<double>::max();
if (distTmp < std::numeric_limits<Distortion>::max())
{
uint64_t bits = xGetIntraFracBitsQTChroma(currTU, COMPONENT_Cb);
costTmp = m_pcRdCost->calcRdCost(bits, distTmp);
if (!currTU.mtsIdx[codeCompId])
{
cbfDCT2 = true;
}
}
else if (!currTU.mtsIdx[codeCompId])
{
cbfDCT2 = false;

Xiaoyu Xiu
committed
}
if (costTmp < bestCostCbCr)
bestCostCbCr = costTmp;
bestDistCbCr = distTmp;
bestJointCbCr = currTU.jointCbCr;
// store data
{
#if KEEP_PRED_AND_RESI_SIGNALS
saveCS.getOrgResiBuf(cbArea).copyFrom(cs.getOrgResiBuf(cbArea));
saveCS.getOrgResiBuf(crArea).copyFrom(cs.getOrgResiBuf(crArea));
saveCS.getPredBuf(cbArea).copyFrom(cs.getPredBuf(cbArea));
saveCS.getPredBuf(crArea).copyFrom(cs.getPredBuf(crArea));
if (keepResi)
{
saveCS.getResiBuf(cbArea).copyFrom(cs.getResiBuf(cbArea));
saveCS.getResiBuf(crArea).copyFrom(cs.getResiBuf(crArea));
}
saveCS.getRecoBuf(cbArea).copyFrom(cs.getRecoBuf(cbArea));
saveCS.getRecoBuf(crArea).copyFrom(cs.getRecoBuf(crArea));
tmpTU.copyComponentFrom(currTU, COMPONENT_Cb);
tmpTU.copyComponentFrom(currTU, COMPONENT_Cr);
ctxBest = m_CABACEstimator->getCtx();
}

Xiaoyu Xiu
committed
}
12743
12744
12745
12746
12747
12748
12749
12750
12751
12752
12753
12754
12755
12756
12757
12758
12759
12760
// Retrieve the best CU data (unless it was the very last one tested)
{
#if KEEP_PRED_AND_RESI_SIGNALS
cs.getPredBuf (cbArea).copyFrom(saveCS.getPredBuf (cbArea));
cs.getOrgResiBuf(cbArea).copyFrom(saveCS.getOrgResiBuf(cbArea));
cs.getPredBuf (crArea).copyFrom(saveCS.getPredBuf (crArea));
cs.getOrgResiBuf(crArea).copyFrom(saveCS.getOrgResiBuf(crArea));
#endif
cs.getPredBuf (cbArea).copyFrom(saveCS.getPredBuf (cbArea));
cs.getPredBuf (crArea).copyFrom(saveCS.getPredBuf (crArea));
if( keepResi )
{
cs.getResiBuf (cbArea).copyFrom(saveCS.getResiBuf (cbArea));
cs.getResiBuf (crArea).copyFrom(saveCS.getResiBuf (crArea));
}
cs.getRecoBuf (cbArea).copyFrom(saveCS.getRecoBuf (cbArea));
cs.getRecoBuf (crArea).copyFrom(saveCS.getRecoBuf (crArea));
currTU.copyComponentFrom(tmpTU, COMPONENT_Cb);
currTU.copyComponentFrom(tmpTU, COMPONENT_Cr);
m_CABACEstimator->getCtx() = ctxBest;
}
// Copy results to the picture structures
#if JVET_Z0118_GDR
cs.updateReconMotIPM(cbArea);
#else
cs.picture->getRecoBuf(cbArea).copyFrom(cs.getRecoBuf(cbArea));
#endif
#if JVET_Z0118_GDR
cs.updateReconMotIPM(crArea);
#else
cs.picture->getRecoBuf(crArea).copyFrom(cs.getRecoBuf(crArea));
cs.picture->getPredBuf(cbArea).copyFrom(cs.getPredBuf(cbArea));
cs.picture->getPredBuf(crArea).copyFrom(cs.getPredBuf(crArea));
cbfs.cbf(COMPONENT_Cb) = TU::getCbf(currTU, COMPONENT_Cb);
cbfs.cbf(COMPONENT_Cr) = TU::getCbf(currTU, COMPONENT_Cr);
currTU.jointCbCr = ( (cbfs.cbf(COMPONENT_Cb) + cbfs.cbf(COMPONENT_Cr)) ? bestJointCbCr : 0 );

Karsten Suehring
committed
}
}
else
{
unsigned numValidTBlocks = ::getNumberValidTBlocks( *cs.pcv );
ChromaCbfs SplitCbfs ( false );
if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
{
partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
}
else if( currTU.cu->ispMode )
{
partitioner.splitCurrArea( ispType, cs );
}

Karsten Suehring
committed
else

Karsten Suehring
committed
THROW( "Implicit TU split not available" );

Karsten Suehring
committed
do
{
#if JVET_AD0120_LBCCP
ChromaCbfs subCbfs = xRecurIntraChromaCodingQT(cs, partitioner, bestCostSoFar, ispType, predStorage
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, pcInterPred
#endif
);
#else
ChromaCbfs subCbfs = xRecurIntraChromaCodingQT(cs, partitioner, bestCostSoFar, ispType
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS && (JVET_AB0143_CCCM_TS || JVET_AC0119_LM_CHROMA_FUSION)
, UnitBuf<Pel>()
#endif
#if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
, pcInterPred
#endif
);
#endif

Karsten Suehring
committed
for( uint32_t ch = COMPONENT_Cb; ch < numValidTBlocks; ch++ )
{
const ComponentID compID = ComponentID( ch );
SplitCbfs.cbf( compID ) |= subCbfs.cbf( compID );
}
} while( partitioner.nextPart( cs ) );
partitioner.exitCurrSplit();
if( lumaUsesISP && cs.dist == MAX_UINT )
{
return cbfs;
}
cbfs.Cb |= SplitCbfs.Cb;
cbfs.Cr |= SplitCbfs.Cr;

Karsten Suehring
committed
if (!lumaUsesISP)
{
for (auto &ptu: cs.tus)
if (currArea.Cb().contains(ptu->Cb()) || (!ptu->Cb().valid() && currArea.Y().contains(ptu->Y())))
TU::setCbfAtDepth(*ptu, COMPONENT_Cb, currDepth, SplitCbfs.Cb);
TU::setCbfAtDepth(*ptu, COMPONENT_Cr, currDepth, SplitCbfs.Cr);
}
}

Karsten Suehring
committed
}
}
return cbfs;
}
uint64_t IntraSearch::xFracModeBitsIntra(PredictionUnit &pu, const uint32_t &uiMode, const ChannelType &chType)
{

Karsten Suehring
committed
#if JVET_Y0065_GPM_INTRA
if (!pu.ciipFlag && !pu.gpmIntraFlag)
#else
if (!pu.ciipFlag)

Karsten Suehring
committed
std::swap(orgMode, pu.intraDir[chType]);
m_CABACEstimator->resetBits();
if( isLuma( chType ) )
{
#if JVET_Y0065_GPM_INTRA
if (!pu.ciipFlag && !pu.gpmIntraFlag)
#else
if (!pu.ciipFlag)
Fabrice URBAN
committed
setLumaIntraPredIdx(pu);
m_CABACEstimator->intra_luma_pred_mode(pu);
}

Karsten Suehring
committed
}
else
{
m_CABACEstimator->intra_chroma_pred_mode( pu );
}
#if JVET_Y0065_GPM_INTRA
if ( !pu.ciipFlag && !pu.gpmIntraFlag )
#else
if ( !pu.ciipFlag )

Karsten Suehring
committed
std::swap(orgMode, pu.intraDir[chType]);
return m_CABACEstimator->getEstFracBits();
}
12899
12900
12901
12902
12903
12904
12905
12906
12907
12908
12909
12910
12911
12912
12913
12914
12915
12916
12917
void IntraSearch::sortRdModeListFirstColorSpace(ModeInfo mode, double cost, char bdpcmMode, ModeInfo* rdModeList, double* rdCostList, char* bdpcmModeList, int& candNum)
{
if (candNum == 0)
{
rdModeList[0] = mode;
rdCostList[0] = cost;
bdpcmModeList[0] = bdpcmMode;
candNum++;
return;
}
int insertPos = -1;
for (int pos = candNum - 1; pos >= 0; pos--)
{
if (cost < rdCostList[pos])
{
insertPos = pos;
}
}

Karsten Suehring
committed
12919
12920
12921
12922
12923
12924
12925
12926
12927
12928
12929
12930
12931
12932
12933
12934
12935
12936
12937
12938
12939
12940
12941
12942
12943
12944
12945
12946
12947
12948
12949
12950
12951
12952
12953
12954
if (insertPos >= 0)
{
for (int i = candNum - 1; i >= insertPos; i--)
{
rdModeList[i + 1] = rdModeList[i];
rdCostList[i + 1] = rdCostList[i];
bdpcmModeList[i + 1] = bdpcmModeList[i];
}
rdModeList[insertPos] = mode;
rdCostList[insertPos] = cost;
bdpcmModeList[insertPos] = bdpcmMode;
candNum++;
}
else
{
rdModeList[candNum] = mode;
rdCostList[candNum] = cost;
bdpcmModeList[candNum] = bdpcmMode;
candNum++;
}
CHECK(candNum > FAST_UDI_MAX_RDMODE_NUM, "exceed intra mode candidate list capacity");
return;
}
void IntraSearch::invalidateBestRdModeFirstColorSpace()
{
int numSaveRdClass = 4 * NUM_LFNST_NUM_PER_SET * 2;
int savedRdModeListSize = FAST_UDI_MAX_RDMODE_NUM;
for (int i = 0; i < numSaveRdClass; i++)
{
m_numSavedRdModeFirstColorSpace[i] = 0;
for (int j = 0; j < savedRdModeListSize; j++)
{
m_savedRdModeFirstColorSpace[i][j] = ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, 0);
m_savedBDPCMModeFirstColorSpace[i][j] = 0;
m_savedRdCostFirstColorSpace[i][j] = MAX_DOUBLE;
}
}
}

Karsten Suehring
committed
void IntraSearch::reduceHadCandList(static_vector<T, N>& candModeList, static_vector<double, N>& candCostList, int& numModesForFullRD, const double thresholdHadCost, const double* mipHadCost, const PredictionUnit &pu, const bool fastMip
#if JVET_AB0157_TMRL
, const double* tmrlCostList
#endif
#if JVET_AC0105_DIRECTIONAL_PLANAR
, const double* dirPlanarCostList
#endif
{
const int maxCandPerType = numModesForFullRD >> 1;
static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> tempRdModeList;
static_vector<double, FAST_UDI_MAX_RDMODE_NUM> tempCandCostList;
const double minCost = candCostList[0];
bool keepOneMip = candModeList.size() > numModesForFullRD;

Christian Helmrich
committed
int numConv = 0;
int numMip = 0;
for (int idx = 0; idx < candModeList.size() - (keepOneMip?0:1); idx++)
{
bool addMode = false;
addMode = (numConv < 3);
numConv += addMode ? 1:0;
addMode = ( numMip < maxCandPerType || (candCostList[idx] < thresholdHadCost * minCost) || keepOneMip );
keepOneMip = false;
numMip += addMode ? 1:0;
}
if( addMode )
{
tempCandCostList.push_back(candCostList[idx]);
}