/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2022, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file DecCu.cpp \brief CU decoder class */ #include "DecCu.h" #include "CommonLib/InterPrediction.h" #include "CommonLib/IntraPrediction.h" #include "CommonLib/Picture.h" #include "CommonLib/UnitTools.h" #include "CommonLib/dtrace_buffer.h" #if RExt__DECODER_DEBUG_TOOL_STATISTICS #include "CommonLib/CodingStatistics.h" #endif #if K0149_BLOCK_STATISTICS #include "CommonLib/ChromaFormat.h" #include "CommonLib/dtrace_blockstatistics.h" #endif //! \ingroup DecoderLib //! \{ // ==================================================================================================================== // Constructor / destructor / create / destroy // ==================================================================================================================== DecCu::DecCu() { m_tmpStorageLCU = NULL; } DecCu::~DecCu() { m_ciipBuffer.destroy(); } void DecCu::init( TrQuant* pcTrQuant, IntraPrediction* pcIntra, InterPrediction* pcInter) { m_pcTrQuant = pcTrQuant; m_pcIntraPred = pcIntra; m_pcInterPred = pcInter; m_ciipBuffer.destroy(); m_ciipBuffer.create(CHROMA_420, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)); // TODO: support other color format } void DecCu::initDecCuReshaper (Reshape* pcReshape, ChromaFormat chromaFormatIDC) { m_pcReshape = pcReshape; if (m_tmpStorageLCU == NULL) { m_tmpStorageLCU = new PelStorage; m_tmpStorageLCU->create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); } } void DecCu::destoryDecCuReshaprBuf() { if (m_tmpStorageLCU) { m_tmpStorageLCU->destroy(); delete m_tmpStorageLCU; m_tmpStorageLCU = NULL; } } // ==================================================================================================================== // Public member functions // ==================================================================================================================== void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) { const int maxNumChannelType = cs.pcv->chrFormat != CHROMA_400 && CS::isDualITree( cs ) ? 2 : 1; if (cs.resetIBCBuffer) { m_pcInterPred->resetIBCBuffer(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight()); cs.resetIBCBuffer = false; } #if JVET_Z0153_IBC_EXT_REF else { const int ctuSize = cs.slice->getSPS()->getMaxCUHeight(); m_pcInterPred->resetVPDUforIBC(cs.pcv->chrFormat, ctuSize, ctuSize, ctuArea.Y().x, ctuArea.Y().y); } #endif #if JVET_Z0118_GDR // reset current IBC Buffer only when VB pass through if (cs.isGdrEnabled() && cs.isInGdrIntervalOrRecoveryPoc()) { #if JVET_Z0153_IBC_EXT_REF m_pcInterPred->resetCurIBCBuffer( cs.pcv->chrFormat, ctuArea.Y(), cs.slice->getSPS()->getMaxCUHeight(), 1 << (cs.sps->getBitDepth(CHANNEL_TYPE_LUMA) - 1) ); #else int gdrEndX = cs.picHeader->getGdrEndX(); if (ctuArea.lx() <= gdrEndX && gdrEndX < ctuArea.lx() + ctuArea.lwidth()) { m_pcInterPred->resetCurIBCBuffer( cs.pcv->chrFormat, ctuArea.Y(), cs.slice->getSPS()->getMaxCUHeight(), 1 << (cs.sps->getBitDepth(CHANNEL_TYPE_LUMA) - 1) ); } #endif } #endif for( int ch = 0; ch < maxNumChannelType; ch++ ) { const ChannelType chType = ChannelType( ch ); Position prevTmpPos; prevTmpPos.x = -1; prevTmpPos.y = -1; for( auto &currCU : cs.traverseCUs( CS::getArea( cs, ctuArea, chType ), chType ) ) { #if JVET_Z0054_BLK_REF_PIC_REORDER m_pcInterPred->setFillCurTplAboveARMC(false); m_pcInterPred->setFillCurTplLeftARMC(false); #endif #if JVET_Z0118_GDR if (cs.isGdrEnabled()) { Slice *slice = currCU.slice; Picture *refPic; bool isInGdrInterval = slice->getPicHeader()->getInGdrInterval(); bool isRecoveryPocPic = slice->getPicHeader()->getIsGdrRecoveryPocPic(); bool isNorPicture = !(isInGdrInterval || isRecoveryPocPic) && slice->isInterB(); if (isNorPicture) { currCU.cs->setReconBuf(PIC_RECONSTRUCTION_0); currCU.cs->picture->setCleanDirty(false); // 1.01 use only dirty reference picture for (int rlist = REF_PIC_LIST_0; rlist < NUM_REF_PIC_LIST_01; rlist++) { int n = slice->getNumRefIdx((RefPicList)rlist); for (int idx = 0; idx < n; idx++) { Picture *refPic = slice->getReferencePicture((RefPicList)rlist, idx); if (refPic) { // when cur picture is normal picture and ref picture is gdr/recovery picture // note: pic.slice.picHeader and pic.cs.picHeader could be different // bool isGdrPic = refPic->cs->picHeader->getInGdrPeriod(); bool isRefInGdrInterval = refPic->cs->picHeader->getInGdrInterval(); bool isRefRecoveryPocPic = refPic->cs->picHeader->getIsGdrRecoveryPocPic(); if (isRefInGdrInterval || isRefRecoveryPocPic) { refPic->setCleanDirty(true); } else { refPic->setCleanDirty(false); } } } } } // 1.02 use clean reference pictures for some CU when gdr starts if (isInGdrInterval || isRecoveryPocPic) { // 1.01 switch recon based on clean/dirty current area bool cleanDirtyFlag; bool isCuClean = currCU.Y().valid() ? cs.isClean(currCU.Y().topLeft(), CHANNEL_TYPE_LUMA) : cs.isClean(currCU.Cb().topLeft(), CHANNEL_TYPE_CHROMA); if (isCuClean) { cleanDirtyFlag = true; } else { cleanDirtyFlag = false; } currCU.cs->setReconBuf((cleanDirtyFlag) ? PIC_RECONSTRUCTION_1 : PIC_RECONSTRUCTION_0); currCU.cs->picture->setCleanDirty(cleanDirtyFlag); for (int rlist = REF_PIC_LIST_0; rlist < NUM_REF_PIC_LIST_01; rlist++) { int n = slice->getNumRefIdx((RefPicList)rlist); for (int idx = 0; idx < n; idx++) { refPic = slice->getReferencePicture((RefPicList)rlist, idx); if (refPic) { refPic->setCleanDirty(cleanDirtyFlag); } } } } } #endif #if !REMOVE_VPDU if(currCU.Y().valid()) { const int vSize = cs.slice->getSPS()->getMaxCUHeight() > 64 ? 64 : cs.slice->getSPS()->getMaxCUHeight(); if((currCU.Y().x % vSize) == 0 && (currCU.Y().y % vSize) == 0) { for(int x = currCU.Y().x; x < currCU.Y().x + currCU.Y().width; x += vSize) { for(int y = currCU.Y().y; y < currCU.Y().y + currCU.Y().height; y += vSize) { m_pcInterPred->resetVPDUforIBC(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight(), vSize, x + g_IBCBufferSize / cs.slice->getSPS()->getMaxCUHeight() / 2, y); } } } } #endif if (currCU.predMode != MODE_INTRA && currCU.predMode != MODE_PLT && currCU.Y().valid()) { xDeriveCUMV(currCU); #if K0149_BLOCK_STATISTICS if(currCU.geoFlag) { storeGeoMergeCtx(m_geoMrgCtx); } #endif } switch( currCU.predMode ) { case MODE_INTER: case MODE_IBC: #if JVET_Y0065_GPM_INTRA #if ENABLE_DIMD && JVET_W0123_TIMD_FUSION if ((cs.slice->getSPS()->getUseDimd() || cs.slice->getSPS()->getUseTimd()) && currCU.geoFlag && currCU.firstPU->gpmIntraFlag) #elif ENABLE_DIMD if (cs.slice->getSPS()->getUseDimd() && currCU.geoFlag && currCU.firstPU->gpmIntraFlag) #elif JVET_W0123_TIMD_FUSION if (cs.slice->getSPS()->getUseTimd() && currCU.geoFlag && currCU.firstPU->gpmIntraFlag) #endif { if ((int)(currCU.firstPU->geoMergeIdx0)-GEO_MAX_NUM_UNI_CANDS > 0 || (int)(currCU.firstPU->geoMergeIdx1)-GEO_MAX_NUM_UNI_CANDS > 0) // dimd/timd { const CompArea &area = currCU.Y(); #if ENABLE_DIMD #if JVET_W0123_TIMD_FUSION if (cs.slice->getSPS()->getUseDimd()) #endif { IntraPrediction::deriveDimdMode(currCU.cs->picture->getRecoBuf(area), area, currCU); } #endif #if JVET_W0123_TIMD_FUSION #if ENABLE_DIMD if (cs.slice->getSPS()->getUseTimd()) #endif { currCU.timdMode = m_pcIntraPred->deriveTimdMode(currCU.cs->picture->getRecoBuf(area), area, currCU); } #endif } } #endif xReconInter( currCU ); break; case MODE_PLT: case MODE_INTRA: #if ENABLE_DIMD if (currCU.dimd) { PredictionUnit *pu = currCU.firstPU; const CompArea &area = currCU.Y(); IntraPrediction::deriveDimdMode(currCU.cs->picture->getRecoBuf(area), area, currCU); pu->intraDir[0] = currCU.dimdMode; } #if JVET_W0123_TIMD_FUSION else if (currCU.timd) { PredictionUnit *pu = currCU.firstPU; const CompArea &area = currCU.Y(); #if SECONDARY_MPM IntraPrediction::deriveDimdMode(currCU.cs->picture->getRecoBuf(area), area, currCU); #endif currCU.timdMode = m_pcIntraPred->deriveTimdMode(currCU.cs->picture->getRecoBuf(area), area, currCU); pu->intraDir[0] = currCU.timdMode; } #endif else if (currCU.firstPU->parseLumaMode) { const CompArea &area = currCU.Y(); IntraPrediction::deriveDimdMode(currCU.cs->picture->getRecoBuf(area), area, currCU); } //redo prediction dir derivation if (currCU.firstPU->parseLumaMode) { #if SECONDARY_MPM uint8_t* mpm_pred = currCU.firstPU->intraMPM; // mpm_idx / rem_intra_luma_pred_mode uint8_t* non_mpm_pred = currCU.firstPU->intraNonMPM; PU::getIntraMPMs( *currCU.firstPU, mpm_pred, non_mpm_pred ); #else unsigned int mpm_pred[NUM_MOST_PROBABLE_MODES]; // mpm_idx / rem_intra_luma_pred_mode PU::getIntraMPMs(*currCU.firstPU, mpm_pred); #endif if (currCU.firstPU->mpmFlag) { currCU.firstPU->intraDir[0] = mpm_pred[currCU.firstPU->ipred_idx]; } else { #if SECONDARY_MPM if (currCU.firstPU->secondMpmFlag) { currCU.firstPU->intraDir[0] = mpm_pred[currCU.firstPU->ipred_idx]; } else { currCU.firstPU->intraDir[0] = non_mpm_pred[currCU.firstPU->ipred_idx]; } #else //postponed sorting of MPMs (only in remaining branch) std::sort(mpm_pred, mpm_pred + NUM_MOST_PROBABLE_MODES); unsigned ipred_mode = currCU.firstPU->ipred_idx; for (uint32_t i = 0; i < NUM_MOST_PROBABLE_MODES; i++) { ipred_mode += (ipred_mode >= mpm_pred[i]); } currCU.firstPU->intraDir[0] = ipred_mode; #endif } } if (currCU.firstPU->parseChromaMode) { unsigned chromaCandModes[NUM_CHROMA_MODE]; PU::getIntraChromaCandModes(*currCU.firstPU, chromaCandModes); CHECK(currCU.firstPU->candId >= NUM_CHROMA_MODE, "Chroma prediction mode index out of bounds"); CHECK(PU::isLMCMode(chromaCandModes[currCU.firstPU->candId]), "The intra dir cannot be LM_CHROMA for this path"); CHECK(chromaCandModes[currCU.firstPU->candId] == DM_CHROMA_IDX, "The intra dir cannot be DM_CHROMA for this path"); #if JVET_Z0050_DIMD_CHROMA_FUSION && ENABLE_DIMD CHECK(chromaCandModes[currCU.firstPU->candId] == DIMD_CHROMA_IDX, "The intra dir cannot be DIMD_CHROMA for this path"); #endif currCU.firstPU->intraDir[1] = chromaCandModes[currCU.firstPU->candId]; } #else #if JVET_W0123_TIMD_FUSION if (currCU.timd) { PredictionUnit *pu = currCU.firstPU; const CompArea &area = currCU.Y(); currCU.timdMode = m_pcIntraPred->deriveTimdMode(currCU.cs->picture->getRecoBuf(area), area, currCU); pu->intraDir[0] = currCU.timdMode; } //redo prediction dir derivation if (currCU.firstPU->parseLumaMode) { #if SECONDARY_MPM uint8_t* mpm_pred = currCU.firstPU->intraMPM; // mpm_idx / rem_intra_luma_pred_mode uint8_t* non_mpm_pred = currCU.firstPU->intraNonMPM; PU::getIntraMPMs( *currCU.firstPU, mpm_pred, non_mpm_pred ); #else unsigned int mpm_pred[NUM_MOST_PROBABLE_MODES]; // mpm_idx / rem_intra_luma_pred_mode PU::getIntraMPMs(*currCU.firstPU, mpm_pred); #endif if (currCU.firstPU->mpmFlag) { currCU.firstPU->intraDir[0] = mpm_pred[currCU.firstPU->ipred_idx]; } else { #if SECONDARY_MPM if (currCU.firstPU->secondMpmFlag) { currCU.firstPU->intraDir[0] = mpm_pred[currCU.firstPU->ipred_idx]; } else { currCU.firstPU->intraDir[0] = non_mpm_pred[currCU.firstPU->ipred_idx]; } #else //postponed sorting of MPMs (only in remaining branch) std::sort(mpm_pred, mpm_pred + NUM_MOST_PROBABLE_MODES); unsigned ipred_mode = currCU.firstPU->ipred_idx; for (uint32_t i = 0; i < NUM_MOST_PROBABLE_MODES; i++) { ipred_mode += (ipred_mode >= mpm_pred[i]); } currCU.firstPU->intraDir[0] = ipred_mode; #endif } } if (currCU.firstPU->parseChromaMode) { unsigned chromaCandModes[NUM_CHROMA_MODE]; PU::getIntraChromaCandModes(*currCU.firstPU, chromaCandModes); CHECK(currCU.firstPU->candId >= NUM_CHROMA_MODE, "Chroma prediction mode index out of bounds"); CHECK(PU::isLMCMode(chromaCandModes[currCU.firstPU->candId]), "The intra dir cannot be LM_CHROMA for this path"); CHECK(chromaCandModes[currCU.firstPU->candId] == DM_CHROMA_IDX, "The intra dir cannot be DM_CHROMA for this path"); currCU.firstPU->intraDir[1] = chromaCandModes[currCU.firstPU->candId]; } #endif #endif xReconIntraQT( currCU ); break; default: THROW( "Invalid prediction mode" ); break; } m_pcInterPred->xFillIBCBuffer(currCU); #if JVET_Z0118_GDR // decompressCtu cs.updateReconMotIPM( currCU ); // decompressCtu : need #endif DTRACE_BLOCK_REC( cs.picture->getRecoBuf( currCU ), currCU, currCU.predMode ); if (CU::isInter(currCU)) { DTRACE_MOT_FIELD(g_trace_ctx, *currCU.firstPU); } } } #if K0149_BLOCK_STATISTICS getAndStoreBlockStatistics(cs, ctuArea); #endif } // ==================================================================================================================== // Protected member functions // ==================================================================================================================== void DecCu::xIntraRecBlk( TransformUnit& tu, const ComponentID compID ) { if( !tu.blocks[ compID ].valid() ) { return; } CodingStructure &cs = *tu.cs; const CompArea &area = tu.blocks[compID]; #if SIGN_PREDICTION const bool isJCCR = tu.jointCbCr && isChroma(compID); const CompArea &areaCr = tu.blocks[isJCCR ? COMPONENT_Cr : compID]; PelBuf piPredCr; if(isJCCR) { piPredCr = cs.getPredBuf( tu.blocks[COMPONENT_Cr] ); } #endif const ChannelType chType = toChannelType( compID ); PelBuf piPred = cs.getPredBuf( area ); #if JVET_AB0061_ITMP_BV_FOR_IBC PredictionUnit &pu = *tu.cs->getPU(area.pos(), chType); #else const PredictionUnit &pu = *tu.cs->getPU( area.pos(), chType ); #endif #if ENABLE_DIMD #if JVET_Z0050_DIMD_CHROMA_FUSION && ENABLE_DIMD if (pu.intraDir[1] == DIMD_CHROMA_IDX && compID == COMPONENT_Cb) { CompArea areaCb = pu.Cb(); CompArea areaCr = pu.Cr(); CompArea lumaArea = CompArea(COMPONENT_Y, pu.chromaFormat, areaCb.lumaPos(), recalcSize(pu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, areaCb.size())); IntraPrediction::deriveDimdChromaMode(cs.picture->getRecoBuf(lumaArea), cs.picture->getRecoBuf(areaCb), cs.picture->getRecoBuf(areaCr), lumaArea, areaCb, areaCr, *pu.cu); } #endif uint32_t uiChFinalMode = PU::getFinalIntraMode(pu, chType); #else const uint32_t uiChFinalMode = PU::getFinalIntraMode(pu, chType); #endif PelBuf pReco = cs.getRecoBuf(area); //===== init availability pattern ===== bool predRegDiffFromTB = CU::isPredRegDiffFromTB(*tu.cu, compID); bool firstTBInPredReg = CU::isFirstTBInPredReg(*tu.cu, compID, area); CompArea areaPredReg(COMPONENT_Y, tu.chromaFormat, area); #if SIGN_PREDICTION if( !isJCCR || compID != COMPONENT_Cr ) { #endif if (tu.cu->ispMode && isLuma(compID)) { if (predRegDiffFromTB) { if (firstTBInPredReg) { CU::adjustPredArea(areaPredReg); m_pcIntraPred->initIntraPatternChTypeISP(*tu.cu, areaPredReg, pReco); } } else { m_pcIntraPred->initIntraPatternChTypeISP(*tu.cu, area, pReco); } } #if JVET_AA0057_CCCM else if ( isLuma(compID) || !pu.cccmFlag ) #else else #endif { m_pcIntraPred->initIntraPatternChType(*tu.cu, area); } //===== get prediction signal ===== #if JVET_AA0057_CCCM if( compID != COMPONENT_Y && pu.cccmFlag ) { // Create both Cb and Cr predictions when here for Cb if( compID == COMPONENT_Cb ) { const PredictionUnit& pu = *tu.cu->firstPU; PelBuf predCr = cs.getPredBuf( tu.blocks[COMPONENT_Cr] ); m_pcIntraPred->xGetLumaRecPixels( pu, area ); m_pcIntraPred->predIntraCCCM( pu, piPred, predCr, uiChFinalMode ); } } else #endif if( compID != COMPONENT_Y && PU::isLMCMode( uiChFinalMode ) ) { const PredictionUnit& pu = *tu.cu->firstPU; m_pcIntraPred->xGetLumaRecPixels( pu, area ); m_pcIntraPred->predIntraChromaLM( compID, piPred, pu, area, uiChFinalMode ); } else { #if JVET_V0130_INTRA_TMP if (PU::isTmp(pu, chType)) { int foundCandiNum; #if JVET_W0069_TMP_BOUNDARY RefTemplateType tempType = m_pcIntraPred->getRefTemplateType(*(tu.cu), tu.cu->blocks[COMPONENT_Y]); if( tempType != NO_TEMPLATE ) { m_pcIntraPred->getTargetTemplate(tu.cu, pu.lwidth(), pu.lheight(), tempType); m_pcIntraPred->candidateSearchIntra(tu.cu, pu.lwidth(), pu.lheight(), tempType); #if JVET_AB0061_ITMP_BV_FOR_IBC m_pcIntraPred->generateTMPrediction(piPred.buf, piPred.stride, foundCandiNum, pu); #else m_pcIntraPred->generateTMPrediction(piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), foundCandiNum); #endif } else { foundCandiNum = 1; m_pcIntraPred->generateTmDcPrediction(piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), 1 << (tu.cu->cs->sps->getBitDepth(CHANNEL_TYPE_LUMA) - 1)); #if JVET_AB0061_ITMP_BV_FOR_IBC pu.interDir = 1; // use list 0 for IBC mode pu.refIdx[REF_PIC_LIST_0] = MAX_NUM_REF; // last idx in the list pu.mv->set(0, 0); pu.bv.set(0, 0); #endif } #else m_pcIntraPred->getTargetTemplate(tu.cu, pu.lwidth(), pu.lheight()); m_pcIntraPred->candidateSearchIntra(tu.cu, pu.lwidth(), pu.lheight()); m_pcIntraPred->generateTMPrediction(piPred.buf, piPred.stride, pu.lwidth(), pu.lheight(), foundCandiNum); #endif assert(foundCandiNum >= 1); } else if (PU::isMIP(pu, chType)) #else if( PU::isMIP( pu, chType ) ) #endif { m_pcIntraPred->initIntraMip( pu, area ); m_pcIntraPred->predIntraMip( compID, piPred, pu ); } else { if (predRegDiffFromTB) { if (firstTBInPredReg) { PelBuf piPredReg = cs.getPredBuf(areaPredReg); m_pcIntraPred->predIntraAng(compID, piPredReg, pu); } } else m_pcIntraPred->predIntraAng(compID, piPred, pu); #if JVET_Z0050_DIMD_CHROMA_FUSION if (compID != COMPONENT_Y && pu.isChromaFusion) { m_pcIntraPred->geneChromaFusionPred(compID, piPred, pu); } #endif } } #if SIGN_PREDICTION #if JVET_AA0057_CCCM if(isJCCR && compID == COMPONENT_Cb && !pu.cccmFlag) // Cr prediction was done already for CCCM #else if(isJCCR && compID == COMPONENT_Cb) #endif { m_pcIntraPred->initIntraPatternChType(*tu.cu, areaCr); if( PU::isLMCMode( uiChFinalMode ) ) { const PredictionUnit& pu = *tu.cu->firstPU; m_pcIntraPred->xGetLumaRecPixels( pu, areaCr ); m_pcIntraPred->predIntraChromaLM( COMPONENT_Cr, piPredCr, pu, areaCr, uiChFinalMode ); } else { if( PU::isMIP( pu, chType ) ) { m_pcIntraPred->initIntraMip( pu, area ); m_pcIntraPred->predIntraMip( COMPONENT_Cr, piPredCr, pu ); } else { m_pcIntraPred->predIntraAng(COMPONENT_Cr, piPredCr, pu); #if JVET_Z0050_DIMD_CHROMA_FUSION if (pu.isChromaFusion) { m_pcIntraPred->geneChromaFusionPred(COMPONENT_Cr, piPredCr, pu); } #endif } } } } #endif const Slice &slice = *cs.slice; bool flag = slice.getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag())); if (flag && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (compID != COMPONENT_Y) && (tu.cbf[COMPONENT_Cb] || tu.cbf[COMPONENT_Cr])) { #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())); #endif const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area); int adj = m_pcReshape->calculateChromaAdjVpduNei(tu, areaY); tu.setChromaAdj(adj); } #if SIGN_PREDICTION flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4); #endif //===== inverse transform ===== PelBuf piResi = cs.getResiBuf( area ); const QpParam cQP( tu, compID ); #if SIGN_PREDICTION bool bJccrWithCr = tu.jointCbCr && !(tu.jointCbCr >> 1); bool bIsJccr = tu.jointCbCr && isChroma(compID); ComponentID signPredCompID = bIsJccr ? (bJccrWithCr ? COMPONENT_Cr : COMPONENT_Cb): compID; bool reshapeChroma = flag && (TU::getCbf(tu, signPredCompID) || tu.jointCbCr) && isChroma(signPredCompID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag(); m_pcTrQuant->predCoeffSigns(tu, compID, reshapeChroma); #endif if( tu.jointCbCr && isChroma(compID) ) { if( compID == COMPONENT_Cb ) { PelBuf resiCr = cs.getResiBuf( tu.blocks[ COMPONENT_Cr ] ); if( tu.jointCbCr >> 1 ) { m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cb, piResi, cQP ); } else { const QpParam qpCr( tu, COMPONENT_Cr ); m_pcTrQuant->invTransformNxN( tu, COMPONENT_Cr, resiCr, qpCr ); } m_pcTrQuant->invTransformICT( tu, piResi, resiCr ); } } else if( TU::getCbf( tu, compID ) ) { m_pcTrQuant->invTransformNxN( tu, compID, piResi, cQP ); } else { piResi.fill( 0 ); } //===== reconstruction ===== #if !SIGN_PREDICTION flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4); #endif if (flag && (TU::getCbf(tu, compID) || tu.jointCbCr) && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()) { piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID)); } if( !tu.cu->ispMode || !isLuma( compID ) ) { cs.setDecomp( area ); } else if( tu.cu->ispMode && isLuma( compID ) && CU::isISPFirst( *tu.cu, tu.blocks[compID], compID ) ) { cs.setDecomp( tu.cu->blocks[compID] ); } #if REUSE_CU_RESULTS CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); PelBuf tmpPred; #endif if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y) { #if REUSE_CU_RESULTS { tmpPred = m_tmpStorageLCU->getBuf(tmpArea); tmpPred.copyFrom(piPred); } #endif } #if KEEP_PRED_AND_RESI_SIGNALS pReco.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRng( compID ) ); #else piPred.reconstruct( piPred, piResi, tu.cu->cs->slice->clpRng( compID ) ); pReco.copyFrom( piPred ); #endif if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y) { #if REUSE_CU_RESULTS { piPred.copyFrom(tmpPred); } #endif } #if REUSE_CU_RESULTS || SIGN_PREDICTION #if !SIGN_PREDICTION if( cs.pcv->isEncoder ) #endif { #if JVET_Z0118_GDR cs.updateReconMotIPM(area, pReco); #else cs.picture->getRecoBuf( area ).copyFrom( pReco ); #endif cs.picture->getPredBuf(area).copyFrom(piPred); } #endif } void DecCu::xIntraRecACTBlk(TransformUnit& tu) { CodingStructure &cs = *tu.cs; const PredictionUnit &pu = *tu.cs->getPU(tu.blocks[COMPONENT_Y], CHANNEL_TYPE_LUMA); const Slice &slice = *cs.slice; CHECK(!tu.Y().valid() || !tu.Cb().valid() || !tu.Cr().valid(), "Invalid TU"); CHECK(&pu != tu.cu->firstPU, "wrong PU fetch"); CHECK(tu.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"); bool flag = slice.getLmcsEnabledFlag() && (slice.isIntra() || (!slice.isIntra() && m_pcReshape->getCTUFlag())); #if JVET_S0234_ACT_CRS_FIX if (flag && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()) #else if (flag && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (tu.cbf[COMPONENT_Cb] || tu.cbf[COMPONENT_Cr])) #endif { #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())); #endif const CompArea &areaY = CompArea(COMPONENT_Y, tu.chromaFormat, area); int adj = m_pcReshape->calculateChromaAdjVpduNei(tu, areaY); tu.setChromaAdj(adj); } 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 piPred = cs.getPredBuf(area); m_pcIntraPred->initIntraPatternChType(*tu.cu, area); #if JVET_V0130_INTRA_TMP && ! JVET_W0069_TMP_BOUNDARY if (PU::isTmp(pu, chType)) { int foundCandiNum; const unsigned int uiStride = cs.picture->getRecoBuf(COMPONENT_Y).stride; m_pcIntraPred->getTargetTemplate(tu.cu, pu.lwidth(), pu.lheight()); m_pcIntraPred->candidateSearchIntra(tu.cu, pu.lwidth(), pu.lheight()); m_pcIntraPred->generateTMPrediction(piPred.buf, uiStride, pu.lwidth(), pu.lheight(), foundCandiNum); } else if (PU::isMIP(pu, chType)) #else if (PU::isMIP(pu, chType)) #endif { m_pcIntraPred->initIntraMip(pu, area); m_pcIntraPred->predIntraMip(compID, piPred, pu); } else { m_pcIntraPred->predIntraAng(compID, piPred, pu); } PelBuf piResi = cs.getResiBuf(area); QpParam cQP(tu, compID); if (tu.jointCbCr && isChroma(compID)) { if (compID == COMPONENT_Cb) { PelBuf resiCr = cs.getResiBuf(tu.blocks[COMPONENT_Cr]); if (tu.jointCbCr >> 1) { m_pcTrQuant->invTransformNxN(tu, COMPONENT_Cb, piResi, cQP); } else { QpParam qpCr(tu, COMPONENT_Cr); m_pcTrQuant->invTransformNxN(tu, COMPONENT_Cr, resiCr, qpCr); } m_pcTrQuant->invTransformICT(tu, piResi, resiCr); } } else { if (TU::getCbf(tu, compID)) { m_pcTrQuant->invTransformNxN(tu, compID, piResi, cQP); } else { piResi.fill(0); } } #if !JVET_S0234_ACT_CRS_FIX flag = flag && (tu.blocks[compID].width*tu.blocks[compID].height > 4); if (flag && (TU::getCbf(tu, compID) || tu.jointCbCr) && isChroma(compID) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()) { piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID)); } #endif cs.setDecomp(area); } cs.getResiBuf(tu).colorSpaceConvert(cs.getResiBuf(tu), false, tu.cu->cs->slice->clpRng(COMPONENT_Y)); for (int i = 0; i < getNumberValidComponents(tu.chromaFormat); i++) { ComponentID compID = (ComponentID)i; const CompArea &area = tu.blocks[compID]; PelBuf piPred = cs.getPredBuf(area); PelBuf piResi = cs.getResiBuf(area); PelBuf piReco = cs.getRecoBuf(area); PelBuf tmpPred; if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y) { CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); tmpPred = m_tmpStorageLCU->getBuf(tmpArea); tmpPred.copyFrom(piPred); } #if JVET_S0234_ACT_CRS_FIX if (flag && isChroma(compID) && (tu.blocks[compID].width*tu.blocks[compID].height > 4) && slice.getPicHeader()->getLmcsChromaResidualScaleFlag()) { piResi.scaleSignal(tu.getChromaAdj(), 0, tu.cu->cs->slice->clpRng(compID)); } #endif piPred.reconstruct(piPred, piResi, tu.cu->cs->slice->clpRng(compID)); piReco.copyFrom(piPred); if (slice.getLmcsEnabledFlag() && (m_pcReshape->getCTUFlag() || slice.isIntra()) && compID == COMPONENT_Y) { piPred.copyFrom(tmpPred); } if (cs.pcv->isEncoder) { #if JVET_Z0118_GDR cs.updateReconMotIPM(area, piReco); #else cs.picture->getRecoBuf(area).copyFrom(piReco); #endif cs.picture->getPredBuf(area).copyFrom(piPred); } } } void DecCu::xReconIntraQT( CodingUnit &cu ) { if (CU::isPLT(cu)) { #if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS if (CS::isDualITree(*cu.cs)) #else if (cu.isSepTree()) #endif { if (cu.chType == CHANNEL_TYPE_LUMA) { xReconPLT(cu, COMPONENT_Y, 1); } if (cu.chromaFormat != CHROMA_400 && (cu.chType == CHANNEL_TYPE_CHROMA)) { xReconPLT(cu, COMPONENT_Cb, 2); } } else { if( cu.chromaFormat != CHROMA_400 ) { xReconPLT(cu, COMPONENT_Y, 3); } else { xReconPLT(cu, COMPONENT_Y, 1); } } return; } if (cu.colorTransform) { xIntraRecACTQT(cu); } else { const uint32_t numChType = ::getNumberValidChannels(cu.chromaFormat); for (uint32_t chType = CHANNEL_TYPE_LUMA; chType < numChType; chType++) { if (cu.blocks[chType].valid()) { xIntraRecQT(cu, ChannelType(chType)); } } } #if JVET_W0123_TIMD_FUSION if (cu.blocks[CHANNEL_TYPE_LUMA].valid()) { PU::spanIpmInfoIntra(*cu.firstPU); } #endif #if JVET_AB0061_ITMP_BV_FOR_IBC if (cu.blocks[CHANNEL_TYPE_LUMA].valid() && cu.tmpFlag) { PU::spanMotionInfo(*cu.firstPU); } #endif } void DecCu::xReconPLT(CodingUnit &cu, ComponentID compBegin, uint32_t numComp) { const SPS& sps = *(cu.cs->sps); TransformUnit& tu = *cu.firstTU; PelBuf curPLTIdx = tu.getcurPLTIdx(compBegin); uint32_t height = cu.block(compBegin).height; uint32_t width = cu.block(compBegin).width; //recon. pixels uint32_t scaleX = getComponentScaleX(COMPONENT_Cb, sps.getChromaFormatIdc()); uint32_t scaleY = getComponentScaleY(COMPONENT_Cb, sps.getChromaFormatIdc()); for (uint32_t y = 0; y < height; y++) { for (uint32_t x = 0; x < width; x++) { for (uint32_t compID = compBegin; compID < (compBegin + numComp); compID++) { const int channelBitDepth = cu.cs->sps->getBitDepth(toChannelType((ComponentID)compID)); const CompArea &area = cu.blocks[compID]; PelBuf picReco = cu.cs->getRecoBuf(area); PLTescapeBuf escapeValue = tu.getescapeValue((ComponentID)compID); if (curPLTIdx.at(x, y) == cu.curPLTSize[compBegin]) { #if JVET_R0351_HIGH_BIT_DEPTH_SUPPORT_VS TCoeff value; #else Pel value; #endif QpParam cQP(tu, (ComponentID)compID); int qp = cQP.Qp(true); int qpRem = qp % 6; int qpPer = qp / 6; if (compBegin != COMPONENT_Y || compID == COMPONENT_Y) { int invquantiserRightShift = IQUANT_SHIFT; int add = 1 << (invquantiserRightShift - 1); value = ((((escapeValue.at(x, y)*g_invQuantScales[0][qpRem]) << qpPer) + add) >> invquantiserRightShift); #if JVET_R0351_HIGH_BIT_DEPTH_SUPPORT_VS value = ClipBD<TCoeff>(value, channelBitDepth); picReco.at(x, y) = Pel(value); #else value = Pel(ClipBD<int>(value, channelBitDepth)); picReco.at(x, y) = value; #endif } else if (compBegin == COMPONENT_Y && compID != COMPONENT_Y && y % (1 << scaleY) == 0 && x % (1 << scaleX) == 0) { uint32_t posYC = y >> scaleY; uint32_t posXC = x >> scaleX; int invquantiserRightShift = IQUANT_SHIFT; int add = 1 << (invquantiserRightShift - 1); value = ((((escapeValue.at(posXC, posYC)*g_invQuantScales[0][qpRem]) << qpPer) + add) >> invquantiserRightShift); #if JVET_R0351_HIGH_BIT_DEPTH_SUPPORT_VS value = ClipBD<TCoeff>(value, channelBitDepth); picReco.at(posXC, posYC) = Pel(value); #else value = Pel(ClipBD<int>(value, channelBitDepth)); picReco.at(posXC, posYC) = value; #endif } } else { uint32_t curIdx = curPLTIdx.at(x, y); if (compBegin != COMPONENT_Y || compID == COMPONENT_Y) { picReco.at(x, y) = cu.curPLT[compID][curIdx]; } else if (compBegin == COMPONENT_Y && compID != COMPONENT_Y && y % (1 << scaleY) == 0 && x % (1 << scaleX) == 0) { uint32_t posYC = y >> scaleY; uint32_t posXC = x >> scaleX; picReco.at(posXC, posYC) = cu.curPLT[compID][curIdx]; } } } } } for (uint32_t compID = compBegin; compID < (compBegin + numComp); compID++) { const CompArea &area = cu.blocks[compID]; PelBuf picReco = cu.cs->getRecoBuf(area); #if JVET_Z0118_GDR cu.cs->updateReconMotIPM(area, picReco); #else cu.cs->picture->getRecoBuf(area).copyFrom(picReco); #endif cu.cs->setDecomp(area); } } /** Function for deriving reconstructed PU/CU chroma samples with QTree structure * \param pcRecoYuv pointer to reconstructed sample arrays * \param pcPredYuv pointer to prediction sample arrays * \param pcResiYuv pointer to residue sample arrays * \param chType texture channel type (luma/chroma) * \param rTu reference to transform data * \ This function derives reconstructed PU/CU chroma samples with QTree recursive structure */ void DecCu::xIntraRecQT(CodingUnit &cu, const ChannelType chType) { for( auto &currTU : CU::traverseTUs( cu ) ) { if( isLuma( chType ) ) { xIntraRecBlk( currTU, COMPONENT_Y ); } else { const uint32_t numValidComp = getNumberValidComponents( cu.chromaFormat ); for( uint32_t compID = COMPONENT_Cb; compID < numValidComp; compID++ ) { xIntraRecBlk( currTU, ComponentID( compID ) ); } } } } void DecCu::xIntraRecACTQT(CodingUnit &cu) { for (auto &currTU : CU::traverseTUs(cu)) { xIntraRecACTBlk(currTU); } } #if !REMOVE_PCM /** Function for filling the PCM buffer of a CU using its reconstructed sample array * \param pCU pointer to current CU * \param depth CU Depth */ void DecCu::xFillPCMBuffer(CodingUnit &cu) { for( auto &currTU : CU::traverseTUs( cu ) ) { for (const CompArea &area : currTU.blocks) { if( !area.valid() ) continue;; CPelBuf source = cu.cs->getRecoBuf(area); PelBuf destination = currTU.getPcmbuf(area.compID); destination.copyFrom(source); } } } #endif #include "CommonLib/dtrace_buffer.h" void DecCu::xReconInter(CodingUnit &cu) { if( cu.geoFlag ) { #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING m_pcInterPred->motionCompensationGeo( cu, m_geoMrgCtx #if JVET_W0097_GPM_MMVD_TM && TM_MRG , m_geoTmMrgCtx #endif #if JVET_Y0065_GPM_INTRA , m_pcIntraPred, (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) ? &m_pcReshape->getFwdLUT() : nullptr #endif ); #if JVET_W0097_GPM_MMVD_TM && TM_MRG MergeCtx& m_geoTmMrgCtx0 = m_geoTmMrgCtx[g_geoTmShape[0][g_GeoParams[cu.firstPU->geoSplitDir][0]]]; MergeCtx& m_geoTmMrgCtx1 = m_geoTmMrgCtx[g_geoTmShape[1][g_GeoParams[cu.firstPU->geoSplitDir][0]]]; #endif #if JVET_W0097_GPM_MMVD_TM PU::spanGeoMMVDMotionInfo #else PU::spanGeoMotionInfo #endif ( *cu.firstPU, m_geoMrgCtx #if JVET_W0097_GPM_MMVD_TM && TM_MRG , m_geoTmMrgCtx0, m_geoTmMrgCtx1 #endif , cu.firstPU->geoSplitDir, cu.firstPU->geoMergeIdx0, cu.firstPU->geoMergeIdx1 #if JVET_W0097_GPM_MMVD_TM #if TM_MRG , cu.firstPU->geoTmFlag0 #endif , cu.firstPU->geoMMVDFlag0, cu.firstPU->geoMMVDIdx0 #if TM_MRG , cu.firstPU->geoTmFlag1 #endif , cu.firstPU->geoMMVDFlag1, cu.firstPU->geoMMVDIdx1 #endif #if JVET_AA0058_GPM_ADP_BLD , cu.firstPU->geoBldIdx #endif ); #else #if JVET_W0097_GPM_MMVD_TM #if TM_MRG #if JVET_Y0065_GPM_INTRA m_pcInterPred->motionCompensationGeo( cu, m_geoMrgCtx, m_geoTmMrgCtx0, m_geoTmMrgCtx1, m_pcIntraPred, (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) ? &m_pcReshape->getFwdLUT() : nullptr ); #else m_pcInterPred->motionCompensationGeo(cu, m_geoMrgCtx, m_geoTmMrgCtx0, m_geoTmMrgCtx1); #endif #if JVET_AA0058_GPM_ADP_BLD PU::spanGeoMMVDMotionInfo(*cu.firstPU, m_geoMrgCtx, m_geoTmMrgCtx0, m_geoTmMrgCtx1, cu.firstPU->geoSplitDir, cu.firstPU->geoMergeIdx0, cu.firstPU->geoMergeIdx1, cu.firstPU->geoTmFlag0, cu.firstPU->geoMMVDFlag0, cu.firstPU->geoMMVDIdx0, cu.firstPU->geoTmFlag1, cu.firstPU->geoMMVDFlag1, cu.firstPU->geoMMVDIdx1, cu.firstPU->geoBldIdx); #else PU::spanGeoMMVDMotionInfo(*cu.firstPU, m_geoMrgCtx, m_geoTmMrgCtx0, m_geoTmMrgCtx1, cu.firstPU->geoSplitDir, cu.firstPU->geoMergeIdx0, cu.firstPU->geoMergeIdx1, cu.firstPU->geoTmFlag0, cu.firstPU->geoMMVDFlag0, cu.firstPU->geoMMVDIdx0, cu.firstPU->geoTmFlag1, cu.firstPU->geoMMVDFlag1, cu.firstPU->geoMMVDIdx1); #endif #else #if JVET_Y0065_GPM_INTRA m_pcInterPred->motionCompensationGeo( cu, m_geoMrgCtx, m_pcIntraPred, (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) ? &m_pcReshape->getFwdLUT() : nullptr ); #else m_pcInterPred->motionCompensationGeo(cu, m_geoMrgCtx); #endif #if JVET_AA0058_GPM_ADP_BLD PU::spanGeoMMVDMotionInfo(*cu.firstPU, m_geoMrgCtx, cu.firstPU->geoSplitDir, cu.firstPU->geoMergeIdx0, cu.firstPU->geoMergeIdx1, cu.firstPU->geoMMVDFlag0, cu.firstPU->geoMMVDIdx0, cu.firstPU->geoMMVDFlag1, cu.firstPU->geoMMVDIdx1, cu.firstPU->geoBldIdx); #else PU::spanGeoMMVDMotionInfo(*cu.firstPU, m_geoMrgCtx, cu.firstPU->geoSplitDir, cu.firstPU->geoMergeIdx0, cu.firstPU->geoMergeIdx1, cu.firstPU->geoMMVDFlag0, cu.firstPU->geoMMVDIdx0, cu.firstPU->geoMMVDFlag1, cu.firstPU->geoMMVDIdx1); #endif #endif #else #if JVET_Y0065_GPM_INTRA m_pcInterPred->motionCompensationGeo( cu, m_geoMrgCtx, m_pcIntraPred, (cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) ? &m_pcReshape->getFwdLUT() : nullptr ); #else m_pcInterPred->motionCompensationGeo( cu, m_geoMrgCtx ); #endif PU::spanGeoMotionInfo( *cu.firstPU, m_geoMrgCtx, cu.firstPU->geoSplitDir, cu.firstPU->geoMergeIdx0, cu.firstPU->geoMergeIdx1 ); #endif #endif } else { #if JVET_X0141_CIIP_TIMD_TM && JVET_W0123_TIMD_FUSION if (cu.firstPU->ciipFlag #if CIIP_PDPC && !cu.firstPU->ciipPDPC #endif ) { PredictionUnit *pu = cu.firstPU; const CompArea &area = cu.Y(); if (cu.slice->getSPS()->getUseTimd() && (cu.lwidth() * cu.lheight() <= CIIP_MAX_SIZE)) { #if SECONDARY_MPM && ENABLE_DIMD IntraPrediction::deriveDimdMode(cu.cs->picture->getRecoBuf(area), area, cu); #endif cu.timdMode = m_pcIntraPred->deriveTimdMode(cu.cs->picture->getRecoBuf(area), area, cu); pu->intraDir[0] = MAP131TO67(cu.timdMode); } } #endif m_pcIntraPred->geneIntrainterPred(cu, m_ciipBuffer); // inter prediction CHECK(CU::isIBC(cu) && cu.firstPU->ciipFlag, "IBC and Ciip cannot be used together"); CHECK(CU::isIBC(cu) && cu.affine, "IBC and Affine cannot be used together"); CHECK(CU::isIBC(cu) && cu.geoFlag, "IBC and geo cannot be used together"); CHECK(CU::isIBC(cu) && cu.firstPU->mmvdMergeFlag, "IBC and MMVD cannot be used together"); const bool luma = cu.Y().valid(); const bool chroma = isChromaEnabled(cu.chromaFormat) && cu.Cb().valid(); if (luma && (chroma || !isChromaEnabled(cu.chromaFormat))) { m_pcInterPred->motionCompensation(cu); } else { m_pcInterPred->motionCompensation(cu, REF_PIC_LIST_0, luma, chroma); } #if MULTI_PASS_DMVR if( cu.firstPU->bdmvrRefine ) { PU::spanMotionInfo( *cu.firstPU, MergeCtx(), m_mvBufBDMVR[0], m_mvBufBDMVR[1], m_pcInterPred->getBdofSubPuMvOffset() ); } #endif } if (cu.Y().valid()) { bool isIbcSmallBlk = CU::isIBC(cu) && (cu.lwidth() * cu.lheight() <= 16); CU::saveMotionInHMVP( cu, isIbcSmallBlk ); } if (cu.firstPU->ciipFlag) { const UnitArea localUnitArea( cu.cs->area.chromaFormat, Area( 0, 0, cu.Y().width, cu.Y().height ) ); #if ENABLE_OBMC && JVET_X0090_CIIP_FIX cu.isobmcMC = true; m_pcInterPred->subBlockOBMC(*cu.firstPU); cu.isobmcMC = false; #endif if( cu.cs->slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() ) { m_pcIntraPred->geneWeightedPred<true>( COMPONENT_Y, cu.cs->getPredBuf( *cu.firstPU ).Y(), *cu.firstPU, cu.cs->getPredBuf( *cu.firstPU ).Y(), m_ciipBuffer.getBuf( localUnitArea.Y() ), m_pcReshape->getFwdLUT().data() ); } else { m_pcIntraPred->geneWeightedPred<false>( COMPONENT_Y, cu.cs->getPredBuf( *cu.firstPU ).Y(), *cu.firstPU, cu.cs->getPredBuf( *cu.firstPU ).Y(), m_ciipBuffer.getBuf( localUnitArea.Y() ) ); } #if INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS if( isChromaEnabled( cu.chromaFormat ) ) #else if( isChromaEnabled( cu.chromaFormat ) && cu.chromaSize().width > 2 ) #endif { m_pcIntraPred->geneWeightedPred<false>( COMPONENT_Cb, cu.cs->getPredBuf( *cu.firstPU ).Cb(), *cu.firstPU, cu.cs->getPredBuf( *cu.firstPU ).Cb(), m_ciipBuffer.getBuf( localUnitArea.Cb() ) ); m_pcIntraPred->geneWeightedPred<false>( COMPONENT_Cr, cu.cs->getPredBuf( *cu.firstPU ).Cr(), *cu.firstPU, cu.cs->getPredBuf( *cu.firstPU ).Cr(), m_ciipBuffer.getBuf( localUnitArea.Cr() ) ); } } #if ENABLE_OBMC cu.isobmcMC = true; #if JVET_X0090_CIIP_FIX #if JVET_Y0065_GPM_INTRA if (!cu.firstPU->ciipFlag && !cu.firstPU->gpmIntraFlag) #else if (!cu.firstPU->ciipFlag) #endif { m_pcInterPred->subBlockOBMC(*cu.firstPU); } #else m_pcInterPred->subBlockOBMC(*cu.firstPU); #endif cu.isobmcMC = false; #endif DTRACE ( g_trace_ctx, D_TMP, "pred " ); DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getPredBuf( cu ), &cu.Y() ); // inter recon xDecodeInterTexture(cu); // clip for only non-zero cbf case CodingStructure &cs = *cu.cs; #if !SIGN_PREDICTION if (cu.rootCbf) { #if !JVET_S0234_ACT_CRS_FIX if (cu.colorTransform) { cs.getResiBuf(cu).colorSpaceConvert(cs.getResiBuf(cu), false, cu.cs->slice->clpRng(COMPONENT_Y)); } #endif #if REUSE_CU_RESULTS const CompArea &area = cu.blocks[COMPONENT_Y]; CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size()); PelBuf tmpPred; #endif if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) { #if REUSE_CU_RESULTS if (cs.pcv->isEncoder) { tmpPred = m_tmpStorageLCU->getBuf(tmpArea); tmpPred.copyFrom(cs.getPredBuf(cu).get(COMPONENT_Y)); } #endif #if JVET_Y0065_GPM_INTRA if (!cu.firstPU->ciipFlag && !cu.firstPU->gpmIntraFlag && !CU::isIBC(cu)) #else if (!cu.firstPU->ciipFlag && !CU::isIBC(cu)) #endif cs.getPredBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT()); } #if KEEP_PRED_AND_RESI_SIGNALS cs.getRecoBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() ); #else cs.getResiBuf( cu ).reconstruct( cs.getPredBuf( cu ), cs.getResiBuf( cu ), cs.slice->clpRngs() ); cs.getRecoBuf( cu ).copyFrom ( cs.getResiBuf( cu ) ); #endif if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) { #if REUSE_CU_RESULTS if (cs.pcv->isEncoder) { cs.getPredBuf(cu).get(COMPONENT_Y).copyFrom(tmpPred); } #endif } } else { cs.getRecoBuf(cu).copyClip(cs.getPredBuf(cu), cs.slice->clpRngs()); #if JVET_Y0065_GPM_INTRA if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->ciipFlag && !cu.firstPU->gpmIntraFlag && !CU::isIBC(cu)) #else if (cs.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->ciipFlag && !CU::isIBC(cu)) #endif { cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT()); } } #if JVET_AA0070_RRIBC if (CU::isIBC(cu) && cu.rribcFlipType) { cu.cs->getRecoBuf(cu).get(COMPONENT_Y).flipSignal(cu.rribcFlipType == 1); if (isChromaEnabled(cu.chromaFormat) && cu.Cb().valid()) { cu.cs->getRecoBuf(cu).get(COMPONENT_Cb).flipSignal(cu.rribcFlipType == 1); cu.cs->getRecoBuf(cu).get(COMPONENT_Cr).flipSignal(cu.rribcFlipType == 1); } } #endif #endif DTRACE ( g_trace_ctx, D_TMP, "reco " ); DTRACE_CRC( g_trace_ctx, D_TMP, *cu.cs, cu.cs->getRecoBuf( cu ), &cu.Y() ); cs.setDecomp(cu); } void DecCu::xDecodeInterTU( TransformUnit & currTU, const ComponentID compID ) { if( !currTU.blocks[compID].valid() ) return; const CompArea &area = currTU.blocks[compID]; CodingStructure& cs = *currTU.cs; //===== inverse transform ===== PelBuf resiBuf = cs.getResiBuf(area); QpParam cQP(currTU, compID); #if SIGN_PREDICTION bool bJccrWithCr = currTU.jointCbCr && !(currTU.jointCbCr >> 1); bool bIsJccr = currTU.jointCbCr && isChroma(compID); ComponentID signPredCompID = bIsJccr ? (bJccrWithCr ? COMPONENT_Cr : COMPONENT_Cb): compID; bool reshapeChroma = currTU.cs->slice->getPicHeader()->getLmcsEnabledFlag() && isChroma(signPredCompID) && (TU::getCbf(currTU, signPredCompID) || currTU.jointCbCr) && currTU.cs->slice->getPicHeader()->getLmcsChromaResidualScaleFlag() && currTU.blocks[signPredCompID].width * currTU.blocks[signPredCompID].height > 4; #if JVET_Y0065_GPM_INTRA if (currTU.cs->slice->getPicHeader()->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && isLuma(compID) && !currTU.cu->firstPU->ciipFlag && !currTU.cu->firstPU->gpmIntraFlag && !CU::isIBC(*currTU.cu)) #else if (currTU.cs->slice->getPicHeader()->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && isLuma(compID) && !currTU.cu->firstPU->ciipFlag && !CU::isIBC(*currTU.cu)) #endif { #if JVET_Z0118_GDR cs.updateReconMotIPM(currTU.blocks[COMPONENT_Y], cs.getPredBuf(currTU.blocks[COMPONENT_Y])); #else cs.picture->getRecoBuf(currTU.blocks[COMPONENT_Y]).copyFrom(cs.getPredBuf(currTU.blocks[COMPONENT_Y])); #endif cs.getPredBuf(currTU.blocks[COMPONENT_Y]).rspSignal(m_pcReshape->getFwdLUT()); } m_pcTrQuant->predCoeffSigns(currTU, compID, reshapeChroma); #if JVET_Y0065_GPM_INTRA if (currTU.cs->slice->getPicHeader()->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && isLuma(compID) && !currTU.cu->firstPU->ciipFlag && !currTU.cu->firstPU->gpmIntraFlag && !CU::isIBC(*currTU.cu)) #else if (currTU.cs->slice->getPicHeader()->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && isLuma(compID) && !currTU.cu->firstPU->ciipFlag && !CU::isIBC(*currTU.cu)) #endif { cs.getPredBuf(currTU.blocks[COMPONENT_Y]).copyFrom(cs.picture->getRecoBuf(currTU.blocks[COMPONENT_Y])); } #endif if( currTU.jointCbCr && isChroma(compID) ) { if( compID == COMPONENT_Cb ) { PelBuf resiCr = cs.getResiBuf( currTU.blocks[ COMPONENT_Cr ] ); if( currTU.jointCbCr >> 1 ) { m_pcTrQuant->invTransformNxN( currTU, COMPONENT_Cb, resiBuf, cQP ); } else { QpParam qpCr(currTU, COMPONENT_Cr); m_pcTrQuant->invTransformNxN( currTU, COMPONENT_Cr, resiCr, qpCr ); } m_pcTrQuant->invTransformICT( currTU, resiBuf, resiCr ); } } else if( TU::getCbf( currTU, compID ) ) { m_pcTrQuant->invTransformNxN( currTU, compID, resiBuf, cQP ); } else { resiBuf.fill( 0 ); } //===== reconstruction ===== const Slice &slice = *cs.slice; #if JVET_S0234_ACT_CRS_FIX if (!currTU.cu->colorTransform && slice.getLmcsEnabledFlag() && isChroma(compID) && (TU::getCbf(currTU, compID) || currTU.jointCbCr) #else if (slice.getLmcsEnabledFlag() && isChroma(compID) && (TU::getCbf(currTU, compID) || currTU.jointCbCr) #endif && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && currTU.blocks[compID].width * currTU.blocks[compID].height > 4) { resiBuf.scaleSignal(currTU.getChromaAdj(), 0, currTU.cu->cs->slice->clpRng(compID)); } #if SIGN_PREDICTION int firstComponent = compID; int lastComponent = compID; if( currTU.jointCbCr && isChroma(compID) ) { if( compID == COMPONENT_Cb ) { firstComponent = MAX_INT; } else { firstComponent -= 1; } } for( auto i = firstComponent; i <= lastComponent; ++i) { ComponentID currCompID = (ComponentID) i; PelBuf compResiBuf = cs.getResiBuf(currTU.blocks[currCompID]); #if JVET_Y0065_GPM_INTRA if( cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && isLuma( currCompID ) && !currTU.cu->firstPU->ciipFlag && !currTU.cu->firstPU->gpmIntraFlag && !CU::isIBC( *currTU.cu ) ) #else if( cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && isLuma( currCompID ) && !currTU.cu->firstPU->ciipFlag && !CU::isIBC( *currTU.cu ) ) #endif { PelBuf picRecoBuff = currTU.cs->picture->getRecoBuf( currTU.blocks[currCompID] ); #if JVET_Z0118_GDR currTU.cs->rspSignalPicture(currTU.blocks[currCompID], m_pcReshape->getFwdLUT()); #else picRecoBuff.rspSignal( cs.getPredBuf( currTU.blocks[currCompID] ), m_pcReshape->getFwdLUT() ); #endif currTU.cs->getRecoBuf( currTU.blocks[currCompID] ).reconstruct( picRecoBuff, compResiBuf, currTU.cu->cs->slice->clpRng( currCompID ) ); } else { currTU.cs->getRecoBuf( currTU.blocks[currCompID] ).reconstruct( cs.getPredBuf( currTU.blocks[currCompID] ), compResiBuf, currTU.cu->cs->slice->clpRng( currCompID ) ); #if JVET_AA0070_RRIBC if (CU::isIBC(*currTU.cu) && currTU.cu->rribcFlipType) { currTU.cs->getRecoBuf(currTU.blocks[currCompID]).flipSignal(currTU.cu->rribcFlipType == 1); } #endif } } #endif } void DecCu::xDecodeInterTexture(CodingUnit &cu) { if( !cu.rootCbf ) { #if SIGN_PREDICTION CodingStructure &cs = *cu.cs; cs.getRecoBuf(cu).copyClip(cs.getPredBuf(cu), cs.slice->clpRngs()); #if JVET_Y0065_GPM_INTRA if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->ciipFlag && !cu.firstPU->gpmIntraFlag && !CU::isIBC(cu)) #else if (cs.picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag() && !cu.firstPU->ciipFlag && !CU::isIBC(cu)) #endif { cs.getRecoBuf(cu).get(COMPONENT_Y).rspSignal(m_pcReshape->getFwdLUT()); } #if JVET_AA0070_RRIBC if (CU::isIBC(cu) && cu.rribcFlipType) { cu.cs->getRecoBuf(cu).get(COMPONENT_Y).flipSignal(cu.rribcFlipType == 1); if (isChromaEnabled(cu.chromaFormat) && cu.Cb().valid()) { cu.cs->getRecoBuf(cu).get(COMPONENT_Cb).flipSignal(cu.rribcFlipType == 1); cu.cs->getRecoBuf(cu).get(COMPONENT_Cr).flipSignal(cu.rribcFlipType == 1); } } #endif #endif return; } const uint32_t uiNumVaildComp = getNumberValidComponents(cu.chromaFormat); #if JVET_S0234_ACT_CRS_FIX if (cu.colorTransform) { CodingStructure &cs = *cu.cs; const Slice &slice = *cs.slice; for (auto& currTU : CU::traverseTUs(cu)) { for (uint32_t ch = 0; ch < uiNumVaildComp; ch++) { const ComponentID compID = ComponentID(ch); if (slice.getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (compID == COMPONENT_Y)) { const CompArea &areaY = currTU.blocks[COMPONENT_Y]; int adj = m_pcReshape->calculateChromaAdjVpduNei(currTU, areaY); currTU.setChromaAdj(adj); } xDecodeInterTU(currTU, compID); } cs.getResiBuf(currTU).colorSpaceConvert(cs.getResiBuf(currTU), false, cu.cs->slice->clpRng(COMPONENT_Y)); if (slice.getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && currTU.blocks[COMPONENT_Cb].width * currTU.blocks[COMPONENT_Cb].height > 4) { cs.getResiBuf(currTU.blocks[COMPONENT_Cb]).scaleSignal(currTU.getChromaAdj(), 0, currTU.cu->cs->slice->clpRng(COMPONENT_Cb)); cs.getResiBuf(currTU.blocks[COMPONENT_Cr]).scaleSignal(currTU.getChromaAdj(), 0, currTU.cu->cs->slice->clpRng(COMPONENT_Cr)); } } } else { #endif #if SIGN_PREDICTION for ( auto& currTU : CU::traverseTUs( cu ) ) { for(uint32_t ch = 0; ch < uiNumVaildComp; ch++) { const ComponentID compID = ComponentID(ch); #else for (uint32_t ch = 0; ch < uiNumVaildComp; ch++) { const ComponentID compID = ComponentID(ch); for( auto& currTU : CU::traverseTUs( cu ) ) { #endif CodingStructure &cs = *cu.cs; const Slice &slice = *cs.slice; if (slice.getLmcsEnabledFlag() && slice.getPicHeader()->getLmcsChromaResidualScaleFlag() && (compID == COMPONENT_Y) && (currTU.cbf[COMPONENT_Cb] || currTU.cbf[COMPONENT_Cr])) { #if LMCS_CHROMA_CALC_CU const CompArea &areaY = cu.blocks[COMPONENT_Y]; #else const CompArea &areaY = currTU.blocks[COMPONENT_Y]; #endif int adj = m_pcReshape->calculateChromaAdjVpduNei(currTU, areaY); currTU.setChromaAdj(adj); } xDecodeInterTU( currTU, compID ); #if SIGN_PREDICTION if(cs.pcv->isEncoder && cs.sps->getNumPredSigns() > 0) { PelBuf picRecoBuff = currTU.cs->picture->getRecoBuf( currTU.blocks[compID] ); picRecoBuff.copyFrom(currTU.cs->getRecoBuf( currTU.blocks[compID] )); } #endif } } #if JVET_S0234_ACT_CRS_FIX } #endif } void DecCu::xDeriveCUMV( CodingUnit &cu ) { for( auto &pu : CU::traversePUs( cu ) ) { MergeCtx mrgCtx; #if RExt__DECODER_DEBUG_TOOL_STATISTICS if( pu.cu->affine ) { CodingStatistics::IncrementStatisticTool( CodingStatisticsClassType{ STATS__TOOL_AFF, pu.Y().width, pu.Y().height } ); } #endif if( pu.mergeFlag ) { #if MULTI_HYP_PRED #if REUSE_CU_RESULTS CHECK(!cu.cs->pcv->isEncoder && cu.skip && !pu.addHypData.empty(), "Dec: additional hypotheseis signalled in SKIP mode"); CHECK(cu.skip && pu.addHypData.size() != pu.numMergedAddHyps, "additional hypotheseis signalled in SKIP mode"); // save signalled add hyp data, to put it at the end after merging MultiHypVec addHypData = { std::begin(pu.addHypData) + pu.numMergedAddHyps, std::end(pu.addHypData) }; #else CHECK(cu.skip && !pu.addHypData.empty(), "additional hypotheseis signalled in SKIP mode"); // save signalled add hyp data, to put it at the end after merging auto addHypData = std::move(pu.addHypData); #endif pu.addHypData.clear(); pu.numMergedAddHyps = 0; #endif if (pu.mmvdMergeFlag || pu.cu->mmvdSkip) { CHECK(pu.ciipFlag == true, "invalid Ciip"); if (pu.cs->sps->getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale(pu.lumaSize()); mrgCtx.subPuMvpMiBuf = MotionBuf(m_SubPuMiBuf, bufSize); } int fPosBaseIdx = #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED !pu.cs->sps->getUseTMMMVD() ? pu.mmvdMergeIdx / VVC_MMVD_MAX_REFINE_NUM : #endif pu.mmvdMergeIdx / MMVD_MAX_REFINE_NUM; PU::getInterMergeCandidates(pu, mrgCtx, 1, fPosBaseIdx + 1); PU::getInterMMVDMergeCandidates(pu, mrgCtx, pu.mmvdMergeIdx ); #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED uint32_t mmvdLUT[MMVD_ADD_NUM]; #if JVET_AA0093_ENHANCED_MMVD_EXTENSION uint16_t mmvdIdx = pu.mmvdMergeIdx; #else uint8_t mmvdIdx = pu.mmvdMergeIdx; #endif m_pcInterPred->sortInterMergeMMVDCandidates(pu, mrgCtx, mmvdLUT, mmvdIdx); mrgCtx.setMmvdMergeCandiInfo(pu, mmvdIdx, mmvdLUT[mmvdIdx]); #else mrgCtx.setMmvdMergeCandiInfo(pu, pu.mmvdMergeIdx); #endif PU::spanMotionInfo(pu, mrgCtx); } else { { if( pu.cu->geoFlag ) { PU::getGeoMergeCandidates( pu, m_geoMrgCtx ); #if JVET_W0097_GPM_MMVD_TM && TM_MRG if (pu.geoTmFlag0) { #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING MergeCtx& m_geoTmMrgCtx0 = m_geoTmMrgCtx[GEO_TM_SHAPE_AL]; #endif m_geoTmMrgCtx0.numValidMergeCand = m_geoMrgCtx.numValidMergeCand; m_geoTmMrgCtx0.BcwIdx[pu.geoMergeIdx0] = BCW_DEFAULT; m_geoTmMrgCtx0.useAltHpelIf[pu.geoMergeIdx0] = false; #if INTER_LIC m_geoTmMrgCtx0.LICFlags[pu.geoMergeIdx0] = false; #endif #if MULTI_HYP_PRED m_geoTmMrgCtx0.addHypNeighbours[pu.geoMergeIdx0] = m_geoMrgCtx.addHypNeighbours[pu.geoMergeIdx0]; #endif m_geoTmMrgCtx0.interDirNeighbours[pu.geoMergeIdx0] = m_geoMrgCtx.interDirNeighbours[pu.geoMergeIdx0]; m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].mv = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].mv; m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].mv = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].mv; m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].refIdx; m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].refIdx; #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING memcpy(&m_geoTmMrgCtx[GEO_TM_SHAPE_A], &m_geoTmMrgCtx0, sizeof(m_geoTmMrgCtx0)); #endif #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING for (uint8_t tmType = GEO_TM_SHAPE_AL; tmType < GEO_NUM_TM_MV_CAND; ++tmType) { if (tmType == GEO_TM_SHAPE_L || (!pu.cs->slice->getSPS()->getUseAltGPMSplitModeCode() && tmType != g_geoTmShape[0][g_GeoParams[pu.geoSplitDir][0]])) { continue; } m_geoTmMrgCtx[tmType].setMergeInfo(pu, pu.geoMergeIdx0); pu.geoTmType = tmType; m_pcInterPred->deriveTMMv(pu); m_geoTmMrgCtx[tmType].mvFieldNeighbours[(pu.geoMergeIdx0 << 1) ].mv.set(pu.mv[0].getHor(), pu.mv[0].getVer()); m_geoTmMrgCtx[tmType].mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].mv.set(pu.mv[1].getHor(), pu.mv[1].getVer()); } #else m_geoTmMrgCtx0.setMergeInfo(pu, pu.geoMergeIdx0); pu.geoTmType = g_geoTmShape[0][g_GeoParams[pu.geoSplitDir][0]]; m_pcInterPred->deriveTMMv(pu); m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1)].mv.set(pu.mv[0].getHor(), pu.mv[0].getVer()); m_geoTmMrgCtx0.mvFieldNeighbours[(pu.geoMergeIdx0 << 1) + 1].mv.set(pu.mv[1].getHor(), pu.mv[1].getVer()); #endif } if (pu.geoTmFlag1) { #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING MergeCtx& m_geoTmMrgCtx1 = m_geoTmMrgCtx[GEO_TM_SHAPE_AL]; #endif m_geoTmMrgCtx1.numValidMergeCand = m_geoMrgCtx.numValidMergeCand; m_geoTmMrgCtx1.BcwIdx[pu.geoMergeIdx1] = BCW_DEFAULT; m_geoTmMrgCtx1.useAltHpelIf[pu.geoMergeIdx1] = false; #if INTER_LIC m_geoTmMrgCtx1.LICFlags[pu.geoMergeIdx1] = false; #endif #if MULTI_HYP_PRED m_geoTmMrgCtx1.addHypNeighbours[pu.geoMergeIdx1] = m_geoMrgCtx.addHypNeighbours[pu.geoMergeIdx1]; #endif m_geoTmMrgCtx1.interDirNeighbours[pu.geoMergeIdx1] = m_geoMrgCtx.interDirNeighbours[pu.geoMergeIdx1]; m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].mv = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].mv; m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].mv = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].mv; m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].refIdx; m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].refIdx = m_geoMrgCtx.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].refIdx; #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING memcpy(&m_geoTmMrgCtx[GEO_TM_SHAPE_L], &m_geoTmMrgCtx1, sizeof(m_geoTmMrgCtx1)); #endif #if JVET_Z0056_GPM_SPLIT_MODE_REORDERING for (uint8_t tmType = GEO_TM_SHAPE_AL; tmType < GEO_NUM_TM_MV_CAND; ++tmType) { if (tmType == GEO_TM_SHAPE_A || (!pu.cs->slice->getSPS()->getUseAltGPMSplitModeCode() && tmType != g_geoTmShape[1][g_GeoParams[pu.geoSplitDir][0]])) { continue; } m_geoTmMrgCtx[tmType].setMergeInfo(pu, pu.geoMergeIdx1); pu.geoTmType = tmType; m_pcInterPred->deriveTMMv(pu); m_geoTmMrgCtx[tmType].mvFieldNeighbours[(pu.geoMergeIdx1 << 1) ].mv.set(pu.mv[0].getHor(), pu.mv[0].getVer()); m_geoTmMrgCtx[tmType].mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].mv.set(pu.mv[1].getHor(), pu.mv[1].getVer()); } #else m_geoTmMrgCtx1.setMergeInfo(pu, pu.geoMergeIdx1); pu.geoTmType = g_geoTmShape[1][g_GeoParams[pu.geoSplitDir][0]]; m_pcInterPred->deriveTMMv(pu); m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1)].mv.set(pu.mv[0].getHor(), pu.mv[0].getVer()); m_geoTmMrgCtx1.mvFieldNeighbours[(pu.geoMergeIdx1 << 1) + 1].mv.set(pu.mv[1].getHor(), pu.mv[1].getVer()); #endif } #endif } else { if( pu.cu->affine ) { AffineMergeCtx affineMergeCtx; if (pu.cs->sps->getSbTMVPEnabledFlag()) { Size bufSize = g_miScaling.scale( pu.lumaSize() ); mrgCtx.subPuMvpMiBuf = MotionBuf( m_SubPuMiBuf, bufSize ); affineMergeCtx.mrgCtx = &mrgCtx; } #if AFFINE_MMVD #if JVET_W0090_ARMC_TM int affMrgIdx = pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumAffineMergeCand()) || (pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE * ADAPTIVE_AFFINE_SUB_GROUP_SIZE + ADAPTIVE_AFFINE_SUB_GROUP_SIZE - 1 : pu.mergeIdx; if (pu.afMmvdFlag) { #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED affMrgIdx = #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_AA0093_ENHANCED_MMVD_EXTENSION !pu.cs->sps->getUseTMMMVD() ? ECM3_AF_MMVD_BASE_NUM : #endif AF_MMVD_BASE_NUM; #else affMrgIdx = pu.afMmvdBaseIdx; #endif } PU::getAffineMergeCand(pu, affineMergeCtx #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION , m_pcInterPred #endif , affMrgIdx , pu.afMmvdFlag #if JVET_Z0139_NA_AFF , pu.mergeIdx == 0 #endif ); #else PU::getAffineMergeCand(pu, affineMergeCtx, (pu.afMmvdFlag ? pu.afMmvdBaseIdx : pu.mergeIdx), pu.afMmvdFlag); #endif if (pu.afMmvdFlag) { pu.mergeIdx = PU::getMergeIdxFromAfMmvdBaseIdx(affineMergeCtx, pu.afMmvdBaseIdx); CHECK(pu.mergeIdx >= pu.cu->slice->getPicHeader()->getMaxNumAffineMergeCand(), "Affine MMVD mode doesn't have a valid base candidate!"); #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED #if JVET_AA0132_CONFIGURABLE_TM_TOOLS if(pu.cs->sps->getUseTMMMVD()) { #endif uint32_t affMmvdLUT[AF_MMVD_NUM]; uint32_t tempVal = pu.afMmvdMergeIdx; m_pcInterPred->sortAffineMergeCandidates(pu, affineMergeCtx, affMmvdLUT, tempVal ); pu.afMmvdMergeIdx = tempVal; int uiMergeCandTemp = affMmvdLUT[pu.afMmvdMergeIdx]; int baseIdx = (int)uiMergeCandTemp / AF_MMVD_MAX_REFINE_NUM; int stepIdx = (int)uiMergeCandTemp - baseIdx * AF_MMVD_MAX_REFINE_NUM; int dirIdx = stepIdx % AF_MMVD_OFFSET_DIR; stepIdx = stepIdx / AF_MMVD_OFFSET_DIR; pu.afMmvdDir = (uint8_t)dirIdx; pu.afMmvdStep = (uint8_t)stepIdx; #if JVET_AA0132_CONFIGURABLE_TM_TOOLS } #endif #endif PU::getAfMmvdMvf(pu, affineMergeCtx, affineMergeCtx.mvFieldNeighbours + (pu.mergeIdx << 1), pu.mergeIdx, pu.afMmvdStep, pu.afMmvdDir); } #if JVET_W0090_ARMC_TM else { if (pu.cs->sps->getUseAML()) #if JVET_Z0139_NA_AFF if (affineMergeCtx.numValidMergeCand > 1) #endif { m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, pu.mergeIdx); } } #endif #else #if JVET_W0090_ARMC_TM int affMrgIdx = pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE + 1)*ADAPTIVE_AFFINE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumAffineMergeCand()) || (pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_AFFINE_SUB_GROUP_SIZE * ADAPTIVE_AFFINE_SUB_GROUP_SIZE + ADAPTIVE_AFFINE_SUB_GROUP_SIZE - 1 : pu.mergeIdx; #if !JVET_Z0139_NA_AFF PU::getAffineMergeCand(pu, affineMergeCtx, affMrgIdx); #else PU::getAffineMergeCand(pu, affineMergeCtx, #if JVET_AA0107_RMVF_AFFINE_MERGE_DERIVATION m_pcInterPred, #endif affMrgIdx, pu.mergeIdx == 0); if (affineMergeCtx.numValidMergeCand > 1) #endif if (pu.cs->sps->getUseAML()) { m_pcInterPred->adjustAffineMergeCandidates(pu, affineMergeCtx, pu.mergeIdx); } #else PU::getAffineMergeCand( pu, affineMergeCtx, pu.mergeIdx ); #endif #endif pu.interDir = affineMergeCtx.interDirNeighbours[pu.mergeIdx]; pu.cu->affineType = affineMergeCtx.affineType[pu.mergeIdx]; pu.cu->BcwIdx = affineMergeCtx.BcwIdx[pu.mergeIdx]; #if INTER_LIC pu.cu->LICFlag = affineMergeCtx.LICFlags[pu.mergeIdx]; #endif pu.mergeType = affineMergeCtx.mergeType[pu.mergeIdx]; if ( pu.mergeType == MRG_TYPE_SUBPU_ATMVP ) { pu.refIdx[0] = affineMergeCtx.mvFieldNeighbours[(pu.mergeIdx << 1) + 0][0].refIdx; pu.refIdx[1] = affineMergeCtx.mvFieldNeighbours[(pu.mergeIdx << 1) + 1][0].refIdx; } else { for (int i = 0; i < 2; ++i) { if (pu.cs->slice->getNumRefIdx(RefPicList(i)) > 0) { MvField* mvField = affineMergeCtx.mvFieldNeighbours[(pu.mergeIdx << 1) + i]; pu.mvpIdx[i] = 0; pu.mvpNum[i] = 0; pu.mvd[i] = Mv(); pu.refIdx[i] = mvField[0].refIdx; pu.mvAffi[i][0] = mvField[0].mv; pu.mvAffi[i][1] = mvField[1].mv; pu.mvAffi[i][2] = mvField[2].mv; } } } #if JVET_AB0112_AFFINE_DMVR if (!pu.afMmvdFlag&&pu.mergeType != MRG_TYPE_SUBPU_ATMVP && PU::checkBDMVRCondition(pu)) { m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); pu.bdmvrRefine = false; if (!affineMergeCtx.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu))) { m_pcInterPred->processBDMVR4Affine(pu); pu.mvAffi[0][0] += m_mvBufBDMVR[0][0]; pu.mvAffi[0][1] += m_mvBufBDMVR[0][0]; pu.mvAffi[0][2] += m_mvBufBDMVR[0][0]; pu.mvAffi[1][0] += m_mvBufBDMVR[1][0]; pu.mvAffi[1][1] += m_mvBufBDMVR[1][0]; pu.mvAffi[1][2] += m_mvBufBDMVR[1][0]; } } #endif PU::spanMotionInfo( pu, mrgCtx ); } #if JVET_X0141_CIIP_TIMD_TM && TM_MRG else if (pu.ciipFlag && pu.tmMergeFlag) { int storeMrgIdx = pu.mergeIdx; pu.tmMergeFlag = false; PU::getInterMergeCandidates(pu, mrgCtx, 0, CIIP_TM_MRG_MAX_NUM_CANDS - 1); mrgCtx.numValidMergeCand = int(pu.cs->sps->getMaxNumCiipTMMergeCand()); pu.tmMergeFlag = true; for (uint32_t uiMergeCand = 0; uiMergeCand < CIIP_TM_MRG_MAX_NUM_CANDS; uiMergeCand++) { mrgCtx.setMergeInfo(pu, uiMergeCand); m_pcInterPred->deriveTMMv(pu); // Store refined motion back to ciipTmMrgCtx mrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir; mrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx; // Bcw may change, because bi may be reduced to uni by deriveTMMv(pu) mrgCtx.mvFieldNeighbours[2 * uiMergeCand].setMvField(pu.mv[0], pu.refIdx[0]); mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(pu.mv[1], pu.refIdx[1]); if (pu.interDir == 1) { mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].setMvField(Mv(), NOT_VALID); } if (pu.interDir == 2) { mrgCtx.mvFieldNeighbours[2 * uiMergeCand].setMvField(Mv(), NOT_VALID); } } #if JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, CIIP_TM_MRG_MAX_NUM_CANDS - 1); } #endif mrgCtx.setMergeInfo(pu, storeMrgIdx); pu.bdmvrRefine = false; PU::spanMotionInfo(pu, mrgCtx); } #endif else { #if JVET_AA0093_REFINED_MOTION_FOR_ARMC #if TM_MRG bool applyBDMVR4TM[TM_MRG_MAX_NUM_INIT_CANDS] = { false }; bool tmMergeRefinedMotion = false; #endif bool admvrRefinedMotion = false; #endif if (CU::isIBC(*pu.cu)) { #if JVET_AA0061_IBC_MBVD if (pu.ibcMbvdMergeFlag) { int fPosIBCBaseIdx = pu.ibcMbvdMergeIdx / IBC_MBVD_MAX_REFINE_NUM; #if JVET_Y0058_IBC_LIST_MODIFY && JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { #if JVET_Z0075_IBC_HMVP_ENLARGE PU::getIBCMergeCandidates(pu, mrgCtx); m_pcInterPred->adjustIBCMergeCandidates(pu, mrgCtx, 0, IBC_MRG_MAX_NUM_CANDS_MEM); #else PU::getIBCMergeCandidates(pu, mrgCtx, (((fPosIBCBaseIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE + 1) * ADAPTIVE_IBC_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumIBCMergeCand()) || (fPosIBCBaseIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE) == 0) ? fPosIBCBaseIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE * ADAPTIVE_IBC_SUB_GROUP_SIZE + ADAPTIVE_IBC_SUB_GROUP_SIZE - 1 : fPosIBCBaseIdx); m_pcInterPred->adjustIBCMergeCandidates(pu, mrgCtx, fPosIBCBaseIdx); #endif } else { #endif PU::getIBCMergeCandidates(pu, mrgCtx, fPosIBCBaseIdx); #if JVET_Y0058_IBC_LIST_MODIFY && JVET_W0090_ARMC_TM } #endif PU::getIbcMbvdMergeCandidates(pu, mrgCtx, fPosIBCBaseIdx + 1); uint32_t ibcMbvdLUT[IBC_MBVD_NUM]; uint32_t ibcMbvdValidNum[IBC_MBVD_BASE_NUM] = { 0 }; int ibcMbvdIdx= pu.ibcMbvdMergeIdx; m_pcInterPred->sortIbcMergeMbvdCandidates(pu, mrgCtx, ibcMbvdLUT, ibcMbvdValidNum, ibcMbvdIdx); bool mbvdCandMisAlign = mrgCtx.setIbcMbvdMergeCandiInfo(pu, ibcMbvdIdx, ibcMbvdLUT[ibcMbvdIdx]); CHECK(mbvdCandMisAlign, "MBVD candidate is invalid"); } else { #endif #if JVET_Y0058_IBC_LIST_MODIFY && JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { #if JVET_Z0075_IBC_HMVP_ENLARGE #if JVET_AA0093_ENHANCED_MMVD_EXTENSION uint16_t mrgCandIdx = pu.mergeIdx; #else uint8_t mrgCandIdx = pu.mergeIdx; #endif PU::getIBCMergeCandidates(pu, mrgCtx); m_pcInterPred->adjustIBCMergeCandidates(pu, mrgCtx, 0, IBC_MRG_MAX_NUM_CANDS_MEM); pu.mergeIdx = mrgCandIdx; #else PU::getIBCMergeCandidates(pu, mrgCtx, (((pu.mergeIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE + 1) * ADAPTIVE_IBC_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumIBCMergeCand()) || (pu.mergeIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_IBC_SUB_GROUP_SIZE * ADAPTIVE_IBC_SUB_GROUP_SIZE + ADAPTIVE_IBC_SUB_GROUP_SIZE - 1 : pu.mergeIdx); m_pcInterPred->adjustIBCMergeCandidates(pu, mrgCtx, pu.mergeIdx); #endif } else #endif PU::getIBCMergeCandidates(pu, mrgCtx, pu.mergeIdx); #if JVET_AA0061_IBC_MBVD } #endif } else #if JVET_X0049_ADAPT_DMVR if (pu.bmMergeFlag) { uint8_t mergeIdx = pu.bmDir == 2 ? pu.mergeIdx - BM_MRG_MAX_NUM_CANDS : pu.mergeIdx; #if JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { uint8_t bmDir = pu.bmDir; #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING int nWidth = pu.lumaSize().width; int nHeight = pu.lumaSize().height; bool tplAvail = #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && !JVET_AA0093_REFINED_MOTION_FOR_ARMC pu.cs->sps->getUseTmvpNmvpReordering() && #endif m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); #if JVET_AA0132_CONFIGURABLE_TM_TOOLS if (pu.cs->sps->getUseTmvpNmvpReordering()) { #endif MergeCtx tmvpMergeCandCtx; #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if ( tplAvail) { #endif PU::getTmvpBMCand(pu, tmvpMergeCandCtx); #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC } #endif pu.bmDir = 0; #if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1, pu.mergeIdx); } else { tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand); } #endif MergeCtx namvpMergeCandCtx; #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if ( tplAvail) { #endif PU::getNonAdjacentBMCand(pu, namvpMergeCandCtx); #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC } #endif pu.bmDir = 0; #if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 3, pu.mergeIdx); } else { namvpMergeCandCtx.numValidMergeCand = std::min(3, namvpMergeCandCtx.numValidMergeCand); } #else if (!tplAvail) { PU::getInterBMCandidates(pu, mrgCtx #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING && JVET_W0090_ARMC_TM , -1 , NULL , NULL #endif ); } else #endif PU::getInterBMCandidates(pu, mrgCtx, -1, &tmvpMergeCandCtx, &namvpMergeCandCtx); #if JVET_AA0132_CONFIGURABLE_TM_TOOLS } #endif #endif #if !JVET_Y0134_TMVP_NAMVP_CAND_REORDERING || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING) #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING else { #endif #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC PU::getInterBMCandidates(pu, mrgCtx, -1); #else PU::getInterBMCandidates(pu, mrgCtx, pu.cs->sps->getUseAML() && (((mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumBMMergeCand()) || (mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : mergeIdx); #endif #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING } #endif #endif pu.bmDir = 0; #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING #if JVET_AA0132_CONFIGURABLE_TM_TOOLS if (pu.cs->sps->getUseTmvpNmvpReordering()) { #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC admvrRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 1); admvrRefinedMotion &= tplAvail; #endif if (tplAvail) { #if JVET_AA0093_REFINED_MOTION_FOR_ARMC m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumBMMergeCand()); if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) { mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; } if (admvrRefinedMotion) { bool subPuRefineList[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, }; bool subPuRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, }; #if JVET_AA0093_ENHANCED_MMVD_EXTENSION uint16_t orgMergeIdx = pu.mergeIdx; #else uint8_t orgMergeIdx = pu.mergeIdx; #endif pu.bmDir = 0; mrgCtx.setMergeInfo( pu, 0 ); pu.bmDir = bmDir; pu.bdmvrRefine = true; for( uint32_t candIdx = 0; candIdx < mrgCtx.numValidMergeCand; candIdx++ ) { pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0; pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx]; pu.mv[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].mv; pu.mv[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv; pu.refIdx[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].refIdx; pu.refIdx[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx; Mv finalMvDir[2]; applyBDMVR4BM[candIdx] = m_pcInterPred->processBDMVRPU2Dir(pu, subPuRefineList[candIdx], finalMvDir); subPuRefineListTmp[candIdx][0] = subPuRefineList[candIdx][0]; subPuRefineListTmp[candIdx][1] = subPuRefineList[candIdx][1]; mrgCtx.mvFieldNeighbours[(candIdx << 1) + bmDir - 1].mv = finalMvDir[bmDir - 1]; } pu.bmDir = 0; m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, bmDir == 2 ? applyBDMVR4BM : NULL, NULL, NULL, mergeIdx + 1, subPuRefineList, subPuRefineListTmp, mergeIdx); pu.bmDir = bmDir; pu.mergeIdx = orgMergeIdx; mrgCtx.setMergeInfo( pu, pu.mergeIdx); m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); m_pcInterPred->processBDMVRSubPU(pu, subPuRefineList[mergeIdx][pu.bmDir - 1]); } #if !JVET_AA0093_REFINED_MOTION_FOR_ARMC else #endif #endif #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND #if !JVET_AA0093_REFINED_MOTION_FOR_ARMC m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumBMMergeCand()); #endif #else m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, mergeIdx + 1, mergeIdx); #endif } #if JVET_AA0132_CONFIGURABLE_TM_TOOLS } #endif #endif #if !JVET_Y0134_TMVP_NAMVP_CAND_REORDERING || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING) #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING else { #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC admvrRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 1); admvrRefinedMotion &= tplAvail; if (admvrRefinedMotion) { if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) { mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; } if (admvrRefinedMotion) { bool subPuRefineList[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, }; bool subPuRefineListTmp[BM_MRG_MAX_NUM_INIT_CANDS][2] = { false, }; #if JVET_AA0093_ENHANCED_MMVD_EXTENSION uint16_t orgMergeIdx = pu.mergeIdx; #else uint8_t orgMergeIdx = pu.mergeIdx; #endif pu.bmDir = 0; mrgCtx.setMergeInfo( pu, 0 ); pu.bmDir = bmDir; pu.bdmvrRefine = true; for( uint32_t candIdx = 0; candIdx < mrgCtx.numValidMergeCand; candIdx++ ) { pu.cu->imv = mrgCtx.useAltHpelIf[candIdx] ? IMV_HPEL : 0; pu.cu->BcwIdx = mrgCtx.BcwIdx[candIdx]; pu.mv[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].mv; pu.mv[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].mv; pu.refIdx[0] = mrgCtx.mvFieldNeighbours[candIdx << 1].refIdx; pu.refIdx[1] = mrgCtx.mvFieldNeighbours[(candIdx << 1) + 1].refIdx; Mv finalMvDir[2]; applyBDMVR4BM[candIdx] = m_pcInterPred->processBDMVRPU2Dir(pu, subPuRefineList[candIdx], finalMvDir); subPuRefineListTmp[candIdx][0] = subPuRefineList[candIdx][0]; subPuRefineListTmp[candIdx][1] = subPuRefineList[candIdx][1]; mrgCtx.mvFieldNeighbours[(candIdx << 1) + bmDir - 1].mv = finalMvDir[bmDir - 1]; } pu.bmDir = 0; m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, bmDir == 2 ? applyBDMVR4BM : NULL, NULL, NULL, mergeIdx + 1, subPuRefineList, subPuRefineListTmp, mergeIdx); pu.bmDir = bmDir; pu.mergeIdx = orgMergeIdx; mrgCtx.setMergeInfo( pu, pu.mergeIdx); m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); m_pcInterPred->processBDMVRSubPU(pu, subPuRefineList[mergeIdx][pu.bmDir - 1]); } } else #endif m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, mergeIdx); #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING } #endif #endif pu.bmDir = bmDir; } else #endif PU::getInterBMCandidates(pu, mrgCtx, mergeIdx); } else #endif #if JVET_W0090_ARMC_TM if (pu.cs->sps->getUseAML()) { #if JVET_Y0134_TMVP_NAMVP_CAND_REORDERING #if JVET_AA0132_CONFIGURABLE_TM_TOOLS if (pu.cs->sps->getUseTmvpNmvpReordering()) { #endif int nWidth = pu.lumaSize().width; int nHeight = pu.lumaSize().height; bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); MergeCtx tmvpMergeCandCtx; #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { #endif PU::getTmvpMergeCand(pu, tmvpMergeCandCtx); #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC } #endif #if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, tmvpMergeCandCtx, 1, pu.mergeIdx); } else { tmvpMergeCandCtx.numValidMergeCand = std::min(1, tmvpMergeCandCtx.numValidMergeCand); } #endif MergeCtx namvpMergeCandCtx; #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { #endif PU::getNonAdjacentMergeCand(pu, namvpMergeCandCtx); #if JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC } #endif #if !JVET_AA0093_DIVERSITY_CRITERION_FOR_ARMC if (tplAvail) { m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, namvpMergeCandCtx, 9, pu.mergeIdx); } else { namvpMergeCandCtx.numValidMergeCand = std::min(9, namvpMergeCandCtx.numValidMergeCand); } #else if (!tplAvail) { PU::getInterMergeCandidates(pu, mrgCtx, 0, -1); mrgCtx.numValidMergeCand = #if TM_MRG #if JVET_AA0132_CONFIGURABLE_TM_TOOLS pu.cs->sps->getUseTMMrgMode() && #endif pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : #endif pu.cs->sps->getMaxNumMergeCand(); } else #endif PU::getInterMergeCandidates(pu, mrgCtx, 0, -1, &tmvpMergeCandCtx, &namvpMergeCandCtx); #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2); tmMergeRefinedMotion &= tplAvail; #if JVET_AA0132_CONFIGURABLE_TM_TOOLS tmMergeRefinedMotion &= pu.cs->sps->getUseTMMrgMode(); #endif #endif if (tplAvail) { #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC if (pu.tmMergeFlag && tmMergeRefinedMotion) { #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, pu.cs->sps->getMaxNumTMMergeCand()); #else m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, mrgCtx.numValidMergeCand, pu.mergeIdx); #endif int tmpPuMrgIdx = pu.mergeIdx; pu.reduceTplSize = true; if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) { mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); } if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) { mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; } for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) { mrgCtx.BcwIdx[ui] = BCW_DEFAULT; #if INTER_LIC mrgCtx.LICFlags[ui] = false; #endif mrgCtx.interDirNeighbours[ui] = 0; mrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; mrgCtx.useAltHpelIf[ui] = false; #if MULTI_HYP_PRED mrgCtx.addHypNeighbours[ui].clear(); #endif mrgCtx.candCost[ui] = MAX_UINT64; } Distortion tempCost[1]; for( uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++ ) { mrgCtx.setMergeInfo( pu, uiMergeCand ); #if MULTI_PASS_DMVR applyBDMVR4TM[uiMergeCand] = PU::checkBDMVRCondition(pu); if (applyBDMVR4TM[uiMergeCand]) { m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1]); pu.bdmvrRefine = true; applyBDMVR4TM[uiMergeCand] = m_pcInterPred->processBDMVR( pu, 1, tempCost ); } else { m_pcInterPred->deriveTMMv(pu, tempCost); } #else m_pcInterPred->deriveTMMv( pu ); #endif mrgCtx.candCost[uiMergeCand] = tempCost[0]; mrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir; mrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx; mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv = pu.mv[0]; mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = pu.refIdx[0]; mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv = pu.mv[1]; mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = pu.refIdx[1]; if( pu.interDir == 1 ) { mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv.setZero(); mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = NOT_VALID; } if( pu.interDir == 2 ) { mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv.setZero(); mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = NOT_VALID; } } pu.reduceTplSize = false; m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, applyBDMVR4TM, NULL, NULL, mrgCtx.numValidMergeCand); pu.mergeIdx = tmpPuMrgIdx; } else #endif #if JVET_Z0102_NO_ARMC_FOR_ZERO_CAND m_pcInterPred->adjustMergeCandidates(pu, mrgCtx, #if TM_MRG pu.tmMergeFlag ? pu.cs->sps->getMaxNumTMMergeCand() : #endif pu.cs->sps->getMaxNumMergeCand()); #else m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, pu.mergeIdx + 1, pu.mergeIdx); #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) { mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; } #endif } #if JVET_AA0132_CONFIGURABLE_TM_TOOLS } #endif #endif #if !JVET_Y0134_TMVP_NAMVP_CAND_REORDERING || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING) #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING else { #endif PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.cs->sps->getUseAML() && (((pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE + 1)*ADAPTIVE_SUB_GROUP_SIZE < pu.cs->sps->getMaxNumMergeCand()) || (pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE) == 0) ? pu.mergeIdx / ADAPTIVE_SUB_GROUP_SIZE * ADAPTIVE_SUB_GROUP_SIZE + ADAPTIVE_SUB_GROUP_SIZE - 1 : pu.mergeIdx); #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC tmMergeRefinedMotion = PU::isArmcRefinedMotionEnabled(pu, 2); int nWidth = pu.lumaSize().width; int nHeight = pu.lumaSize().height; bool tplAvail = m_pcInterPred->xAMLGetCurBlkTemplate(pu, nWidth, nHeight); tmMergeRefinedMotion &= tplAvail; #if JVET_AA0132_CONFIGURABLE_TM_TOOLS tmMergeRefinedMotion &= pu.cs->sps->getUseTMMrgMode(); #endif if (pu.tmMergeFlag && tmMergeRefinedMotion) { int tmpPuMrgIdx = pu.mergeIdx; pu.reduceTplSize = true; if (mrgCtx.numValidMergeCand > pu.cs->sps->getMaxNumTMMergeCand()) { mrgCtx.numValidMergeCand = pu.cs->sps->getMaxNumTMMergeCand(); } if (mrgCtx.numCandToTestEnc > mrgCtx.numValidMergeCand) { mrgCtx.numCandToTestEnc = mrgCtx.numValidMergeCand; } for (uint32_t ui = mrgCtx.numValidMergeCand; ui < NUM_MERGE_CANDS; ++ui) { mrgCtx.BcwIdx[ui] = BCW_DEFAULT; #if INTER_LIC mrgCtx.LICFlags[ui] = false; #endif mrgCtx.interDirNeighbours[ui] = 0; mrgCtx.mvFieldNeighbours[(ui << 1)].refIdx = NOT_VALID; mrgCtx.mvFieldNeighbours[(ui << 1) + 1].refIdx = NOT_VALID; mrgCtx.useAltHpelIf[ui] = false; #if MULTI_HYP_PRED mrgCtx.addHypNeighbours[ui].clear(); #endif mrgCtx.candCost[ui] = MAX_UINT64; } Distortion tempCost[1]; for( uint32_t uiMergeCand = 0; uiMergeCand < mrgCtx.numValidMergeCand; uiMergeCand++ ) { mrgCtx.setMergeInfo( pu, uiMergeCand ); #if MULTI_PASS_DMVR applyBDMVR4TM[uiMergeCand] = PU::checkBDMVRCondition(pu); if (applyBDMVR4TM[uiMergeCand]) { m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[uiMergeCand << 1], m_mvBufBDMVR[(uiMergeCand << 1) + 1]); pu.bdmvrRefine = true; applyBDMVR4TM[uiMergeCand] = m_pcInterPred->processBDMVR( pu, 1, tempCost ); } else { m_pcInterPred->deriveTMMv(pu, tempCost); } #else m_pcInterPred->deriveTMMv( pu ); #endif mrgCtx.candCost[uiMergeCand] = tempCost[0]; mrgCtx.interDirNeighbours[uiMergeCand] = pu.interDir; mrgCtx.BcwIdx[uiMergeCand] = pu.cu->BcwIdx; mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv = pu.mv[0]; mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = pu.refIdx[0]; mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv = pu.mv[1]; mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = pu.refIdx[1]; if( pu.interDir == 1 ) { mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].mv.setZero(); mrgCtx.mvFieldNeighbours[2 * uiMergeCand + 1].refIdx = NOT_VALID; } if( pu.interDir == 2 ) { mrgCtx.mvFieldNeighbours[2 * uiMergeCand].mv.setZero(); mrgCtx.mvFieldNeighbours[2 * uiMergeCand].refIdx = NOT_VALID; } } pu.reduceTplSize = false; m_pcInterPred->adjustMergeCandidatesInOneCandidateGroup(pu, mrgCtx, applyBDMVR4TM, NULL, NULL, mrgCtx.numValidMergeCand); pu.mergeIdx = tmpPuMrgIdx; } else #endif m_pcInterPred->adjustInterMergeCandidates(pu, mrgCtx, pu.mergeIdx); #if JVET_AA0132_CONFIGURABLE_TM_TOOLS && JVET_Y0134_TMVP_NAMVP_CAND_REORDERING } #endif #endif } else { PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.mergeIdx); } #else PU::getInterMergeCandidates(pu, mrgCtx, 0, pu.mergeIdx); #endif #if JVET_AA0061_IBC_MBVD if (!pu.ibcMbvdMergeFlag) { #endif mrgCtx.setMergeInfo( pu, pu.mergeIdx ); #if JVET_AA0061_IBC_MBVD } #endif #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC if (pu.tmMergeFlag && tmMergeRefinedMotion) { pu.bdmvrRefine = applyBDMVR4TM[pu.mergeIdx]; if (pu.bdmvrRefine) { m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); pu.bdmvrRefine = m_pcInterPred->processBDMVR( pu ); } else { m_pcInterPred->deriveTMMv(pu); } } #endif #if JVET_AA0093_REFINED_MOTION_FOR_ARMC if (pu.bmMergeFlag) { pu.bdmvrRefine = true; } #endif #if (TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG)) && !MULTI_PASS_DMVR if (pu.tmMergeFlag) { m_pcInterPred->deriveTMMv(pu); #if JVET_Z0084_IBC_TM && IBC_TM_MRG if (CU::isIBC(*pu.cu)) { pu.bv = pu.mv[0]; pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); } #endif } #endif #if MULTI_PASS_DMVR #if JVET_AA0093_REFINED_MOTION_FOR_ARMC #if TM_MRG if (PU::checkBDMVRCondition(pu) && (!pu.tmMergeFlag || (pu.tmMergeFlag && !tmMergeRefinedMotion)) && (!pu.bmMergeFlag || (pu.bmMergeFlag && !admvrRefinedMotion))) #else if (PU::checkBDMVRCondition(pu) && (!pu.bmMergeFlag || (pu.bmMergeFlag && !admvrRefinedMotion))) #endif #else if (PU::checkBDMVRCondition(pu)) #endif { m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); pu.bdmvrRefine = true; CHECK(mrgCtx.numValidMergeCand <= 0, "this is not possible"); #if JVET_X0049_ADAPT_DMVR #if TM_MRG if (!pu.tmMergeFlag && !pu.bmMergeFlag && mrgCtx.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu))) #else if (!pu.bmMergeFlag && mrgCtx.xCheckSimilarMotion(pu.mergeIdx, PU::getBDMVRMvdThreshold(pu))) #endif #else #if TM_MRG if( !pu.tmMergeFlag && mrgCtx.xCheckSimilarMotion( pu.mergeIdx, PU::getBDMVRMvdThreshold( pu ) ) ) #else if( mrgCtx.xCheckSimilarMotion( pu.mergeIdx, PU::getBDMVRMvdThreshold( pu ) ) ) #endif #endif { // span motion to subPU for (int subPuIdx = 0; subPuIdx < MAX_NUM_SUBCU_DMVR; subPuIdx++) { m_mvBufBDMVR[0][subPuIdx] = pu.mv[0]; m_mvBufBDMVR[1][subPuIdx] = pu.mv[1]; } } else { pu.bdmvrRefine = m_pcInterPred->processBDMVR( pu ); } } #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) else { #if TM_MRG && JVET_AA0093_REFINED_MOTION_FOR_ARMC if (pu.tmMergeFlag && !tmMergeRefinedMotion) #else if (pu.tmMergeFlag) #endif { m_pcInterPred->deriveTMMv(pu); #if JVET_Z0084_IBC_TM && IBC_TM_MRG if (CU::isIBC(*pu.cu)) { pu.bv = pu.mv[0]; pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); } #endif } } #endif #endif #if MULTI_HYP_PRED CHECK(pu.Y().area() <= MULTI_HYP_PRED_RESTRICT_BLOCK_SIZE && !pu.addHypData.empty(), "There are add hyps in small block") #endif #if MULTI_PASS_DMVR if( !pu.bdmvrRefine ) { PU::spanMotionInfo( pu, mrgCtx ); } #else PU::spanMotionInfo( pu, mrgCtx ); #endif } } } } #if MULTI_HYP_PRED // put saved additional hypotheseis to the end #if JVET_Z0118_GDR int n = (int) addHypData.capacity(); int s = (int) pu.addHypData.size(); int e = (int) (addHypData.end() - addHypData.begin()); if ((s + e) < n) { pu.addHypData.insert(pu.addHypData.end(), std::make_move_iterator(addHypData.begin()), std::make_move_iterator(addHypData.end())); } #else pu.addHypData.insert(pu.addHypData.end(), std::make_move_iterator(addHypData.begin()), std::make_move_iterator(addHypData.end())); #endif #endif } else { #if JVET_Z0054_BLK_REF_PIC_REORDER #if REUSE_CU_RESULTS if (!cu.cs->pcv->isEncoder) #endif { #if TM_AMVP m_pcInterPred->clearTplAmvpBuffer(); #endif if (pu.cu->affine) { for (uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++) { if (pu.interDir & (1 << uiRefListIdx)) { pu.mvdAffi[uiRefListIdx][0].changeAffinePrecAmvr2Internal(pu.cu->imv); pu.mvdAffi[uiRefListIdx][1].changeAffinePrecAmvr2Internal(pu.cu->imv); if (cu.affineType == AFFINEMODEL_6PARAM) { pu.mvdAffi[uiRefListIdx][2].changeAffinePrecAmvr2Internal(pu.cu->imv); } } } } else if (CU::isIBC(*pu.cu) && pu.interDir == 1) { pu.mvd[REF_PIC_LIST_0].changeIbcPrecAmvr2Internal(pu.cu->imv); } else { for (uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++) { if (pu.interDir & (1 << uiRefListIdx)) { pu.mvd[uiRefListIdx].changeTransPrecAmvr2Internal(pu.cu->imv); } } } if (PU::useRefPairList(pu)) { m_pcInterPred->setBiRefIdx(pu); } if (PU::useRefCombList(pu)) { m_pcInterPred->setUniRefListAndIdx(pu); } } #endif #if !JVET_Z0054_BLK_REF_PIC_REORDER #if REUSE_CU_RESULTS if ( cu.imv && !pu.cu->affine && !cu.cs->pcv->isEncoder ) #else if (cu.imv && !pu.cu->affine) #endif { PU::applyImv(pu, mrgCtx, m_pcInterPred); } else #endif { #if JVET_X0083_BM_AMVP_MERGE_MODE #if REUSE_CU_RESULTS if (!cu.cs->pcv->isEncoder && (pu.amvpMergeModeFlag[REF_PIC_LIST_0] || pu.amvpMergeModeFlag[REF_PIC_LIST_1])) #else if (pu.amvpMergeModeFlag[REF_PIC_LIST_0] || pu.amvpMergeModeFlag[REF_PIC_LIST_1]) #endif { CHECK(pu.interDir != 3, "this is not possible"); const RefPicList refListMerge = pu.amvpMergeModeFlag[REF_PIC_LIST_0] ? REF_PIC_LIST_0 : REF_PIC_LIST_1; const RefPicList refListAmvp = RefPicList(1 - refListMerge); int orgRefIdxAMVP = pu.refIdx[refListAmvp]; int orgInterDir = pu.interDir; int orgMvpIdxL0 = pu.mvpIdx[REF_PIC_LIST_0]; int orgMvpIdxL1 = pu.mvpIdx[REF_PIC_LIST_1]; Mv orgMvd0 = pu.mvd[0]; Mv orgMvd1 = pu.mvd[1]; // this part is to derive the merge info m_pcInterPred->getAmvpMergeModeMergeList(pu, m_mvFieldAmListDec, orgRefIdxAMVP); // if there was set PU merge info, restore the AMVP information pu.mvpIdx[REF_PIC_LIST_0] = orgMvpIdxL0; pu.mvpIdx[REF_PIC_LIST_1] = orgMvpIdxL1; pu.interDir = orgInterDir; pu.mergeFlag = false; pu.mvd[0] = orgMvd0; pu.mvd[1] = orgMvd1; pu.refIdx[refListAmvp] = orgRefIdxAMVP; } #endif if( pu.cu->affine ) { for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { RefPicList eRefList = RefPicList( uiRefListIdx ); if ( pu.cs->slice->getNumRefIdx( eRefList ) > 0 && ( pu.interDir & ( 1 << uiRefListIdx ) ) ) { AffineAMVPInfo affineAMVPInfo; PU::fillAffineMvpCand( pu, eRefList, pu.refIdx[eRefList], affineAMVPInfo ); const unsigned mvpIdx = pu.mvpIdx[eRefList]; pu.mvpNum[eRefList] = affineAMVPInfo.numCand; // Mv mv[3]; CHECK( pu.refIdx[eRefList] < 0, "Unexpected negative refIdx." ); #if JVET_Z0054_BLK_REF_PIC_REORDER if (!pu.cs->sps->getUseARL()) { #else if (!cu.cs->pcv->isEncoder) { pu.mvdAffi[eRefList][0].changeAffinePrecAmvr2Internal(pu.cu->imv); pu.mvdAffi[eRefList][1].changeAffinePrecAmvr2Internal(pu.cu->imv); if (cu.affineType == AFFINEMODEL_6PARAM) { pu.mvdAffi[eRefList][2].changeAffinePrecAmvr2Internal(pu.cu->imv); } } #endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED if (pu.isMvsdApplicable()) { Mv absMvd[3]; absMvd[0] = Mv(pu.mvdAffi[eRefList][0].getAbsMv()); absMvd[1] = Mv(pu.mvdAffi[eRefList][1].getAbsMv()); absMvd[2] = (cu.affineType == AFFINEMODEL_6PARAM) ? Mv(pu.mvdAffi[eRefList][2].getAbsMv()) : Mv(0, 0); if ((absMvd[0] != Mv(0, 0) || absMvd[1] != Mv(0, 0) || absMvd[2] != Mv(0, 0)) && pu.isMvsdApplicable()) { std::vector<Mv> cMvdDerivedVec, cMvdDerivedVec2, cMvdDerivedVec3; #if JVET_Z0054_BLK_REF_PIC_REORDER m_pcInterPred->deriveMvdSignAffine(affineAMVPInfo.mvCandLT[mvpIdx], affineAMVPInfo.mvCandRT[mvpIdx], affineAMVPInfo.mvCandLB[mvpIdx], absMvd, pu, eRefList, pu.refIdx[eRefList], cMvdDerivedVec, cMvdDerivedVec2, cMvdDerivedVec3); #else m_pcInterPred->deriveMvdSignAffine(affineAMVPInfo.mvCandLT[mvpIdx], affineAMVPInfo.mvCandRT[mvpIdx], affineAMVPInfo.mvCandLB[mvpIdx], absMvd[0], absMvd[1], absMvd[2], pu, eRefList, pu.refIdx[eRefList], cMvdDerivedVec, cMvdDerivedVec2, cMvdDerivedVec3); #endif CHECK(pu.mvsdIdx[eRefList] >= cMvdDerivedVec.size(), ""); m_pcInterPred->deriveMVDFromMVSDIdxAffine(pu, eRefList, cMvdDerivedVec, cMvdDerivedVec2, cMvdDerivedVec3); } } #endif #if JVET_Z0054_BLK_REF_PIC_REORDER } #endif Mv mvLT = affineAMVPInfo.mvCandLT[mvpIdx] + pu.mvdAffi[eRefList][0]; Mv mvRT = affineAMVPInfo.mvCandRT[mvpIdx] + pu.mvdAffi[eRefList][1]; mvRT += pu.mvdAffi[eRefList][0]; Mv mvLB; if ( cu.affineType == AFFINEMODEL_6PARAM ) { mvLB = affineAMVPInfo.mvCandLB[mvpIdx] + pu.mvdAffi[eRefList][2]; mvLB += pu.mvdAffi[eRefList][0]; } pu.mvAffi[eRefList][0] = mvLT; pu.mvAffi[eRefList][1] = mvRT; pu.mvAffi[eRefList][2] = mvLB; } } } else if (CU::isIBC(*pu.cu) && pu.interDir == 1) { AMVPInfo amvpInfo; #if JVET_Z0084_IBC_TM && IBC_TM_AMVP PU::fillIBCMvpCand(pu, amvpInfo, m_pcInterPred); #else PU::fillIBCMvpCand(pu, amvpInfo); #endif pu.mvpNum[REF_PIC_LIST_0] = amvpInfo.numCand; Mv mvd = pu.mvd[REF_PIC_LIST_0]; #if !JVET_Z0054_BLK_REF_PIC_REORDER #if REUSE_CU_RESULTS if (!cu.cs->pcv->isEncoder) #endif { mvd.changeIbcPrecAmvr2Internal(pu.cu->imv); } #endif if (pu.cs->sps->getMaxNumIBCMergeCand() == 1) { CHECK( pu.mvpIdx[REF_PIC_LIST_0], "mvpIdx for IBC mode should be 0" ); } pu.mv[REF_PIC_LIST_0] = amvpInfo.mvCand[pu.mvpIdx[REF_PIC_LIST_0]] + mvd; pu.mv[REF_PIC_LIST_0].mvCliptoStorageBitDepth(); #if JVET_AA0070_RRIBC if (pu.cu->rribcFlipType == 1) { pu.mv[REF_PIC_LIST_0].setVer(0); } else if (pu.cu->rribcFlipType == 2) { pu.mv[REF_PIC_LIST_0].setHor(0); } #endif #if JVET_Z0160_IBC_ZERO_PADDING pu.bv = pu.mv[0]; pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); #endif } else { #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED Mv cMvpL0; #endif for ( uint32_t uiRefListIdx = 0; uiRefListIdx < 2; uiRefListIdx++ ) { RefPicList eRefList = RefPicList( uiRefListIdx ); if ((pu.cs->slice->getNumRefIdx(eRefList) > 0 || (eRefList == REF_PIC_LIST_0 && CU::isIBC(*pu.cu))) && (pu.interDir & (1 << uiRefListIdx))) { AMVPInfo amvpInfo; #if JVET_X0083_BM_AMVP_MERGE_MODE if (pu.amvpMergeModeFlag[eRefList] == true) { #if REUSE_CU_RESULTS if (!cu.cs->pcv->isEncoder) { #endif #if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE const int mvFieldMergeIdx = pu.refIdx[1 - eRefList] * AMVP_MAX_NUM_CANDS_MEM + pu.mvpIdx[1 - eRefList]; #else const int mvFieldMergeIdx = pu.refIdx[1 - eRefList] * AMVP_MAX_NUM_CANDS + pu.mvpIdx[1 - eRefList]; #endif pu.mv[eRefList] = m_mvFieldAmListDec[mvFieldMergeIdx].mv; pu.refIdx[eRefList] = m_mvFieldAmListDec[mvFieldMergeIdx].refIdx; #if REUSE_CU_RESULTS } #endif } else { if (pu.amvpMergeModeFlag[1 - eRefList] == true) { #if TM_AMVP #if JVET_Y0128_NON_CTC || (JVET_AA0132_CONFIGURABLE_TM_TOOLS && TM_AMVP) amvpInfo.numCand = PU::checkTmEnableCondition(pu.cs->sps, pu.cs->pps, pu.cu->slice->getRefPic(eRefList, pu.refIdx[eRefList])) ? 1 : 2; #else amvpInfo.numCand = 1; #endif #else amvpInfo.numCand = AMVP_MAX_NUM_CANDS; #endif #if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE amvpInfo.numCand += 1; #endif #if REUSE_CU_RESULTS if (cu.cs->pcv->isEncoder) { amvpInfo.mvCand[pu.mvpIdx[eRefList]] = pu.mv[eRefList] - pu.mvd[eRefList]; } else #endif { #if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE const int mvFieldAmvpIdx = MAX_NUM_AMVP_CANDS_MAX_REF + pu.refIdx[eRefList] * AMVP_MAX_NUM_CANDS_MEM + pu.mvpIdx[eRefList]; #else const int mvFieldAmvpIdx = MAX_NUM_AMVP_CANDS_MAX_REF + pu.refIdx[eRefList] * AMVP_MAX_NUM_CANDS + pu.mvpIdx[eRefList]; #endif amvpInfo.mvCand[pu.mvpIdx[eRefList]] = m_mvFieldAmListDec[mvFieldAmvpIdx].mv; } } else #endif PU::fillMvpCand(pu, eRefList, pu.refIdx[eRefList], amvpInfo #if TM_AMVP , m_pcInterPred #endif ); pu.mvpNum [eRefList] = amvpInfo.numCand; #if JVET_Z0054_BLK_REF_PIC_REORDER #if JVET_X0083_BM_AMVP_MERGE_MODE if( (!PU::useRefCombList(pu) && !PU::useRefPairList(pu)) || (pu.amvpMergeModeFlag[REF_PIC_LIST_0] || pu.amvpMergeModeFlag[REF_PIC_LIST_1])) #else if(!PU::useRefCombList(pu) && !PU::useRefPairList(pu)) #endif { #else if (!cu.cs->pcv->isEncoder) { pu.mvd[eRefList].changeTransPrecAmvr2Internal(pu.cu->imv); } #endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED if (pu.isMvsdApplicable() && pu.mvd[eRefList].isMvsdApplicable()) { if (pu.cu->smvdMode) { if (eRefList == REF_PIC_LIST_0) { cMvpL0 = amvpInfo.mvCand[pu.mvpIdx[eRefList]]; } else { std::vector<Mv> cMvdDerivedVec; Mv cMvdKnownAtDecoder = Mv(pu.mvd[REF_PIC_LIST_0].getAbsHor(), pu.mvd[REF_PIC_LIST_0].getAbsVer()); m_pcInterPred->deriveMvdSignSMVD(cMvpL0, amvpInfo.mvCand[pu.mvpIdx[1]], cMvdKnownAtDecoder, pu, cMvdDerivedVec); //pass the absolute Mvd value as MVd may be negative while CU reuse at encoder. CHECK(pu.mvsdIdx[REF_PIC_LIST_0] >= cMvdDerivedVec.size(), ""); int mvsdIdx = pu.mvsdIdx[REF_PIC_LIST_0]; Mv cMvd = m_pcInterPred->deriveMVDFromMVSDIdxTrans(mvsdIdx, cMvdDerivedVec); CHECK(cMvd == Mv(0, 0), " zero MVD for SMVD!"); pu.mvd[REF_PIC_LIST_0] = cMvd; pu.mv[REF_PIC_LIST_0] = cMvpL0 + pu.mvd[REF_PIC_LIST_0]; pu.mv[REF_PIC_LIST_0].mvCliptoStorageBitDepth(); pu.mvd[REF_PIC_LIST_1].set(-pu.mvd[REF_PIC_LIST_0].hor, -pu.mvd[REF_PIC_LIST_0].ver); } } else { std::vector<Mv> cMvdDerivedVec; Mv cMvdKnownAtDecoder = Mv(pu.mvd[eRefList].getAbsHor(), pu.mvd[eRefList].getAbsVer()); m_pcInterPred->deriveMvdSign(amvpInfo.mvCand[pu.mvpIdx[eRefList]], cMvdKnownAtDecoder, pu, eRefList, pu.refIdx[eRefList], cMvdDerivedVec); //pass the absolute Mvd value as MVd may be negative while CU reuse at encoder. CHECK(pu.mvsdIdx[eRefList] >= cMvdDerivedVec.size(), ""); int mvsdIdx = pu.mvsdIdx[eRefList]; Mv cMvd = m_pcInterPred->deriveMVDFromMVSDIdxTrans(mvsdIdx, cMvdDerivedVec); CHECK(cMvd == Mv(0, 0), " zero MVD!"); pu.mvd[eRefList] = cMvd; } } #endif #if JVET_Z0054_BLK_REF_PIC_REORDER } #endif pu.mv[eRefList] = amvpInfo.mvCand[pu.mvpIdx[eRefList]] + pu.mvd[eRefList]; pu.mv[eRefList].mvCliptoStorageBitDepth(); #if JVET_X0083_BM_AMVP_MERGE_MODE } #endif } } #if JVET_X0083_BM_AMVP_MERGE_MODE if ((pu.amvpMergeModeFlag[0] || pu.amvpMergeModeFlag[1]) && PU::checkBDMVRCondition(pu)) { m_pcInterPred->setBdmvrSubPuMvBuf(m_mvBufBDMVR[0], m_mvBufBDMVR[1]); pu.bdmvrRefine = true; // span motion to subPU for (int subPuIdx = 0; subPuIdx < MAX_NUM_SUBCU_DMVR; subPuIdx++) { m_mvBufBDMVR[0][subPuIdx] = pu.mv[0]; m_mvBufBDMVR[1][subPuIdx] = pu.mv[1]; } } #endif } #if JVET_X0083_BM_AMVP_MERGE_MODE if (!pu.bdmvrRefine) #endif PU::spanMotionInfo( pu, mrgCtx ); } } if( !cu.geoFlag ) { if( g_mctsDecCheckEnabled && !MCTSHelper::checkMvBufferForMCTSConstraint( pu, true ) ) { printf( "DECODER: pu motion vector across tile boundaries (%d,%d,%d,%d)\n", pu.lx(), pu.ly(), pu.lwidth(), pu.lheight() ); } } if (CU::isIBC(cu)) { const int cuPelX = pu.Y().x; const int cuPelY = pu.Y().y; int roiWidth = pu.lwidth(); int roiHeight = pu.lheight(); const unsigned int lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth(); int xPred = pu.mv[0].getHor() >> MV_FRACTIONAL_BITS_INTERNAL; int yPred = pu.mv[0].getVer() >> MV_FRACTIONAL_BITS_INTERNAL; #if JVET_Z0118_GDR if (cu.cs->isGdrEnabled()) { if (cu.cs->isClean(cu)) { CHECK(!m_pcInterPred->isLumaBvValid(lcuWidth, cuPelX, cuPelY, roiWidth, roiHeight, xPred, yPred), "invalid block vector for IBC detected."); } } else { CHECK(!m_pcInterPred->isLumaBvValid(lcuWidth, cuPelX, cuPelY, roiWidth, roiHeight, xPred, yPred), "invalid block vector for IBC detected."); } #else CHECK(!m_pcInterPred->isLumaBvValid(lcuWidth, cuPelX, cuPelY, roiWidth, roiHeight, xPred, yPred), "invalid block vector for IBC detected."); #endif } #if MULTI_HYP_PRED { bool derivedMrgList = false; #if REUSE_CU_RESULTS if (!cu.cs->pcv->isEncoder) #endif for (int i = pu.numMergedAddHyps; i < int(pu.addHypData.size()); ++i) { auto &mhData = pu.addHypData[i]; #if INTER_LIC mhData.LICFlag = pu.cu->LICFlag; #endif mhData.imv = pu.cu->imv; if (mhData.isMrg) { if (!derivedMrgList) { PU::getGeoMergeCandidates(pu, m_geoMrgCtx); derivedMrgList = true; } int refList = m_geoMrgCtx.interDirNeighbours[mhData.mrgIdx] - 1; CHECK(refList != 0 && refList != 1, ""); mhData.refIdx = m_geoMrgCtx.mvFieldNeighbours[(mhData.mrgIdx << 1) + refList].refIdx; mhData.mv = m_geoMrgCtx.mvFieldNeighbours[(mhData.mrgIdx << 1) + refList].mv; mhData.refList = refList; mhData.imv = m_geoMrgCtx.useAltHpelIf[mhData.mrgIdx] ? IMV_HPEL : 0; continue; } if (pu.cu->affine) { mhData.mvd.changeAffinePrecAmvr2Internal(pu.cu->imv); } else { mhData.mvd.changeTransPrecAmvr2Internal(pu.cu->imv); } const Mv mvp = PU::getMultiHypMVP(pu, mhData); mhData.mv = mvp + mhData.mvd; mhData.mv.mvCliptoStorageBitDepth(); } } #endif } } //! \}