diff --git a/source/Lib/CommonLib/CodingStructure.h b/source/Lib/CommonLib/CodingStructure.h index aa41d96111a05bcd4ef733a685e2dc232ec67569..db56903aa1a01590686b33e8729793912e17a96e 100644 --- a/source/Lib/CommonLib/CodingStructure.h +++ b/source/Lib/CommonLib/CodingStructure.h @@ -195,6 +195,10 @@ public: LutMotionCand motionLut; +#if JVET_O1170_CHECK_BV_AT_DECODER + bool resetIBCBuffer; +#endif + void addMiToLut(static_vector<MotionInfo, MAX_NUM_HMVP_CANDS>& lut, const MotionInfo &mi); private: diff --git a/source/Lib/CommonLib/InterPrediction.cpp b/source/Lib/CommonLib/InterPrediction.cpp index e785c83a72d1ece2fa32fb945cef25c07198d501..2cc44e815a7c488e99dc943020d53f7bf583bd5e 100644 --- a/source/Lib/CommonLib/InterPrediction.cpp +++ b/source/Lib/CommonLib/InterPrediction.cpp @@ -146,9 +146,16 @@ void InterPrediction::destroy() xFree(m_cRefSamplesDMVRL1[ch]); m_cRefSamplesDMVRL1[ch] = nullptr; } +#if JVET_O1170_IBC_VIRTUAL_BUFFER + m_IBCBuffer.destroy(); +#endif } +#if JVET_O1170_IBC_VIRTUAL_BUFFER +void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize ) +#else void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC ) +#endif { m_pcRdCost = pcRdCost; @@ -214,6 +221,13 @@ void InterPrediction::init( RdCost* pcRdCost, ChromaFormat chromaFormatIDC ) const int MVBUFFER_SIZE = MAX_CU_SIZE / MIN_PU_SIZE; m_storedMv = new Mv[MVBUFFER_SIZE*MVBUFFER_SIZE]; } +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (m_IBCBuffer.bufs.empty()) + { + m_IBCBufferWidth = 128 * 128 / ctuSize; + m_IBCBuffer.create(UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, ctuSize))); + } +#endif } // ==================================================================================================================== @@ -1306,6 +1320,22 @@ void InterPrediction::motionCompensation( PredictionUnit &pu, PelUnitBuf &predBu CHECK(predBufWOBIO && pu.mhIntraFlag, "the case should not happen!"); #endif +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (!pu.cs->pcv->isEncoder) + { + if (CU::isIBC(*pu.cu)) + { + CHECK(!luma, "IBC only for Chroma is not allowed."); + xIntraBlockCopy(pu, predBuf, COMPONENT_Y); + if (chroma) + { + xIntraBlockCopy(pu, predBuf, COMPONENT_Cb); + xIntraBlockCopy(pu, predBuf, COMPONENT_Cr); + } + return; + } + } +#endif // dual tree handling for IBC as the only ref if ((!luma || !chroma) && eRefPicList == REF_PIC_LIST_0) { @@ -2368,4 +2398,169 @@ void InterPrediction::cacheAssign( CacheModel *cache ) } #endif +#if JVET_O1170_IBC_VIRTUAL_BUFFER +void InterPrediction::xFillIBCBuffer(CodingUnit &cu) +{ + for (auto &currPU : CU::traverseTUs(cu)) + { + for (const CompArea &area : currPU.blocks) + { + if (!area.valid()) continue;; + + const unsigned int lcuWidth = cu.cs->slice->getSPS()->getMaxCUWidth(); + int shiftSample = ::getComponentScaleX(area.compID, cu.chromaFormat); + const int ctuSizeLog2 = g_aucLog2[lcuWidth] - shiftSample; + const int pux = area.x & ((m_IBCBufferWidth >> shiftSample) - 1); + const int puy = area.y & (( 1 << ctuSizeLog2 ) - 1); + assert(area.width <= (1 << ctuSizeLog2)); + assert(puy + area.height <= (1 << ctuSizeLog2)); + assert(pux + area.width <= (m_IBCBufferWidth >> shiftSample)); + const CompArea dstArea = CompArea(area.compID, cu.chromaFormat, Position(pux, puy), Size(area.width, area.height)); + CPelBuf srcBuf = cu.cs->getRecoBuf(area); + PelBuf dstBuf = m_IBCBuffer.getBuf(dstArea); + dstBuf.copyFrom(srcBuf); + } + } +} + +void InterPrediction::xIntraBlockCopy(PredictionUnit &pu, PelUnitBuf &predBuf, const ComponentID compID) +{ + const unsigned int lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth(); + int shiftSample = ::getComponentScaleX(compID, pu.chromaFormat); + const int ctuSizeLog2 = g_aucLog2[lcuWidth] - shiftSample; + pu.bv = pu.mv[REF_PIC_LIST_0]; + pu.bv.changePrecision(MV_PRECISION_INTERNAL, MV_PRECISION_INT); + int refx, refy; + if (compID == COMPONENT_Y) + { + refx = pu.Y().x + pu.bv.hor; + refy = pu.Y().y + pu.bv.ver; + } + else + {//Cb or Cr + refx = pu.Cb().x + (pu.bv.hor >> shiftSample); + refy = pu.Cb().y + (pu.bv.ver >> shiftSample); + } + refx &= ((m_IBCBufferWidth >> shiftSample) - 1); + refy &= ((1 << ctuSizeLog2) - 1); + + if (compID == COMPONENT_Y) + { + if (refx + predBuf.Y().width <= (m_IBCBufferWidth >> shiftSample)) + { + const CompArea srcArea = CompArea(compID, pu.chromaFormat, Position(refx, refy), Size(predBuf.Y().width, predBuf.Y().height)); + const CPelBuf refBuf = m_IBCBuffer.getBuf(srcArea); + predBuf.Y().copyFrom(refBuf); + } + else + {//wrap around + { + int width = (m_IBCBufferWidth >> shiftSample) - refx; + const CompArea srcArea = CompArea(compID, pu.cu->chromaFormat, Position(refx, refy), Size(width, predBuf.Y().height)); + CPelBuf srcBuf = m_IBCBuffer.getBuf(srcArea); + PelBuf dstBuf = PelBuf(predBuf.Y().bufAt(Position(0, 0)), predBuf.Y().stride, Size(width, predBuf.Y().height)); + dstBuf.copyFrom(srcBuf); + } + { + int width = refx + predBuf.Y().width - (m_IBCBufferWidth >> shiftSample); + const CompArea srcArea = CompArea(compID, pu.cu->chromaFormat, Position(0, refy), Size(width, predBuf.Y().height)); + CPelBuf srcBuf = m_IBCBuffer.getBuf(srcArea); + PelBuf dstBuf = PelBuf(predBuf.Y().bufAt(Position((m_IBCBufferWidth >> shiftSample) - refx, 0)), predBuf.Y().stride, Size(width, predBuf.Y().height)); + dstBuf.copyFrom(srcBuf); + } + } + } + else + { + if (compID == COMPONENT_Cb) + {//Cb + if (refx + predBuf.Cb().width <= (m_IBCBufferWidth >> shiftSample)) + { + const CompArea srcArea = CompArea(compID, pu.chromaFormat, Position(refx, refy), Size(predBuf.Cb().width, predBuf.Cb().height)); + const CPelBuf refBuf = m_IBCBuffer.getBuf(srcArea); + predBuf.Cb().copyFrom(refBuf); + } + else + {//wrap around + { + int width = (m_IBCBufferWidth >> shiftSample) - refx; + const CompArea srcArea = CompArea(compID, pu.cu->chromaFormat, Position(refx, refy), Size(width, predBuf.Cb().height)); + CPelBuf srcBuf = m_IBCBuffer.getBuf(srcArea); + PelBuf dstBuf = PelBuf(predBuf.Cb().bufAt(Position(0, 0)), predBuf.Cb().stride, Size(width, predBuf.Cb().height)); + dstBuf.copyFrom(srcBuf); + } + { + int width = refx + predBuf.Cb().width - (m_IBCBufferWidth >> shiftSample); + const CompArea srcArea = CompArea(compID, pu.cu->chromaFormat, Position(0, refy), Size(width, predBuf.Cb().height)); + CPelBuf srcBuf = m_IBCBuffer.getBuf(srcArea); + PelBuf dstBuf = PelBuf(predBuf.Cb().bufAt(Position((m_IBCBufferWidth >> shiftSample) - refx, 0)), predBuf.Cb().stride, Size(width, predBuf.Cb().height)); + dstBuf.copyFrom(srcBuf); + } + } + } + else + {//Cr + if (refx + predBuf.Cb().width <= (m_IBCBufferWidth >> shiftSample)) + { + const CompArea srcArea = CompArea(compID, pu.chromaFormat, Position(refx, refy), Size(predBuf.Cr().width, predBuf.Cr().height)); + const CPelBuf refBuf = m_IBCBuffer.getBuf(srcArea); + predBuf.Cr().copyFrom(refBuf); + } + else + {//wrap around + { + int width = (m_IBCBufferWidth >> shiftSample) - refx; + const CompArea srcArea = CompArea(compID, pu.cu->chromaFormat, Position(refx, refy), Size(width, predBuf.Cr().height)); + CPelBuf srcBuf = m_IBCBuffer.getBuf(srcArea); + PelBuf dstBuf = PelBuf(predBuf.Cr().bufAt(Position(0, 0)), predBuf.Cr().stride, Size(width, predBuf.Cr().height)); + dstBuf.copyFrom(srcBuf); + } + { + int width = refx + predBuf.Cr().width - (m_IBCBufferWidth >> shiftSample); + const CompArea srcArea = CompArea(compID, pu.cu->chromaFormat, Position(0, refy), Size(width, predBuf.Cr().height)); + CPelBuf srcBuf = m_IBCBuffer.getBuf(srcArea); + PelBuf dstBuf = PelBuf(predBuf.Cr().bufAt(Position((m_IBCBufferWidth >> shiftSample) - refx, 0)), predBuf.Cr().stride, Size(width, predBuf.Cr().height)); + dstBuf.copyFrom(srcBuf); + } + } + } + } +} + +#if JVET_O1170_CHECK_BV_AT_DECODER +void InterPrediction::resetIBCBuffer(const ChromaFormat chromaFormatIDC, const int ctuSize) +{ + const UnitArea area = UnitArea(chromaFormatIDC, Area(0, 0, m_IBCBufferWidth, ctuSize)); + m_IBCBuffer.getBuf(area).fill(-1); +} + +void InterPrediction::resetVPDUforIBC(const ChromaFormat chromaFormatIDC, const int ctuSize, const int vSize, const int xPos, const int yPos) +{ + const UnitArea area = UnitArea(chromaFormatIDC, Area(xPos & (m_IBCBufferWidth - 1), yPos & (ctuSize - 1), vSize, vSize)); + m_IBCBuffer.getBuf(area).fill(-1); +} + +bool InterPrediction::isLumaBvValid(const int ctuSize, const int xCb, const int yCb, const int width, const int height, const int xBv, const int yBv) +{ + if(((yCb + yBv) & (ctuSize - 1)) + height > ctuSize) + { + return false; + } + int refTLx = xCb + xBv; + int refTLy = (yCb + yBv) & (ctuSize - 1); + PelBuf buf = m_IBCBuffer.Y(); + for(int x = 0; x < width; x += 4) + { + for(int y = 0; y < height; y += 4) + { + if(buf.at((x + refTLx) & (m_IBCBufferWidth - 1), y + refTLy) == -1) return false; + if(buf.at((x + 3 + refTLx) & (m_IBCBufferWidth - 1), y + refTLy) == -1) return false; + if(buf.at((x + refTLx) & (m_IBCBufferWidth - 1), y + 3 + refTLy) == -1) return false; + if(buf.at((x + 3 + refTLx) & (m_IBCBufferWidth - 1), y + 3 + refTLy) == -1) return false; + } + } + return true; +} +#endif +#endif //! \} diff --git a/source/Lib/CommonLib/InterPrediction.h b/source/Lib/CommonLib/InterPrediction.h index a8f2d57f8a769fdc9b5c1f5dea56f8e1df42b3fc..a6bcd6939dbfded81abc982e5b2036e825746148 100644 --- a/source/Lib/CommonLib/InterPrediction.h +++ b/source/Lib/CommonLib/InterPrediction.h @@ -114,6 +114,11 @@ protected: Pel* m_gradY1; bool m_subPuMC; +#if JVET_O1170_IBC_VIRTUAL_BUFFER + int m_IBCBufferWidth; + PelStorage m_IBCBuffer; + void xIntraBlockCopy (PredictionUnit &pu, PelUnitBuf &predBuf, const ComponentID compID); +#endif int rightShiftMSB(int numer, int denom); void applyBiOptFlow(const PredictionUnit &pu, const CPelUnitBuf &yuvSrc0, const CPelUnitBuf &yuvSrc1, const int &refIdx0, const int &refIdx1, PelUnitBuf &yuvDst, const BitDepths &clipBitDepths); bool xCalcBiPredSubBlkDist(const PredictionUnit &pu, const Pel* yuvSrc0, const int src0Stride, const Pel* yuvSrc1, const int src1Stride, const BitDepths &clipBitDepths); @@ -171,7 +176,11 @@ public: InterPrediction(); virtual ~InterPrediction(); +#if JVET_O1170_IBC_VIRTUAL_BUFFER + void init (RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize); +#else void init (RdCost* pcRdCost, ChromaFormat chromaFormatIDC); +#endif // inter void motionCompensation (PredictionUnit &pu, PelUnitBuf& predBuf, const RefPicList &eRefPicList = REF_PIC_LIST_X @@ -214,6 +223,14 @@ public: int getShareState() const { return m_shareState; } #endif static bool isSubblockVectorSpreadOverLimit( int a, int b, int c, int d, int predType ); +#if JVET_O1170_IBC_VIRTUAL_BUFFER + void xFillIBCBuffer(CodingUnit &cu); +#if JVET_O1170_CHECK_BV_AT_DECODER + void resetIBCBuffer(const ChromaFormat chromaFormatIDC, const int ctuSize); + void resetVPDUforIBC(const ChromaFormat chromaFormatIDC, const int ctuSize, const int vSize, const int xPos, const int yPos); + bool isLumaBvValid(const int ctuSize, const int xCb, const int yCb, const int width, const int height, const int xBv, const int yBv); +#endif +#endif }; //! \} diff --git a/source/Lib/CommonLib/TypeDef.h b/source/Lib/CommonLib/TypeDef.h index a0dd80f7442eb090d6950fa775aa730a191d36a1..318806f676bf6cbd528b0fe7e64699398e484760 100644 --- a/source/Lib/CommonLib/TypeDef.h +++ b/source/Lib/CommonLib/TypeDef.h @@ -50,6 +50,11 @@ #include <assert.h> #include <cassert> +#define JVET_O1170_IBC_VIRTUAL_BUFFER 1 // JVET-O1170/O1171: IBC virtual buffer +#if JVET_O1170_IBC_VIRTUAL_BUFFER +#define JVET_O1170_CHECK_BV_AT_DECODER 1 // For decoder to check if a BV is valid or not +#endif + #define JVET_O1136_TS_BDPCM_SIGNALLING 1 // JVET-O1136: Unified syntax for JVET-O0165/O0200/O0783 on TS and BDPCM signalling #define JVET_O0219_LFNST_TRANSFORM_SET_FOR_LMCMODE 1 diff --git a/source/Lib/CommonLib/UnitTools.cpp b/source/Lib/CommonLib/UnitTools.cpp index 3aec86d1c7ecd686ae3016706a192622e5ba08ab..e695125f19df9ab7b9a0727db740498ae718c799 100644 --- a/source/Lib/CommonLib/UnitTools.cpp +++ b/source/Lib/CommonLib/UnitTools.cpp @@ -1649,6 +1649,8 @@ bool PU::checkDMVRCondition(const PredictionUnit& pu) return false; } } + +#if !JVET_O1170_IBC_VIRTUAL_BUFFER // for ibc pu validation bool PU::isBlockVectorValid(PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xStartInCU, int yStartInCU, int xBv, int yBv, int ctuSize) { @@ -1726,6 +1728,7 @@ bool PU::isBlockVectorValid(PredictionUnit& pu, int xPos, int yPos, int width, i return true; }// for ibc pu validation +#endif static int xGetDistScaleFactor(const int &iCurrPOC, const int &iCurrRefPOC, const int &iColPOC, const int &iColRefPOC) { diff --git a/source/Lib/CommonLib/UnitTools.h b/source/Lib/CommonLib/UnitTools.h index 4423e858dd4b5a70a93fc0c4473909a679954872..11033466ce3e351fc895164cdbe5d97884248e1f 100644 --- a/source/Lib/CommonLib/UnitTools.h +++ b/source/Lib/CommonLib/UnitTools.h @@ -202,7 +202,9 @@ namespace PU bool isAddNeighborMv (const Mv& currMv, Mv* neighborMvs, int numNeighborMv); void getIbcMVPsEncOnly(PredictionUnit &pu, Mv* mvPred, int& nbPred); bool getDerivedBV(PredictionUnit &pu, const Mv& currentMv, Mv& derivedMv); +#if !JVET_O1170_IBC_VIRTUAL_BUFFER bool isBlockVectorValid(PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xStartInCU, int yStartInCU, int xBv, int yBv, int ctuSize); +#endif bool checkDMVRCondition(const PredictionUnit& pu); } diff --git a/source/Lib/DecoderLib/DecCu.cpp b/source/Lib/DecoderLib/DecCu.cpp index 13367e597e1da487143a8b5295d23d99bbe1eac2..ba1571a5286b893dd87ad14136ff280e3a478746 100644 --- a/source/Lib/DecoderLib/DecCu.cpp +++ b/source/Lib/DecoderLib/DecCu.cpp @@ -109,6 +109,13 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) } bool sharePrepareCondition = ((!cs.pcv->isEncoder) && (!(cs.slice->isIntra()) || cs.slice->getSPS()->getIBCFlag())); +#if JVET_O1170_CHECK_BV_AT_DECODER + if (cs.resetIBCBuffer) + { + m_pcInterPred->resetIBCBuffer(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight()); + cs.resetIBCBuffer = false; + } +#endif for( int ch = 0; ch < maxNumChannelType; ch++ ) { const ChannelType chType = ChannelType( ch ); @@ -117,6 +124,16 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) for( auto &currCU : cs.traverseCUs( CS::getArea( cs, ctuArea, chType ), chType ) ) { +#if JVET_O1170_CHECK_BV_AT_DECODER + if(currCU.Y().valid()) + { + const int vSize = cs.slice->getSPS()->getMaxCUHeight() > 64 ? 64 : cs.slice->getSPS()->getMaxCUHeight(); + if((currCU.Y().x % vSize) == 0 && (currCU.Y().y % vSize) == 0) + { + m_pcInterPred->resetVPDUforIBC(cs.pcv->chrFormat, cs.slice->getSPS()->getMaxCUHeight(), vSize, currCU.Y().x, currCU.Y().y); + } + } +#endif if(sharePrepareCondition) { if ((currCU.shareParentPos.x >= 0) && (!(currCU.shareParentPos.x == prevTmpPos.x && currCU.shareParentPos.y == prevTmpPos.y))) @@ -155,6 +172,9 @@ void DecCu::decompressCtu( CodingStructure& cs, const UnitArea& ctuArea ) { xFillPCMBuffer( currCU ); } +#if JVET_O1170_IBC_VIRTUAL_BUFFER + m_pcInterPred->xFillIBCBuffer(currCU); +#endif DTRACE_BLOCK_REC( cs.picture->getRecoBuf( currCU ), currCU, currCU.predMode ); } @@ -900,12 +920,20 @@ void DecCu::xDeriveCUMV( CodingUnit &cu ) const int cuPelY = pu.Y().y; int roiWidth = pu.lwidth(); int roiHeight = pu.lheight(); +#if !JVET_O1170_CHECK_BV_AT_DECODER const int picWidth = pu.cs->slice->getSPS()->getPicWidthInLumaSamples(); const int picHeight = pu.cs->slice->getSPS()->getPicHeightInLumaSamples(); +#endif const unsigned int lcuWidth = pu.cs->slice->getSPS()->getMaxCUWidth(); int xPred = pu.mv[0].getHor() >> MV_FRACTIONAL_BITS_INTERNAL; int yPred = pu.mv[0].getVer() >> MV_FRACTIONAL_BITS_INTERNAL; +#if JVET_O1170_CHECK_BV_AT_DECODER + CHECK(!m_pcInterPred->isLumaBvValid(lcuWidth, cuPelX, cuPelY, roiWidth, roiHeight, xPred, yPred), "invalid block vector for IBC detected."); +#else +#if !JVET_O1170_IBC_VIRTUAL_BUFFER CHECK(!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, xPred, yPred, lcuWidth), "invalid block vector for IBC detected."); +#endif +#endif } } } diff --git a/source/Lib/DecoderLib/DecLib.cpp b/source/Lib/DecoderLib/DecLib.cpp index 64e053eeb8e13faf42ccc42fa5824ac8d1c3d291..e26fff9d50f47180c58cf9fbff09d7410ed31f6c 100644 --- a/source/Lib/DecoderLib/DecLib.cpp +++ b/source/Lib/DecoderLib/DecLib.cpp @@ -841,7 +841,11 @@ void DecLib::xActivateParameterSets() m_cSAO.create( sps->getPicWidthInLumaSamples(), sps->getPicHeightInLumaSamples(), sps->getChromaFormatIdc(), sps->getMaxCUWidth(), sps->getMaxCUHeight(), sps->getMaxCodingDepth(), pps->getPpsRangeExtension().getLog2SaoOffsetScale(CHANNEL_TYPE_LUMA), pps->getPpsRangeExtension().getLog2SaoOffsetScale(CHANNEL_TYPE_CHROMA) ); m_cLoopFilter.create( sps->getMaxCodingDepth() ); m_cIntraPred.init( sps->getChromaFormatIdc(), sps->getBitDepth( CHANNEL_TYPE_LUMA ) ); +#if JVET_O1170_IBC_VIRTUAL_BUFFER + m_cInterPred.init( &m_cRdCost, sps->getChromaFormatIdc(), sps->getMaxCUHeight() ); +#else m_cInterPred.init( &m_cRdCost, sps->getChromaFormatIdc() ); +#endif if (sps->getUseReshaper()) { m_cReshaper.createDec(sps->getBitDepth(CHANNEL_TYPE_LUMA)); diff --git a/source/Lib/DecoderLib/DecSlice.cpp b/source/Lib/DecoderLib/DecSlice.cpp index 1da86e80022a9934be94379e57652b229858578d..b4a4db3205eae555a17509e0a72734cea625b383 100644 --- a/source/Lib/DecoderLib/DecSlice.cpp +++ b/source/Lib/DecoderLib/DecSlice.cpp @@ -188,6 +188,9 @@ void DecSlice::decompressSlice( Slice* slice, InputBitstream* bitstream, int deb { cs.motionLut.lut.resize(0); cs.motionLut.lutIbc.resize(0); +#if JVET_O1170_CHECK_BV_AT_DECODER + cs.resetIBCBuffer = true; +#endif #if !JVET_O0078_SINGLE_HMVPLUT cs.motionLut.lutShareIbc.resize(0); #endif diff --git a/source/Lib/EncoderLib/EncCu.cpp b/source/Lib/EncoderLib/EncCu.cpp index 482d694b75ec11fc62d8a80afaa889ed232917b2..bcf0831e8b5d15e665f33adf1c9bc07496b33ae2 100644 --- a/source/Lib/EncoderLib/EncCu.cpp +++ b/source/Lib/EncoderLib/EncCu.cpp @@ -3090,7 +3090,11 @@ void EncCu::xCheckRDCostIBCModeMerge2Nx2N(CodingStructure *&tempCS, CodingStruct int xPred = pu.bv.getHor(); int yPred = pu.bv.getVer(); +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (!m_pcInterSearch->searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, xPred, yPred, lcuWidth)) // not valid bv derived +#else if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, xPred, yPred, lcuWidth)) // not valid bv derived +#endif { numValidBv--; continue; diff --git a/source/Lib/EncoderLib/InterSearch.cpp b/source/Lib/EncoderLib/InterSearch.cpp index 9aaac4ded7edcc3ff8ef90f5afc19a24b88d726d..3299beb8910c3dd8737666079461e45159c5fafc 100644 --- a/source/Lib/EncoderLib/InterSearch.cpp +++ b/source/Lib/EncoderLib/InterSearch.cpp @@ -252,7 +252,11 @@ void InterSearch::init( EncCfg* pcEncCfg, } const ChromaFormat cform = pcEncCfg->getChromaFormatIdc(); +#if JVET_O1170_IBC_VIRTUAL_BUFFER + InterPrediction::init( pcRdCost, cform, maxCUHeight ); +#else InterPrediction::init( pcRdCost, cform ); +#endif for( uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++ ) { @@ -995,7 +999,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct& cS && !((yPred < srTop) || (yPred > srBottom)) && !((xPred < srLeft) || (xPred > srRight))) { +#if JVET_O1170_IBC_VIRTUAL_BUFFER + bool validCand = searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, xPred, yPred, lcuWidth); +#else bool validCand = PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, xPred, yPred, lcuWidth); +#endif if (validCand) { @@ -1016,7 +1024,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct& cS const int boundY = (0 - roiHeight - puPelOffsetY); for (int y = std::max(srchRngVerTop, 0 - cuPelY); y <= boundY; ++y) { +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (!searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, y, lcuWidth)) +#else if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, 0, y, lcuWidth)) +#endif { continue; } @@ -1041,7 +1053,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct& cS const int boundX = std::max(srchRngHorLeft, -cuPelX); for (int x = 0 - roiWidth - puPelOffsetX; x >= boundX; --x) { +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (!searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, 0, lcuWidth)) +#else if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, x, 0, lcuWidth)) +#endif { continue; } @@ -1092,7 +1108,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct& cS if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth)) continue; +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (!searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, y, lcuWidth)) +#else if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, x, y, lcuWidth)) +#endif { continue; } @@ -1132,7 +1152,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct& cS if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth)) continue; +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (!searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, y, lcuWidth)) +#else if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, x, y, lcuWidth)) +#endif { continue; } @@ -1189,7 +1213,11 @@ void InterSearch::xIntraPatternSearch(PredictionUnit& pu, IntTZSearchStruct& cS if ((x == 0) || ((int)(cuPelX + x + roiWidth) >= picWidth)) continue; +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (!searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, x, y, lcuWidth)) +#else if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, x, y, lcuWidth)) +#endif { continue; } @@ -1308,7 +1336,11 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, int xBv = bv.hor; int yBv = bv.ver; +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (searchBv(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xBv, yBv, lcuWidth)) +#else if (PU::isBlockVectorValid(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, 0, 0, xBv, yBv, lcuWidth)) +#endif { buffered = true; Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xBv, yBv, pu.cs->sps->getAMVREnabledFlag()); @@ -1343,7 +1375,11 @@ void InterSearch::xIBCEstimation(PredictionUnit& pu, PelUnitBuf& origBuf, int xPred = cMvPredEncOnly[cand].getHor(); int yPred = cMvPredEncOnly[cand].getVer(); +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (searchBv(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, xPred, yPred, lcuWidth)) +#else if (PU::isBlockVectorValid(pu, cuPelX, cuPelY, iRoiWidth, iRoiHeight, iPicWidth, iPicHeight, 0, 0, xPred, yPred, lcuWidth)) +#endif { Distortion sad = m_pcRdCost->getBvCostMultiplePreds(xPred, yPred, pu.cs->sps->getAMVREnabledFlag()); m_cDistParam.cur.buf = cStruct.piRefY + cStruct.iRefStride * yPred + xPred; @@ -1581,7 +1617,11 @@ void InterSearch::xxIBCHashSearch(PredictionUnit& pu, Mv* mvPred, int numMvPred, Mv candMv; candMv.set(tmp.x, tmp.y); +#if JVET_O1170_IBC_VIRTUAL_BUFFER + if (!searchBv(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, candMv.getHor(), candMv.getVer(), lcuWidth)) +#else if (!PU::isBlockVectorValid(pu, cuPelX, cuPelY, roiWidth, roiHeight, picWidth, picHeight, 0, 0, candMv.getHor(), candMv.getVer(), lcuWidth)) +#endif { continue; } @@ -7876,3 +7916,82 @@ uint64_t InterSearch::xCalcPuMeBits(PredictionUnit& pu) } return m_CABACEstimator->getEstFracBits(); } + +#if JVET_O1170_IBC_VIRTUAL_BUFFER +bool InterSearch::searchBv(PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xBv, int yBv, int ctuSize) +{ + const int ctuSizeLog2 = g_aucLog2[ctuSize]; + + int refRightX = xPos + xBv + width - 1; + int refBottomY = yPos + yBv + height - 1; + + int refLeftX = xPos + xBv; + int refTopY = yPos + yBv; + + if ((xPos + xBv) < 0) + { + return false; + } + if (refRightX >= picWidth) + { + return false; + } + + if ((yPos + yBv) < 0) + { + return false; + } + if (refBottomY >= picHeight) + { + return false; + } + if ((xBv + width) > 0 && (yBv + height) > 0) + { + return false; + } + + // Don't search the above CTU row + if (refTopY >> ctuSizeLog2 < yPos >> ctuSizeLog2) + return false; + + // Don't search the below CTU row + if (refBottomY >> ctuSizeLog2 > yPos >> ctuSizeLog2) + { + return false; + } + + // in the same CTU line + int numLeftCTUs = (1 << ((7 - ctuSizeLog2) << 1)) - ((ctuSizeLog2 < 7) ? 1 : 0); + if ((refRightX >> ctuSizeLog2 <= xPos >> ctuSizeLog2) && (refLeftX >> ctuSizeLog2 >= (xPos >> ctuSizeLog2) - numLeftCTUs)) + { + + // in the same CTU, or left CTU + // if part of ref block is in the left CTU, some area can be referred from the not-yet updated local CTU buffer + if (((refLeftX >> ctuSizeLog2) == ((xPos >> ctuSizeLog2) - 1)) && (ctuSizeLog2 == 7)) + { + // ref block's collocated block in current CTU + const Position refPosCol = pu.Y().topLeft().offset(xBv + ctuSize, yBv); + int offset64x = (refPosCol.x >> (ctuSizeLog2 - 1)) << (ctuSizeLog2 - 1); + int offset64y = (refPosCol.y >> (ctuSizeLog2 - 1)) << (ctuSizeLog2 - 1); + const Position refPosCol64x64 = {offset64x, offset64y}; + if (pu.cs->isDecomp(refPosCol64x64, toChannelType(COMPONENT_Y))) + return false; + if (refPosCol64x64 == pu.Y().topLeft()) + return false; + } + } + else + return false; + + // in the same CTU, or valid area from left CTU. Check if the reference block is already coded + const Position refPosLT = pu.Y().topLeft().offset(xBv, yBv); + const Position refPosBR = pu.Y().bottomRight().offset(xBv, yBv); + const ChannelType chType = toChannelType(COMPONENT_Y); + if (!pu.cs->isDecomp(refPosBR, chType)) + return false; + if (!pu.cs->isDecomp(refPosLT, chType)) + return false; + return true; + +} +#endif \ No newline at end of file diff --git a/source/Lib/EncoderLib/InterSearch.h b/source/Lib/EncoderLib/InterSearch.h index 105d518086ac59677d9724f86162eec45d2faf85..34fe70eb27810350ca17da9ff9e9f5914e0ec321 100644 --- a/source/Lib/EncoderLib/InterSearch.h +++ b/source/Lib/EncoderLib/InterSearch.h @@ -322,6 +322,9 @@ public: #endif void resetSavedAffineMotion(); void storeAffineMotion( Mv acAffineMv[2][3], int16_t affineRefIdx[2], EAffineModel affineType, int gbiIdx ); +#if JVET_O1170_IBC_VIRTUAL_BUFFER + bool searchBv(PredictionUnit& pu, int xPos, int yPos, int width, int height, int picWidth, int picHeight, int xBv, int yBv, int ctuSize); +#endif protected: /// sub-function for motion vector refinement used in fractional-pel accuracy