From 93451e4a526d4c946d95e2cc309427563af15a35 Mon Sep 17 00:00:00 2001 From: Frank Bossen <fbossen@gmail.com> Date: Thu, 27 Jul 2023 14:24:36 -0400 Subject: [PATCH] Clean up code from JVET-AD0045 (encoder DMVR avoidance) Also addresses #1608 --- source/Lib/CommonLib/InterPrediction.cpp | 152 +++++++++-------------- source/Lib/EncoderLib/EncCu.cpp | 14 +-- 2 files changed, 68 insertions(+), 98 deletions(-) diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 2e1e58e2a..31b57753c 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -1803,6 +1803,14 @@ void InterPrediction::xDmvrInitialMc(const PredictionUnit &pu, const ClpRngs &cl } } +#if JVET_AD0045 +static constexpr int ACTIVITY_TH[MAX_QP + 1] = { + 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, + 7, 7, 8, 9, 9, 10, 10, 11, 12, 13, 13, 14, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37, +}; +#endif + void InterPrediction::xProcessDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvDst, const ClpRngs &clpRngs, const bool applyBdof) { @@ -1886,39 +1894,25 @@ void InterPrediction::xProcessDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvDst, con PelBuf(m_acYuvPred[l][COMPONENT_Cr], pcYuvDst.Cr())); srcPred[l] = srcPred[l].subBuf(UnitAreaRelative(pu, subPu)); } + #if JVET_AD0045 - int xx = -1; - int yy = -1; - static const int ACTIVITY_TH[MAX_QP + 1] = - { - 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 9, 9, 10, 10, 11, 12, 13, 13, 14, 15, 16, 17, 18, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 30, 31, 32, 33, 34, 36, 36, 36, 36, 37, 37, 37, 37, 37, 37 - }; - int spatActivity[2]; - bool riskArtifact = false; - int boundaryDiffHorEdge; - int boundaryDiffVerEdge; - int xmax = pu.lumaSize().width / DMVR_SUBCU_WIDTH; - int mvThreshold = 28; // subblock motion difference threshold - int spatActivityThreshold = ACTIVITY_TH[pu.cu->qp]; - int boundaryDiffThreshold = 10; //subblock boundary activity threshold - if ((pu.cu->slice->getPPS()->getPPSId() == ENC_PPS_ID_RPR) && pu.cu->slice->getSPS()->getGOPBasedRPREnabledFlag()) // corresponds to encoding in 1/2 reduced resolution when GOP based RPR is used - { - boundaryDiffThreshold = 5; - } + bool riskArtifact = false; + const int widthInSubPu = pu.lumaSize().width / DMVR_SUBCU_WIDTH; + const int spatActivityThreshold = ACTIVITY_TH[std::max<int>(0, pu.cu->qp)]; + + // subblock boundary activity threshold + // corresponds to encoding in 1/2 reduced resolution when GOP based RPR is used + const int boundaryDiffThreshold = + pu.cu->slice->getPPS()->getPPSId() == ENC_PPS_ID_RPR && pu.cu->slice->getSPS()->getGOPBasedRPREnabledFlag() ? 5 + : 10; #endif int subPuIdx = 0; for (int yStart = 0; yStart < pu.lumaSize().height; yStart += dy) { -#if JVET_AD0045 - yy++; -#endif for (int xStart = 0; xStart < pu.lumaSize().width; xStart += dx) { -#if JVET_AD0045 - xx++; -#endif const int x = puPos.x + xStart; const int y = puPos.y + yStart; @@ -1929,33 +1923,37 @@ void InterPrediction::xProcessDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvDst, con xDmvrPrefetch(subPu, true); xDmvrInitialMc(subPu, clpRngs); + #if JVET_AD0045 - if (xDmvrGetEncoderCheckFlag()) + bool checkDmvr = xDmvrGetEncoderCheckFlag() && xStart != 0 && yStart != 0; + if (checkDmvr) { - for (int theRef = 0; theRef < 2; theRef++) + checkDmvr = false; + + CHECK(dx != DMVR_SUBCU_WIDTH, "bad subblock width"); + CHECK(dy != DMVR_SUBCU_HEIGHT, "bad subblock height"); + + for (int listIdx = 0; listIdx < NUM_REF_PIC_LIST_01; listIdx++) { int blkSumAct = 0; - int numSample = 0; - const ptrdiff_t blkStride = m_dmvrInitialPred[theRef].stride; - const Pel* piOrg = m_dmvrInitialPred[theRef].buf; + const ptrdiff_t blkStride = m_dmvrInitialPred[listIdx].stride; + const Pel* org = m_dmvrInitialPred[listIdx].buf; - piOrg += blkStride; // start from the second row for (int row = 1; row < DMVR_SUBCU_HEIGHT; row++) { for (int col = 1; col < DMVR_SUBCU_WIDTH; col++) { - int horAct = std::abs(piOrg[col] - piOrg[col - 1]); - int verAct = std::abs(piOrg[col] - piOrg[col - blkStride]); - - blkSumAct += horAct; - blkSumAct += verAct; - numSample++; + blkSumAct += std::abs(org[row * blkStride + col] - org[row * blkStride + col - 1]); + blkSumAct += std::abs(org[row * blkStride + col] - org[row * blkStride + col - blkStride]); } - piOrg += blkStride; } - int avgSampleAct = int((double)blkSumAct / numSample); - spatActivity[theRef] = avgSampleAct; + + if (blkSumAct / ((DMVR_SUBCU_WIDTH - 1) * (DMVR_SUBCU_HEIGHT - 1)) < spatActivityThreshold) + { + checkDmvr = true; + break; + } } } #endif @@ -2015,67 +2013,42 @@ void InterPrediction::xProcessDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvDst, con subPu.cu->slice->getSPS()->getBitDepths(), subPu.cu->slice->clpRngs(), applyBdofSubPu, false, false, nullptr); #if JVET_AD0045 - if (xDmvrGetEncoderCheckFlag()) + if (checkDmvr) { + checkDmvr = false; + + const ptrdiff_t blkStride = pcYuvDst.bufs[COMPONENT_Y].stride; + const Pel* org = subPredBuf.bufs[COMPONENT_Y].buf; + // check boundary diff above - if (yy != 0) // omit check for block boundary - { - int blkSumAct = 0; - int numSample = 0; + int blkSumAct = 0; - const ptrdiff_t blkStride = pcYuvDst.bufs[COMPONENT_Y].stride; - const Pel* piOrg = subPredBuf.bufs[COMPONENT_Y].buf; - for (int row = 0; row < 1; row++) - { - for (int col = 0; col < DMVR_SUBCU_WIDTH; col++) - { - int verAct = std::abs(piOrg[col] - piOrg[col - blkStride]); - blkSumAct += verAct; - numSample++; - } - piOrg += blkStride; - } - int avgSampleAct = int((double)blkSumAct / numSample); - boundaryDiffHorEdge = avgSampleAct; - } - else + for (int col = 0; col < DMVR_SUBCU_WIDTH; col++) { - boundaryDiffHorEdge = 0; + blkSumAct += std::abs(org[col] - org[col - blkStride]); } - // check boundary diff left - // vertical edge - if (xx != 0) // omit check for block boundary - { - int blkSumAct = 0; - int numSample = 0; + checkDmvr = blkSumAct / DMVR_SUBCU_WIDTH > boundaryDiffThreshold; - const ptrdiff_t blkStride = pcYuvDst.bufs[COMPONENT_Y].stride; - const Pel* piOrg = subPredBuf.bufs[COMPONENT_Y].buf; + if (!checkDmvr) + { // check boundary diff left + blkSumAct = 0; + for (int row = 0; row < DMVR_SUBCU_HEIGHT; row++) { - for (int col = 0; col < 1; col++) - { - int horAct = std::abs(piOrg[col] - piOrg[col - 1]); - blkSumAct += horAct; - numSample++; - } - piOrg += blkStride; + blkSumAct += std::abs(org[row * blkStride] - org[row * blkStride - 1]); } - int avgSampleAct = int((double)blkSumAct / numSample); - boundaryDiffVerEdge = avgSampleAct; - } - else - { - boundaryDiffVerEdge = 0; + checkDmvr = blkSumAct / DMVR_SUBCU_HEIGHT > boundaryDiffThreshold; } - if (xx > 0 && yy > 0) + + if (checkDmvr) { - int theMvDiffX = abs(pu.mvdL0SubPu[xx + yy * xmax].getHor() - pu.mvdL0SubPu[xx - 1 + yy * xmax].getHor()); - int theMvDiffY = abs(pu.mvdL0SubPu[xx + yy * xmax].getVer() - pu.mvdL0SubPu[xx - 1 + yy * xmax].getVer()); - int theMvDiffX2 = abs(pu.mvdL0SubPu[xx + yy * xmax].getHor() - pu.mvdL0SubPu[xx + (yy - 1) * xmax].getHor()); - int theMvDiffY2 = abs(pu.mvdL0SubPu[xx + yy * xmax].getVer() - pu.mvdL0SubPu[xx + (yy - 1) * xmax].getVer()); - if ((theMvDiffX >= mvThreshold || theMvDiffY >= mvThreshold || theMvDiffX2 >= mvThreshold || theMvDiffY2 >= mvThreshold) && ((spatActivity[0] < spatActivityThreshold) || (spatActivity[1] < spatActivityThreshold)) && ((boundaryDiffVerEdge > boundaryDiffThreshold) || (boundaryDiffHorEdge > boundaryDiffThreshold))) + constexpr int MV_THRESHOLD = 28; // subblock motion difference threshold + + if (abs(pu.mvdL0SubPu[subPuIdx].hor - pu.mvdL0SubPu[subPuIdx - 1].hor) >= MV_THRESHOLD + || abs(pu.mvdL0SubPu[subPuIdx].ver - pu.mvdL0SubPu[subPuIdx - 1].ver) >= MV_THRESHOLD + || abs(pu.mvdL0SubPu[subPuIdx].hor - pu.mvdL0SubPu[subPuIdx - widthInSubPu].hor) >= MV_THRESHOLD + || abs(pu.mvdL0SubPu[subPuIdx].ver - pu.mvdL0SubPu[subPuIdx - widthInSubPu].ver) >= MV_THRESHOLD) { riskArtifact = true; } @@ -2084,9 +2057,6 @@ void InterPrediction::xProcessDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvDst, con #endif subPuIdx++; } -#if JVET_AD0045 - xx = -1; -#endif } #if JVET_AD0045 if (xDmvrGetEncoderCheckFlag()) diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 439ae9344..8c7c007be 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -2972,13 +2972,13 @@ void EncCu::addRegularCandsToPruningList(const MergeCtx& mergeCtx, const UnitAre #endif { #if JVET_AD0045 - bool enableVisualCheck = false; - if (((m_pcEncCfg->getFrameRate().getFloatVal() <= DMVR_ENC_SELECT_FRAME_RATE_THR) || !(m_pcEncCfg->getDMVREncMvSelectDisableHighestTemporalLayer() && (pu->cu->slice->getTLayer() == (pu->cu->slice->getSPS()->getMaxTLayers() - 1)))) - && m_pcEncCfg->getDMVREncMvSelection() - && (pu->lumaSize().width >= DMVR_ENC_SELECT_SIZE_THR && pu->lumaSize().height >= DMVR_ENC_SELECT_SIZE_THR)) - { - enableVisualCheck = true; // only set this to true when cfg, size, tid, framerate all fulfilled - } + // only set this to true when cfg, size, tid, framerate all fulfilled + const bool enableVisualCheck = (m_pcEncCfg->getFrameRate().getFloatVal() <= DMVR_ENC_SELECT_FRAME_RATE_THR + || !m_pcEncCfg->getDMVREncMvSelectDisableHighestTemporalLayer() + || pu->cu->slice->getTLayer() != pu->cu->slice->getSPS()->getMaxTLayers() - 1) + && m_pcEncCfg->getDMVREncMvSelection() + && pu->lumaSize().width >= DMVR_ENC_SELECT_SIZE_THR + && pu->lumaSize().height >= DMVR_ENC_SELECT_SIZE_THR; m_pcInterSearch->xDmvrSetEncoderCheckFlag(enableVisualCheck); #endif for (uint32_t uiMergeCand = 0; uiMergeCand < mergeCtx.numValidMergeCand; uiMergeCand++) -- GitLab