diff --git a/cfg/per-class/classF.cfg b/cfg/per-class/classF.cfg index b9fbf3fb3dbcbeb349be11d2651488fdb0af669e..7a61bc17ba0823f34f033cf139accdb2ae89bd1b 100644 --- a/cfg/per-class/classF.cfg +++ b/cfg/per-class/classF.cfg @@ -16,3 +16,4 @@ IBCGPM: 1 BvpCluster: 1 IBCBiPred: 0 IBCNonAdjCand: 1 +IBCFilter: 1 \ No newline at end of file diff --git a/source/App/EncoderApp/EncApp.cpp b/source/App/EncoderApp/EncApp.cpp index 734a22232eaf15b721e99c034231b5f42596d088..421aa470dfbc5b66364e2dd2c459cb5450211e09 100644 --- a/source/App/EncoderApp/EncApp.cpp +++ b/source/App/EncoderApp/EncApp.cpp @@ -964,6 +964,9 @@ void EncApp::xInitLibCfg() #if JVET_AC0112_IBC_LIC m_cEncLib.setIbcLic ( m_ibcLic ); #endif +#if JVET_AE0159_FIBC + m_cEncLib.setIbcFilter ( m_ibcFilter ); +#endif #if JVET_AE0169_BIPREDICTIVE_IBC m_cEncLib.setIbcBiPred ( m_ibcBiPred ); #endif diff --git a/source/App/EncoderApp/EncAppCfg.cpp b/source/App/EncoderApp/EncAppCfg.cpp index 9a4def6bd16b2df244f6144b5835c7807117bf5f..c3b680eaf03daf5124e980ca3c77562c2bfc2732 100644 --- a/source/App/EncoderApp/EncAppCfg.cpp +++ b/source/App/EncoderApp/EncAppCfg.cpp @@ -1229,6 +1229,9 @@ bool EncAppCfg::parseCfg( int argc, char* argv[] ) #if JVET_AC0112_IBC_LIC ("IBCLIC", m_ibcLic, true, "IBC LIC mode (0:off, 1:on) [default: on]" ) #endif +#if JVET_AE0159_FIBC + ("IBCFilter", m_ibcFilter, false, "Filtered IBC mode (0:off, 1:on) [default: off]" ) +#endif #if JVET_AE0169_BIPREDICTIVE_IBC ("IBCBiPred", m_ibcBiPred, true, "IBC BiPred mode in I-Slice (0:off, 1:on) [default: on]" ) #endif @@ -5464,6 +5467,9 @@ void EncAppCfg::xPrintParameter() #if JVET_AC0112_IBC_LIC msg( VERBOSE, "IBCLIC:%d ", m_ibcLic ); #endif +#if JVET_AE0159_FIBC + msg( VERBOSE, "IBCFilter:%d ", m_ibcFilter ); +#endif #if JVET_AE0169_BIPREDICTIVE_IBC msg( VERBOSE, "IBCBiPred:%d ", m_ibcBiPred ); #endif diff --git a/source/App/EncoderApp/EncAppCfg.h b/source/App/EncoderApp/EncAppCfg.h index d8dc49c69c9abf5f19156e5d1f57230cbfaf9503..5ca908e396fe778768e911622cabe822abce5bbb 100644 --- a/source/App/EncoderApp/EncAppCfg.h +++ b/source/App/EncoderApp/EncAppCfg.h @@ -542,6 +542,9 @@ protected: #if JVET_AC0112_IBC_LIC bool m_ibcLic; #endif +#if JVET_AE0159_FIBC + bool m_ibcFilter; +#endif #if JVET_AE0169_BIPREDICTIVE_IBC bool m_ibcBiPred; #endif diff --git a/source/Lib/CommonLib/CommonDef.h b/source/Lib/CommonLib/CommonDef.h index e59bf940e969e3219e3c4527383054c72cee2cab..bdae9f2928e1124ebf6c7052048b08a5c3d13d80 100644 --- a/source/Lib/CommonLib/CommonDef.h +++ b/source/Lib/CommonLib/CommonDef.h @@ -1154,7 +1154,11 @@ static const int INTER_CCCM_MAX_REF_SAMPLES = 256; static const int NUM_DBV_POSITION = 5; static const int DBV_TEMPLATE_SIZE = 1; #endif - +#if JVET_AE0159_FIBC +static const int FIBC_TEMPLATE_SIZE = 4; +static const int FIBC_PADDING = 1; +static const int FIBC_PARAMS = 7; +#endif #if JVET_Y0152_TT_ENC_SPEEDUP static constexpr int FAST_METHOD_TT_ENC_SPEEDUP = 0x0001; ///< Embedding flag, which, if false, de-activates all the following ABT_ENC_SPEEDUP_* modes static constexpr int FAST_METHOD_HOR_XOR_VER = 0x0002; diff --git a/source/Lib/CommonLib/ContextModelling.cpp b/source/Lib/CommonLib/ContextModelling.cpp index cf3e26ad1922c3912c26fb237f0e37fb4bdd01e2..888508c23280f273ab6f7a0f8c83a7f88ecc9697 100644 --- a/source/Lib/CommonLib/ContextModelling.cpp +++ b/source/Lib/CommonLib/ContextModelling.cpp @@ -620,6 +620,9 @@ void MergeCtx::setMergeInfo( PredictionUnit& pu, int candIdx ) #if JVET_AC0112_IBC_LIC pu.cu->ibcLicFlag = ibcLicFlags[candIdx]; #endif +#if JVET_AE0159_FIBC + pu.cu->ibcFilterFlag = ibcFilterFlags[candIdx]; +#endif #if JVET_AA0070_RRIBC pu.cu->rribcFlipType = rribcFlipTypes[candIdx]; } @@ -684,6 +687,9 @@ void MergeCtx::setIbcL1Info( PredictionUnit& pu, int candIdx ) pu.refIdx[REF_PIC_LIST_1] = MAX_NUM_REF; pu.cu->ibcLicFlag = 0; pu.cu->rribcFlipType = 0; +#if JVET_AE0159_FIBC + pu.cu->ibcFilterFlag = false; +#endif } #endif @@ -831,6 +837,9 @@ void MergeCtx::initMrgCand(int cnt) #if JVET_AC0112_IBC_LIC ibcLicFlags[cnt] = false; #endif +#if JVET_AE0159_FIBC + ibcFilterFlags[cnt] = false; +#endif #if JVET_AA0070_RRIBC rribcFlipTypes[cnt] = 0; #endif @@ -1774,6 +1783,9 @@ bool MergeCtx::setIbcMbvdMergeCandiInfo(PredictionUnit& pu, int candIdx, int can #if JVET_AC0112_IBC_LIC pu.cu->ibcLicFlag = (pu.interDir == 3) ? false : ibcLicFlags[fPosBaseIdx]; #endif +#if JVET_AE0159_FIBC + pu.cu->ibcFilterFlag = (pu.interDir == 3) ? false : ibcFilterFlags[fPosBaseIdx]; +#endif #if JVET_AA0070_RRIBC pu.cu->rribcFlipType = (pu.interDir == 3) ? 0 : rribcFlipTypes[fPosBaseIdx]; #endif @@ -1781,6 +1793,9 @@ bool MergeCtx::setIbcMbvdMergeCandiInfo(PredictionUnit& pu, int candIdx, int can #if JVET_AC0112_IBC_LIC pu.cu->ibcLicFlag = ibcLicFlags[fPosBaseIdx]; #endif +#if JVET_AE0159_FIBC + pu.cu->ibcFilterFlag = ibcFilterFlags[fPosBaseIdx]; +#endif #if JVET_AA0070_RRIBC pu.cu->rribcFlipType = rribcFlipTypes[fPosBaseIdx]; #endif @@ -1855,3 +1870,18 @@ unsigned DeriveCtx::CtxPltCopyFlag( const unsigned prevRunType, const unsigned d return ucCtxLut[RUN_IDX_THRE]; } } + +#if JVET_AE0159_FIBC +unsigned DeriveCtx::ctxIbcFilterFlag(const CodingUnit& cu) +{ + const CodingStructure *cs = cu.cs; + unsigned ctxId = 0; + const Position pos = cu.chType == CHANNEL_TYPE_CHROMA ? cu.chromaPos() : cu.lumaPos(); + const CodingUnit *cuLeft = cs->getCURestricted(pos.offset(-1, 0), cu, cu.chType); + ctxId += (cuLeft && !cuLeft->firstPU->mergeFlag && (cuLeft->ibcLicFlag || cuLeft->ibcFilterFlag)) ? 1 : 0; + + const CodingUnit *cuAbove = cs->getCURestricted(pos.offset(0, -1), cu, cu.chType); + ctxId += (cuAbove && !cuAbove->firstPU->mergeFlag && (cuAbove->ibcLicFlag || cuAbove->ibcFilterFlag)) ? 1 : 0; + return ctxId; +} +#endif \ No newline at end of file diff --git a/source/Lib/CommonLib/ContextModelling.h b/source/Lib/CommonLib/ContextModelling.h index 049fb897cb9bde099953de31030f2de463175c3e..b47833471ee7a43eb60ba57acab6e13d686b7685 100644 --- a/source/Lib/CommonLib/ContextModelling.h +++ b/source/Lib/CommonLib/ContextModelling.h @@ -564,6 +564,9 @@ public: #if JVET_AC0112_IBC_LIC bool ibcLicFlags[NUM_MERGE_CANDS]; #endif +#if JVET_AE0159_FIBC + bool ibcFilterFlags[NUM_MERGE_CANDS]; +#endif #if JVET_AA0070_RRIBC int rribcFlipTypes[NUM_MERGE_CANDS]; #endif @@ -584,6 +587,9 @@ public: #if JVET_AC0112_IBC_LIC bool ibcLicFlags [ MRG_MAX_NUM_CANDS ]; #endif +#if JVET_AE0159_FIBC + bool ibcFilterFlags [ MRG_MAX_NUM_CANDS ]; +#endif #if JVET_AA0070_RRIBC int rribcFlipTypes[MRG_MAX_NUM_CANDS]; #endif @@ -770,7 +776,9 @@ int ctxSmMvdBin(const int iPreviousBinIsCorrect2, const int iPreviousBinIsCorrec #if JVET_AC0104_IBC_BVD_PREDICTION int CtxSmBvdBin(const int iPreviousBinIsCorrect2, const int iPreviousBinIsCorrect, const int isHor, const int significance); #endif - +#if JVET_AE0159_FIBC +unsigned ctxIbcFilterFlag(const CodingUnit& cu); +#endif } #endif // __CONTEXTMODELLING__ diff --git a/source/Lib/CommonLib/Contexts.cpp b/source/Lib/CommonLib/Contexts.cpp index c2dbf87d9444a63c2defb73ddda001bdd29883c2..3a2c4b845f7d91fe268d627f5e47b38170464e63 100644 --- a/source/Lib/CommonLib/Contexts.cpp +++ b/source/Lib/CommonLib/Contexts.cpp @@ -3218,6 +3218,19 @@ const CtxSet ContextSetCfg::IbcGpmBldIdx = ContextSetCfg::addCtxSet #if JVET_AC0112_IBC_LIC const CtxSet ContextSetCfg::IbcLicFlag = ContextSetCfg::addCtxSet ({ +#if JVET_AE0159_FIBC + { CNU, CNU, CNU, CNU, }, + { CNU, CNU, CNU, CNU, }, + { 27, 25, 26, 12, }, + { DWS, DWS, DWS, DWS, }, + { DWS, DWS, DWS, DWS, }, + { 1, 6, 2, 0, }, + { DWE, DWE, DWE, DWE, }, + { DWE, DWE, DWE, DWE, }, + { 32, 32, 32, 32, }, + { DWO, DWO, DWO, DWO, }, + { DWO, DWO, DWO, DWO, }, +#else { CNU, }, { CNU, }, { CNU, }, @@ -3229,6 +3242,7 @@ const CtxSet ContextSetCfg::IbcLicFlag = ContextSetCfg::addCtxSet { DWE, }, { DWO, }, { DWO, }, +#endif }); #endif diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index 5339df7a691be9db61cbbb2527f466641174145a..2026f527c1ee785f22defeed7d594e13e7b4ee76 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -319,6 +319,13 @@ InterPrediction::InterPrediction() } } #endif +#if JVET_AE0159_FIBC + m_ibcRefBuf = nullptr; + m_a = nullptr; + m_y = nullptr; + m_samples = nullptr; + m_pcIntraPred = nullptr; +#endif } InterPrediction::~InterPrediction() @@ -504,6 +511,13 @@ void InterPrediction::destroy() } } #endif +#if JVET_AE0159_FIBC + m_a = nullptr; + m_y = nullptr; + m_samples = nullptr; + m_pcIntraPred = nullptr; + m_ibcRefBuf = nullptr; +#endif #if JVET_AE0059_INTER_CCCM if (m_interCccm) { @@ -13192,6 +13206,9 @@ void InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u #if JVET_AC0112_IBC_LIC mrgCtxTmp.ibcLicFlags[ui] = false; #endif +#if JVET_AE0159_FIBC + mrgCtxTmp.ibcFilterFlags[ui] = false; +#endif #if JVET_AA0070_RRIBC mrgCtxTmp.rribcFlipTypes[ui] = 0; #endif @@ -13220,6 +13237,9 @@ void InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u #if JVET_AC0112_IBC_LIC mrgCtxTmp.ibcLicFlags[uiMergeCand] = mrgCtx.ibcLicFlags[uiMergeCand]; #endif +#if JVET_AE0159_FIBC + mrgCtxTmp.ibcFilterFlags[uiMergeCand] = mrgCtx.ibcFilterFlags[uiMergeCand]; +#endif #if JVET_AA0070_RRIBC mrgCtxTmp.rribcFlipTypes[uiMergeCand] = mrgCtx.rribcFlipTypes[uiMergeCand]; #endif @@ -13249,6 +13269,9 @@ void InterPrediction::updateIBCCandInfo(PredictionUnit &pu, MergeCtx& mrgCtx, u #if JVET_AC0112_IBC_LIC mrgCtx.ibcLicFlags[uiMergeCand] = mrgCtxTmp.ibcLicFlags[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]]; #endif +#if JVET_AE0159_FIBC + mrgCtx.ibcFilterFlags[uiMergeCand] = mrgCtxTmp.ibcFilterFlags[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand%ADAPTIVE_IBC_SUB_GROUP_SIZE]]; +#endif #if JVET_AA0070_RRIBC mrgCtx.rribcFlipTypes[uiMergeCand] = mrgCtxTmp.rribcFlipTypes[RdCandList[uiMergeCand / ADAPTIVE_IBC_SUB_GROUP_SIZE][uiMergeCand % ADAPTIVE_IBC_SUB_GROUP_SIZE]]; #endif @@ -13529,6 +13552,9 @@ void InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx, #if JVET_AC0112_IBC_LIC mrgCtxTmp.ibcLicFlags[ui] = false; #endif +#if JVET_AE0159_FIBC + mrgCtxTmp.ibcFilterFlags[ui] = false; +#endif #if JVET_AA0070_RRIBC mrgCtxTmp.rribcFlipTypes[ui] = 0; #endif @@ -13551,6 +13577,9 @@ void InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx, #if JVET_AC0112_IBC_LIC mrgCtxTmp.ibcLicFlags[uiMergeCand] = mrgCtx.ibcLicFlags[uiMergeCand]; #endif +#if JVET_AE0159_FIBC + mrgCtxTmp.ibcFilterFlags[uiMergeCand] = mrgCtx.ibcFilterFlags[uiMergeCand]; +#endif #if JVET_AA0070_RRIBC mrgCtxTmp.rribcFlipTypes[uiMergeCand] = mrgCtx.rribcFlipTypes[uiMergeCand]; #endif @@ -13574,6 +13603,9 @@ void InterPrediction::updateIBCCandInfo( PredictionUnit &pu, MergeCtx& mrgCtx, #if JVET_AC0112_IBC_LIC mrgCtx.ibcLicFlags[uiMergeCand] = mrgCtxTmp.ibcLicFlags[RdCandList[uiMergeCand - startPos]]; #endif +#if JVET_AE0159_FIBC + mrgCtx.ibcFilterFlags[uiMergeCand] = mrgCtxTmp.ibcFilterFlags[RdCandList[uiMergeCand - startPos]]; +#endif #if JVET_AA0070_RRIBC mrgCtx.rribcFlipTypes[uiMergeCand] = mrgCtxTmp.rribcFlipTypes[RdCandList[uiMergeCand - startPos]]; #endif @@ -15553,6 +15585,391 @@ void InterPrediction::xGetLICParamGeneral(const CodingUnit& cu, } #endif +#if JVET_AE0159_FIBC +void InterPrediction::setIbcFilterBuffers(Pel (*a)[CCCM_REF_SAMPLES_MAX], Pel* y, Pel* samples, IntraPrediction* pcIntra) +{ + m_pcIntraPred = pcIntra; + m_ibcRefBuf = pcIntra->getCccmBufferLuma(); + m_a = a; + m_y = y; + m_samples = samples; +} +void InterPrediction::xCalIbcFilterParam(PelBuf& piPred, CodingUnit* cu, const ComponentID compID, const Mv& mv, unsigned int uiBlkWidth, unsigned int uiBlkHeight) +{ + CompArea area = cu->blocks[compID]; + xGetIbcFilterRefBuf(piPred, cu, compID, mv, uiBlkWidth, uiBlkHeight); + int areaWidth, areaHeight, refSizeX, refSizeY; + refSizeX = m_ibcRefArea.x; + refSizeY = m_ibcRefArea.y; + areaWidth = m_ibcRefArea.width; + areaHeight = m_ibcRefArea.height; + int refStride = areaWidth + 2 * FIBC_PADDING; // Including paddings required for the 2D filter + int refOrigin = refStride * FIBC_PADDING + FIBC_PADDING; + PelBuf tmpRefBuf = PelBuf(m_ibcRefBuf + refOrigin, refStride, areaWidth, areaHeight); + + CccmModel ibcflmModel(FIBC_PARAMS , cu->cs->sps->getBitDepth(toChannelType(compID))); + + if ((refSizeX == 0) && (refSizeY == 0)) // Number of samples can go to zero in the multimode case + { + ibcflmModel.clearModel(); + for (int i = 0; i < FIBC_PARAMS; i++) + { + cu->ibcFilterParams[i] = ibcflmModel.params[i]; + } + return; + } + + int sampleNum = 0; + + Pel* ref = cu->cs->picture->getRecoBuf(area).buf; // cur Template + int picStride = cu->cs->picture->getRecoBuf(area).stride; + + ref = ref - refSizeY * picStride - refSizeX; + +#if JVET_AB0174_CCCM_DIV_FREE + int offset = 1 << (cu->slice->getSPS()->getBitDepth(toChannelType(compID)) - 1); + if (refSizeX || refSizeY) + { + int refPosX = refSizeX > 0 ? refSizeX - 1 : 0; + int refPosY = refSizeY > 0 ? refSizeY - 1 : 0; + Pel* refOffset = ref + refPosY * picStride + refPosX; + offset = refOffset[0]; + } +#endif + // Collect reference data to input matrix m_a and target vector m_y + for (int y = 0; y < areaHeight; y++) + { + for (int x = 0; x < areaWidth; x++) + { + if (x >= refSizeX && y >= refSizeY) + { + continue; + } + // 7-tap cross + m_a[0][sampleNum] = tmpRefBuf.at(x, y); // C + m_a[1][sampleNum] = tmpRefBuf.at(x, y - 1); // N + m_a[2][sampleNum] = tmpRefBuf.at(x, y + 1); // S + m_a[3][sampleNum] = tmpRefBuf.at(x - 1, y); // W + m_a[4][sampleNum] = tmpRefBuf.at(x + 1, y); // E + m_a[5][sampleNum] = ibcflmModel.nonlinear(tmpRefBuf.at(x, y)); + m_a[6][sampleNum] = ibcflmModel.bias(); + + m_y[sampleNum++] = ref[x]; + } + ref += picStride; + } + + if (!sampleNum) // Number of samples can go to zero in the multimode case + { + ibcflmModel.clearModel(); + } + else + { + m_pcIntraPred->getCccmBufferSolver()->solve1(m_a, m_y, sampleNum, offset, ibcflmModel); + } + + for (int i = 0; i < FIBC_PARAMS; i++) + { + cu->ibcFilterParams[i] = ibcflmModel.params[i]; + } +} + + +void InterPrediction::xGetIbcFilterRefBuf(PelBuf& piPred, CodingUnit* cu, const ComponentID compID, const Mv& bv, unsigned int uiBlkWidth, unsigned int uiBlkHeight) +{ + const int shiftSampleHor = ::getComponentScaleX(compID, cu->chromaFormat); + const int shiftSampleVer = ::getComponentScaleY(compID, cu->chromaFormat); + int pX = bv.getHor() >> (MV_FRACTIONAL_BITS_INTERNAL + shiftSampleHor); + int pY = bv.getVer() >> (MV_FRACTIONAL_BITS_INTERNAL + shiftSampleVer); + + int iOffsetY, iOffsetX; + Pel* refTarget; + + int uiHeight = uiBlkHeight; + int uiWidth = uiBlkWidth; + + Pel* ref = cu->cs->picture->getRecoBuf(cu->cs->picture->blocks[compID]).buf; + int picStride = cu->cs->picture->getRecoBuf(cu->cs->picture->blocks[compID]).stride; + + iOffsetY = pY; + iOffsetX = pX; + refTarget = ref + (cu->blocks[compID].pos().y +iOffsetY) * picStride + (cu->blocks[compID].pos().x + iOffsetX); + + int areaWidth = uiWidth + FIBC_TEMPLATE_SIZE; + int areaHeight = uiHeight + FIBC_TEMPLATE_SIZE; + int refSizeX = 0; + int refSizeY = 0; + + Pel* refTemp = nullptr; + bool paddingTop = true, paddingLeft = true, paddingRight = true, paddingBottom = true; + + const CodingUnit* const cuAbove = cu->cs->getCU(cu->blocks[compID].pos().offset(0, -FIBC_TEMPLATE_SIZE), toChannelType(compID)); + const CodingUnit* const cuLeft = cu->cs->getCU(cu->blocks[compID].pos().offset(-FIBC_TEMPLATE_SIZE, 0), toChannelType(compID)); + bool refBvTopValid = false; + bool refBvLeftValid = false; + bool refBvTopRightValid = false; + bool refBvLeftBottomValid = false; + int filterIdx = 1; + // above + if (cuAbove) + { + Mv mvTop(0, -(FIBC_TEMPLATE_SIZE << (MV_FRACTIONAL_BITS_INTERNAL + shiftSampleVer))); + mvTop += bv; + MotionInfo miTop; + miTop.mv[0] = mvTop; + miTop.refIdx[0] = MAX_NUM_REF; + + if (PU::checkIsIBCFilterCandidateValid(*cu->firstPU, miTop, filterIdx, true, true)) + { + refBvTopValid = true; + } + if (refBvTopValid) + { + Mv mvTop1(0, -((1 + shiftSampleVer) << MV_FRACTIONAL_BITS_INTERNAL)); + mvTop1 += mvTop; + MotionInfo miTop1; + miTop1.mv[0] = mvTop1; + miTop1.refIdx[0] = MAX_NUM_REF; + + if (PU::checkIsIBCFilterCandidateValid(*cu->firstPU, miTop1, filterIdx, true, true)) + { + paddingTop = false; + } + //TopRight + Mv mvTopRight(((1 + shiftSampleVer) << MV_FRACTIONAL_BITS_INTERNAL), 0); + mvTopRight += mvTop; + MotionInfo miTopRight; + miTopRight.mv[0] = mvTopRight; + miTopRight.refIdx[0] = MAX_NUM_REF; + if (PU::checkIsIBCFilterCandidateValid(*cu->firstPU, miTopRight, filterIdx, true, true)) + { + refBvTopRightValid = true; + } + } + } + + //Left + if (cuLeft) + { + Mv mvLeft(-(FIBC_TEMPLATE_SIZE << (MV_FRACTIONAL_BITS_INTERNAL + shiftSampleHor)), 0); + mvLeft += bv; + MotionInfo miLeft; + miLeft.mv[0] = mvLeft; + miLeft.refIdx[0] = MAX_NUM_REF; + if (PU::checkIsIBCFilterCandidateValid(*cu->firstPU, miLeft, filterIdx, true, false)) + { + refBvLeftValid = true; + } + if (refBvLeftValid) + { + Mv mvLeft1(-((1 + shiftSampleHor) << MV_FRACTIONAL_BITS_INTERNAL), 0); + mvLeft1 += mvLeft; + MotionInfo miLeft1; + miLeft1.mv[0] = mvLeft1; + miLeft1.refIdx[0] = MAX_NUM_REF; + if (PU::checkIsIBCFilterCandidateValid(*cu->firstPU, miLeft1, filterIdx, true, false)) + { + paddingLeft = false; + } + //Left-Bottom + Mv mvLeftBot(0, ((1 + shiftSampleHor) << MV_FRACTIONAL_BITS_INTERNAL)); + mvLeftBot += mvLeft; + MotionInfo miLeftBot; + miLeftBot.mv[0] = mvLeftBot; + miLeftBot.refIdx[0] = MAX_NUM_REF; + + if (PU::checkIsIBCFilterCandidateValid(*cu->firstPU, miLeftBot, filterIdx, true, true)) + { + refBvLeftBottomValid = true; + } + } + } + //Right + Mv mvRight(((1 + shiftSampleHor) << MV_FRACTIONAL_BITS_INTERNAL), 0); + mvRight += bv; + MotionInfo miRight; + miRight.mv[0] = mvRight; + miRight.refIdx[0] = MAX_NUM_REF; + if (PU::checkIsIBCFilterCandidateValid(*cu->firstPU, miRight, filterIdx, false, false)) + { + if ((!refBvTopValid) || refBvTopRightValid) + { + paddingRight = false; + } + } + //Bottom + Mv mvBot(0, ((1 + shiftSampleHor) << MV_FRACTIONAL_BITS_INTERNAL)); + mvBot += bv; + MotionInfo miBot; + miBot.mv[0] = mvBot; + miBot.refIdx[0] = MAX_NUM_REF; + + if (PU::checkIsIBCFilterCandidateValid(*cu->firstPU, miBot, filterIdx, false, true)) + { + if ((!refBvLeftValid) || refBvLeftBottomValid) + { + paddingBottom = false; + } + } + + if ((bool)cuAbove && refBvTopValid && (bool)cuLeft && refBvLeftValid ) + { + refSizeX = FIBC_TEMPLATE_SIZE; + refSizeY = FIBC_TEMPLATE_SIZE; + areaWidth = uiWidth + FIBC_TEMPLATE_SIZE; + areaHeight = uiHeight + FIBC_TEMPLATE_SIZE; + refTemp = refTarget - FIBC_TEMPLATE_SIZE * picStride - FIBC_TEMPLATE_SIZE; + } + else if ((bool)cuAbove && refBvTopValid) + { + refSizeX = 0; + refSizeY = FIBC_TEMPLATE_SIZE; + areaWidth = uiWidth; + areaHeight = uiHeight + FIBC_TEMPLATE_SIZE; + refTemp = refTarget - FIBC_TEMPLATE_SIZE * picStride; + } + else if ((bool)cuLeft && refBvLeftValid) + { + refSizeX = FIBC_TEMPLATE_SIZE; + refSizeY = 0; + areaWidth = uiWidth + FIBC_TEMPLATE_SIZE; + areaHeight = uiHeight; + refTemp = refTarget - FIBC_TEMPLATE_SIZE; + } + else + { + refSizeX = 0; + refSizeY = 0; + areaWidth = uiWidth; + areaHeight = uiHeight; + refTemp = refTarget; + m_ibcRefArea = Area(refSizeX, refSizeY, areaWidth, areaHeight); + return; + } + m_ibcRefArea = Area(refSizeX, refSizeY, areaWidth, areaHeight); + + int refStride = areaWidth + 2 * FIBC_PADDING; // Including paddings required for the 2D filter + int refOrigin = refStride * FIBC_PADDING + FIBC_PADDING; + + PelBuf tmpRefBuf = PelBuf(m_ibcRefBuf + refOrigin, refStride, areaWidth, areaHeight); + PelBuf srcRefBuf = PelBuf(refTemp, picStride, areaWidth, areaHeight); + + bool isFracMv = cu->cs->sps->getIBCFracFlag() && (compID == COMPONENT_Y ? bv.isFracMv() : bv.isFracMv<false>(cu->chromaFormat)); + if (isFracMv) + { + int filterIdx = 1; + Mv curMv; + curMv.set(bv.hor + (-refSizeX << MV_FRACTIONAL_BITS_INTERNAL), bv.ver + ((-refSizeY) << MV_FRACTIONAL_BITS_INTERNAL)); + PelUnitBuf pcUnitBuf(cu->chromaFormat, tmpRefBuf, tmpRefBuf, tmpRefBuf); + getPredIBCBlk(*cu->firstPU, compID, cu->slice->getPic(), curMv, pcUnitBuf, filterIdx == 1, true); + } + +#if JVET_AB0174_CCCM_DIV_FREE + int offset = 1 << (cu->slice->getSPS()->getBitDepth(toChannelType(compID)) - 1); + if (refSizeX || refSizeY) + { + int refPosX = refSizeX > 0 ? refSizeX - 1 : 0; + int refPosY = refSizeY > 0 ? refSizeY - 1 : 0; + offset = srcRefBuf.at(refPosX, refPosY); + } +#endif + for (int y = (paddingTop ? 0 : -1); y < (paddingBottom ? areaHeight : areaHeight + 1); y++) + { + for (int x = (paddingLeft ? 0 : -1); x < (paddingRight ? areaWidth : areaWidth + 1); x++) + { +#if JVET_AB0174_CCCM_DIV_FREE + if ((x >= refSizeX) && (y >= refSizeY) && (x < (refSizeX + uiWidth)) && (y < (refSizeY + uiHeight))) + { + tmpRefBuf.at(x, y) = piPred.at(x - refSizeX, y - refSizeY) - offset; + } + else + { + if (isFracMv && (x >= 0) && (y >= 0) && (x < areaWidth) && (y < areaHeight)) + { + tmpRefBuf.at(x, y) = tmpRefBuf.at(x, y) - offset; + } + else + { + tmpRefBuf.at(x, y) = srcRefBuf.at(x, y) - offset; + } + } +#else + tmpRefBuf.at(x, y) = srcRefBuf.at(x, y); +#endif + } + + } + + + // Pad top area + if (paddingTop) + { + for (int x = (paddingLeft ? 0 : -1); x < (paddingRight ? areaWidth : areaWidth + 1); x++) + { + tmpRefBuf.at(x, -1) = tmpRefBuf.at(x, 0); + } + } + // Pad bottom area + if (paddingBottom) + { + for (int x = (paddingLeft ? 0 : -1); x < (paddingRight ? areaWidth : areaWidth + 1); x++) + { + tmpRefBuf.at(x, areaHeight) = tmpRefBuf.at(x, areaHeight - 1); + } + } + + // Pad right area + if (paddingRight) + { + for (int y = -1; y <= areaHeight; y++) + { + tmpRefBuf.at(areaWidth, y) = tmpRefBuf.at(areaWidth - 1, y); + } + } + // Pad left area + if (paddingLeft) + { + for (int y = -1; y <= areaHeight; y++) + { + tmpRefBuf.at(-1, y) = tmpRefBuf.at(0, y); + } + } +} +void InterPrediction::xGenerateIbcFilterPred(PelBuf& piPred, unsigned int uiBlkWidth, unsigned int uiBlkHeight, const ComponentID compID, CodingUnit* cu) +{ + if ((m_ibcRefArea.x == 0) && (m_ibcRefArea.y == 0)) // Number of samples can go to zero in the multimode case + { + return; + } + const ClpRng& clpRng(cu->cs->slice->clpRng(compID)); + CccmModel ibcflmModel( FIBC_PARAMS, cu->cs->sps->getBitDepth(toChannelType(compID))); + memcpy(&ibcflmModel.params[0], &cu->ibcFilterParams[0], FIBC_PARAMS * sizeof(int64_t)); + + // Get Luma Buffer + int refStride = m_ibcRefArea.width + 2 * FIBC_PADDING; // Including paddings required for the 2D filter + int refOrigin = refStride * (m_ibcRefArea.y + FIBC_PADDING) + m_ibcRefArea.x + FIBC_PADDING; + PelBuf tmpRefBuf = PelBuf(m_ibcRefBuf + refOrigin, refStride, uiBlkWidth, uiBlkHeight); + + for (int y = 0; y < tmpRefBuf.height; y++) + { + for (int x = 0; x < tmpRefBuf.width; x++) + { + // 7-tap cross + m_samples[0] = tmpRefBuf.at(x, y); // C + m_samples[1] = tmpRefBuf.at(x, y - 1); // N + m_samples[2] = tmpRefBuf.at(x, y + 1); // S + m_samples[3] = tmpRefBuf.at(x - 1, y); // W + m_samples[4] = tmpRefBuf.at(x + 1, y); // E + m_samples[5] = ibcflmModel.nonlinear(tmpRefBuf.at(x, y)); + m_samples[6] = ibcflmModel.bias(); + + piPred.at(x, y) = ClipPel<Pel>(ibcflmModel.convolve(m_samples), clpRng); + } + } + return; +} +#endif + #if INTER_LIC template <bool trueAfalseL> void InterPrediction::xGetPredBlkTpl(const CodingUnit& cu, const ComponentID compID, const CPelBuf& refBuf, const Mv& mv, const int posW, const int posH, const int tplSize, Pel* predBlkTpl @@ -15643,6 +16060,35 @@ void InterPrediction::xLocalIlluComp(const PredictionUnit& pu, PelBuf& dstBuf ) { +#if JVET_AE0159_FIBC + if ((pu.cu->ibcLicFlag) && (!pu.cu->ibcFilterFlag)) + { +#if JVET_AD0213_LIC_IMP + Pel* refLeftTemplate = m_pcLICRefLeftTemplate[0][compID]; + Pel* refAboveTemplate = m_pcLICRefAboveTemplate[0][compID]; + Pel* recLeftTemplate = m_pcIBCLICRecLeftTemplate[compID]; + Pel* recAboveTemplate = m_pcIBCLICRecAboveTemplate[compID]; +#else + Pel* refLeftTemplate = m_pcLICRefLeftTemplate; + Pel* refAboveTemplate = m_pcLICRefAboveTemplate; + Pel* recLeftTemplate = m_pcLICRecLeftTemplate; + Pel* recAboveTemplate = m_pcLICRecAboveTemplate; +#endif + int numTemplate[2] = { 0 , 0 }; // 0:Above, 1:Left + xGetSublkTemplate(*pu.cu, compID, bv, pu.blocks[compID].width, pu.blocks[compID].height, 0, 0, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate); + + int shift = 0, scale = 0, offset = 0; + xGetLICParamGeneral(*pu.cu, compID, numTemplate, refLeftTemplate, refAboveTemplate, recLeftTemplate, recAboveTemplate, shift, scale, offset); + + const ClpRng& clpRng = pu.cu->cs->slice->clpRng(compID); + dstBuf.linearTransform(scale, shift, offset, true, clpRng); + } + else if ((pu.cu->ibcLicFlag) && (pu.cu->ibcFilterFlag )) + { + xCalIbcFilterParam(dstBuf, pu.cu, compID, bv, pu.blocks[compID].width, pu.blocks[compID].height ); + xGenerateIbcFilterPred(dstBuf, pu.blocks[compID].width, pu.blocks[compID].height, compID, pu.cu); + } +#else #if JVET_AD0213_LIC_IMP Pel* refLeftTemplate = m_pcLICRefLeftTemplate[0][compID]; Pel* refAboveTemplate = m_pcLICRefAboveTemplate[0][compID]; @@ -15662,6 +16108,7 @@ void InterPrediction::xLocalIlluComp(const PredictionUnit& pu, const ClpRng& clpRng = pu.cu->cs->slice->clpRng(compID); dstBuf.linearTransform(scale, shift, offset, true, clpRng); +#endif } void InterPrediction::xGetSublkTemplate(const CodingUnit& cu, @@ -30122,4 +30569,4 @@ inline int InterCccm::computeOffset(const PelBuf &buf) sum += buf.at(0,buf.height-1); return ((sum + 2) >> 2); } -#endif \ No newline at end of file +#endif diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index 791595fe122421b81807554aa1a8ec2187c2a225..982266d33afc9e9c903624ccfbc82024a824f9a0 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -319,6 +319,15 @@ protected: Pel m_acYuvRefAMLBiPredTemplateIdMotionCache[MAX_NUM_REFIDX][NUM_REF_PIC_LIST_01][MAX_NUM_CANDS][2][MAX_CU_SIZE]; #endif +#if JVET_AE0159_FIBC + IntraPrediction* m_pcIntraPred; + Area m_ibcRefArea; + Pel *m_ibcRefBuf; + Pel *m_y; + Pel *m_samples; + Pel (*m_a)[CCCM_REF_SAMPLES_MAX]; +#endif + void xIntraBlockCopy (PredictionUnit &pu, PelUnitBuf &predBuf, const ComponentID compID); int rightShiftMSB(int numer, int denom); #if MULTI_PASS_DMVR @@ -1044,6 +1053,12 @@ public: #if INTER_LIC || JVET_AC0112_IBC_LIC void xGetLICParamGeneral (const CodingUnit& cu, const ComponentID compID, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, int& shift, int& scale, int& offset); #endif +#if JVET_AE0159_FIBC + void xGetIbcFilterRefBuf(PelBuf& piPred, CodingUnit* pcCU, const ComponentID compID, const Mv& mv, unsigned int uiBlkWidth, unsigned int uiBlkHeight ); + void xCalIbcFilterParam(PelBuf& piPred, CodingUnit* pcCU, const ComponentID compID, const Mv& mv, unsigned int uiBlkWidth, unsigned int uiBlkHeight ); + void xGenerateIbcFilterPred(PelBuf& piPred, unsigned int uiBlkWidth, unsigned int uiBlkHeight, const ComponentID compID, CodingUnit* pcCU); + void setIbcFilterBuffers(Pel (*m_a_intra)[CCCM_REF_SAMPLES_MAX], Pel *m_cb_intra,Pel *m_samples_intra, IntraPrediction* pcIntra); +#endif #if INTER_LIC #if JVET_AA0146_WRAP_AROUND_FIX void xGetSublkTemplate (const CodingUnit& cu, const ComponentID compID, const Picture& refPic, const Mv& mv, const int sublkWidth, const int sublkHeight, const int posW, const int posH, int* numTemplate, Pel* refLeftTemplate, Pel* refAboveTemplate, Pel* recLeftTemplate, Pel* recAboveTemplate, bool wrapRef = false); diff --git a/source/Lib/CommonLib/IntraPrediction.h b/source/Lib/CommonLib/IntraPrediction.h index ee89f914b0a5646852be9c588d52199a4b5970fb..359e4f59a17676fa1346a97cc4ddf04351573909 100644 --- a/source/Lib/CommonLib/IntraPrediction.h +++ b/source/Lib/CommonLib/IntraPrediction.h @@ -382,12 +382,16 @@ protected: Pel m_a[CCCM_NUM_PARAMS_MAX][CCCM_REF_SAMPLES_MAX]; Pel m_cb[CCCM_REF_SAMPLES_MAX]; Pel m_cr[CCCM_REF_SAMPLES_MAX]; -#if JVET_AE0059_INTER_CCCM +#if JVET_AE0059_INTER_CCCM || JVET_AE0159_FIBC public: Pel (*getCccmBufferA())[CCCM_REF_SAMPLES_MAX] { return m_a; }; Pel* getCccmBufferCb() { return m_cb; }; Pel* getCccmBufferCr() { return m_cr; }; Pel* getCccmBufferSamples() { return m_samples; }; +#if JVET_AE0159_FIBC + CccmCovariance* getCccmBufferSolver() { return &m_cccmSolver; }; + Pel* getCccmBufferLuma() { return *m_cccmLumaBuf; }; +#endif protected: #endif #endif diff --git a/source/Lib/CommonLib/MotionInfo.h b/source/Lib/CommonLib/MotionInfo.h index 42b3c10a3b60b2f49be8ac5e4ffd5abfac42e94c..01e3a7298c45a138e607401d534fac94334f3293 100644 --- a/source/Lib/CommonLib/MotionInfo.h +++ b/source/Lib/CommonLib/MotionInfo.h @@ -187,6 +187,9 @@ struct MotionInfo #if JVET_AC0112_IBC_LIC bool useIbcLic; #endif +#if JVET_AE0159_FIBC + bool useIbcFilter; +#endif #if JVET_AA0070_RRIBC int rribcFlipType; Position centerPos; diff --git a/source/Lib/CommonLib/Slice.cpp b/source/Lib/CommonLib/Slice.cpp index 12fc9f92f2e55baad462b0a9502b432566be37b3..a92ef3022d9203f2d58f8c8ef3549463d876c91c 100644 --- a/source/Lib/CommonLib/Slice.cpp +++ b/source/Lib/CommonLib/Slice.cpp @@ -3643,6 +3643,9 @@ SPS::SPS() #if JVET_AC0112_IBC_LIC , m_ibcLic ( false ) #endif +#if JVET_AE0159_FIBC + , m_ibcFilter ( false ) +#endif #if JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES , m_ibcNonAdjCand ( false ) #endif diff --git a/source/Lib/CommonLib/Slice.h b/source/Lib/CommonLib/Slice.h index 0748223487ebe64845c708c862efee4b711377e3..65039ea8836d20d2677d876541e1b7a9d48b1ba4 100644 --- a/source/Lib/CommonLib/Slice.h +++ b/source/Lib/CommonLib/Slice.h @@ -1554,6 +1554,9 @@ private: #if JVET_AC0112_IBC_LIC bool m_ibcLic; #endif +#if JVET_AE0159_FIBC + bool m_ibcFilter; +#endif #if JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES bool m_ibcNonAdjCand; #endif @@ -2156,6 +2159,10 @@ void setCCALFEnabledFlag( bool b ) void setUseIbcLic(bool b) { m_ibcLic = b; } bool getUseIbcLic() const { return m_ibcLic; } #endif +#if JVET_AE0159_FIBC + void setUseIbcFilter(bool b) { m_ibcFilter = b; } + bool getUseIbcFilter() const { return m_ibcFilter; } +#endif #if JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES void setUseIbcNonAdjCand(bool b) { m_ibcNonAdjCand = b; } bool getUseIbcNonAdjCand() const { return m_ibcNonAdjCand; } diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index 536625f3d17e44a6f84c4242d97454ed137bb5b7..7719e5081aa2c52255efe0653cbec92a1bb5694f 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -213,6 +213,7 @@ #define JVET_AC0071_DBV 1 // JVET-AC0071: Direct block vector mode for chroma prediction #define JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS 1 // JVET-AD0208: IBC adaptation for camera-captured contents and IBC extension to fractional-pel BV #define JVET_AE0084_IBC_LIC_INHERITANCE 1 // JVET-AE0084: Harmonization of IBC HMVP and IBC-LIC +#define JVET_AE0159_FIBC 1 // JVET-AE0159: Filtered Intra Block Copy (FIBC) #define JVET_AE0169_GPM_IBC_IBC 1 // JVET-AE0169: Bi-predictive IBC GPM #define JVET_AE0169_BIPREDICTIVE_IBC 1 // JVET-AE0169: IBC BVP-merge and bi-predictive IBC merge diff --git a/source/Lib/CommonLib/Unit.cpp b/source/Lib/CommonLib/Unit.cpp index 59c195d5e09bc30f6b52c2ff58835a916fb0813e..49508044105e08bbf9d59d1b38e4d5110f237331 100644 --- a/source/Lib/CommonLib/Unit.cpp +++ b/source/Lib/CommonLib/Unit.cpp @@ -410,6 +410,13 @@ CodingUnit& CodingUnit::operator=( const CodingUnit& other ) #if JVET_AC0112_IBC_LIC ibcLicFlag = other.ibcLicFlag; #endif +#if JVET_AE0159_FIBC + ibcFilterFlag = other.ibcFilterFlag; + if (slice->getSPS()->getUseIbcFilter()) + { + memcpy(ibcFilterParams, other.ibcFilterParams, FIBC_PARAMS * sizeof(int64_t)); + } +#endif #if JVET_AA0070_RRIBC rribcFlipType = other.rribcFlipType; #endif @@ -617,6 +624,13 @@ void CodingUnit::initData() #if JVET_AC0112_IBC_LIC ibcLicFlag = false; #endif +#if JVET_AE0159_FIBC + for (int i = 0; i < FIBC_PARAMS; i++) + { + ibcFilterParams[i] = -1; + } + ibcFilterFlag = false; +#endif #if JVET_AA0070_RRIBC rribcFlipType = 0; #endif diff --git a/source/Lib/CommonLib/Unit.h b/source/Lib/CommonLib/Unit.h index e8c27172190364c6400f1d96dbde35312b143641..412f1442c8f71cb12b744a67d783a0e1746ac7fa 100644 --- a/source/Lib/CommonLib/Unit.h +++ b/source/Lib/CommonLib/Unit.h @@ -422,6 +422,10 @@ struct CodingUnit : public UnitArea #if JVET_AC0112_IBC_LIC bool ibcLicFlag; #endif +#if JVET_AE0159_FIBC + int64_t ibcFilterParams[FIBC_PARAMS]; + bool ibcFilterFlag; +#endif #if JVET_AA0070_RRIBC int rribcFlipType; #endif diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 56d0fcfdb527ad64f17d6209fdc044fdc4cc8683..294f0c81cb44d3233e74ae4cdd0802f487e604b0 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -4128,6 +4128,13 @@ bool PU::addMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const int #else mrgCtx.ibcLicFlags [cnt] = miNeighbor.useIbcLic; #endif +#endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags [cnt] = mrgCtx.rribcFlipTypes[cnt] ? false : miNeighbor.useIbcFilter; +#else + mrgCtx.ibcFilterFlags [cnt] = miNeighbor.useIbcFilter; +#endif #endif mrgCtx.mvFieldNeighbours[cnt << 1].setMvField(miNeighbor.mv[0], miNeighbor.refIdx[0]); @@ -4441,6 +4448,13 @@ bool PU::addIBCMergeHMVPCand(const CodingStructure &cs, MergeCtx &mrgCtx, const #endif #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = mrgCtx.rribcFlipTypes[cnt] == 0 ? miNeighbor.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miNeighbor.useIbcFilter; +#endif +#endif #if !JVET_Z0084_IBC_TM if (slice.isInterB()) { @@ -4601,6 +4615,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #if JVET_AC0112_IBC_LIC mrgCtx.ibcLicFlags[ui] =false; #endif +#if JVET_AE0159_FIBC + mrgCtx.ibcFilterFlags[ui] = false; +#endif #if JVET_AA0070_RRIBC mrgCtx.rribcFlipTypes[ui] = 0; #endif @@ -4688,6 +4705,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #else mrgCtx.ibcLicFlags[cnt] = miLeft.isIBCmot? miLeft.useIbcLic : false; #endif +#endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miLeft.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miLeft.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miLeft.isIBCmot? miLeft.useIbcFilter : false; +#endif #endif if (mrgCandIdx == cnt) { @@ -4748,6 +4772,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #else mrgCtx.ibcLicFlags[cnt] = miLeftL1.isIBCmot? miLeftL1.useIbcLic : false; #endif +#endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miLeftL1.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miLeftL1.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miLeftL1.isIBCmot? miLeftL1.useIbcFilter : false; +#endif #endif if (mrgCandIdx == cnt) { @@ -4830,6 +4861,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miAbove.isIBCmot ? miAbove.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miAbove.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miAbove.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miAbove.isIBCmot ? miAbove.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) ) @@ -4897,6 +4935,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miAboveL1.isIBCmot ? miAboveL1.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miAboveL1.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miAboveL1.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miAboveL1.isIBCmot ? miAboveL1.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) ) @@ -4983,6 +5028,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miAboveRight.isIBCmot? miAboveRight.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miAboveRight.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miAboveRight.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miAboveRight.isIBCmot? miAboveRight.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) ) @@ -5046,6 +5098,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miAboveRightL1.isIBCmot? miAboveRightL1.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miAboveRightL1.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miAboveRightL1.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miAboveRightL1.isIBCmot? miAboveRightL1.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) ) @@ -5128,6 +5187,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miBelowLeft.isIBCmot ? miBelowLeft.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miBelowLeft.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miBelowLeft.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miBelowLeft.isIBCmot ? miBelowLeft.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) ) @@ -5190,6 +5256,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miBelowLeftL1.isIBCmot ? miBelowLeftL1.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miBelowLeftL1.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miBelowLeftL1.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miBelowLeftL1.isIBCmot ? miBelowLeftL1.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) ) @@ -5284,6 +5357,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miAboveLeft.isIBCmot ? miAboveLeft.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miAboveLeft.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miAboveLeft.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miAboveLeft.isIBCmot ? miAboveLeft.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) ) @@ -5347,6 +5427,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miAboveLeftL1.isIBCmot ? miAboveLeftL1.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miAboveLeftL1.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miAboveLeftL1.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miAboveLeftL1.isIBCmot ? miAboveLeftL1.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if( !mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh) ) @@ -5504,6 +5591,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miNonAdjacent.isIBCmot ? miNonAdjacent.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miNonAdjacent.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miNonAdjacent.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miNonAdjacent.isIBCmot ? miNonAdjacent.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if (!mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh)) #endif @@ -5570,6 +5664,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miNonAdjacentL1.isIBCmot ? miNonAdjacentL1.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miNonAdjacentL1.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miNonAdjacentL1.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miNonAdjacentL1.isIBCmot ? miNonAdjacentL1.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if (!mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh)) @@ -5699,6 +5800,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miNonAdjacent.isIBCmot ? miNonAdjacent.useIbcLic : false; #endif #endif +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miNonAdjacent.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miNonAdjacent.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miNonAdjacent.isIBCmot ? miNonAdjacent.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if (!mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh)) #endif @@ -5766,7 +5874,13 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const mrgCtx.ibcLicFlags[cnt] = miNonAdjacentL1.isIBCmot ? miNonAdjacentL1.useIbcLic : false; #endif #endif - +#if JVET_AE0159_FIBC +#if JVET_AA0070_RRIBC + mrgCtx.ibcFilterFlags[cnt] = miNonAdjacentL1.isIBCmot && mrgCtx.rribcFlipTypes[cnt] == 0 ? miNonAdjacentL1.useIbcFilter : false; +#else + mrgCtx.ibcFilterFlags[cnt] = miNonAdjacentL1.isIBCmot ? miNonAdjacentL1.useIbcFilter : false; +#endif +#endif #if JVET_Z0084_IBC_TM if (!mrgCtx.xCheckSimilarIBCMotion(cnt, mvdSimilarityThresh)) #endif @@ -5999,6 +6113,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #if JVET_AC0112_IBC_LIC mrgCtx.ibcLicFlags[cnt] = false; #endif +#if JVET_AE0159_FIBC + mrgCtx.ibcFilterFlags[cnt] = false; +#endif #if JVET_AA0070_RRIBC mrgCtx.rribcFlipTypes[cnt] = 0; #endif @@ -6029,6 +6146,9 @@ void PU::getIBCMergeCandidates(const PredictionUnit &pu, MergeCtx& mrgCtx, const #if JVET_AC0112_IBC_LIC mrgCtx.ibcLicFlags[cnt] = false; #endif +#if JVET_AE0159_FIBC + mrgCtx.ibcFilterFlags[cnt] = false; +#endif #if JVET_AA0070_RRIBC mrgCtx.rribcFlipTypes[cnt] = 0; #endif @@ -6194,6 +6314,16 @@ uint32_t PU::checkValidBv(const PredictionUnit& pu, ComponentID compID, int comp } #endif +#if JVET_AE0159_FIBC +bool PU::checkIsIBCFilterCandidateValid(const PredictionUnit& pu, const MotionInfo miNeighbor, int filterIdx, bool isRefTemplate, bool isRefAbove) +{ + int roiWidth = (isRefTemplate && !isRefAbove) ? FIBC_TEMPLATE_SIZE : pu.lwidth(); + int roiHeight = (isRefTemplate && isRefAbove) ? FIBC_TEMPLATE_SIZE : pu.lheight(); + uint32_t validType = checkValidBv(pu, COMPONENT_Y, roiWidth, roiHeight, miNeighbor.mv[REF_PIC_LIST_0], true, filterIdx); + return validType != IBC_BV_INVALID; +} +#endif + bool PU::searchBv(const PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xBv, int yBv, int ctuSize #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS , int xFilterTap, int yFilterTap, ComponentID compID @@ -7149,6 +7279,9 @@ void PU::getInterMergeCandidates( const PredictionUnit &pu, MergeCtx& mrgCtx, #if JVET_AC0112_IBC_LIC mrgCtx.ibcLicFlags[ui] = false; #endif +#if JVET_AE0159_FIBC + mrgCtx.ibcFilterFlags[ui] = false; +#endif #if JVET_AA0070_RRIBC mrgCtx.rribcFlipTypes[ui] = 0; #endif @@ -19380,6 +19513,9 @@ void PU::spanMotionInfo( PredictionUnit &pu, const MergeCtx &mrgCtx ) #if JVET_AC0112_IBC_LIC mi.useIbcLic = mi.isIBCmot ? pu.cu->ibcLicFlag : 0; #endif +#if JVET_AE0159_FIBC + mi.useIbcFilter = mi.isIBCmot ? pu.cu->ibcFilterFlag : false; +#endif #if JVET_AA0070_RRIBC mi.rribcFlipType = mi.isIBCmot ? pu.cu->rribcFlipType : 0; #endif diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 6c58fbd29c2f29e483d66f14115473d848754c07..55a999e2573550c9e4f4ff407e679391d92de6d0 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -307,6 +307,9 @@ namespace PU , bool checkAllRefValid = false ); #endif +#if JVET_AE0159_FIBC + bool checkIsIBCFilterCandidateValid(const PredictionUnit &pu, const MotionInfo miNeighbor, int filterIdx = 0, bool isRefTemplate = false, bool isRefAbove = false); +#endif #if JVET_Y0058_IBC_LIST_MODIFY || JVET_Z0084_IBC_TM || JVET_AA0061_IBC_MBVD || JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS bool searchBv(const PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xBv, int yBv, int ctuSize #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS diff --git a/source/Lib/DecoderLib/CABACReader.cpp b/source/Lib/DecoderLib/CABACReader.cpp index b40d8aabc1d0b8df72fe0b1a1924ba59e5012c0c..50c0f00f19cfd506f917a7d9d7a894e1af73ee68 100644 --- a/source/Lib/DecoderLib/CABACReader.cpp +++ b/source/Lib/DecoderLib/CABACReader.cpp @@ -4707,6 +4707,46 @@ void CABACReader::ibcGpmAdaptBlendIdx(PredictionUnit& pu) #if JVET_AC0112_IBC_LIC void CABACReader::cuIbcLicFlag( CodingUnit& cu ) { +#if JVET_AE0159_FIBC + if (!(cu.cs->sps->getUseIbcLic() || cu.cs->sps->getUseIbcFilter()) || !CU::isIBC(cu) || cu.firstPU->mergeFlag) + { + cu.ibcLicFlag = false; + return; + } +#if JVET_AA0070_RRIBC + if (cu.rribcFlipType > 0) + { + cu.ibcLicFlag = false; + return; + } +#endif + if (cu.lwidth() * cu.lheight() < 32) + { + cu.ibcLicFlag = false; + return; + } + if ((cu.lx() >= FIBC_TEMPLATE_SIZE || cu.ly() >= FIBC_TEMPLATE_SIZE) && (cu.cs->slice->getSliceType() == I_SLICE) && cu.cs->sps->getUseIbcFilter() ) + { + unsigned ctxIdx = 1 + DeriveCtx::ctxIbcFilterFlag(cu); + cu.ibcFilterFlag = m_BinDecoder.decodeBin(Ctx::IbcLicFlag(ctxIdx)); + } + else + { + cu.ibcFilterFlag = false; + } + if (!cu.ibcFilterFlag && (cu.lwidth() * cu.lheight() <= 256)) + { + cu.ibcLicFlag = m_BinDecoder.decodeBin(Ctx::IbcLicFlag(0)); + } + else if (!cu.ibcFilterFlag) // (cu.lwidth() * cu.lheight() > 256) + { + cu.ibcLicFlag = false; + } + else + { + cu.ibcLicFlag = true; + } +#else if (!cu.cs->sps->getUseIbcLic() || !CU::isIBC(cu) || cu.firstPU->mergeFlag) { cu.ibcLicFlag = false; @@ -4725,6 +4765,7 @@ void CABACReader::cuIbcLicFlag( CodingUnit& cu ) return; } cu.ibcLicFlag = m_BinDecoder.decodeBin( Ctx::IbcLicFlag() ); +#endif } #endif diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 8e32a9b281bc17ab7355f2c7c13a5839184821b4..eb1c1535c7e36eeb37856ec9ca8a68fb67fb1dd0 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -122,6 +122,9 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) #if JVET_AE0059_INTER_CCCM m_pcInterPred->m_interCccm->setCccmBuffers(m_pcIntraPred->getCccmBufferA(),m_pcIntraPred->getCccmBufferCb(),m_pcIntraPred->getCccmBufferCr(),m_pcIntraPred->getCccmBufferSamples()); #endif +#if JVET_AE0159_FIBC + m_pcInterPred->setIbcFilterBuffers(m_pcIntraPred->getCccmBufferA(),m_pcIntraPred->getCccmBufferCb(),m_pcIntraPred->getCccmBufferSamples(), m_pcIntraPred); +#endif #if JVET_Z0118_GDR // reset current IBC Buffer only when VB pass through if (cs.isGdrEnabled() && cs.isInGdrIntervalOrRecoveryPoc()) @@ -3844,6 +3847,9 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) m_pcInterPred->adjustIbcMergeRribcCand(pu, mrgCtx, 0, IBC_MRG_MAX_NUM_CANDS_MEM); pu.cu->rribcFlipType = 0; pu.cu->ibcLicFlag = 0; +#if JVET_AE0159_FIBC + pu.cu->ibcFilterFlag = false; +#endif } #endif pu.cu->imv = imv; diff --git a/source/Lib/DecoderLib/VLCReader.cpp b/source/Lib/DecoderLib/VLCReader.cpp index 3ab589c1f422f6cf178fc0437cdfaf510e5eb43e..be18036c2c114fe7553e666bf93bb285f6109959 100644 --- a/source/Lib/DecoderLib/VLCReader.cpp +++ b/source/Lib/DecoderLib/VLCReader.cpp @@ -2713,6 +2713,9 @@ void HLSyntaxReader::parseSPS(SPS* pcSPS) #if JVET_AC0112_IBC_LIC READ_FLAG( uiCode, "sps_ibc_lic_enabled_flag" ); pcSPS->setUseIbcLic ( uiCode != 0 ); #endif +#if JVET_AE0159_FIBC + READ_FLAG( uiCode, "sps_ibc_filter_enabled_flag" ); pcSPS->setUseIbcFilter ( uiCode != 0 ); +#endif #if JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES READ_FLAG( uiCode, "sps_ibc_non_adjacent_spatial_candidates_enabled_flag"); pcSPS->setUseIbcNonAdjCand(uiCode != 0); #endif diff --git a/source/Lib/EncoderLib/CABACWriter.cpp b/source/Lib/EncoderLib/CABACWriter.cpp index d0e4cad1ae15ec3c462fab935b3563baec149218..61390d5dcb2f88de32ce57ceca99495e675e73a5 100644 --- a/source/Lib/EncoderLib/CABACWriter.cpp +++ b/source/Lib/EncoderLib/CABACWriter.cpp @@ -4206,7 +4206,11 @@ void CABACWriter::ibcGpmAdaptBlendIdx(const int flag) #if JVET_AC0112_IBC_LIC void CABACWriter::cuIbcLicFlag(const CodingUnit& cu) { +#if JVET_AE0159_FIBC + if (!(cu.cs->sps->getUseIbcLic() || cu.cs->sps->getUseIbcFilter() ) || !CU::isIBC(cu) || cu.firstPU->mergeFlag) +#else if (!cu.cs->sps->getUseIbcLic() || !CU::isIBC(cu) || cu.firstPU->mergeFlag) +#endif { return; } @@ -4216,11 +4220,35 @@ void CABACWriter::cuIbcLicFlag(const CodingUnit& cu) return; } #endif +#if JVET_AE0159_FIBC + if (cu.lwidth() * cu.lheight() < 32 ) +#else if (cu.lwidth() * cu.lheight() < 32 || cu.lwidth() * cu.lheight() > 256) +#endif { return; } +#if JVET_AE0159_FIBC + if (cu.ibcFilterFlag) + { + CHECK(!cu.ibcLicFlag, "LIC flag has to be 1 when FIBC is 1"); + } + if (cu.lx() < FIBC_TEMPLATE_SIZE && cu.ly() < FIBC_TEMPLATE_SIZE) + { + CHECK(cu.ibcFilterFlag, "FIBC has to be 0 when not enough template"); + } + if ((cu.lx() >= FIBC_TEMPLATE_SIZE || cu.ly() >= FIBC_TEMPLATE_SIZE) && (cu.cs->slice->getSliceType() == I_SLICE) && cu.cs->sps->getUseIbcFilter() ) + { + unsigned ctxIdx = 1 + DeriveCtx::ctxIbcFilterFlag(cu); + m_BinEncoder.encodeBin(cu.ibcFilterFlag ? 1 : 0, Ctx::IbcLicFlag(ctxIdx)); + } + if (!cu.ibcFilterFlag && (cu.lwidth() * cu.lheight() <= 256)) + { + m_BinEncoder.encodeBin(cu.ibcLicFlag ? 1 : 0, Ctx::IbcLicFlag(0)); + } +#else m_BinEncoder.encodeBin(cu.ibcLicFlag ? 1 : 0, Ctx::IbcLicFlag()); +#endif } #endif diff --git a/source/Lib/EncoderLib/EncCfg.h b/source/Lib/EncoderLib/EncCfg.h index 38ad1487530fd0d26b52461e5a57d17fd90965fe..f38777671e23aca917b76af4363d1169e14d87b8 100644 --- a/source/Lib/EncoderLib/EncCfg.h +++ b/source/Lib/EncoderLib/EncCfg.h @@ -553,6 +553,9 @@ protected: #if JVET_AC0112_IBC_LIC bool m_ibcLic; #endif +#if JVET_AE0159_FIBC + bool m_ibcFilter; +#endif #if JVET_AE0169_BIPREDICTIVE_IBC bool m_ibcBiPred; #endif @@ -1488,6 +1491,10 @@ public: void setIbcLic ( bool b ) { m_ibcLic = b; } bool getIbcLic () const { return m_ibcLic; } #endif +#if JVET_AE0159_FIBC + void setIbcFilter ( bool b ) { m_ibcFilter = b; } + bool getIbcFilter () const { return m_ibcFilter; } +#endif #if JVET_AE0169_BIPREDICTIVE_IBC void setIbcBiPred ( bool b ) { m_ibcBiPred = b; } bool getIbcBiPred () const { return m_ibcBiPred; } diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index f2f30f7cef50289212ad0cc31c047bb9fcb51cf9..998ed1a2079b0524e318befcac764f4a38f0465c 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -12426,6 +12426,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_AC0112_IBC_LIC cu.ibcLicFlag = false; #endif +#if JVET_AE0159_FIBC + cu.ibcFilterFlag = false; +#endif #if JVET_AA0070_RRIBC cu.rribcFlipType = 0; pu.mergeFlag = true; @@ -12656,6 +12659,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct #endif #if JVET_AC0112_IBC_LIC cu.ibcLicFlag = false; +#endif +#if JVET_AE0159_FIBC + cu.ibcFilterFlag = false; #endif cu.geoFlag = false; @@ -14530,6 +14536,9 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct #if JVET_AC0112_IBC_LIC cu.ibcLicFlag = false; #endif +#if JVET_AE0159_FIBC + cu.ibcFilterFlag = false; +#endif #if JVET_AA0070_RRIBC cu.rribcFlipType = 0; @@ -14989,7 +14998,11 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best double curBestCost = bestCS->cost; bool searchedByHash[1] = {false}; Distortion tempCost[1] = {0}; +#if JVET_AE0159_FIBC + Distortion searchCost[3] = {0, 0, 0}; +#else Distortion searchCost[2] = {0, 0}; +#endif #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS m_pcInterSearch->m_bestSrchCostIntBv.init(true); #if JVET_AC0112_IBC_LIC @@ -15014,8 +15027,14 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best #if JVET_AC0112_IBC_LIC bool skipSecondLicPass = false; +#if JVET_AE0159_FIBC + double bestNonLicCost = MAX_DOUBLE; + int licIdxMax = (m_pcEncCfg->getIntraPeriod() == 1) && tempCS->slice->getSPS()->getUseIbcLic() && (tempCS->area.lx() > 0 || tempCS->area.ly() > 0) ? 2 : tempCS->slice->getSPS()->getUseIbcLic() && (tempCS->area.lx() > FIBC_TEMPLATE_SIZE || tempCS->area.ly() > FIBC_TEMPLATE_SIZE) ? 3 : (tempCS->slice->getSPS()->getUseIbcLic() && (tempCS->area.lx() > 0 || tempCS->area.ly() > 0) ? 2 : 1); + if ( tempCS->area.lwidth() * tempCS->area.lheight() < 32 ) +#else int licIdxMax = tempCS->slice->getSPS()->getUseIbcLic() && (tempCS->area.lx() > 0 || tempCS->area.ly() > 0) ? 2 : 1; if (tempCS->area.lwidth() * tempCS->area.lheight() < 32 || tempCS->area.lwidth() * tempCS->area.lheight() > 256) +#endif { licIdxMax = 1; } @@ -15062,6 +15081,12 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best } for (int licIdx = 0; licIdx < licIdxMax; licIdx++) { +#if JVET_AE0159_FIBC + if (licIdx == 1 && tempCS->area.lwidth() * tempCS->area.lheight() > 256) + { + continue; + } +#endif if (licIdx == 1 && skipSecondLicPass) { continue; @@ -15095,7 +15120,27 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best cu.imv = 0; cu.sbtInfo = 0; #if JVET_AC0112_IBC_LIC +#if JVET_AE0159_FIBC + cu.ibcLicFlag = licIdx > 0 ? true: false; + if (m_pcEncCfg->getIntraPeriod() == 1) + { + cu.ibcFilterFlag = false; + } + else + { + cu.ibcFilterFlag = licIdx > 1 ? true : false; + if ( cu.ibcLicFlag && !cu.ibcFilterFlag && tempCS->area.lwidth() * tempCS->area.lheight() > 256) + { + continue; + } + } + if ((licIdx == 2) && ( !tempCS->slice->getSPS()->getUseIbcFilter() || cu.cs->slice->getSliceType() != I_SLICE)) + { + continue; + } +#else cu.ibcLicFlag = licIdx; +#endif #endif CU::addPUs(cu); @@ -15268,6 +15313,19 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best } #endif #endif +#if JVET_AE0159_FIBC + if (tempCS->slice->getSPS()->getUseIbcFilter()) + { + if (!cu.ibcLicFlag) + { + bestNonLicCost = min(dCost, bestNonLicCost); + } + else if (dCost > 1.4 * bestNonLicCost) + { + continue; + } + } +#endif #if JVET_AC0112_IBC_LIC if (licIdx == 0 && searchedByHash[0]) { @@ -15302,7 +15360,11 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best #else searchCost[licIdx] = tempCost[0]; #endif +#if JVET_AE0159_FIBC + if (licIdx > 0 && searchCost[0] > 0 && searchCost[licIdx] > 1.05 * searchCost[0]) +#else if (licIdx > 0 && searchCost[0] > 0 && searchCost[1] > 1.05 * searchCost[0]) +#endif { continue; } @@ -15419,7 +15481,11 @@ void EncCu::xCheckRDCostIBCMode(CodingStructure *&tempCS, CodingStructure *&best } #endif #if JVET_AC0112_IBC_LIC +#if JVET_AE0159_FIBC + if ( !tempCS->slice->getSPS()->getUseIbcFilter() && licIdx == 0 && tempCS->cost > curBestCost * 1.4) +#else if (licIdx == 0 && tempCS->cost > curBestCost * 1.4) +#endif { skipSecondLicPass = true; } diff --git a/source/Lib/EncoderLib/EncLib.cpp b/source/Lib/EncoderLib/EncLib.cpp index a54e330dd3697d930f4c665422ec30c4803e2b3d..11fac02b8d19c4c56e5b0c11cbff34f8aec367ea 100644 --- a/source/Lib/EncoderLib/EncLib.cpp +++ b/source/Lib/EncoderLib/EncLib.cpp @@ -753,6 +753,9 @@ void EncLib::init( bool isFieldCoding, AUWriterIf* auWriterIf ) #if JVET_AE0059_INTER_CCCM m_cInterSearch.m_interCccm->setCccmBuffers(m_cIntraSearch.getCccmBufferA(),m_cIntraSearch.getCccmBufferCb(),m_cIntraSearch.getCccmBufferCr(),m_cIntraSearch.getCccmBufferSamples()); +#endif +#if JVET_AE0159_FIBC + m_cInterSearch.setIbcFilterBuffers(m_cIntraSearch.getCccmBufferA(),m_cIntraSearch.getCccmBufferCb(),m_cIntraSearch.getCccmBufferSamples(), &m_cIntraSearch); #endif m_iMaxRefPicNum = 0; @@ -1943,6 +1946,9 @@ void EncLib::xInitSPS( SPS& sps ) #if JVET_AC0112_IBC_LIC sps.setUseIbcLic ( m_ibcLic ); #endif +#if JVET_AE0159_FIBC + sps.setUseIbcFilter ( m_ibcFilter ); +#endif #if JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES sps.setUseIbcNonAdjCand ( m_ibcNonAdjCand ); #endif diff --git a/source/Lib/EncoderLib/EncSlice.cpp b/source/Lib/EncoderLib/EncSlice.cpp index 0231639449b7320f9af15cdbc325989e104c2151..473babd859c22ed94e432adc19699c46ad3093b0 100644 --- a/source/Lib/EncoderLib/EncSlice.cpp +++ b/source/Lib/EncoderLib/EncSlice.cpp @@ -1857,6 +1857,15 @@ void EncSlice::encodeCtus( Picture* pcPic, const bool bCompressEntireSlice, cons } } #endif +#if JVET_AE0159_FIBC + if (m_pcCuEncoder->getEncCfg()->getIbcFilter()) + { + SPS* spsTmp = const_cast<SPS*>(cs.sps); + hashBlkHitPerc = (hashBlkHitPerc == -1) ? m_pcCuEncoder->getIbcHashMap().calHashBlkMatchPerc(cs.area.Y()) : hashBlkHitPerc; + bool isSCC = hashBlkHitPerc >= 20; + spsTmp->setUseIbcFilter(isSCC); + } +#endif #if JVET_AD0188_CCP_MERGE if ((pCfg->getSwitchPOC() != pcPic->poc || -1 == pCfg->getDebugCTU())) { diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 2192f49efc6dec7fd5e557badb142b65f7b0dccc..9a6be749f330605e6f827f60baf688f635238d42 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -2487,8 +2487,16 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Mv *pc m_cDistParam.useMR = false; #if JVET_AC0112_IBC_LIC +#if JVET_AE0159_FIBC + PelUnitBuf predBuf = pu.cs->getPredBuf(pu); + if (!pu.cs->sps->getUseIbcFilter()) + { + m_cDistParam.useMR = pu.cu->ibcLicFlag ? true : false ; + } +#else m_cDistParam.useMR = pu.cu->ibcLicFlag; #endif +#endif #if !JVET_AA0070_RRIBC m_pcRdCost->setDistParam(m_cDistParam, *cStruct.pcPatternKey, cStruct.piRefY, cStruct.iRefStride, m_lumaClpRng.bd, COMPONENT_Y, cStruct.subShiftMode); #endif @@ -2800,7 +2808,29 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Mv *pc buffered = true; Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xBv, yBv, pu.cs->sps->getAMVREnabledFlag()); #endif +#if JVET_AE0159_FIBC + if (pu.cs->sps->getUseIbcFilter()) + { + if (pu.cu->ibcLicFlag) + { + pu.mv[0] = Mv((xBv << MV_FRACTIONAL_BITS_INTERNAL), (yBv << MV_FRACTIONAL_BITS_INTERNAL)); + getPredIBCBlk(pu, COMPONENT_Y, pu.cu->slice->getPic(), pu.mv[0], predBuf, false); + m_cDistParam.cur.buf = predBuf.Y().buf; + m_cDistParam.cur.stride = predBuf.Y().stride; + } + else + { + m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yBv + xBv; + m_cDistParam.cur.stride = cStruct.iRefStride; + } + } + else + { + m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yBv + xBv; + } +#else m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yBv + xBv; +#endif #if JVET_AE0169_BIPREDICTIVE_IBC sad += ((m_cDistParam.distFunc(m_cDistParam)+sadAdd)>>sadShift); #else @@ -2922,7 +2952,29 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, Mv *pc #else Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getAMVREnabledFlag()); #endif +#if JVET_AE0159_FIBC + if (pu.cs->sps->getUseIbcFilter()) + { + if (pu.cu->ibcLicFlag) + { + pu.mv[0] = Mv((xPred << MV_FRACTIONAL_BITS_INTERNAL), (yPred << MV_FRACTIONAL_BITS_INTERNAL)); + getPredIBCBlk(pu, COMPONENT_Y, pu.cu->slice->getPic(), pu.mv[0], predBuf, false); + m_cDistParam.cur.buf = predBuf.Y().buf; + m_cDistParam.cur.stride = predBuf.Y().stride; + } + else + { + m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yPred + xPred; + m_cDistParam.cur.stride = cStruct.iRefStride; + } + } + else + { + m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yPred + xPred; + } +#else m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yPred + xPred; +#endif #if JVET_AE0169_BIPREDICTIVE_IBC sad += ((m_cDistParam.distFunc(m_cDistParam)+sadAdd)>>sadShift); #else @@ -3506,6 +3558,9 @@ bool InterSearch::predIBCSearch(CodingUnit& cu, Partitioner& partitioner, const pu.interDir = 1; pu.mergeFlag = false; pu.cu->ibcLicFlag = 0; +#if JVET_AE0159_FIBC + pu.cu->ibcFilterFlag = false; +#endif } #endif pu.cu->rribcFlipType = 0; @@ -4197,7 +4252,14 @@ Distortion InterSearch::xPredIBCFracPelSearch(PredictionUnit& pu PelUnitBuf predBuf = pu.cs->getPredBuf(pu); DistParam distParam; #if JVET_AC0112_IBC_LIC +#if JVET_AE0159_FIBC + if (!pu.cs->sps->getUseIbcFilter()) + { + distParam.useMR = pu.cu->ibcLicFlag ? true : false ; + } +#else distParam.useMR = pu.cu->ibcLicFlag; +#endif #endif m_pcRdCost->setDistParam(distParam, tmpOrgLuma[0], predBuf.Y().buf, predBuf.Y().stride, pu.cs->sps->getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y, 0, 1, false); m_pcRdCost->getMotionCost(0); @@ -4205,6 +4267,112 @@ Distortion InterSearch::xPredIBCFracPelSearch(PredictionUnit& pu for (int i = 0; i < intBvList.cnt; ++i) { +#if JVET_AE0159_FIBC + if (m_pcEncCfg->getIntraPeriod() != 1) //non-AI + { + pu.cu->imv = IMV_FPEL; + pu.bv = intBvList.mvList[i]; + pu.mv[0] = intBvList.mvList[i]; + pu.mv[0].changePrecision(MV_PRECISION_INT, MV_PRECISION_INTERNAL); +#if JVET_AC0112_IBC_LIC + if (pu.cu->ibcLicFlag) + { + getPredIBCBlk(pu, COMPONENT_Y, pu.cu->slice->getPic(), pu.mv[0], predBuf, useBilinearMC); + distParam.cur.buf = predBuf.Y().buf; + distParam.cur.stride = predBuf.Y().stride; + } + else +#endif + { + Position offset = pu.Y().pos().offset(pu.bv.getHor(), pu.bv.getVer()); + CPelBuf refBuf = pu.cu->slice->getPic()->getRecoBuf(CompArea(COMPONENT_Y, pu.chromaFormat, offset, Size(pu.lwidth(), pu.lheight())), false); + distParam.cur.buf = refBuf.buf; + distParam.cur.stride = refBuf.stride; + } +#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV || JVET_AA0070_RRIBC + int bvType = intBvList.bvTypeList[i]; +#else + int bvType = 0; +#endif +#if JVET_AE0169_BIPREDICTIVE_IBC + if (pu.interDir == 3) + { +#if JVET_AA0070_RRIBC + tmpOrgLuma[0] = tmpOrgBvpMerge[i]; +#else + distParam.org = tmpOrgBvpMerge[i]; +#endif + } +#endif +#if JVET_AA0070_RRIBC +#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV + distParam.org = tmpOrgLuma[intBvList.bvFlipList[i] ? bvType : 0]; +#else + distParam.org = tmpOrgLuma[bvType]; +#endif +#endif + + uint32_t addExtraBits = 1 + bvType +#if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC + + (bvType == 0 ? 0 : (intBvList.bvFlipList[i] ? 2 : 0)) +#endif + ; + bool has4PelIMV = (pu.bv.getHor() & 3) == 0 && (pu.bv.getVer() & 3) == 0; +#if JVET_AE0169_BIPREDICTIVE_IBC + uint8_t tempMvpIdx[3] = { 0, 0, 0 }; + Distortion tempBvCost[3] = + { + m_pcRdCost->getBvCostSingle(pu.mv[0], amvpInfoList[IMV_OFF][bvType], IMV_OFF, imvForZeroMvd, bvType == 2, bvType == 1, addExtraBits, tempMvpIdx[0]), + m_pcRdCost->getBvCostSingle(pu.mv[0], amvpInfoList[IMV_FPEL][bvType], IMV_FPEL, imvForZeroMvd, bvType == 2, bvType == 1, addExtraBits, tempMvpIdx[1]), + has4PelIMV ? m_pcRdCost->getBvCostSingle(pu.mv[0], amvpInfoList[IMV_4PEL][bvType], IMV_4PEL, imvForZeroMvd, bvType == 2, bvType == 1, addExtraBits, tempMvpIdx[2]) : std::numeric_limits<Distortion>::max() + }; +#if JVET_AE0169_BIPREDICTIVE_IBC + if (pu.interDir == 3) + { + tempBvCost[0] += m_pcRdCost->getBvpMergeCost(intBvList.mergeIdxList[i]); + tempBvCost[1] += m_pcRdCost->getBvpMergeCost(intBvList.mergeIdxList[i]); + if (has4PelIMV) + { + tempBvCost[2] += m_pcRdCost->getBvpMergeCost(intBvList.mergeIdxList[i]); + } + } +#endif + uint8_t bestIdx = (tempBvCost[2] < tempBvCost[1] && tempBvCost[2] < tempBvCost[0]) ? 2 : (tempBvCost[1] < tempBvCost[0]) ? 1 : 0; + intBvList.imvList [i] = ImvMode(bestIdx); +#else + uint8_t tempMvpIdx[2] = { 0, 0 }; + Distortion tempBvCost[2] = + { + m_pcRdCost->getBvCostSingle(pu.mv[0], amvpInfoList[IMV_FPEL][bvType], IMV_FPEL, imvForZeroMvd, bvType == 2, bvType == 1, addExtraBits, tempMvpIdx[0]), + has4PelIMV ? m_pcRdCost->getBvCostSingle(pu.mv[0], amvpInfoList[IMV_4PEL][bvType], IMV_4PEL, imvForZeroMvd, bvType == 2, bvType == 1, addExtraBits, tempMvpIdx[1]) : std::numeric_limits<Distortion>::max() + }; +#if JVET_AE0169_BIPREDICTIVE_IBC + if (pu.interDir == 3) + { + tempBvCost[0] += m_pcRdCost->getBvpMergeCost(intBvList.mergeIdxList[i]); + if (has4PelIMV) + { + tempBvCost[1] += m_pcRdCost->getBvpMergeCost(intBvList.mergeIdxList[i]); + } + } +#endif + uint8_t bestIdx = tempBvCost[1] < tempBvCost[0] ? 1 : 0; + intBvList.imvList[i] = bestIdx == 0 ? IMV_FPEL : IMV_4PEL; +#endif + intBvList.mvpIdxList[i] = tempMvpIdx[bestIdx]; + intBvList.costList[i] = tempBvCost[bestIdx] + distParam.distFunc(distParam); + intBvList.mvList[i] = pu.mv[0]; + } + else + { + const int ibcLicLoopNum = pu.cu->ibcLicFlag && pu.cs->sps->getUseIbcFilter() && (pu.cu->slice->getSliceType() == I_SLICE) ? 2 : 1; + int bestLicIdc = 0; + Distortion bestLicCost = MAX_UINT64; + for (int licIdc = 0; licIdc < ibcLicLoopNum; licIdc++) + { + pu.cu->ibcFilterFlag = licIdc > 0 ? true: false; +#endif + pu.cu->imv = IMV_FPEL; pu.bv = intBvList.mvList[i]; pu.mv[0] = intBvList.mvList[i]; @@ -4275,7 +4443,24 @@ Distortion InterSearch::xPredIBCFracPelSearch(PredictionUnit& pu } } #endif - +#if JVET_AE0159_FIBC + if (pu.cu->ibcLicFlag ) + { + uint8_t bestIdx = (tempBvCost[2] < tempBvCost[1] && tempBvCost[2] < tempBvCost[0]) ? 2 : (tempBvCost[1] < tempBvCost[0]) ? 1 : 0; + m_bestSrchCostIbcFilter.imvList[licIdc] = ImvMode(bestIdx); + m_bestSrchCostIbcFilter.mvpIdxList[licIdc] = tempMvpIdx[bestIdx]; + m_bestSrchCostIbcFilter.costList[licIdc] = tempBvCost[bestIdx] + distParam.distFunc(distParam); + m_bestSrchCostIbcFilter.mvList[licIdc] = pu.mv[0]; + Distortion currCost = licIdc == 0 ? Distortion(m_bestSrchCostIbcFilter.costList[licIdc] * 0.95) : m_bestSrchCostIbcFilter.costList[licIdc]; + if (currCost < bestLicCost) + { + bestLicIdc = licIdc; + bestLicCost = currCost; + } + } + else + { +#endif uint8_t bestIdx = (tempBvCost[2] < tempBvCost[1] && tempBvCost[2] < tempBvCost[0]) ? 2 : (tempBvCost[1] < tempBvCost[0]) ? 1 : 0; intBvList.imvList [i] = ImvMode(bestIdx); #else @@ -4302,7 +4487,22 @@ Distortion InterSearch::xPredIBCFracPelSearch(PredictionUnit& pu intBvList.mvpIdxList[i] = tempMvpIdx[bestIdx]; intBvList.costList [i] = tempBvCost[bestIdx] + distParam.distFunc(distParam); intBvList.mvList [i] = pu.mv[0]; +#if JVET_AE0159_FIBC + } +#endif + } +#if JVET_AE0159_FIBC } + if (pu.cu->ibcLicFlag) + { + intBvList.imvList[i] = m_bestSrchCostIbcFilter.imvList[bestLicIdc]; + intBvList.mvpIdxList[i] = m_bestSrchCostIbcFilter.mvpIdxList[bestLicIdc]; + intBvList.costList[i] = m_bestSrchCostIbcFilter.costList[bestLicIdc]; + intBvList.mvList[i] = m_bestSrchCostIbcFilter.mvList[bestLicIdc]; + intBvList.bvFilter[i] = bestLicIdc; + } + } +#endif } distParam.cur.buf = predBuf.Y().buf; distParam.cur.stride = predBuf.Y().stride; @@ -4324,6 +4524,12 @@ Distortion InterSearch::xPredIBCFracPelSearch(PredictionUnit& pu #if JVET_AA0070_RRIBC && JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV bool& bestFlipMode = intBvList.bvFlipList[candIdx]; #endif +#if JVET_AE0159_FIBC + if (pu.cs->sps->getUseIbcFilter() && m_pcEncCfg->getIntraPeriod() == 1) + { + pu.cu->ibcFilterFlag = intBvList.bvFilter[candIdx]; + } +#endif pu.cu->imv = imv; const Mv centerMv = bestMv; @@ -4516,6 +4722,12 @@ Distortion InterSearch::xPredIBCFracPelSearch(PredictionUnit& pu #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV pu.cu->rribcFlipType = intBvList.bvFlipList[bestCandIdx] ? pu.cu->rribcFlipType : 0; #endif +#endif +#if JVET_AE0159_FIBC + if (pu.cs->sps->getUseIbcFilter() && m_pcEncCfg->getIntraPeriod() == 1) + { + pu.cu->ibcFilterFlag = pu.cu->ibcLicFlag ? intBvList.bvFilter[bestCandIdx] : 0; + } #endif pu.cu->imv = intBvList.imvList [bestCandIdx]; diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h index 10b005c5e8798f3eb3bc8b7e4c74b621834399de..110bb6af18459586d22b91671337e3edaee930ec 100644 --- a/source/Lib/EncoderLib/InterSearch.h +++ b/source/Lib/EncoderLib/InterSearch.h @@ -413,6 +413,9 @@ struct SrchCostBv #if JVET_AA0070_RRIBC && JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV bool bvFlipList[capacity]; #endif +#if JVET_AE0159_FIBC + bool bvFilter[capacity]; +#endif SrchCostBv() : cnt (0) @@ -430,6 +433,9 @@ struct SrchCostBv if (resetHistoryMv) { mvList[maxSize].setZero(); +#if JVET_AE0159_FIBC + bvFilter[maxSize] = false; +#endif } } @@ -635,6 +641,9 @@ private: PelStorage m_tmpStorageCUflipV; public: SrchCostIntBv m_bestSrchCostIntBv; +#if JVET_AE0159_FIBC + SrchCostIntBv m_bestSrchCostIbcFilter; +#endif private: #endif PelStorage m_tmpAffiStorage; diff --git a/source/Lib/EncoderLib/VLCWriter.cpp b/source/Lib/EncoderLib/VLCWriter.cpp index a101845d880e5a0b5df33bf6b16c454425fb2f0a..75784221cd2c3441a2b270bc0d1c4e445248d3ab 100644 --- a/source/Lib/EncoderLib/VLCWriter.cpp +++ b/source/Lib/EncoderLib/VLCWriter.cpp @@ -1752,6 +1752,9 @@ void HLSWriter::codeSPS( const SPS* pcSPS ) #if JVET_AC0112_IBC_LIC WRITE_FLAG( pcSPS->getUseIbcLic() ? 1 : 0, "sps_ibc_lic_enabled_flag" ); #endif +#if JVET_AE0159_FIBC + WRITE_FLAG( pcSPS->getUseIbcFilter() ? 1 : 0, "sps_ibc_filter_enabled_flag" ); +#endif #if JVET_AE0094_IBC_NONADJACENT_SPATIAL_CANDIDATES WRITE_FLAG(pcSPS->getUseIbcNonAdjCand() ? 1 : 0, "sps_ibc_non_adjacent_spatial_candidates_enabled_flag"); #endif