/* The copyright in this software is being made available under the BSD * License, included below. This software may be subject to other third party * and contributor rights, including patent rights, and no such rights are * granted under this license. * * Copyright (c) 2010-2023, ITU/ISO/IEC * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may * be used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. */ /** \file InterPrediction.h \brief inter prediction class (header) */ #ifndef __INTERPREDICTION__ #define __INTERPREDICTION__ // Include files #include "InterpolationFilter.h" #include "WeightPrediction.h" #include "Buffer.h" #include "Unit.h" #include "Picture.h" #include "RdCost.h" // forward declaration class Mv; //! \ingroup CommonLib //! \{ // ==================================================================================================================== // Class definition // ==================================================================================================================== class MergeCtx { public: MergeCtx() : numValidMergeCand(0), hasMergedCandList(false) {} ~MergeCtx() {} public: MvField mvFieldNeighbours[MRG_MAX_NUM_CANDS][2]; #if GDR_ENABLED // note : check if source of mv and mv itself is valid bool mvSolid[MRG_MAX_NUM_CANDS][2]; bool mvValid[MRG_MAX_NUM_CANDS][2]; Position mvPos[MRG_MAX_NUM_CANDS][2]; MvpType mvType[MRG_MAX_NUM_CANDS][2]; #endif uint8_t bcwIdx[MRG_MAX_NUM_CANDS]; unsigned char interDirNeighbours[ MRG_MAX_NUM_CANDS ]; int numValidMergeCand; bool hasMergedCandList; MotionBuf subPuMvpMiBuf; MvField mmvdBaseMv[MmvdIdx::BASE_MV_NUM][2]; #if GDR_ENABLED bool mmvdSolid[MmvdIdx::BASE_MV_NUM][2]; bool mmvdValid[MmvdIdx::BASE_MV_NUM][2]; #endif void setMmvdMergeCandiInfo(PredictionUnit &pu, MmvdIdx candIdx); void getMmvdDeltaMv(const Slice& slice, const MmvdIdx candIdx, Mv deltaMv[NUM_REF_PIC_LIST_01]) const; bool mmvdUseAltHpelIf[MmvdIdx::BASE_MV_NUM]; bool useAltHpelIf [ MRG_MAX_NUM_CANDS ]; #if JVET_AC0139_UNIFIED_MERGE void setMergeInfo( PredictionUnit& pu, int candIdx ) const; #else void setMergeInfo( PredictionUnit& pu, int candIdx ); #endif }; class AffineMergeCtx { public: AffineMergeCtx() : numValidMergeCand(0) { for (int i = 0; i < AFFINE_MRG_MAX_NUM_CANDS; i++) { affineType[i] = AffineModel::_4_PARAMS; } } ~AffineMergeCtx() {} public: std::array mvFieldNeighbours[AFFINE_MRG_MAX_NUM_CANDS]; #if GDR_ENABLED std::array mvSolid[AFFINE_MRG_MAX_NUM_CANDS]; std::array mvValid[AFFINE_MRG_MAX_NUM_CANDS]; bool isSolid(const int idx, const int l) { bool solid = true; for (auto &c: mvSolid[idx]) { solid &= c[l]; } return solid; } bool isValid(const int idx, const int l) { bool valid = true; for (auto &c: mvValid[idx]) { valid &= c[l]; } return valid; } #endif unsigned char interDirNeighbours[AFFINE_MRG_MAX_NUM_CANDS]; AffineModel affineType[AFFINE_MRG_MAX_NUM_CANDS]; uint8_t bcwIdx[AFFINE_MRG_MAX_NUM_CANDS]; int numValidMergeCand; int maxNumMergeCand; MergeCtx *mrgCtx; MergeType mergeType[AFFINE_MRG_MAX_NUM_CANDS]; }; class InterPrediction : public WeightPrediction { private: protected: InterpolationFilter m_if; Pel* m_acYuvPred [NUM_REF_PIC_LIST_01][MAX_NUM_COMPONENT]; Pel* m_filteredBlock [LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL][LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL][MAX_NUM_COMPONENT]; Pel* m_filteredBlockTmp [LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL][MAX_NUM_COMPONENT]; static constexpr int TMP_RPR_WIDTH = MAX_CU_SIZE + 16; static constexpr int TMP_RPR_HEIGHT = MAX_CU_SIZE * MAX_SCALING_RATIO + 16; Pel *m_filteredBlockTmpRPR; ChromaFormat m_currChromaFormat; ComponentID m_maxCompIDToPred; ///< tells the predictor to only process the components up to (inklusive) this one - useful to skip chroma components during RD-search RdCost* m_pcRdCost; PelStorage m_geoPartBuf[2]; static constexpr int MVBUFFER_SIZE = MAX_CU_SIZE / MIN_PU_SIZE; Mv* m_storedMv; // buffers for initial prediction that is used to calculate DMVR refinement Pel *m_yuvPredTempDmvr[NUM_REF_PIC_LIST_01]; PelBuf m_dmvrInitialPred[NUM_REF_PIC_LIST_01]; // buffers for padded data, initially filled by xDmvrPrefetch(), padded by xDmvrPad() Pel *m_refSamplesDmvr[NUM_REF_PIC_LIST_01][MAX_NUM_COMPONENT]; PelUnitBuf m_yuvRefBufDmvr[NUM_REF_PIC_LIST_01]; static const std::array m_dmvrSearchOffsets; static constexpr int AFFINE_SUBBLOCK_WIDTH_EXT = AFFINE_SUBBLOCK_SIZE + 2 * PROF_BORDER_EXT_W; static constexpr int AFFINE_SUBBLOCK_HEIGHT_EXT = AFFINE_SUBBLOCK_SIZE + 2 * PROF_BORDER_EXT_H; Pel m_gradBuf[2][AFFINE_SUBBLOCK_WIDTH_EXT * AFFINE_SUBBLOCK_HEIGHT_EXT]; // PROF skip flags for encoder speedup bool m_skipProf{ false }; bool m_skipProfCond{ false }; bool m_biPredSearchAffine{ false }; Pel* m_gradX0; Pel* m_gradY0; Pel* m_gradX1; Pel *m_gradY1; int m_IBCBufferWidth; PelStorage m_IBCBuffer; void xIntraBlockCopy (PredictionUnit &pu, PelUnitBuf &predBuf, const ComponentID compID); 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); void xPredInterUni(const PredictionUnit &pu, const RefPicList &eRefPicList, PelUnitBuf &pcYuvPred, const bool bi, const bool bioApplied, const bool luma, const bool chroma); void xPredInterBi(PredictionUnit &pu, PelUnitBuf &pcYuvPred, bool luma, bool chroma, PelUnitBuf *yuvPredTmp, bool isSubPu); void xPredInterBlk(const ComponentID compID, const PredictionUnit &pu, const Picture *refPic, const Mv &_mv, PelUnitBuf &dstPic, bool bi, const ClpRng &clpRng, bool bioApplied, bool isIBC, const ScalingRatio scalingRatio, bool bilinearMC, Pel *srcPadBuf, ptrdiff_t srcPadStride, Pel *bdofDstBuf); void xPredInterBlk(const ComponentID compID, const PredictionUnit &pu, const Picture *refPic, const Mv &_mv, PelUnitBuf &dstPic, bool bi, const ClpRng &clpRng, bool bioApplied, bool isIBC, RefPicList l) { xPredInterBlk(compID, pu, refPic, _mv, dstPic, bi, clpRng, bioApplied, isIBC, SCALE_1X, false, nullptr, 0, isLuma(compID) && bioApplied ? m_filteredBlockTmp[2 + l][compID] : nullptr); } void xAddBIOAvg4(const Pel *src0, ptrdiff_t src0Stride, const Pel *src1, ptrdiff_t src1Stride, Pel *dst, ptrdiff_t dstStride, const Pel *gradX0, const Pel *gradX1, const Pel *gradY0, const Pel *gradY1, ptrdiff_t gradStride, int width, int height, int tmpx, int tmpy, int shift, int offset, const ClpRng &clpRng); void xBioGradFilter(Pel *pSrc, ptrdiff_t srcStride, int width, int height, ptrdiff_t gradStride, Pel *gradX, Pel *gradY, int bitDepth); void xCalcBIOPar (const Pel* srcY0Temp, const Pel* srcY1Temp, const Pel* gradX0, const Pel* gradX1, const Pel* gradY0, const Pel* gradY1, int* dotProductTemp1, int* dotProductTemp2, int* dotProductTemp3, int* dotProductTemp5, int* dotProductTemp6, const int src0Stride, const int src1Stride, const int gradStride, const int widthG, const int heightG, int bitDepth); void xCalcBlkGradient (int sx, int sy, int *arraysGx2, int *arraysGxGy, int *arraysGxdI, int *arraysGy2, int *arraysGydI, int &sGx2, int &sGy2, int &sGxGy, int &sGxdI, int &sGydI, int width, int height, int unitSize); void xWeightedAverage(const PredictionUnit &pu, const CPelUnitBuf &pcYuvSrc0, const CPelUnitBuf &pcYuvSrc1, PelUnitBuf &pcYuvDst, const BitDepths &clipBitDepths, const ClpRngs &clpRngs, bool bioApplied, bool lumaOnly, bool chromaOnly, PelUnitBuf *yuvDstTmp); #if GDR_ENABLED bool xPredAffineBlk(const ComponentID &compID, const PredictionUnit &pu, const Picture *refPic, const Mv *_mv, PelUnitBuf &dstPic, const bool bi, const ClpRng &clpRng, const bool genChromaMv = false, const ScalingRatio = SCALE_1X); #else void xPredAffineBlk(const ComponentID &compID, const PredictionUnit &pu, const Picture *refPic, const Mv *_mv, PelUnitBuf &dstPic, const bool bi, const ClpRng &clpRng, const bool genChromaMv = false, const ScalingRatio = SCALE_1X); #endif static bool xCheckIdenticalMotion( const PredictionUnit& pu ); void xSubPuMC(PredictionUnit &pu, PelUnitBuf &predBuf, const RefPicList &eRefPicList, bool luma, bool chroma); void xSubPuBio(PredictionUnit &pu, PelUnitBuf &predBuf, const RefPicList &eRefPicList, PelUnitBuf *yuvDstTmp); void destroy(); MotionInfo m_SubPuMiBuf[(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)]; #if JVET_J0090_MEMORY_BANDWITH_MEASURE CacheModel *m_cacheModel; #endif PelStorage m_colorTransResiBuf[3]; // 0-org; 1-act; 2-tmp public: InterPrediction(); virtual ~InterPrediction(); void init (RdCost* pcRdCost, ChromaFormat chromaFormatIDC, const int ctuSize); // inter void motionCompensation(PredictionUnit &pu, PelUnitBuf &predBuf, RefPicList eRefPicList, bool luma, bool chroma, PelUnitBuf *predBufWOBIO, bool isSubPu); void motionCompensation(PredictionUnit &pu, PelUnitBuf &predBuf, RefPicList eRefPicList) { motionCompensation(pu, predBuf, eRefPicList, true, true, nullptr, false); } void motionCompensatePu(PredictionUnit &pu, RefPicList eRefPicList, bool luma, bool chroma); void motionCompensateCu(CodingUnit &cu, RefPicList eRefPicList, bool luma, bool chroma); void motionCompensationGeo(CodingUnit &cu, MergeCtx &GeoMrgCtx); void weightedGeoBlk(PredictionUnit &pu, const uint8_t splitDir, ChannelType channel, PelUnitBuf &predDst, PelUnitBuf &predSrc0, PelUnitBuf &predSrc1); // DMVR related definitions using DmvrDist = int32_t; static constexpr DmvrDist UNDEFINED_DMVR_DIST = -1; void xDmvrPrefetch(const PredictionUnit &pu, bool forLuma); void xDmvrPad(const PredictionUnit &pu); void xDmvrFinalMc(const PredictionUnit &pu, PelUnitBuf yuvSrc[NUM_REF_PIC_LIST_01], bool applyBdof, const Mv startMV[NUM_REF_PIC_LIST_01], bool blockMoved); void xDmvrIntegerRefine(int bd, DmvrDist &minCost, Mv &deltaMv, DmvrDist *sadPtr, int width, int height); Mv xDmvrSubpelRefine(const DmvrDist *sadPtr); DmvrDist xDmvrCost(int bitDepth, const Mv &mvd, int width, int height); void xDmvrInitialMc(const PredictionUnit &pu, const ClpRngs &clpRngs); void xProcessDMVR(PredictionUnit &pu, PelUnitBuf &pcYuvDst, const ClpRngs &clpRngs, const bool applyBdof); #if JVET_J0090_MEMORY_BANDWITH_MEASURE void cacheAssign( CacheModel *cache ); #endif static bool isSubblockVectorSpreadOverLimit( int a, int b, int c, int d, int predType ); void xFillIBCBuffer(CodingUnit &cu); 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); bool xPredInterBlkRPR(const ScalingRatio scalingRatio, const PPS &pps, const CompArea &blk, const Picture *refPic, const Mv &mv, Pel *dst, const ptrdiff_t dstStride, const bool bi, const bool wrapRef, const ClpRng &clpRng, const InterpolationFilter::Filter filterIndex, const bool useAltHpelIf = false); }; //! \} #endif // __INTERPREDICTION__