From 8108d2eb0c6d13066096da0bb6cc05558e3c1c80 Mon Sep 17 00:00:00 2001 From: Donghyun Kim <kimddng@etri.re.kr> Date: Mon, 11 Nov 2024 19:21:19 +0000 Subject: [PATCH] JVET-AJ0161: OBMC extension with intra prediction (Test 3.3b) --- source/Lib/CommonLib/CommonDef.h | 8 + source/Lib/CommonLib/InterPrediction.cpp | 249 ++++++++- source/Lib/CommonLib/InterPrediction.h | 30 +- source/Lib/CommonLib/IntraPrediction.cpp | 664 +++++++++++++++++++++++ source/Lib/CommonLib/IntraPrediction.h | 18 +- source/Lib/CommonLib/TypeDef.h | 1 + source/Lib/CommonLib/UnitTools.cpp | 176 ++++++ source/Lib/CommonLib/UnitTools.h | 4 + source/Lib/DecoderLib/DecCu.cpp | 15 + source/Lib/EncoderLib/EncCu.cpp | 79 +++ 10 files changed, 1241 insertions(+), 3 deletions(-) diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index 16f3f31c1..85128bf80 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -1255,6 +1255,14 @@ static const int ADAPTIVE_IBC_SUB_GROUP_SIZE = 6; #if JVET_Z0061_TM_OBMC static const int TM_OBMC_TEMPLATE_SIZE = 1; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +enum INTRA_OBMC_NEIGH_STATE +{ + INTRA_OBMC_BOTH_NEIGH_AVAIL = 0, + INTRA_OBMC_ONLY_ABOVE_AVAIL = 1, + INTRA_OBMC_ONLY_LEFT_AVAIL = 2 +}; +#endif #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED static const int ADAPTIVE_SUB_GROUP_SIZE_MMVD = MMVD_MAX_REFINE_NUM; diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 5b73a4764..5cc6cea10 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -466,6 +466,13 @@ void InterPrediction::destroy() xFree(m_pcRefTplLeft ); m_pcRefTplLeft = nullptr; xFree(m_pcRefTplAbove); m_pcRefTplAbove = nullptr; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++) + { + xFree(m_intraOBMCBuf[ch]); m_intraOBMCBuf[ch] = nullptr; + xFree(m_beforeOBMCBuf[ch]); m_beforeOBMCBuf[ch] = nullptr; + } +#endif #if INTER_LIC || JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED #if JVET_AD0213_LIC_IMP for (int i = 0; i < MAX_NUM_COMPONENT; i++) @@ -642,6 +649,13 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, cons { m_affineDmvrBlockTmp[i] = (Pel*)xMalloc(Pel, memBlockWidthExt*memBlockHeight*memBlockNum); } +#endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ ) + { + m_intraOBMCBuf[c] = (Pel*)xMalloc(Pel, MAX_CU_SIZE * MAX_CU_SIZE); + m_beforeOBMCBuf[c] = (Pel*)xMalloc(Pel, MAX_CU_SIZE * MAX_CU_SIZE); + } #endif m_geoPartBuf[0].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); m_geoPartBuf[1].create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE))); @@ -8172,7 +8186,11 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, const RefPicList & * 2. Before motion estimation, subtract (scaled) predictors generated by applying neighboring motions to current CU/PU from the original signal of current CU/PU, * to make the motion estimation biased to OBMC. */ +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst, IntraPrediction *pcIntraPred) +#else void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) +#endif { if ( pu.cs->sps->getUseOBMC() == false @@ -8196,6 +8214,20 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) } #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (!m_dimdForOBMCFilled) + { + m_modeGetCheck[0] = pcIntraPred->getGradForOBMC(pu, pu.cu->cs->picture->getRecoBuf(pu.Y()), pu.Y(), *pu.cu, true, pu.cs->pcv->minCUWidth, m_modeBuf[0]); + m_modeGetCheck[1] = pcIntraPred->getGradForOBMC(pu, pu.cu->cs->picture->getRecoBuf(pu.Y()), pu.Y(), *pu.cu, false, pu.cs->pcv->minCUWidth, m_modeBuf[1]); + + m_dimdForOBMCFilled = true; + } + + PelUnitBuf predIntra = PelUnitBuf(pu.chromaFormat, PelBuf(m_intraOBMCBuf[COMPONENT_Y], pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height), + PelBuf(m_intraOBMCBuf[COMPONENT_Cb], pu.blocks[COMPONENT_Cb].width, pu.blocks[COMPONENT_Cb].height), + PelBuf(m_intraOBMCBuf[COMPONENT_Cr], pu.blocks[COMPONENT_Cr].width, pu.blocks[COMPONENT_Cr].height)); +#endif + const UnitArea orgPuArea = pu; PredictionUnit subPu = pu; @@ -8245,6 +8277,10 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) subPu.cu->licFlag = false; #endif subPu.ciipFlag = false; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + subPu.multiRefIdx = 0; + subPu.ciipPDPC = false; +#endif #if TM_MRG || (JVET_Z0084_IBC_TM && IBC_TM_MRG) subPu.tmMergeFlag = false; #endif @@ -8261,6 +8297,13 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) PelUnitBuf pcYuvTmpPredL0 = m_tmpObmcBufL0.subBuf(UnitAreaRelative(*pu.cu, pu)); PelUnitBuf pcYuvTmpPredT0 = m_tmpObmcBufT0.subBuf(UnitAreaRelative(*pu.cu, pu)); +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + PelUnitBuf beforeOBMC = PelUnitBuf(pu.chromaFormat, PelBuf(m_beforeOBMCBuf[COMPONENT_Y], pu.blocks[COMPONENT_Y].width, pu.blocks[COMPONENT_Y].height), + PelBuf(m_beforeOBMCBuf[COMPONENT_Cb], pu.blocks[COMPONENT_Cb].width, pu.blocks[COMPONENT_Cb].height), + PelBuf(m_beforeOBMCBuf[COMPONENT_Cr], pu.blocks[COMPONENT_Cr].width, pu.blocks[COMPONENT_Cr].height)); + beforeOBMC.copyFrom(pcYuvPred); +#endif + for (int iBlkBoundary = 0; iBlkBoundary < 2; iBlkBoundary++) // 0 - top; 1 - left { unsigned int uiLengthInBlock = ((iBlkBoundary == 0) ? uiWidthInBlock : uiHeightInBlock); @@ -8355,13 +8398,20 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) subPu.cu->altLMFlag = neighPu->cu->altLMFlag; subPu.cu->altLMParaUnit = neighPu->cu->secAltLMParaUnit; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + PelUnitBuf cTmpBeforeOBMC = beforeOBMC.subBuf(predArea); +#endif #if JVET_AA0132_CONFIGURABLE_TM_TOOLS if (iOBMCmode == -1) { xSubBlockMotionCompensation(subPu, cTmp1); for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++) { +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + xSubblockOBMC(ComponentID(compID), subPu, cPred, cTmp1, cTmpBeforeOBMC, iBlkBoundary, false, false); +#else xSubblockOBMC(ComponentID(compID), subPu, cPred, cTmp1, iBlkBoundary); +#endif } iSub += iLength; } @@ -8377,7 +8427,11 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++) { +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + xSubblockTMOBMC(ComponentID(compID), subPu, cPred, cTmp1, cTmpBeforeOBMC, iBlkBoundary, iOBMCmode); +#else xSubblockTMOBMC(ComponentID(compID), subPu, cPred, cTmp1, iBlkBoundary, iOBMCmode); +#endif } iSub += iLength; } @@ -8387,7 +8441,11 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++) { +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + xSubblockTMOBMC(ComponentID(compID), subPu, cPred, cTmp1, cTmpBeforeOBMC, iBlkBoundary, iOBMCmode); +#else xSubblockTMOBMC(ComponentID(compID), subPu, cPred, cTmp1, iBlkBoundary, iOBMCmode); +#endif } iSub += iLength; } @@ -8430,6 +8488,54 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) iSub += iLength; #endif } +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + else if (iState == 1 && m_modeGetCheck[iBlkBoundary]) + { + int cumLength = 0; + while (cumLength < iLength) + { + cumLength++; + int currLength = 1; + while ((m_modeBuf[iBlkBoundary][iSub] == m_modeBuf[iBlkBoundary][iSub + currLength]) + && (cumLength < iLength) && (currLength < (MAX_INTRA_SIZE / uiMinCUW))) + { + currLength++; + cumLength++; + } + + const bool intraOBMCCond = (((iBlkBoundary == 0) && ((m_modeBuf[iBlkBoundary][iSub] >= DIA_IDX) && (m_modeBuf[iBlkBoundary][iSub] <= VDIA_IDX))) + || ((iBlkBoundary == 1) && (m_modeBuf[iBlkBoundary][iSub] > DC_IDX) && (m_modeBuf[iBlkBoundary][iSub] <= DIA_IDX))); + if (!intraOBMCCond) + { + iSub += currLength; + continue; + } + + if (iBlkBoundary == 0) + { + subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(orgPuArea.lumaPos().offset(iSub * uiMinCUW, 0), Size{ currLength*uiMinCUW, uiMinCUW }))); + } + else + { + subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(orgPuArea.lumaPos().offset(0, iSub * uiMinCUW), Size{ uiMinCUW, currLength*uiMinCUW }))); + } + + const UnitArea predArea = UnitAreaRelative(orgPuArea, subPu); + PelUnitBuf cPredForBlend = pcYuvPred.subBuf(predArea); + PelUnitBuf cTmp = predIntra.subBuf(predArea); + + subBlockIntraForOBMC(subPu, iSub, (iBlkBoundary == 0), cTmp, pcIntraPred); + + for (int compID = 0; compID < MAX_NUM_COMPONENT; compID++) + { + PelUnitBuf cTmpBeforeOBMC = beforeOBMC.subBuf(predArea); + xSubblockOBMC(ComponentID(compID), subPu, cPredForBlend, cTmp, cTmpBeforeOBMC, iBlkBoundary, false, true); + } + + iSub += currLength; + } + } +#endif else if (iState == 1 || iState == 3) // consecutive intra neighbors or skip OBMC based on MV similarity { iSub += iLength; @@ -8598,7 +8704,12 @@ void InterPrediction::subBlockOBMC(PredictionUnit &pu, PelUnitBuf* pDst) } // Function for (weighted) averaging predictors of current block and predictors generated by applying neighboring motions to current block. +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +void InterPrediction::xSubblockOBMC(const ComponentID eComp, PredictionUnit &pu, PelUnitBuf &pcYuvPredDst, PelUnitBuf &pcYuvPredSrc, + PelUnitBuf &pcYuvBefore, int iDir, bool bSubMotion, bool bIsIntra) +#else void InterPrediction::xSubblockOBMC(const ComponentID eComp, PredictionUnit &pu, PelUnitBuf &pcYuvPredDst, PelUnitBuf &pcYuvPredSrc, int iDir, bool bSubMotion) +#endif { int iWidth = pu.blocks[eComp].width; int iHeight = pu.blocks[eComp].height; @@ -8612,9 +8723,17 @@ void InterPrediction::xSubblockOBMC(const ComponentID eComp, PredictionUnit &pu, Pel* pOrgSrc = pcYuvPredSrc.bufs[eComp].buf; const int strideDst = pcYuvPredDst.bufs[eComp].stride; const int strideSrc = pcYuvPredSrc.bufs[eComp].stride; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + Pel* pBefore = pcYuvBefore.bufs[eComp].buf; + const int strideBefore = pcYuvBefore.bufs[eComp].stride; +#endif #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (!bIsIntra && skipObmcConditionByPixel(pu, eComp, iWidth, iHeight, pOrgSrc, strideSrc, pBefore, strideBefore, pu.cs->sps->getBitDepth(toChannelType(eComp)))) +#else if (skipObmcConditionByPixel(pu, eComp, iWidth, iHeight, pOrgSrc, strideSrc, pOrgDst, strideDst, pu.cs->sps->getBitDepth(toChannelType(eComp)))) +#endif { return; } @@ -9889,7 +10008,11 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx PU::spanMotionInfo(pu); #endif cu.isobmcMC = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + subBlockOBMC(pu, &tmpGeoBuf0, pcIntraPred); +#else subBlockOBMC(pu, &tmpGeoBuf0); +#endif cu.isobmcMC = false; #if JVET_AG0164_AFFINE_GPM if (pu.affineGPM[0]) @@ -10058,7 +10181,11 @@ void InterPrediction::motionCompensationGeo( CodingUnit &cu, MergeCtx &geoMrgCtx PU::spanMotionInfo(pu); #endif cu.isobmcMC = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + subBlockOBMC(pu, &tmpGeoBuf1, pcIntraPred); +#else subBlockOBMC(pu, &tmpGeoBuf1); +#endif cu.isobmcMC = false; #if JVET_AG0164_AFFINE_GPM if (pu.affineGPM[1]) @@ -20941,7 +21068,11 @@ void InterPrediction::xSubblockOBMCCopy(const ComponentID eComp, PredictionUnit } void InterPrediction::xSubblockTMOBMC(const ComponentID eComp, PredictionUnit &pu, PelUnitBuf &pcYuvPredDst, - PelUnitBuf &pcYuvPredSrc, int iDir, int iOBMCmode) + PelUnitBuf &pcYuvPredSrc, +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + PelUnitBuf &pcYuvBefore, +#endif + int iDir, int iOBMCmode) { int iWidth = pu.blocks[eComp].width; int iHeight = pu.blocks[eComp].height; @@ -20955,9 +21086,17 @@ void InterPrediction::xSubblockTMOBMC(const ComponentID eComp, PredictionUnit &p Pel * pOrgSrc = pcYuvPredSrc.bufs[eComp].buf; const int strideDst = pcYuvPredDst.bufs[eComp].stride; const int strideSrc = pcYuvPredSrc.bufs[eComp].stride; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + Pel * pBefore = pcYuvBefore.bufs[eComp].buf; + const int strideBefore = pcYuvBefore.bufs[eComp].stride; +#endif #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (skipObmcConditionByPixel(pu, eComp, iWidth, iHeight, pOrgSrc, strideSrc, pBefore, strideBefore, pu.cs->sps->getBitDepth(toChannelType(eComp)))) +#else if (skipObmcConditionByPixel(pu, eComp, iWidth, iHeight, pOrgSrc, strideSrc, pOrgDst, strideDst, pu.cs->sps->getBitDepth(toChannelType(eComp)))) +#endif { return; } @@ -40379,3 +40518,111 @@ std::vector<Mv> InterPrediction::deriveMVDFromMVSDIdxAffineSI(PredictionUnit& pu return true; } #endif + +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + void InterPrediction::subBlockIntraForOBMC(PredictionUnit &subPu, const int iSub, const bool isAbove, PelUnitBuf &cTmp, IntraPrediction *pcIntraPred) + { + const uint32_t uiMinCUW = subPu.cs->pcv->minCUWidth; + const int scaleX = getComponentScaleX((ComponentID)COMPONENT_Cb, subPu.chromaFormat); + const int scaleY = getComponentScaleX((ComponentID)COMPONENT_Cb, subPu.chromaFormat); + + const int origIntraDir[2] = {subPu.intraDir[0], subPu.intraDir[1]}; + subPu.intraDir[0] = m_modeBuf[isAbove ? 0 : 1][iSub]; + subPu.intraDir[1] = m_modeBuf[isAbove ? 0 : 1][iSub]; + + pcIntraPred->m_intraOBMCNeighState = (iSub == 0) ? INTRA_OBMC_BOTH_NEIGH_AVAIL : (isAbove ? INTRA_OBMC_ONLY_ABOVE_AVAIL : INTRA_OBMC_ONLY_LEFT_AVAIL); + + bool prepareRef = false; + prepareRef |= (isAbove && subPu.Y().topLeft().x != 0 && subPu.intraDir[0] < VER_IDX); + prepareRef |= (!isAbove && subPu.Y().topLeft().y != 0 && subPu.intraDir[0] > HOR_IDX); + prepareRef &= pcIntraPred->m_intraOBMCNeighState != INTRA_OBMC_BOTH_NEIGH_AVAIL; + pcIntraPred->m_refSampleForOBMC = prepareRef; + + CodingUnit *origCu = subPu.cu; + CodingUnit tempCu = *subPu.cu; + tempCu.firstPU = &subPu; + subPu.cu = &tempCu; + subPu.cu->UnitArea::operator=(UnitArea(subPu)); + + for (uint32_t c = 0; c < MAX_NUM_COMPONENT; c++) + { + const uint32_t uiScaledMinCUW = c == 0 ? uiMinCUW : (isAbove ? (uiMinCUW >> scaleX) : (uiMinCUW >> scaleY)); + + if (iSub != 0) + { + pcIntraPred->initIntraPatternChTypeOBMC(tempCu, subPu.blocks[c]); + } + else + { + pcIntraPred->initIntraPatternChType(tempCu, subPu.blocks[c]); + } + const int sizeSide = (isAbove ? subPu.blocks[c].height : subPu.blocks[c].width) + 2; + + if (prepareRef) + { + memset(pcIntraPred->m_refSampleForOBMCBuf, -1, sizeof( Pel ) * (MAX_INTRA_SIZE + 3)); + memset(pcIntraPred->m_refSampleForOBMCBufFiltered, -1, sizeof( Pel ) * (MAX_INTRA_SIZE + 3)); + const PelBuf pRecoBuf = subPu.cu->cs->picture->getRecoBuf().bufs[c]; + for (int i = 0; i <= sizeSide; i++) + { + const int currPos_ = isAbove ? (subPu.blocks[c].topLeft().x - 1 - i) : (subPu.blocks[c].topLeft().y - 1 - i); + const Position currPos = isAbove ? Position(currPos_, subPu.blocks[c].topLeft().y - 1) : Position(subPu.blocks[c].topLeft().x - 1, currPos_); + + if ((currPos_ + 1) % uiScaledMinCUW == 0) + { + bool valid = subPu.cs->isDecomp(currPos, (c == 0) ? CHANNEL_TYPE_LUMA : CHANNEL_TYPE_CHROMA); + if (valid) + { + valid = (subPu.cs->getCURestricted(currPos, *subPu.cu, (c == 0) ? CHANNEL_TYPE_LUMA : CHANNEL_TYPE_CHROMA) != NULL); + } + if (!valid) + { + for (int j = i; j <= sizeSide; j++) + { + pcIntraPred->m_refSampleForOBMCBuf[j] = pcIntraPred->m_refSampleForOBMCBuf[i-1]; + } + break; + } + } + + pcIntraPred->m_refSampleForOBMCBuf[i] = pRecoBuf.at(currPos); + } + + if (pcIntraPred->getIpaParam()->refFilterFlag) + { + pcIntraPred->m_refSampleForOBMCBufFiltered[0] = pcIntraPred->m_refSampleForOBMCBuf[0]; + pcIntraPred->m_refSampleForOBMCBufFiltered[sizeSide] = pcIntraPred->m_refSampleForOBMCBuf[sizeSide]; + for (int i = 1; i < sizeSide; i++) + { + pcIntraPred->m_refSampleForOBMCBufFiltered[i] = (pcIntraPred->m_refSampleForOBMCBuf[i - 1] + 2 * pcIntraPred->m_refSampleForOBMCBuf[i] + pcIntraPred->m_refSampleForOBMCBuf[i + 1] + 2) >> 2; + } + } + else + { + for (int i = 0; i <= sizeSide; i++) + { + pcIntraPred->m_refSampleForOBMCBufFiltered[i] = pcIntraPred->m_refSampleForOBMCBuf[i]; + } + } + } + + pcIntraPred->predIntraAng(ComponentID(c), cTmp.bufs[c], subPu); + + if (c == 0) + { + if (subPu.cs->picHeader->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag()) + { + cTmp.bufs[c].rspSignal(m_pcReshape->getInvLUT()); + } + } + } + + pcIntraPred->m_refSampleForOBMC = false; + + subPu.cu = origCu; + pcIntraPred->m_intraOBMCNeighState = INTRA_OBMC_BOTH_NEIGH_AVAIL; + + subPu.intraDir[0] = origIntraDir[0]; + subPu.intraDir[1] = origIntraDir[1]; + } +#endif \ No newline at end of file diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index af488be51..bd92d7aef 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -200,6 +200,10 @@ private: static const int m_LICShiftDiff = 12; int m_LICMultApprox[64]; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + Pel* m_intraOBMCBuf[MAX_NUM_COMPONENT]; + Pel* m_beforeOBMCBuf[MAX_NUM_COMPONENT]; +#endif #if JVET_AG0136_INTRA_TMP_LIC std::array<int, 7> m_arrayLicParams; @@ -578,7 +582,11 @@ protected: bool xCheckIdenticalMotionInfo(MotionInfo orgMotionInfo, MotionInfo targetMotionInfo, MergeType puMergeType); #endif #if ENABLE_OBMC +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + void xSubblockOBMC(const ComponentID eComp, PredictionUnit &pu, PelUnitBuf &pcYuvPredDst, PelUnitBuf &pcYuvPredSrc, PelUnitBuf &pcYuvBefore, int iDir, bool bSubMotion = false, bool bIsIntra = false); +#else void xSubblockOBMC(const ComponentID eComp, PredictionUnit &pu, PelUnitBuf &pcYuvPredDst, PelUnitBuf &pcYuvPredSrc, int iDir, bool bSubMotion = false); +#endif void xSubBlockMotionCompensation(PredictionUnit &pu, PelUnitBuf &pcYuvPred); void xSubblockOBMCBlending(const ComponentID eComp, PredictionUnit &pu, PelUnitBuf &pcYuvPredDst, PelUnitBuf &pcYuvPredSrc1, PelUnitBuf &pcYuvPredSrc2, PelUnitBuf &pcYuvPredSrc3, PelUnitBuf &pcYuvPredSrc4, bool isAboveAvail = false, bool isLeftAvail = false, bool isBelowAvail = false, bool isRightAvail = false, bool bSubMotion = false); #endif @@ -747,7 +755,11 @@ public: } #endif #if ENABLE_OBMC +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + void subBlockOBMC(PredictionUnit &pu, PelUnitBuf *pDst = nullptr, IntraPrediction *pcIntraPred = nullptr); +#else void subBlockOBMC(PredictionUnit &pu, PelUnitBuf *pDst = nullptr); +#endif #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL bool isSCC(const PredictionUnit &pu); bool skipObmcConditionByPixel(PredictionUnit& pu, ComponentID comp, int width, int height, const Pel* src, int strideSrc, const Pel* dst, int strideDst, int bitDepth); @@ -1050,7 +1062,10 @@ public: void xSubblockOBMCCopy(const ComponentID eComp, PredictionUnit &pu, PelUnitBuf &pcYuvPredDst, PelUnitBuf &pcYuvPredSrc, int iDir); void xSubblockTMOBMC(const ComponentID eComp, PredictionUnit &pu, PelUnitBuf &pcYuvPredDst, PelUnitBuf &pcYuvPredSrc, - int iDir, int iOBMCmode = 0); +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + PelUnitBuf &pcYuvBefore, +#endif + int iDir, int iOBMCmode = 0); #endif #if JVET_W0090_ARMC_TM || JVET_AA0070_RRIBC void updateCandList(uint32_t uiCand, Distortion uiCost, uint32_t uiMrgCandNum, uint32_t* rdCandList, Distortion* candCostList); @@ -1705,6 +1720,16 @@ public: void setFillCurTplAboveARMC(bool b) { m_fillCurTplAboveARMC = b; } void setFillCurTplLeftARMC(bool b) { m_fillCurTplLeftARMC = b; } #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +private: + bool m_dimdForOBMCFilled; + int m_modeBuf[2][MAX_CU_SIZE >> MIN_CU_LOG2]; + int m_modeGetCheck[2]; +public: + void setDIMDForOBMC(bool b) { m_dimdForOBMCFilled = b; } + void setModeGetCheck(int i, bool b) { m_modeGetCheck[i] = b; } + void setClearModeBuf(int i) { memset(m_modeBuf[i], -1, sizeof(int) * (MAX_CU_SIZE >> MIN_CU_LOG2)); } +#endif #if JVET_AG0276_NLIC public: @@ -1872,6 +1897,9 @@ public: #if JVET_AF0073_INTER_CCP_MERGE bool deriveInterCcpMergePrediction( TransformUnit* tu, const PelBuf& lumaReconstruction, PelBuf& inBufCb, PelBuf& inBufCr, PelBuf& outBufCb, PelBuf& outBufCr, CCPModelCandidate interCcpMergeList[], int validNum); #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + void subBlockIntraForOBMC(PredictionUnit &subPu, const int iSub, const bool isAbove, PelUnitBuf &cTmp, IntraPrediction *pcIntraPred); +#endif }; #if TM_AMVP || TM_MRG || JVET_Z0084_IBC_TM diff --git a/source/Lib/CommonLib/IntraPrediction.cpp b/source/Lib/CommonLib/IntraPrediction.cpp index 1bd8636ef..d4e4c4d13 100644 --- a/source/Lib/CommonLib/IntraPrediction.cpp +++ b/source/Lib/CommonLib/IntraPrediction.cpp @@ -152,6 +152,12 @@ IntraPrediction::IntraPrediction() #if MMLM m_encPreRDRun = false; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_intraOBMCNeighState = INTRA_OBMC_BOTH_NEIGH_AVAIL; + m_refSampleForOBMC = false; + memset(m_refSampleForOBMCBuf, -1, sizeof( Pel ) * (MAX_INTRA_SIZE + 3)); + memset(m_refSampleForOBMCBufFiltered, -1, sizeof( Pel ) * (MAX_INTRA_SIZE + 3)); +#endif #if JVET_V0130_INTRA_TMP m_pppTarPatch = NULL; #endif @@ -3654,6 +3660,13 @@ void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompA } } +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (pu.cu->isobmcMC) + { + m_ipaParam.applyPDPC &= (m_intraOBMCNeighState == INTRA_OBMC_BOTH_NEIGH_AVAIL); + m_ipaParam.useGradPDPC &= (m_intraOBMCNeighState == INTRA_OBMC_BOTH_NEIGH_AVAIL); + } +#endif // high level conditions and DC intra prediction if( sps.getSpsRangeExtension().getIntraSmoothingDisabledFlag() || !isLuma( chType ) @@ -3696,6 +3709,13 @@ void IntraPrediction::initPredIntraParams(const PredictionUnit & pu, const CompA #endif } +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (pu.cu->isobmcMC) + { + filterFlag = false; + } +#endif + // Selelection of either ([1 2 1] / 4 ) refrence filter OR Gaussian 4-tap interpolation filter if (filterFlag) { @@ -3857,9 +3877,30 @@ void IntraPrediction::xPredIntraAng( const CPelBuf &pSrc, PelBuf &pDst, const Ch // Extend the Main reference to the left. int sizeSide = bIsModeVer ? height : width; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (m_refSampleForOBMC && (m_intraOBMCNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL && intraPredAngle == -32)) + { + for (int k = 1; k <= width + 2; k++) + { + int val = m_refSampleForOBMCBufFiltered[k]; + refMain[k] = (Pel)ClipPel(val, clpRng); + } + } +#endif // left extend by 1 for (int k = -(sizeSide + 1); k <= -1; k++) { +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (m_refSampleForOBMC && !(m_intraOBMCNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL && intraPredAngle == -32)) + { + if ((m_intraOBMCNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL && bIsModeVer == true) || (m_intraOBMCNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL && bIsModeVer == false)) + { + int val = m_refSampleForOBMCBufFiltered[abs(k)]; + refMain[k] = (Pel)ClipPel(val, clpRng); + } + continue; + } +#endif int frac32precision = (-k * absInvAngle + 8) >> 4; int intpel = frac32precision >> 5; int fracpel = frac32precision & 31; @@ -5337,6 +5378,12 @@ inline int isAboveAvailable ( const CodingUnit &cu, const ChannelType &chT inline int isLeftAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *validFlags ); inline int isAboveRightAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posRT, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *validFlags ); inline int isBelowLeftAvailable ( const CodingUnit &cu, const ChannelType &chType, const Position &posLB, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *validFlags ); +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +inline int isAboveAvailableOBMC ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *validFlags, const int obmcNeighState ); +inline int isLeftAvailableOBMC ( const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *validFlags, const int obmcNeighState ); +inline int isAboveRightAvailableOBMC ( const CodingUnit &cu, const ChannelType &chType, const Position &posRT, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *validFlags, const int obmcNeighState ); +inline int isBelowLeftAvailableOBMC ( const CodingUnit &cu, const ChannelType &chType, const Position &posLB, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *validFlags, const int obmcNeighState ); +#endif #if JVET_AB0155_SGPM void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompArea &area, const bool forceRefFilterFlag, @@ -5380,6 +5427,13 @@ void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompAre #if JVET_AC0112_IBC_GPM m_ipaParam.fetchRef2nd &= !cu.firstPU->ibcGpmFlag; #endif +#endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (cu.isobmcMC) + { + applyFusion = false; + m_ipaParam.fetchRef2nd = false; + } #endif if (!forceRefFilterFlag) @@ -5435,6 +5489,38 @@ void IntraPrediction::initIntraPatternChType(const CodingUnit &cu, const CompAre } } +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +void IntraPrediction::initIntraPatternChTypeOBMC(const CodingUnit &cu, const CompArea &area) +{ +#if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS + CHECK(area.width == 2, "Width of 2 is not supported"); +#endif + const CodingStructure& cs = *cu.cs; + + m_ipaParam.fetchRef2nd = false; + + initPredIntraParams(*cu.firstPU, area, *cs.sps); + + m_ipaParam.applyFusion = false; + + Pel *refBufUnfiltered = m_refBuffer[area.compID][PRED_BUF_UNFILTERED]; + Pel *refBufFiltered = m_refBuffer[area.compID][PRED_BUF_FILTERED]; + + setReferenceArrayLengths( area ); +#if JVET_AH0209_PDP + m_refAvailable = false; +#endif + // ----- Step 1: unfiltered reference samples ----- + xFillReferenceSamplesOBMC(cs.picture->getRecoBuf(area), refBufUnfiltered, area, cu); + + // ----- Step 2: filtered reference samples ----- + if( m_ipaParam.refFilterFlag) + { + xFilterReferenceSamples( refBufUnfiltered, refBufFiltered, area, *cs.sps, cu.firstPU->multiRefIdx ); + } +} +#endif + void IntraPrediction::initIntraPatternChTypeISP(const CodingUnit& cu, const CompArea& area, PelBuf& recBuf, const bool forceRefFilterFlag) { const CodingStructure& cs = *cu.cs; @@ -5800,7 +5886,11 @@ void IntraPrediction::xFillReferenceSamples2(const CPelBuf &recoBuf, const CompA void IntraPrediction::xFillReferenceSamples( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu ) { #if JVET_AH0209_PDP +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (m_intraOBMCNeighState == INTRA_OBMC_BOTH_NEIGH_AVAIL && !cu.firstPU->multiRefIdx && !cu.ispMode && !cu.plIdx) +#else if (!cu.firstPU->multiRefIdx && !cu.ispMode && !cu.plIdx) +#endif { xFillReferenceSamples2(recoBuf, area, cu); } @@ -6171,6 +6261,372 @@ void IntraPrediction::xFillReferenceSamples( const CPelBuf &recoBuf, Pel* refBuf } } +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +void IntraPrediction::xFillReferenceSamplesOBMC( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu ) +{ + m_refAvailable = false; + + const ChannelType chType = toChannelType( area.compID ); + const CodingStructure &cs = *cu.cs; + const SPS &sps = *cs.sps; + const PreCalcValues &pcv = *cs.pcv; + + const int multiRefIdx = (area.compID == COMPONENT_Y) ? cu.firstPU->multiRefIdx : 0; + + const int tuWidth = area.width; + const int tuHeight = area.height; + const int predSize = m_topRefLength; + const int predHSize = m_leftRefLength; + const int predStride = predSize + 1 + multiRefIdx; + m_refBufferStride[area.compID] = predStride; + + const bool noShift = pcv.noChroma2x2 && area.width == 4; // don't shift on the lowest level (chroma not-split) + const int unitWidth = tuWidth <= 2 && cu.ispMode && isLuma(area.compID) ? tuWidth : pcv.minCUWidth >> (noShift ? 0 : getComponentScaleX(area.compID, sps.getChromaFormatIdc())); + const int unitHeight = tuHeight <= 2 && cu.ispMode && isLuma(area.compID) ? tuHeight : pcv.minCUHeight >> (noShift ? 0 : getComponentScaleY(area.compID, sps.getChromaFormatIdc())); + + #if JVET_Y0116_EXTENDED_MRL_LIST + int leftMrlUnitNum = multiRefIdx / unitHeight; + int aboveMrlUnitNum = multiRefIdx / unitWidth; +#endif + + const int totalAboveUnits = (predSize + (unitWidth - 1)) / unitWidth; + const int totalLeftUnits = (predHSize + (unitHeight - 1)) / unitHeight; +#if JVET_Y0116_EXTENDED_MRL_LIST + const int totalUnits = totalAboveUnits + totalLeftUnits + 1 + leftMrlUnitNum + aboveMrlUnitNum; //+1 for top-left +#else + const int totalUnits = totalAboveUnits + totalLeftUnits + 1; //+1 for top-left +#endif + const int numAboveUnits = std::max<int>( tuWidth / unitWidth, 1 ); + const int numLeftUnits = std::max<int>( tuHeight / unitHeight, 1 ); + const int numAboveRightUnits = totalAboveUnits - numAboveUnits; + const int numLeftBelowUnits = totalLeftUnits - numLeftUnits; + + CHECK( numAboveUnits <= 0 || numLeftUnits <= 0 || numAboveRightUnits <= 0 || numLeftBelowUnits <= 0, "Size not supported" ); + + // ----- Step 1: analyze neighborhood ----- + const Position posLT = area; + const Position posRT = area.topRight(); + const Position posLB = area.bottomLeft(); + +#if JVET_Y0116_EXTENDED_MRL_LIST +#if JVET_AC0094_REF_SAMPLES_OPT + bool neighborFlags[4 * (MAX_NUM_PART_IDXS_IN_CTU_WIDTH << 2) + MAX_REF_LINE_IDX + 1]; +#else + bool neighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + MAX_REF_LINE_IDX + 1]; +#endif +#else + bool neighborFlags[4 * MAX_NUM_PART_IDXS_IN_CTU_WIDTH + 1]; +#endif + int numIntraNeighbor = 0; + + memset( neighborFlags, 0, totalUnits ); + + neighborFlags[totalLeftUnits+leftMrlUnitNum] = isAboveLeftAvailable( cu, chType, posLT.offset(-multiRefIdx, -multiRefIdx) ); + numIntraNeighbor += neighborFlags[totalLeftUnits+leftMrlUnitNum] ? 1 : 0; + numIntraNeighbor += isAboveAvailableOBMC ( cu, chType, posLT.offset(-aboveMrlUnitNum*unitWidth, -multiRefIdx), aboveMrlUnitNum, unitWidth, (neighborFlags + totalLeftUnits + 1 + leftMrlUnitNum), m_intraOBMCNeighState ); + numIntraNeighbor += isLeftAvailableOBMC ( cu, chType, posLT.offset(-multiRefIdx, -leftMrlUnitNum*unitHeight), leftMrlUnitNum, unitHeight, (neighborFlags + totalLeftUnits - 1 + leftMrlUnitNum), m_intraOBMCNeighState ); + numIntraNeighbor += isAboveAvailableOBMC ( cu, chType, posLT.offset(0, -multiRefIdx), numAboveUnits, unitWidth, (neighborFlags + totalLeftUnits + 1 + leftMrlUnitNum + aboveMrlUnitNum), m_intraOBMCNeighState ); + numIntraNeighbor += isAboveRightAvailableOBMC( cu, chType, posRT.offset(0, -multiRefIdx), numAboveRightUnits, unitWidth, (neighborFlags + totalLeftUnits + 1 + leftMrlUnitNum + aboveMrlUnitNum + numAboveUnits), m_intraOBMCNeighState ); + numIntraNeighbor += isLeftAvailableOBMC ( cu, chType, posLT.offset(-multiRefIdx, 0), numLeftUnits, unitHeight, (neighborFlags + totalLeftUnits - 1), m_intraOBMCNeighState ); + numIntraNeighbor += isBelowLeftAvailableOBMC ( cu, chType, posLB.offset(-multiRefIdx, 0), numLeftBelowUnits, unitHeight, (neighborFlags + totalLeftUnits - 1 - numLeftUnits), m_intraOBMCNeighState ); + + // ----- Step 2: fill reference samples (depending on neighborhood) ----- + + const Pel* srcBuf = recoBuf.buf; + const int srcStride = recoBuf.stride; + Pel* ptrDst = refBufUnfiltered; + const Pel* ptrSrc; + + // Fill top-left sample(s) if available + ptrSrc = srcBuf - (1 + multiRefIdx) * srcStride - (1 + multiRefIdx); + ptrDst = refBufUnfiltered; +#if JVET_Y0116_EXTENDED_MRL_LIST + if (neighborFlags[totalLeftUnits+leftMrlUnitNum]) +#else + if (neighborFlags[totalLeftUnits]) +#endif + { + ptrDst[0] = ptrSrc[0]; + ptrDst[predStride] = ptrSrc[0]; +#if JVET_Y0116_EXTENDED_MRL_LIST + for (int i = 1; i <= multiRefIdx-leftMrlUnitNum*unitHeight; i++) +#else + for (int i = 1; i <= multiRefIdx; i++) +#endif + { + ptrDst[i] = ptrSrc[i]; + ptrDst[i + predStride] = ptrSrc[i * srcStride]; + } + } + + + if (m_intraOBMCNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL) + { + // Fill left & below-left samples if available (downwards) +#if JVET_Y0116_EXTENDED_MRL_LIST + ptrSrc += (1 + multiRefIdx - leftMrlUnitNum * unitHeight) * srcStride; + ptrDst += (1 + multiRefIdx - leftMrlUnitNum * unitHeight) + predStride; +#else + ptrSrc += (1 + multiRefIdx) * srcStride; + ptrDst += (1 + multiRefIdx) + predStride; +#endif +#if JVET_Y0116_EXTENDED_MRL_LIST + for (int unitIdx = totalLeftUnits + leftMrlUnitNum - 1; unitIdx > 0; unitIdx--) +#else + for (int unitIdx = totalLeftUnits - 1; unitIdx > 0; unitIdx--) +#endif + { + if (neighborFlags[unitIdx]) + { + for (int i = 0; i < unitHeight; i++) + { + ptrDst[i] = ptrSrc[i * srcStride]; + } + } + ptrSrc += unitHeight * srcStride; + ptrDst += unitHeight; + } + // Fill last below-left sample(s) + if (neighborFlags[0]) + { + int lastSample = (predHSize % unitHeight == 0) ? unitHeight : predHSize % unitHeight; + for (int i = 0; i < lastSample; i++) + { + ptrDst[i] = ptrSrc[i * srcStride]; + } + } + } + + if (m_intraOBMCNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL) + { + // Fill above & above-right samples if available (left-to-right) +#if JVET_Y0116_EXTENDED_MRL_LIST + ptrSrc = srcBuf - srcStride * (1 + multiRefIdx) - aboveMrlUnitNum * unitWidth; + ptrDst = refBufUnfiltered + 1 + multiRefIdx - aboveMrlUnitNum * unitWidth; +#else + ptrSrc = srcBuf - srcStride * (1 + multiRefIdx); + ptrDst = refBufUnfiltered + 1 + multiRefIdx; +#endif +#if JVET_Y0116_EXTENDED_MRL_LIST + for (int unitIdx = totalLeftUnits + leftMrlUnitNum + 1; unitIdx < totalUnits - 1; unitIdx++) +#else + for (int unitIdx = totalLeftUnits + 1; unitIdx < totalUnits - 1; unitIdx++) +#endif + { + if (neighborFlags[unitIdx]) + { + for (int j = 0; j < unitWidth; j++) + { + ptrDst[j] = ptrSrc[j]; + } + } + ptrSrc += unitWidth; + ptrDst += unitWidth; + } + // Fill last above-right sample(s) + if (neighborFlags[totalUnits - 1]) + { + int lastSample = (predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth; + for (int j = 0; j < lastSample; j++) + { + ptrDst[j] = ptrSrc[j]; + } + } + } + + // pad from first available down to the last below-left + ptrDst = refBufUnfiltered; + int lastAvailUnit = 0; + if (!neighborFlags[0]) + { + int firstAvailUnit = 1; + while (firstAvailUnit < totalUnits && !neighborFlags[firstAvailUnit]) + { + firstAvailUnit++; + } + + // first available sample + int firstAvailRow = -1; + int firstAvailCol = 0; + +#if JVET_Y0116_EXTENDED_MRL_LIST + if (firstAvailUnit < totalLeftUnits + leftMrlUnitNum) + { + firstAvailRow = (totalLeftUnits + leftMrlUnitNum - firstAvailUnit) * unitHeight + multiRefIdx - leftMrlUnitNum * unitHeight; + } + else if (firstAvailUnit == totalLeftUnits + leftMrlUnitNum) + { + firstAvailRow = multiRefIdx - leftMrlUnitNum * unitHeight; + } + else + { + firstAvailCol = (firstAvailUnit - totalLeftUnits - leftMrlUnitNum - 1) * unitWidth + 1 + multiRefIdx - aboveMrlUnitNum * unitWidth; + } +#else + if (firstAvailUnit < totalLeftUnits) + { + firstAvailRow = (totalLeftUnits - firstAvailUnit) * unitHeight + multiRefIdx; + } + else if (firstAvailUnit == totalLeftUnits) + { + firstAvailRow = multiRefIdx; + } + else + { + firstAvailCol = (firstAvailUnit - totalLeftUnits - 1) * unitWidth + 1 + multiRefIdx; + } +#endif + const Pel firstAvailSample = ptrDst[firstAvailRow < 0 ? firstAvailCol : firstAvailRow + predStride]; + + // last sample below-left (n.a.) + int lastRow = predHSize + multiRefIdx; + + if (m_intraOBMCNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL) + { + lastRow = std::min(lastRow, 1); + } + else + { + firstAvailCol = std::min(firstAvailCol, 1); + } + + // fill left column + for (int i = lastRow; i > firstAvailRow; i--) + { + ptrDst[i + predStride] = firstAvailSample; + } + // fill top row + if (firstAvailCol > 0) + { + for (int j = 0; j < firstAvailCol; j++) + { + ptrDst[j] = firstAvailSample; + } + } + lastAvailUnit = firstAvailUnit; + } + + // pad all other reference samples. + int currUnit = lastAvailUnit + 1; + + if (m_intraOBMCNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL) + { + currUnit = std::max(totalLeftUnits+leftMrlUnitNum+1, currUnit); + } + + while (currUnit < totalUnits) + { + if (m_intraOBMCNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL && (totalLeftUnits+leftMrlUnitNum+1 < currUnit)) + { + break; + } + + if (!neighborFlags[currUnit]) // samples not available + { + // last available sample + int lastAvailRow = -1; + int lastAvailCol = 0; +#if JVET_Y0116_EXTENDED_MRL_LIST + if (lastAvailUnit < totalLeftUnits + leftMrlUnitNum) + { + lastAvailRow = (totalLeftUnits + leftMrlUnitNum - lastAvailUnit - 1) * unitHeight + multiRefIdx - leftMrlUnitNum * unitHeight + 1; + } + else if (lastAvailUnit == totalLeftUnits + leftMrlUnitNum) + { + lastAvailCol = multiRefIdx- leftMrlUnitNum * unitHeight; + } + else + { + lastAvailCol = (lastAvailUnit - totalLeftUnits - leftMrlUnitNum) * unitWidth + multiRefIdx - aboveMrlUnitNum * unitWidth; + } +#else + if (lastAvailUnit < totalLeftUnits) + { + lastAvailRow = (totalLeftUnits - lastAvailUnit - 1) * unitHeight + multiRefIdx + 1; + } + else if (lastAvailUnit == totalLeftUnits) + { + lastAvailCol = multiRefIdx; + } + else + { + lastAvailCol = (lastAvailUnit - totalLeftUnits) * unitWidth + multiRefIdx; + } +#endif + const Pel lastAvailSample = ptrDst[lastAvailRow < 0 ? lastAvailCol : lastAvailRow + predStride]; + + // fill current unit with last available sample +#if JVET_Y0116_EXTENDED_MRL_LIST + if (currUnit < totalLeftUnits + leftMrlUnitNum) + { + if (m_intraOBMCNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL) + { + for (int i = lastAvailRow - 1; i >= lastAvailRow - unitHeight; i--) + { + ptrDst[i + predStride] = lastAvailSample; + } + } + } + else if (currUnit == totalLeftUnits + leftMrlUnitNum) + { + if (m_intraOBMCNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL) + { + for (int i = 0; i < multiRefIdx - leftMrlUnitNum * unitHeight + 1; i++) + { + ptrDst[i + predStride] = lastAvailSample; + } + } + if (m_intraOBMCNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL) + { + for (int j = 0; j < multiRefIdx - aboveMrlUnitNum * unitWidth + 1; j++) + { + ptrDst[j] = lastAvailSample; + } + } + } + else + { + int numSamplesInUnit = (currUnit == totalUnits - 1) ? ((predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth) : unitWidth; + for (int j = lastAvailCol + 1; j <= lastAvailCol + numSamplesInUnit; j++) + { + ptrDst[j] = lastAvailSample; + } + } +#else + if (currUnit < totalLeftUnits) + { + for (int i = lastAvailRow - 1; i >= lastAvailRow - unitHeight; i--) + { + ptrDst[i + predStride] = lastAvailSample; + } + } + else if (currUnit == totalLeftUnits) + { + for (int i = 0; i < multiRefIdx + 1; i++) + { + ptrDst[i + predStride] = lastAvailSample; + } + for (int j = 0; j < multiRefIdx + 1; j++) + { + ptrDst[j] = lastAvailSample; + } + } + else + { + int numSamplesInUnit = (currUnit == totalUnits - 1) ? ((predSize % unitWidth == 0) ? unitWidth : predSize % unitWidth) : unitWidth; + for (int j = lastAvailCol + 1; j <= lastAvailCol + numSamplesInUnit; j++) + { + ptrDst[j] = lastAvailSample; + } + } +#endif + } + lastAvailUnit = currUnit; + currUnit++; + } +} +#endif + #if JVET_AH0136_CHROMA_REORDERING void IntraPrediction::xFillReferenceSamplesForCoLuma(const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu) { @@ -6640,10 +7096,17 @@ void IntraPrediction::xFilterReferenceSamples(const Pel *refBufUnfiltered, Pel * refBufFiltered[0] = topLeft; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (!(m_intraOBMCNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL && m_refSampleForOBMC)) + { +#endif for (int i = 1; i < predSize; i++) { refBufFiltered[i] = (refBufUnfiltered[i - 1] + 2 * refBufUnfiltered[i] + refBufUnfiltered[i + 1] + 2) >> 2; } +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + } +#endif refBufFiltered[predSize] = refBufUnfiltered[predSize]; refBufFiltered += predStride; @@ -6651,10 +7114,17 @@ void IntraPrediction::xFilterReferenceSamples(const Pel *refBufUnfiltered, Pel * refBufFiltered[0] = topLeft; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + if (!(m_intraOBMCNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL && m_refSampleForOBMC)) + { +#endif for (int i = 1; i < predHSize; i++) { refBufFiltered[i] = (refBufUnfiltered[i - 1] + 2 * refBufUnfiltered[i] + refBufUnfiltered[i + 1] + 2) >> 2; } +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + } +#endif refBufFiltered[predHSize] = refBufUnfiltered[predHSize]; } @@ -10237,6 +10707,70 @@ void IntraPrediction::ibcCiipBlending(Pel *pDst, int strideDst, const Pel *pSrc0 } #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +bool IntraPrediction::getGradForOBMC(const PredictionUnit pu, const CPelBuf &recoBuf, const CompArea &area, CodingUnit &cu, const bool isAbove, const int blkSize, int* modeBuf) +{ + const int templateSize = 1; + + const CodingStructure &cs = *cu.cs; + + const Pel *pReco = recoBuf.buf; + const uint32_t uiWidth = area.width; + const uint32_t uiHeight = area.height; + const int iStride = recoBuf.stride; + + int totalUnits; + if (isAbove) + { + const Position posNeighbor(pu.lumaPos().offset(1, -1)); + + PredictionUnit* tmpPu = pu.cs->getPU(posNeighbor, pu.chType); + if (tmpPu == nullptr) + { + return false; + } + + totalUnits = uiWidth / blkSize; + } + else + { + const Position posNeighbor(pu.lumaPos().offset(-1, 1)); + + PredictionUnit* tmpPu = pu.cs->getPU(posNeighbor, pu.chType); + if (tmpPu == nullptr) + { + return false; + } + + totalUnits = uiHeight / blkSize; + } + memset(modeBuf, -1, sizeof(int) * totalUnits); + + const Position posLT = cu.Y().topLeft().offset(-1, -1); + const Position posLB = cu.Y().bottomLeft().offset(-1, 1); + const Position posRT = cu.Y().topRight().offset(1, -1); + + if (isAbove) + { + const bool isExistFirst = (cs.getCURestricted(posLT, cu, cu.chType) != nullptr); + const bool isExistLast = (cs.getCURestricted(posRT, cu, cu.chType) != nullptr); + const Pel *pRecoAbove = pReco - 2 * iStride; + + calcGradForOBMC(pu, pRecoAbove, iStride, totalUnits, templateSize, blkSize, modeBuf, isAbove, isExistFirst, isExistLast); + } + else + { + const bool isExistFirst = (cs.getCURestricted(posLT, cu, cu.chType) != nullptr); + const bool isExistLast = (cs.getCURestricted(posLB, cu, cu.chType) != nullptr); + const Pel *pRecoLeft = pReco - 2; + + calcGradForOBMC(pu, pRecoLeft, iStride, totalUnits, templateSize, blkSize, modeBuf, isAbove, isExistFirst, isExistLast); + } + + return true; +} +#endif + #if ENABLE_DIMD void IntraPrediction::deriveDimdMode(const CPelBuf &recoBuf, const CompArea &area, CodingUnit &cu) { @@ -12703,6 +13237,136 @@ int isBelowLeftAvailable(const CodingUnit &cu, const ChannelType &chType, const return numIntra; } +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +int isAboveAvailableOBMC(const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *bValidFlags, const int obmcNeighState) +{ + if (obmcNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL) + { + return 0; + } + + const CodingStructure& cs = *cu.cs; + + bool * validFlags = bValidFlags; + int numIntra = 0; + const int maxDx = uiNumUnitsInPU * unitWidth; + + for (int dx = 0; dx < maxDx; dx += unitWidth) + { + const Position refPos = posLT.offset(dx, -1); + + if (!cs.isDecomp(refPos, chType)) + { + break; + } + + const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL); + numIntra += valid ? 1 : 0; + *validFlags = valid; + + validFlags++; + } + + return numIntra; +} + +int isLeftAvailableOBMC(const CodingUnit &cu, const ChannelType &chType, const Position &posLT, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *bValidFlags, const int obmcNeighState) +{ + if (obmcNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL) + { + return 0; + } + + const CodingStructure& cs = *cu.cs; + + bool * validFlags = bValidFlags; + int numIntra = 0; + const int maxDy = uiNumUnitsInPU * unitHeight; + + for (int dy = 0; dy < maxDy; dy += unitHeight) + { + const Position refPos = posLT.offset(-1, dy); + + if (!cs.isDecomp(refPos, chType)) + { + break; + } + + const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL); + numIntra += valid ? 1 : 0; + *validFlags = valid; + + validFlags--; + } + + return numIntra; +} + +int isAboveRightAvailableOBMC(const CodingUnit &cu, const ChannelType &chType, const Position &posRT, const uint32_t uiNumUnitsInPU, const uint32_t unitWidth, bool *bValidFlags, const int obmcNeighState ) +{ + if (obmcNeighState == INTRA_OBMC_ONLY_LEFT_AVAIL) + { + return 0; + } + + const CodingStructure& cs = *cu.cs; + + bool * validFlags = bValidFlags; + int numIntra = 0; + const int maxDx = uiNumUnitsInPU * unitWidth; + + for (int dx = 0; dx < maxDx; dx += unitWidth) + { + const Position refPos = posRT.offset(unitWidth + dx, -1); + + if (!cs.isDecomp(refPos, chType)) + { + break; + } + + const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL); + numIntra += valid ? 1 : 0; + *validFlags = valid; + + validFlags++; + } + + return numIntra; +} + +int isBelowLeftAvailableOBMC(const CodingUnit &cu, const ChannelType &chType, const Position &posLB, const uint32_t uiNumUnitsInPU, const uint32_t unitHeight, bool *bValidFlags, const int obmcNeighState ) +{ + if (obmcNeighState == INTRA_OBMC_ONLY_ABOVE_AVAIL) + { + return 0; + } + + const CodingStructure& cs = *cu.cs; + + bool * validFlags = bValidFlags; + int numIntra = 0; + const int maxDy = uiNumUnitsInPU * unitHeight; + + for (int dy = 0; dy < maxDy; dy += unitHeight) + { + const Position refPos = posLB.offset(-1, unitHeight + dy); + + if (!cs.isDecomp(refPos, chType)) + { + break; + } + + const bool valid = (cs.getCURestricted(refPos, cu, chType) != NULL); + numIntra += valid ? 1 : 0; + *validFlags = valid; + + validFlags--; + } + + return numIntra; +} +#endif + #if JVET_AA0126_GLM Pel IntraPrediction::xGlmGetLumaVal(const int s[6], const int c[6], const int glmIdx, const Pel val) const { diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h index b833e2b26..d702673e5 100644 --- a/source/Lib/CommonLib/IntraPrediction.h +++ b/source/Lib/CommonLib/IntraPrediction.h @@ -258,6 +258,12 @@ public: #if MMLM bool m_encPreRDRun; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + int m_intraOBMCNeighState; + bool m_refSampleForOBMC; + Pel m_refSampleForOBMCBuf[MAX_INTRA_SIZE + 3]; + Pel m_refSampleForOBMCBufFiltered[MAX_INTRA_SIZE + 3]; +#endif #if JVET_AC0147_CCCM_NO_SUBSAMPLING #if JVET_AD0202_CCCM_MDF @@ -561,7 +567,9 @@ protected: #endif void xFillReferenceSamples ( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu ); - +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + void xFillReferenceSamplesOBMC( const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu ); +#endif #if JVET_AH0136_CHROMA_REORDERING void xFillReferenceSamplesForCoLuma(const CPelBuf &recoBuf, Pel* refBufUnfiltered, const CompArea &area, const CodingUnit &cu); #endif @@ -812,6 +820,11 @@ public: ); #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + const IntraPredParam* getIpaParam () { return &m_ipaParam; }; + bool getGradForOBMC(const PredictionUnit pu, const CPelBuf &recoBuf, const CompArea &area, CodingUnit &cu, const bool isAbove, const int blkSize, int* modeBuf); +#endif + #if ENABLE_DIMD static void deriveDimdMode (const CPelBuf &recoBuf, const CompArea &area, CodingUnit &cu); #if JVET_Z0050_DIMD_CHROMA_FUSION && ENABLE_DIMD @@ -1046,6 +1059,9 @@ public: #else void initIntraPatternChType (const CodingUnit &cu, const CompArea &area, const bool forceRefFilterFlag = false); // use forceRefFilterFlag to get both filtered and unfiltered buffers #endif +#endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + void initIntraPatternChTypeOBMC(const CodingUnit &cu, const CompArea &area); #endif void initIntraPatternChTypeISP (const CodingUnit& cu, const CompArea& area, PelBuf& piReco, const bool forceRefFilterFlag = false); // use forceRefFilterFlag to get both filtered and unfiltered buffers diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 9c70282d9..dd2bbe4da 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -292,6 +292,7 @@ #if ENABLE_OBMC #define JVET_AC0335_CONTENT_ADAPTIVE_OBMC_ENABLING 1 // JVET-AC0335: Content adaptive OBMC enabling #define JVET_AD0193_ADAPTIVE_OBMC_CONTROL 1 // JVET-AD0193: Adaptive OBMC control +#define JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED 1 // JVET-AJ0161: OBMC extension with intra prediction #endif #if JVET_X0049_BDMVR_SW_OPT diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 7d0faa132..5c98aea75 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -33076,6 +33076,182 @@ int buildHistogram(const Pel *pReco, int iStride, uint32_t uiHeight, uint32_t ui } #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +void calcGradForOBMC(const PredictionUnit pu, const Pel *pReco, const int iStride, const int totalUnits, const int templateSize, const int blkSize, int *modeBuf, const int isAbove, const bool isExistFirst, const bool isExistLast) +{ + int angTable[17] = { 0, 2048, 4096, 6144, 8192, 12288, 16384, 20480, 24576, + 28672, 32768, 36864, 40960, 47104, 53248, 59392, 65536 }; + int offsets[4] = { HOR_IDX, HOR_IDX, VER_IDX, VER_IDX }; + int dirs[4] = { -1, 1, -1, 1 }; + int mapXgrY1[2][2] = { { 1, 0 }, { 0, 1 } }; + int mapXgrY0[2][2] = { { 2, 3 }, { 3, 2 } }; + + int toSaveAmp[NUM_LUMA_MODE]; + const Position startPos = pu.Y().topLeft().offset(isAbove ? 0 : -1, isAbove ? -1 : 0); + PredictionUnit* tmpPu = nullptr; + MotionInfo mi; + + const int extraPosNum = 2; + bool prevSaved = false; + int savedPrevAmp[extraPosNum << 1]; + int savedPrevAng[extraPosNum << 1]; + + for (int i = 0; i < (extraPosNum << 1); i++) + { + savedPrevAmp[i] = -1; + savedPrevAng[i] = -1; + } + + int i = 0; + + while (i < totalUnits) + { + const int off = i * blkSize; + const Position posSubBlock(startPos.offset(isAbove ? off : 0, isAbove ? 0 : off)); + tmpPu = pu.cs->getPU(posSubBlock, pu.chType); + mi = tmpPu->getMotionInfo(posSubBlock); + + if (mi.isInter && !mi.isIBCmot) + { + if (tmpPu->gpmIntraFlag || tmpPu->gpmInterIbcFlag) + { + i++; + } + else + { + int forNext; + if (isAbove) + { + forNext = tmpPu->Y().bottomRight().x - posSubBlock.x; + forNext /= blkSize; + } + else + { + forNext = tmpPu->Y().bottomRight().y - posSubBlock.y; + forNext /= blkSize; + } + forNext++; + + for (int k = 0; k < forNext; k++) + { + mi = tmpPu->getMotionInfo(posSubBlock.offset(isAbove ? blkSize * k : 0, isAbove ? 0 : blkSize * k)); + } + i += forNext; + } + + prevSaved = false; + continue; + } + + memset(toSaveAmp, 0, sizeof(int) * NUM_LUMA_MODE); + int bestMode = PLANAR_IDX; + + for (int j = -extraPosNum; j < blkSize + extraPosNum; j++) + { + if ((!isExistFirst && (i == 0) && (j < 0)) || (!isExistLast && ((i + 1) >= totalUnits) && (j >= blkSize - 1))) + { + continue; + } + + int iAmp = 0, iAngUneven = -1; + if (j < extraPosNum && prevSaved) + { + iAmp = savedPrevAmp[j + extraPosNum]; + iAngUneven = savedPrevAng[j + extraPosNum]; + toSaveAmp[iAngUneven] += iAmp; + } + else + { + const Pel *pRec = &(pReco[isAbove ? (i * blkSize + j) : ((i * blkSize + j) * iStride)]); + + int iDy = pRec[0] + pRec[iStride] - pRec[+1] - pRec[iStride + 1]; + int iDx = - pRec[0] + pRec[iStride] - pRec[+1] + pRec[iStride + 1]; + + if (iDy == 0 && iDx == 0) + { + if (j >= blkSize - extraPosNum) + { + savedPrevAmp[j - (blkSize - extraPosNum)] = 0; + savedPrevAng[j - (blkSize - extraPosNum)] = 0; + } + continue; + } + + iAmp = (int) (abs(iDx) + abs(iDy)); + if (iDx != 0 && iDy != 0) + { + int signx = iDx < 0 ? 1 : 0; + int signy = iDy < 0 ? 1 : 0; + int absx = iDx < 0 ? -iDx : iDx; + int absy = iDy < 0 ? -iDy : iDy; + int gtY = absx > absy ? 1 : 0; + int region = gtY ? mapXgrY1[signy][signx] : mapXgrY0[signy][signx]; +#if JVET_X0149_TIMD_DIMD_LUT + int s0 = gtY ? absy : absx; + int s1 = gtY ? absx : absy; + int x = floorLog2(s1); + int norm = (s1 << 4 >> x) & 15; + int v = g_gradDivTable[norm] | 8; + x += (norm != 0); + int shift = 13 - x; + int ratio; + if (shift < 0) + { + shift = -shift; + int add = (1 << (shift - 1)); + ratio = (s0 * v + add) >> shift; + } + else + { + ratio = (s0 * v) << shift; + } +#else + float fRatio = gtY ? static_cast<float>(absy) / static_cast<float>(absx) + : static_cast<float>(absx) / static_cast<float>(absy); + float fRatioScaled = fRatio * (1 << 16); + int ratio = static_cast<int>(fRatioScaled); +#endif + int idx = 16; + for (int i = 1; i < 17; i++) + { + if (ratio <= angTable[i]) + { + idx = ratio - angTable[i - 1] < angTable[i] - ratio ? i - 1 : i; + break; + } + } + + iAngUneven = offsets[region] + dirs[region] * idx; + } + else + { + iAngUneven = iDx == 0 ? VER_IDX : HOR_IDX; + } + + CHECK(iAngUneven < 0, "Wrong mode in DIMD histogram"); + CHECK(iAngUneven >= NUM_LUMA_MODE, "Wrong mode in DIMD histogram"); + + toSaveAmp[iAngUneven] += iAmp; + + if (j >= blkSize - extraPosNum) + { + savedPrevAmp[j - (blkSize - extraPosNum)] = iAmp; + savedPrevAng[j - (blkSize - extraPosNum)] = iAngUneven; + } + } + if (toSaveAmp[iAngUneven] > toSaveAmp[bestMode]) + { + bestMode = iAngUneven; + } + } + + prevSaved = true; + modeBuf[i] = bestMode; + i++; + } +} +#endif + #if JVET_AG0164_AFFINE_GPM int PU::getAffGPMCtxOffset(const PredictionUnit& pu) { diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 49b8239e1..287548ad3 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -1471,3 +1471,7 @@ void getTemporalBv(const PredictionUnit &pu, std::vector<MotionInfo>& temporalMi #if JVET_AG0061_INTER_LFNST_NSPT int buildHistogram(const Pel *pReco, int iStride, uint32_t uiHeight, uint32_t uiWidth, int *piHistogram, int direction, int bw, int bh); #endif + +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED +void calcGradForOBMC(const PredictionUnit pu, const Pel *pReco, const int iStride, const int totalUnits, const int templateSize, const int blkSize, int *modeBuf, const int isAbove, const bool isExistFirst, const bool isExistLast); +#endif \ No newline at end of file diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 4ce223339..ab9ed528c 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -160,6 +160,13 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) for( auto &currCU : cs.traverseCUs( CS::getArea( cs, ctuArea, chType ), chType ) ) { +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterPred->setDIMDForOBMC(false); + m_pcInterPred->setModeGetCheck(0, false); + m_pcInterPred->setModeGetCheck(1, false); + m_pcInterPred->setClearModeBuf(0); + m_pcInterPred->setClearModeBuf(1); +#endif #if JVET_Z0054_BLK_REF_PIC_REORDER m_pcInterPred->setFillCurTplAboveARMC(false); m_pcInterPred->setFillCurTplLeftARMC(false); @@ -2306,7 +2313,11 @@ void DecCu::xReconInter(CodingUnit &cu) 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; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterPred->subBlockOBMC(*cu.firstPU, nullptr, m_pcIntraPred); +#else m_pcInterPred->subBlockOBMC(*cu.firstPU); +#endif cu.isobmcMC = false; #endif #if JVET_AG0135_AFFINE_CIIP @@ -2369,7 +2380,11 @@ void DecCu::xReconInter(CodingUnit &cu) if (!cu.firstPU->ciipFlag) #endif { +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterPred->subBlockOBMC(*cu.firstPU, nullptr, m_pcIntraPred); +#else m_pcInterPred->subBlockOBMC(*cu.firstPU); +#endif } #else m_pcInterPred->subBlockOBMC(*cu.firstPU); diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 81a2b847f..01bdfccc3 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -1138,6 +1138,13 @@ void EncCu::xCompressCU( CodingStructure*& tempCS, CodingStructure*& bestCS, Par tempCS->splitRdCostBest = NULL; #endif m_modeCtrl->initCULevel( partitioner, *tempCS ); +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->setDIMDForOBMC(false); + m_pcInterSearch->setModeGetCheck(0, false); + m_pcInterSearch->setModeGetCheck(1, false); + m_pcInterSearch->setClearModeBuf(0); + m_pcInterSearch->setClearModeBuf(1); +#endif #if JVET_Z0054_BLK_REF_PIC_REORDER m_pcInterSearch->setFillCurTplAboveARMC(false); m_pcInterSearch->setFillCurTplLeftARMC(false); @@ -4750,7 +4757,11 @@ void EncCu::xCheckRDCostHashInter( CodingStructure *&tempCS, CodingStructure *&b #else cu.obmcFlag = true; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(*cu.firstPU, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(*cu.firstPU); +#endif cu.isobmcMC = false; #endif xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode, 0 @@ -9214,7 +9225,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if JVET_AG0135_AFFINE_CIIP } #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu); +#endif cu.isobmcMC = false; #endif #if JVET_AG0135_AFFINE_CIIP @@ -9758,7 +9773,11 @@ void EncCu::xCheckRDCostMerge2Nx2N( CodingStructure *&tempCS, CodingStructure *& #if JVET_X0090_CIIP_FIX if (!pu.ciipFlag) { +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu); +#endif } #else m_pcInterSearch->subBlockOBMC( pu ); @@ -10261,7 +10280,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct obmcBuf.copyFrom(predSrc); pu.cu->isobmcMC = true; pu.cu->obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, &obmcBuf, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu, &obmcBuf); +#endif pu.cu->affine = false; pu.cu->isobmcMC = false; }; @@ -11695,7 +11718,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, !isIntra0 ? &predSrc0 : &predSrc1, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu, !isIntra0 ? &predSrc0 : &predSrc1); +#endif cu.isobmcMC = false; #endif #if JVET_AG0164_AFFINE_GPM @@ -11712,7 +11739,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct PU::spanMotionInfo2(pu, MergeCtx()); cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, &predSrc0, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu, &predSrc0); +#endif pu.cu->affine = false; pu.cu->isobmcMC = false; @@ -11726,7 +11757,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct PU::spanMotionInfo2(pu, MergeCtx()); cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, &predSrc1, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu, &predSrc1); +#endif pu.cu->affine = false; pu.cu->isobmcMC = false; @@ -12045,7 +12080,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu); +#endif cu.isobmcMC = false; #if JVET_Y0065_GPM_INTRA } @@ -13937,7 +13976,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, !isIntra0 ? &predSrcTemp0 : &predSrcTemp1, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu, !isIntra0 ? &predSrcTemp0 : &predSrcTemp1); +#endif cu.isobmcMC = false; #endif #if JVET_AG0164_AFFINE_GPM @@ -13954,7 +13997,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct PU::spanMotionInfo2(pu, MergeCtx()); cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, &predSrcTemp0, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu, &predSrcTemp0); +#endif pu.cu->affine = false; cu.isobmcMC = false; @@ -13968,7 +14015,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct PU::spanMotionInfo2(pu, MergeCtx()); cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, &predSrcTemp1, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu, &predSrcTemp1); +#endif pu.cu->affine = false; cu.isobmcMC = false; } @@ -14537,7 +14588,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct #endif cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu); +#endif cu.isobmcMC = false; #if JVET_Y0065_GPM_INTRA } @@ -14747,7 +14802,11 @@ void EncCu::xCheckRDCostMergeGeoComb2Nx2N(CodingStructure *&tempCS, CodingStruct { cu.isobmcMC = true; cu.obmcFlag = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(pu, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(pu); +#endif cu.isobmcMC = false; } #endif @@ -22074,7 +22133,11 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC CHECK(cu.obmcFlag == false, "this is not possible"); #endif cu.isobmcMC = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(*cu.firstPU, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(*cu.firstPU); +#endif cu.isobmcMC = false; xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0 , 0 @@ -22191,7 +22254,11 @@ void EncCu::xCheckRDCostInter( CodingStructure *&tempCS, CodingStructure *&bestC #else cu.obmcFlag = true; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(*cu.firstPU, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(*cu.firstPU); +#endif cu.isobmcMC = false; #endif xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0 @@ -22608,7 +22675,11 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes #endif CodingStructure *prevCS = tempCS; cu.isobmcMC = true; +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(*cu.firstPU, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(*cu.firstPU); +#endif cu.isobmcMC = false; xEncodeInterResidual( tempCS, bestCS, partitioner, encTestMode, 0 , 0 @@ -22724,7 +22795,11 @@ bool EncCu::xCheckRDCostInterIMV(CodingStructure *&tempCS, CodingStructure *&bes #else cu.obmcFlag = true; #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(*cu.firstPU, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(*cu.firstPU); +#endif cu.isobmcMC = false; #endif xEncodeInterResidual( tempCS, bestCS, partitioner, encTestModeBase, 0 @@ -24730,7 +24805,11 @@ void EncCu::xCheckRDCostInterMultiHyp2Nx2N(CodingStructure *&tempCS, CodingStruc #if JVET_AD0193_ADAPTIVE_OBMC_CONTROL } #endif +#if JVET_AJ0161_OBMC_EXT_WITH_INTRA_PRED + m_pcInterSearch->subBlockOBMC(*cu.firstPU, nullptr, m_pcIntraSearch); +#else m_pcInterSearch->subBlockOBMC(*cu.firstPU); +#endif cu.isobmcMC = false; #endif xEncodeInterResidual(tempCS, bestCS, partitioner, encTestMode); -- GitLab