Skip to content
Snippets Groups Projects
InterPrediction.cpp 121 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* 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-2019, 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     Prediction.cpp
        \brief    prediction class
    */
    
    #include "InterPrediction.h"
    
    #include "Buffer.h"
    #include "UnitTools.h"
    
    Valeri George's avatar
    Valeri George committed
    #include "MCTS.h"
    
    
    #include <memory.h>
    #include <algorithm>
    
    //! \ingroup CommonLib
    //! \{
    
    // ====================================================================================================================
    // Constructor / destructor / initialize
    // ====================================================================================================================
    
    InterPrediction::InterPrediction()
    :
      m_currChromaFormat( NUM_CHROMA_FORMAT )
    , m_maxCompIDToPred ( MAX_NUM_COMPONENT )
    , m_pcRdCost        ( nullptr )
    
    , m_storedMv        ( nullptr )
    
    #if JVET_O0070_PROF
    , m_skipPROF (false)
    , m_encOnly  (false)
    , m_isBi     (false)
    #endif
    
    , m_gradX0(nullptr)
    , m_gradY0(nullptr)
    , m_gradX1(nullptr)
    , m_gradY1(nullptr)
    
    , m_subPuMC(false)
    
    {
      for( uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++ )
      {
        for( uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++ )
        {
          m_acYuvPred[refList][ch] = nullptr;
        }
      }
    
      for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
      {
    
        for( uint32_t i = 0; i < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL; i++ )
    
          for( uint32_t j = 0; j < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL; j++ )
    
          {
            m_filteredBlock[i][j][c] = nullptr;
          }
    
          m_filteredBlockTmp[i][c] = nullptr;
        }
      }
    
      m_cYuvPredTempDMVRL1 = nullptr;
      m_cYuvPredTempDMVRL0 = nullptr;
      for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
      {
        m_cRefSamplesDMVRL0[ch] = nullptr;
        m_cRefSamplesDMVRL1[ch] = nullptr;
      }
    
    }
    
    InterPrediction::~InterPrediction()
    {
      destroy();
    }
    
    void InterPrediction::destroy()
    {
      for( uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++ )
      {
        for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
        {
          xFree( m_acYuvPred[i][c] );
          m_acYuvPred[i][c] = nullptr;
        }
      }
    
      for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
      {
    
        for( uint32_t i = 0; i < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL; i++ )
    
          for( uint32_t j = 0; j < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL; j++ )
    
          {
            xFree( m_filteredBlock[i][j][c] );
            m_filteredBlock[i][j][c] = nullptr;
          }
    
          xFree( m_filteredBlockTmp[i][c] );
          m_filteredBlockTmp[i][c] = nullptr;
        }
      }
    
    rlliao's avatar
    rlliao committed
      m_triangleBuf.destroy();
    
      if (m_storedMv != nullptr)
      {
        delete[]m_storedMv;
    
        m_storedMv = nullptr;
    
      xFree(m_gradX0);   m_gradX0 = nullptr;
      xFree(m_gradY0);   m_gradY0 = nullptr;
      xFree(m_gradX1);   m_gradX1 = nullptr;
      xFree(m_gradY1);   m_gradY1 = nullptr;
    
      xFree(m_cYuvPredTempDMVRL0);
      m_cYuvPredTempDMVRL0 = nullptr;
      xFree(m_cYuvPredTempDMVRL1);
      m_cYuvPredTempDMVRL1 = nullptr;
      for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
      {
        xFree(m_cRefSamplesDMVRL0[ch]);
        m_cRefSamplesDMVRL0[ch] = nullptr;
        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;
    
    
      // if it has been initialised before, but the chroma format has changed, release the memory and start again.
      if( m_acYuvPred[REF_PIC_LIST_0][COMPONENT_Y] != nullptr && m_currChromaFormat != chromaFormatIDC )
      {
        destroy();
      }
    
      m_currChromaFormat = chromaFormatIDC;
      if( m_acYuvPred[REF_PIC_LIST_0][COMPONENT_Y] == nullptr ) // check if first is null (in which case, nothing initialised yet)
      {
        for( uint32_t c = 0; c < MAX_NUM_COMPONENT; c++ )
        {
    
          int extWidth = MAX_CU_SIZE + (2 * BIO_EXTEND_SIZE + 2) + 16;
          int extHeight = MAX_CU_SIZE + (2 * BIO_EXTEND_SIZE + 2) + 1;
    
          extWidth = extWidth > (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + 16) ? extWidth : MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + 16;
          extHeight = extHeight > (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + 1) ? extHeight : MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + 1;
    
          for( uint32_t i = 0; i < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL; i++ )
    
          {
            m_filteredBlockTmp[i][c] = ( Pel* ) xMalloc( Pel, ( extWidth + 4 ) * ( extHeight + 7 + 4 ) );
    
    
            for( uint32_t j = 0; j < LUMA_INTERPOLATION_FILTER_SUB_SAMPLE_POSITIONS_SIGNAL; j++ )
    
            {
              m_filteredBlock[i][j][c] = ( Pel* ) xMalloc( Pel, extWidth * extHeight );
            }
          }
    
          // new structure
          for( uint32_t i = 0; i < NUM_REF_PIC_LIST_01; i++ )
          {
            m_acYuvPred[i][c] = ( Pel* ) xMalloc( Pel, MAX_CU_SIZE * MAX_CU_SIZE );
          }
        }
    
    
    rlliao's avatar
    rlliao committed
        m_triangleBuf.create(UnitArea(chromaFormatIDC, Area(0, 0, MAX_CU_SIZE, MAX_CU_SIZE)));
    
        m_gradX0 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
        m_gradY0 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
        m_gradX1 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
        m_gradY1 = (Pel*)xMalloc(Pel, BIO_TEMP_BUFFER_SIZE);
    
      if (m_cYuvPredTempDMVRL0 == nullptr && m_cYuvPredTempDMVRL1 == nullptr)
    
        m_cYuvPredTempDMVRL0 = (Pel*)xMalloc(Pel, (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)) * (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)));
        m_cYuvPredTempDMVRL1 = (Pel*)xMalloc(Pel, (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)) * (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION)));
        for (uint32_t ch = 0; ch < MAX_NUM_COMPONENT; ch++)
        {
          m_cRefSamplesDMVRL0[ch] = (Pel*)xMalloc(Pel, (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA) * (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA));
          m_cRefSamplesDMVRL1[ch] = (Pel*)xMalloc(Pel, (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA) * (MAX_CU_SIZE + (2 * DMVR_NUM_ITERATION) + NTAPS_LUMA));
        }
    
    #if !JVET_J0090_MEMORY_BANDWITH_MEASURE
      m_if.initInterpolationFilter( true );
    #endif
    
      if (m_storedMv == nullptr)
      {
        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
    
    }
    
    // ====================================================================================================================
    // Public member functions
    // ====================================================================================================================
    
    bool InterPrediction::xCheckIdenticalMotion( const PredictionUnit &pu )
    {
      const Slice &slice = *pu.cs->slice;
    
      if( slice.isInterB() && !pu.cs->pps->getWPBiPred() )
      {
        if( pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0 )
        {
          int RefPOCL0 = slice.getRefPic( REF_PIC_LIST_0, pu.refIdx[0] )->getPOC();
          int RefPOCL1 = slice.getRefPic( REF_PIC_LIST_1, pu.refIdx[1] )->getPOC();
    
          if( RefPOCL0 == RefPOCL1 )
          {
            if( !pu.cu->affine )
            {
              if( pu.mv[0] == pu.mv[1] )
              {
                return true;
              }
            }
            else
            {
    
              if ( (pu.cu->affineType == AFFINEMODEL_4PARAM && (pu.mvAffi[0][0] == pu.mvAffi[1][0]) && (pu.mvAffi[0][1] == pu.mvAffi[1][1]))
                || (pu.cu->affineType == AFFINEMODEL_6PARAM && (pu.mvAffi[0][0] == pu.mvAffi[1][0]) && (pu.mvAffi[0][1] == pu.mvAffi[1][1]) && (pu.mvAffi[0][2] == pu.mvAffi[1][2])) )
    
              {
                return true;
              }
            }
          }
        }
      }
    
      return false;
    }
    
    void InterPrediction::xSubPuMC( PredictionUnit& pu, PelUnitBuf& predBuf, const RefPicList &eRefPicList /*= REF_PIC_LIST_X*/ )
    {
    
      // compute the location of the current PU
      Position puPos    = pu.lumaPos();
      Size puSize       = pu.lumaSize();
    
      int numPartLine, numPartCol, puHeight, puWidth;
      {
    
        numPartLine = std::max(puSize.width >> ATMVP_SUB_BLOCK_SIZE, 1u);
        numPartCol = std::max(puSize.height >> ATMVP_SUB_BLOCK_SIZE, 1u);
        puHeight = numPartCol == 1 ? puSize.height : 1 << ATMVP_SUB_BLOCK_SIZE;
        puWidth = numPartLine == 1 ? puSize.width : 1 << ATMVP_SUB_BLOCK_SIZE;
    
      }
    
      PredictionUnit subPu;
    
      subPu.cs        = pu.cs;
      subPu.cu        = pu.cu;
      subPu.mergeType = MRG_TYPE_DEFAULT_N;
    
    
      bool isAffine = pu.cu->affine;
    
      // join sub-pus containing the same motion
      bool verMC = puSize.height > puSize.width;
      int  fstStart = (!verMC ? puPos.y : puPos.x);
      int  secStart = (!verMC ? puPos.x : puPos.y);
      int  fstEnd = (!verMC ? puPos.y + puSize.height : puPos.x + puSize.width);
      int  secEnd = (!verMC ? puPos.x + puSize.width : puPos.y + puSize.height);
      int  fstStep = (!verMC ? puHeight : puWidth);
      int  secStep = (!verMC ? puWidth : puHeight);
    
    
      for (int fstDim = fstStart; fstDim < fstEnd; fstDim += fstStep)
      {
        for (int secDim = secStart; secDim < secEnd; secDim += secStep)
        {
          int x = !verMC ? secDim : fstDim;
          int y = !verMC ? fstDim : secDim;
          const MotionInfo &curMi = pu.getMotionInfo(Position{ x, y });
    
          int length = secStep;
          int later  = secDim + secStep;
    
          while (later < secEnd)
          {
            const MotionInfo &laterMi = !verMC ? pu.getMotionInfo(Position{ later, fstDim }) : pu.getMotionInfo(Position{ fstDim, later });
            if (laterMi == curMi)
            {
              length += secStep;
            }
            else
            {
              break;
            }
            later += secStep;
          }
          int dx = !verMC ? length : puWidth;
          int dy = !verMC ? puHeight : length;
    
          subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, dx, dy)));
          subPu = curMi;
          PelUnitBuf subPredBuf = predBuf.subBuf(UnitAreaRelative(pu, subPu));
    
          motionCompensation(subPu, subPredBuf, eRefPicList);
          secDim = later - secStep;
        }
      }
    
      m_subPuMC = false;
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
    void InterPrediction::xSubPuBio(PredictionUnit& pu, PelUnitBuf& predBuf, const RefPicList &eRefPicList /*= REF_PIC_LIST_X*/, PelUnitBuf* yuvDstTmp /*= NULL*/)
    #else
    
    void InterPrediction::xSubPuBio(PredictionUnit& pu, PelUnitBuf& predBuf, const RefPicList &eRefPicList /*= REF_PIC_LIST_X*/)
    
    {
      // compute the location of the current PU
      Position puPos = pu.lumaPos();
      Size puSize = pu.lumaSize();
    
      PredictionUnit subPu;
    
      subPu.cs = pu.cs;
      subPu.cu = pu.cu;
      subPu.mergeType = pu.mergeType;
      subPu.mmvdMergeFlag = pu.mmvdMergeFlag;
      subPu.mmvdEncOptMode = pu.mmvdEncOptMode;
      subPu.mergeFlag = pu.mergeFlag;
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
      subPu.mhIntraFlag = pu.mhIntraFlag;
    #endif
    
      subPu.mvRefine = pu.mvRefine;
      subPu.refIdx[0] = pu.refIdx[0];
      subPu.refIdx[1] = pu.refIdx[1];
      int  fstStart = puPos.y;
      int  secStart = puPos.x;
      int  fstEnd = puPos.y + puSize.height;
      int  secEnd = puPos.x + puSize.width;
      int  fstStep = std::min((int)MAX_BDOF_APPLICATION_REGION, (int)puSize.height);
      int  secStep = std::min((int)MAX_BDOF_APPLICATION_REGION, (int)puSize.width);
      for (int fstDim = fstStart; fstDim < fstEnd; fstDim += fstStep)
      {
        for (int secDim = secStart; secDim < secEnd; secDim += secStep)
        {
          int x = secDim;
          int y = fstDim;
          int dx = secStep;
          int dy = fstStep;
    
          const MotionInfo &curMi = pu.getMotionInfo(Position{ x, y });
    
          subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, dx, dy)));
          subPu = curMi;
          PelUnitBuf subPredBuf = predBuf.subBuf(UnitAreaRelative(pu, subPu));
    
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
          if (yuvDstTmp)
          {
            PelUnitBuf subPredBufTmp = yuvDstTmp->subBuf(UnitAreaRelative(pu, subPu));
            motionCompensation(subPu, subPredBuf, eRefPicList, true, true, &subPredBufTmp);
          }
          else
    #endif
    
          motionCompensation(subPu, subPredBuf, eRefPicList);
        }
      }
    }
    
    #if !JVET_O0258_REMOVE_CHROMA_IBC_FOR_DUALTREE
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    void InterPrediction::xChromaMC(PredictionUnit &pu, PelUnitBuf& pcYuvPred)
    {
      // separated tree, chroma
      const CompArea lumaArea = CompArea(COMPONENT_Y, pu.chromaFormat, pu.Cb().lumaPos(), recalcSize(pu.chromaFormat, CHANNEL_TYPE_CHROMA, CHANNEL_TYPE_LUMA, pu.Cb().size()));
      PredictionUnit subPu;
      subPu.cs = pu.cs;
      subPu.cu = pu.cu;
    
      Picture * refPic = pu.cu->slice->getPic();
      for (int y = lumaArea.y; y < lumaArea.y + lumaArea.height; y += MIN_PU_SIZE)
      {
        for (int x = lumaArea.x; x < lumaArea.x + lumaArea.width; x += MIN_PU_SIZE)
        {
          const MotionInfo &curMi = pu.cs->picture->cs->getMotionInfo(Position{ x, y });
    
          subPu.UnitArea::operator=(UnitArea(pu.chromaFormat, Area(x, y, MIN_PU_SIZE, MIN_PU_SIZE)));
          PelUnitBuf subPredBuf = pcYuvPred.subBuf(UnitAreaRelative(pu, subPu));
    
          xPredInterBlk(COMPONENT_Cb, subPu, refPic, curMi.mv[0], subPredBuf, false, pu.cu->slice->clpRng(COMPONENT_Cb)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
          xPredInterBlk(COMPONENT_Cr, subPu, refPic, curMi.mv[0], subPredBuf, false, pu.cu->slice->clpRng(COMPONENT_Cr)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        }
      }
    }
    
    void InterPrediction::xPredInterUni(const PredictionUnit& pu, const RefPicList& eRefPicList, PelUnitBuf& pcYuvPred, const bool& bi
                                       , const bool& bioApplied
    
                                       , const bool luma, const bool chroma
    
    {
      const SPS &sps = *pu.cs->sps;
    
      int iRefIdx = pu.refIdx[eRefPicList];
      Mv mv[3];
    
    Yu Han's avatar
    Yu Han committed
      bool isIBC = false;
    
      CHECK( !CU::isIBC( *pu.cu ) && pu.lwidth() == 4 && pu.lheight() == 4, "invalid 4x4 inter blocks" );
    
    Yu Han's avatar
    Yu Han committed
      if (CU::isIBC(*pu.cu))
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      {
    
    Yu Han's avatar
    Yu Han committed
        isIBC = true;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      }
    
      if( pu.cu->affine )
      {
        CHECK( iRefIdx < 0, "iRefIdx incorrect." );
    
    
        mv[0] = pu.mvAffi[eRefPicList][0];
        mv[1] = pu.mvAffi[eRefPicList][1];
        mv[2] = pu.mvAffi[eRefPicList][2];
    
    
      if( !pu.cu->affine )
      {
    #if JVET_O1164_PS
        clipMv( mv[0], pu.cu->lumaPos(), pu.cu->lumaSize(), sps, *pu.cs->pps );
    #else
        clipMv( mv[0], pu.cu->lumaPos(), pu.cu->lumaSize(), sps );
    #endif
      }
    
    
      for( uint32_t comp = COMPONENT_Y; comp < pcYuvPred.bufs.size() && comp <= m_maxCompIDToPred; comp++ )
      {
        const ComponentID compID = ComponentID( comp );
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
        if (compID == COMPONENT_Y && !luma)
          continue;
        if (compID != COMPONENT_Y && !chroma)
          continue;
    
          CHECK( bioApplied, "BIO is not allowed with affine" );
    
    #if JVET_O0070_PROF
          m_iRefListIdx = eRefPicList;
    #endif
    
    #if JVET_O1164_RPR
    
          xPredAffineBlk( compID, pu, pu.cu->slice->getRefPic( eRefPicList, iRefIdx )->unscaledPic, mv, pcYuvPred, bi, pu.cu->slice->clpRng( compID ), pu.cu->slice->getScalingRatio( eRefPicList, iRefIdx ));
    
          xPredAffineBlk( compID, pu, pu.cu->slice->getRefPic( eRefPicList, iRefIdx ), mv, pcYuvPred, bi, pu.cu->slice->clpRng( compID ) );
    
    Yu Han's avatar
    Yu Han committed
          if (isIBC)
          {
            xPredInterBlk(compID, pu, pu.cu->slice->getPic(), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng(compID)
              , bioApplied
              , isIBC
            );
          }
          else
          {
    
    #if JVET_O1164_RPR
    
            xPredInterBlk( compID, pu, pu.cu->slice->getRefPic( eRefPicList, iRefIdx )->unscaledPic, mv[0], pcYuvPred, bi, pu.cu->slice->clpRng( compID ), bioApplied, isIBC, pu.cu->slice->getScalingRatio( eRefPicList, iRefIdx ) );
    
    Yu Han's avatar
    Yu Han committed
            xPredInterBlk(compID, pu, pu.cu->slice->getRefPic(eRefPicList, iRefIdx), mv[0], pcYuvPred, bi, pu.cu->slice->clpRng(compID)
              , bioApplied
              , isIBC
            );
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
    void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred, PelUnitBuf* yuvPredTmp /*= NULL*/)
    #else
    
    void InterPrediction::xPredInterBi(PredictionUnit& pu, PelUnitBuf &pcYuvPred)
    
    {
      const PPS   &pps   = *pu.cs->pps;
      const Slice &slice = *pu.cs->slice;
    
      CHECK( !pu.cu->affine && pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0 && ( pu.lwidth() + pu.lheight() == 12 ), "invalid 4x8/8x4 bi-predicted blocks" );
    
      WPScalingParam *wp0;
      WPScalingParam *wp1;
      int refIdx0 = pu.refIdx[REF_PIC_LIST_0];
      int refIdx1 = pu.refIdx[REF_PIC_LIST_1];
      pu.cs->slice->getWpScaling(REF_PIC_LIST_0, refIdx0, wp0);
      pu.cs->slice->getWpScaling(REF_PIC_LIST_1, refIdx1, wp1);
    
    #if JVET_O1140_SLICE_DISABLE_BDOF_DMVR_FLAG
      if (pu.cs->sps->getBDOFEnabledFlag() && (!pu.cs->slice->getDisBdofDmvrFlag()))
    #else
    
      if (pu.cs->sps->getBDOFEnabledFlag())
    
      {
        if (pu.cu->affine || m_subPuMC)
        {
    
          const bool biocheck0 = !((wp0[COMPONENT_Y].bPresentFlag || wp1[COMPONENT_Y].bPresentFlag) && slice.getSliceType() == B_SLICE);
    
          const bool biocheck1 = !(pps.getUseWP() && slice.getSliceType() == P_SLICE);
          if (biocheck0
            && biocheck1
    
            && PU::isBiPredFromDifferentDir(pu)
    
    #if JVET_O0634_BDOF_SIZE_CONSTRAINT
            && (pu.Y().height >= 8)
            && (pu.Y().width >= 8)
            && ((pu.Y().height * pu.Y().width) >= 128)
    #else
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
        if (bioApplied && pu.mhIntraFlag)
          bioApplied = false;
    #endif
    
    
        if (bioApplied && pu.cu->smvdMode)
        {
          bioApplied = false;
        }
    
    
        if (pu.cu->cs->sps->getUseGBi() && bioApplied && pu.cu->GBiIdx != GBI_DEFAULT)
    
      if (pu.mmvdEncOptMode == 2 && pu.mmvdMergeFlag) {
        bioApplied = false;
      }
    
      bool dmvrApplied = false;
      dmvrApplied = (pu.mvRefine) && PU::checkDMVRCondition(pu);
    
    
    #if JVET_O1164_RPR
      bool samePicSize = PU::isRefPicSameSize( pu );
      dmvrApplied = dmvrApplied && samePicSize;
      bioApplied = bioApplied && samePicSize;
    #endif
    
    
      for (uint32_t refList = 0; refList < NUM_REF_PIC_LIST_01; refList++)
      {
        if( pu.refIdx[refList] < 0)
        {
          continue;
        }
    
        RefPicList eRefPicList = (refList ? REF_PIC_LIST_1 : REF_PIC_LIST_0);
    
    
    Yu Han's avatar
    Yu Han committed
        CHECK(CU::isIBC(*pu.cu) && eRefPicList != REF_PIC_LIST_0, "Invalid interdir for ibc mode");
        CHECK(CU::isIBC(*pu.cu) && pu.refIdx[refList] != MAX_NUM_REF, "Invalid reference index for ibc mode");
    
    Yu Han's avatar
    Yu Han committed
        CHECK((CU::isInter(*pu.cu) && pu.refIdx[refList] >= slice.getNumRefIdx(eRefPicList)), "Invalid reference index");
    
        m_iRefListIdx = refList;
    
        PelUnitBuf pcMbBuf = ( pu.chromaFormat == CHROMA_400 ?
                               PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[refList][0], pcYuvPred.Y())) :
                               PelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[refList][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[refList][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[refList][2], pcYuvPred.Cr())) );
    
        if (pu.refIdx[0] >= 0 && pu.refIdx[1] >= 0)
        {
    
          if (dmvrApplied)
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
          {
            if (yuvPredTmp)
              xPredInterUni(pu, eRefPicList, pcMbBuf, true, false, true, true);
            continue;
          }
    #else
    
            continue; // mc will happen in processDMVR
    
          xPredInterUni ( pu, eRefPicList, pcMbBuf, true
    
            , bioApplied
            , true, true
          );
    
        }
        else
        {
          if( ( (pps.getUseWP() && slice.getSliceType() == P_SLICE) || (pps.getWPBiPred() && slice.getSliceType() == B_SLICE) ) )
          {
    
            xPredInterUni ( pu, eRefPicList, pcMbBuf, true
    
              , bioApplied
              , true, true
            );
    
            xPredInterUni( pu, eRefPicList, pcMbBuf, pu.cu->triangle
    
              , bioApplied
              , true, true
            );
    
      CPelUnitBuf srcPred0 = ( pu.chromaFormat == CHROMA_400 ?
                               CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y())) :
                               CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[0][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[0][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[0][2], pcYuvPred.Cr())) );
      CPelUnitBuf srcPred1 = ( pu.chromaFormat == CHROMA_400 ?
                               CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y())) :
                               CPelUnitBuf(pu.chromaFormat, PelBuf(m_acYuvPred[1][0], pcYuvPred.Y()), PelBuf(m_acYuvPred[1][1], pcYuvPred.Cb()), PelBuf(m_acYuvPred[1][2], pcYuvPred.Cr())) );
    
      if( !pu.cu->triangle && (!dmvrApplied) && (!bioApplied) && pps.getWPBiPred() && slice.getSliceType() == B_SLICE && pu.cu->GBiIdx==GBI_DEFAULT)
    
      {
        xWeightedPredictionBi( pu, srcPred0, srcPred1, pcYuvPred, m_maxCompIDToPred );
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
        if (yuvPredTmp)
          yuvPredTmp->copyFrom(pcYuvPred);
    #endif
    
      else if( !pu.cu->triangle && pps.getUseWP() && slice.getSliceType() == P_SLICE )
    
      {
        xWeightedPredictionUni( pu, srcPred0, REF_PIC_LIST_0, pcYuvPred, -1, m_maxCompIDToPred );
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
        if (yuvPredTmp)
          yuvPredTmp->copyFrom(pcYuvPred);
    #endif
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
          if (yuvPredTmp)
          {
            yuvPredTmp->addAvg(srcPred0, srcPred1, slice.clpRngs(), false);
          }
    #endif
    
          xProcessDMVR(pu, pcYuvPred, slice.clpRngs(), bioApplied);
        }
        else
        {
    
    #if JVET_O0108_DIS_DMVR_BDOF_CIIP
          xWeightedAverage( pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), bioApplied, yuvPredTmp);
    #else
    
          xWeightedAverage( pu, srcPred0, srcPred1, pcYuvPred, slice.getSPS()->getBitDepths(), slice.clpRngs(), bioApplied );
    
    }
    
    void InterPrediction::xPredInterBlk ( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv& _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng
    
    Yu Han's avatar
    Yu Han committed
                                         , bool isIBC
    
    #if JVET_O1164_RPR
                                         , const std::pair<int, int> scalingRatio
    #endif
    
                                         , SizeType dmvrWidth
                                         , SizeType dmvrHeight
                                         , bool bilinearMC
                                         , Pel *srcPadBuf
                                         , int32_t srcPadStride
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
                                        )
    
    {
      JVET_J0090_SET_REF_PICTURE( refPic, compID );
      const ChromaFormat  chFmt = pu.chromaFormat;
      const bool          rndRes = !bi;
    
    
      int shiftHor = MV_FRACTIONAL_BITS_INTERNAL + ::getComponentScaleX(compID, chFmt);
      int shiftVer = MV_FRACTIONAL_BITS_INTERNAL + ::getComponentScaleY(compID, chFmt);
    
      bool  wrapRef = false;
      Mv    mv(_mv);
    
      if( !isIBC && pu.cs->sps->getWrapAroundEnabledFlag() )
    
    #if JVET_O1164_PS
        wrapRef = wrapClipMv( mv, pu.blocks[0].pos(), pu.blocks[0].size(), pu.cs->sps, pu.cs->pps );
    #else
        wrapRef = wrapClipMv( mv, pu.blocks[0].pos(), pu.blocks[0].size(), pu.cs->sps );
    #endif
      }
    
    
    #if JVET_O0057_ALTHPELIF
      bool useAltHpelIf = pu.cu->imv == IMV_HPEL;
    #endif
    
      CHECK( pu.blocks[compID].width != dstPic.bufs[compID].width, "Destination buffer width doesn't match PU width" );
      CHECK( pu.blocks[compID].height != dstPic.bufs[compID].height, "Destination buffer height doesn't match PU height" );
    
      if( !isIBC && xPredInterBlkRPR( scalingRatio, *pu.cs->pps, pu.blocks[compID], refPic, mv, dstPic.bufs[compID].buf, dstPic.bufs[compID].stride, bi, wrapRef, clpRng, 0, useAltHpelIf ) )
    
      {
        CHECK( bilinearMC, "DMVR should be disabled with RPR" );
        CHECK( bioApplied, "BDOF should be disabled with RPR" );
    
      int xFrac = mv.hor & ((1 << shiftHor) - 1);
      int yFrac = mv.ver & ((1 << shiftVer) - 1);
    
    Yu Han's avatar
    Yu Han committed
      if (isIBC)
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      {
        xFrac = yFrac = 0;
    
        JVET_J0090_SET_CACHE_ENABLE( false );
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      }
    
      PelBuf &dstBuf  = dstPic.bufs[compID];
      unsigned width  = dstBuf.width;
      unsigned height = dstBuf.height;
    
      CPelBuf refBuf;
      {
    
        Position offset = pu.blocks[compID].pos().offset( mv.getHor() >> shiftHor, mv.getVer() >> shiftVer );
    
          refBuf = refPic->getRecoBuf(CompArea(compID, chFmt, offset, Size(dmvrWidth, dmvrHeight)), wrapRef);
    
        refBuf = refPic->getRecoBuf( CompArea( compID, chFmt, offset, pu.blocks[compID].size() ), wrapRef);
    
      if (NULL != srcPadBuf)
      {
        refBuf.buf = srcPadBuf;
        refBuf.stride = srcPadStride;
      }
      if (dmvrWidth)
      {
        width = dmvrWidth;
        height = dmvrHeight;
      }
    
      // backup data
      int backupWidth = width;
      int backupHeight = height;
      Pel *backupDstBufPtr = dstBuf.buf;
      int backupDstBufStride = dstBuf.stride;
    
    
      if (bioApplied && compID == COMPONENT_Y)
    
        width = width + 2 * BIO_EXTEND_SIZE + 2;
        height = height + 2 * BIO_EXTEND_SIZE + 2;
    
    
        // change MC output
        dstBuf.stride = width;
        dstBuf.buf = m_filteredBlockTmp[2 + m_iRefListIdx][compID] + 2 * dstBuf.stride + 2;
      }
    
    
    #if JVET_O0057_ALTHPELIF && !JVET_O1164_RPR
    
    ahenkel's avatar
    ahenkel committed
       bool useAltHpelIf = pu.cu->imv == IMV_HPEL;
    #endif
    
    
    #if JVET_O0057_ALTHPELIF
    
    ahenkel's avatar
    ahenkel committed
        m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng, bilinearMC, bilinearMC, useAltHpelIf);
    
        m_if.filterHor(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, xFrac, rndRes, chFmt, clpRng, bilinearMC, bilinearMC);
    
    #if JVET_O0057_ALTHPELIF
    
    ahenkel's avatar
    ahenkel committed
        m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng, bilinearMC, bilinearMC, useAltHpelIf);
    
        m_if.filterVer(compID, (Pel*)refBuf.buf, refBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, true, rndRes, chFmt, clpRng, bilinearMC, bilinearMC);
    
        PelBuf tmpBuf = dmvrWidth ? PelBuf(m_filteredBlockTmp[0][compID], Size(dmvrWidth, dmvrHeight)) : PelBuf(m_filteredBlockTmp[0][compID], pu.blocks[compID]);
        if (dmvrWidth == 0)
          tmpBuf.stride = dstBuf.stride;
    
    
        int vFilterSize = isLuma(compID) ? NTAPS_LUMA : NTAPS_CHROMA;
    
        if (bilinearMC)
        {
          vFilterSize = NTAPS_BILINEAR;
        }
    
    #if JVET_O0057_ALTHPELIF
    
    ahenkel's avatar
    ahenkel committed
        m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng, bilinearMC, bilinearMC, useAltHpelIf);
    
        m_if.filterHor(compID, (Pel*)refBuf.buf - ((vFilterSize >> 1) - 1) * refBuf.stride, refBuf.stride, tmpBuf.buf, tmpBuf.stride, backupWidth, backupHeight + vFilterSize - 1, xFrac, false, chFmt, clpRng, bilinearMC, bilinearMC);
    
    #if JVET_O0057_ALTHPELIF
    
    ahenkel's avatar
    ahenkel committed
        m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng, bilinearMC, bilinearMC, useAltHpelIf);
    
        m_if.filterVer(compID, (Pel*)tmpBuf.buf + ((vFilterSize >> 1) - 1) * tmpBuf.stride, tmpBuf.stride, dstBuf.buf, dstBuf.stride, backupWidth, backupHeight, yFrac, false, rndRes, chFmt, clpRng, bilinearMC, bilinearMC);
    
      JVET_J0090_SET_CACHE_ENABLE( srcPadStride == 0 ); // Enabled only in non-DMVR process, In DMVR process, srcPadStride is always non-zero
    
      if (bioApplied && compID == COMPONENT_Y)
    
    Daniel Luo's avatar
    Daniel Luo committed
        const int shift = std::max<int>(2, (IF_INTERNAL_PREC - clpRng.bd));
    
    #if JVET_O0594_BDOF_REF_SAMPLE_PADDING
        int xOffset = (xFrac < 8) ? 1 : 0;
        int yOffset = (yFrac < 8) ? 1 : 0;
        const Pel* refPel = refBuf.buf - yOffset * refBuf.stride - xOffset;
    #else
    
    Daniel Luo's avatar
    Daniel Luo committed
        const Pel* refPel = refBuf.buf - refBuf.stride - 1;
    
    Daniel Luo's avatar
    Daniel Luo committed
        Pel* dstPel = m_filteredBlockTmp[2 + m_iRefListIdx][compID] + dstBuf.stride + 1;
        for (int w = 0; w < (width - 2 * BIO_EXTEND_SIZE); w++)
        {
          Pel val = leftShift_round(refPel[w], shift);
          dstPel[w] = val - (Pel)IF_INTERNAL_OFFS;
        }
    
    
    #if JVET_O0594_BDOF_REF_SAMPLE_PADDING
        refPel = refBuf.buf + (1 - yOffset)*refBuf.stride - xOffset;
    #else
    
    Daniel Luo's avatar
    Daniel Luo committed
        refPel = refBuf.buf - 1;
    
    Daniel Luo's avatar
    Daniel Luo committed
        dstPel = m_filteredBlockTmp[2 + m_iRefListIdx][compID] + 2 * dstBuf.stride + 1;
        for (int h = 0; h < (height - 2 * BIO_EXTEND_SIZE - 2); h++)
        {
          Pel val = leftShift_round(refPel[0], shift);
          dstPel[0] = val - (Pel)IF_INTERNAL_OFFS;
    
          val = leftShift_round(refPel[width - 3], shift);
          dstPel[width - 3] = val - (Pel)IF_INTERNAL_OFFS;
    
          refPel += refBuf.stride;
          dstPel += dstBuf.stride;
        }
    
    
    #if JVET_O0594_BDOF_REF_SAMPLE_PADDING
        refPel = refBuf.buf + (height - 2 * BIO_EXTEND_SIZE - 2 + 1 - yOffset)*refBuf.stride - xOffset;
    #else
    
    Daniel Luo's avatar
    Daniel Luo committed
        refPel = refBuf.buf + (height - 2 * BIO_EXTEND_SIZE - 2)*refBuf.stride - 1;
    
    Daniel Luo's avatar
    Daniel Luo committed
        dstPel = m_filteredBlockTmp[2 + m_iRefListIdx][compID] + (height - 2 * BIO_EXTEND_SIZE)*dstBuf.stride + 1;
        for (int w = 0; w < (width - 2 * BIO_EXTEND_SIZE); w++)
        {
          Pel val = leftShift_round(refPel[w], shift);
          dstPel[w] = val - (Pel)IF_INTERNAL_OFFS;
        }
    
        // restore data
    
        width = backupWidth;
        height = backupHeight;
        dstBuf.buf = backupDstBufPtr;
        dstBuf.stride = backupDstBufStride;
      }
    
    bool InterPrediction::isSubblockVectorSpreadOverLimit( int a, int b, int c, int d, int predType )
    
    {
      int s4 = ( 4 << 11 );
      int filterTap = 6;
    
      if ( predType == 3 )
      {
        int refBlkWidth  = std::max( std::max( 0, 4 * a + s4 ), std::max( 4 * c, 4 * a + 4 * c + s4 ) ) - std::min( std::min( 0, 4 * a + s4 ), std::min( 4 * c, 4 * a + 4 * c + s4 ) );
        int refBlkHeight = std::max( std::max( 0, 4 * b ), std::max( 4 * d + s4, 4 * b + 4 * d + s4 ) ) - std::min( std::min( 0, 4 * b ), std::min( 4 * d + s4, 4 * b + 4 * d + s4 ) );
        refBlkWidth  = ( refBlkWidth >> 11 ) + filterTap + 3;
        refBlkHeight = ( refBlkHeight >> 11 ) + filterTap + 3;
    
        if ( refBlkWidth * refBlkHeight > ( filterTap + 9 ) * ( filterTap + 9 ) )
        {
          return true;
        }
      }
      else
      {
        int refBlkWidth  = std::max( 0, 4 * a + s4 ) - std::min( 0, 4 * a + s4 );
        int refBlkHeight = std::max( 0, 4 * b ) - std::min( 0, 4 * b );
        refBlkWidth  = ( refBlkWidth >> 11 ) + filterTap + 3;
        refBlkHeight = ( refBlkHeight >> 11 ) + filterTap + 3;
        if ( refBlkWidth * refBlkHeight > ( filterTap + 9 ) * ( filterTap + 5 ) )
        {
          return true;
        }
    
        refBlkWidth  = std::max( 0, 4 * c ) - std::min( 0, 4 * c );
        refBlkHeight = std::max( 0, 4 * d + s4 ) - std::min( 0, 4 * d + s4 );
        refBlkWidth  = ( refBlkWidth >> 11 ) + filterTap + 3;
        refBlkHeight = ( refBlkHeight >> 11 ) + filterTap + 3;
        if ( refBlkWidth * refBlkHeight > ( filterTap + 5 ) * ( filterTap + 9 ) )
        {
          return true;
        }
      }
      return false;
    }
    
    
    #if JVET_O1164_RPR
    void InterPrediction::xPredAffineBlk( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng, const std::pair<int, int> scalingRatio )
    #else
    
    void InterPrediction::xPredAffineBlk( const ComponentID& compID, const PredictionUnit& pu, const Picture* refPic, const Mv* _mv, PelUnitBuf& dstPic, const bool& bi, const ClpRng& clpRng )
    
    {
    
      JVET_J0090_SET_REF_PICTURE( refPic, compID );
      const ChromaFormat chFmt = pu.chromaFormat;
      int iScaleX = ::getComponentScaleX( compID, chFmt );
      int iScaleY = ::getComponentScaleY( compID, chFmt );
    
      Mv mvLT =_mv[0];
      Mv mvRT =_mv[1];
      Mv mvLB =_mv[2];
    
    
      // get affine sub-block width and height
      const int width  = pu.Y().width;
      const int height = pu.Y().height;
      int blockWidth = AFFINE_MIN_BLOCK_SIZE;
      int blockHeight = AFFINE_MIN_BLOCK_SIZE;
    
    
      CHECK(blockWidth  > (width >> iScaleX ), "Sub Block width  > Block width");
    
      CHECK(blockHeight > (height >> iScaleY), "Sub Block height > Block height");
    
      const int MVBUFFER_SIZE = MAX_CU_SIZE / MIN_PU_SIZE;
    
      const int cxWidth  = width  >> iScaleX;
      const int cxHeight = height >> iScaleY;
      const int iHalfBW  = blockWidth  >> 1;
      const int iHalfBH  = blockHeight >> 1;
    
      const int iBit = MAX_CU_DEPTH;
      int iDMvHorX, iDMvHorY, iDMvVerX, iDMvVerY;
    
      iDMvHorX = (mvRT - mvLT).getHor() << (iBit - floorLog2(cxWidth));
      iDMvHorY = (mvRT - mvLT).getVer() << (iBit - floorLog2(cxWidth));
    
      if ( pu.cu->affineType == AFFINEMODEL_6PARAM )
      {
    
        iDMvVerX = (mvLB - mvLT).getHor() << (iBit - floorLog2(cxHeight));
        iDMvVerY = (mvLB - mvLT).getVer() << (iBit - floorLog2(cxHeight));
    
      }
      else
      {
        iDMvVerX = -iDMvHorY;
        iDMvVerY = iDMvHorX;
      }
    
      int iMvScaleHor = mvLT.getHor() << iBit;
      int iMvScaleVer = mvLT.getVer() << iBit;
      const SPS &sps    = *pu.cs->sps;
      const int iMvShift = 4;
      const int iOffset  = 8;
    
    #if JVET_O1164_PS
      const int iHorMax = ( pu.cs->pps->getPicWidthInLumaSamples() + iOffset - pu.Y().x - 1 ) << iMvShift;
    #else
    
      const int iHorMax = ( sps.getPicWidthInLumaSamples()     + iOffset -      pu.Y().x - 1 ) << iMvShift;
    
      const int iHorMin = (      -(int)pu.cs->pcv->maxCUWidth  - iOffset - (int)pu.Y().x + 1 ) << iMvShift;
    
    #if JVET_O1164_PS
      const int iVerMax = ( pu.cs->pps->getPicHeightInLumaSamples() + iOffset - pu.Y().y - 1 ) << iMvShift;
    #else
    
      const int iVerMax = ( sps.getPicHeightInLumaSamples()    + iOffset -      pu.Y().y - 1 ) << iMvShift;
    
      const int iVerMin = (      -(int)pu.cs->pcv->maxCUHeight - iOffset - (int)pu.Y().y + 1 ) << iMvShift;
    
    
      PelBuf tmpBuf = PelBuf(m_filteredBlockTmp[0][compID], pu.blocks[compID]);
    
      const int vFilterSize = isLuma(compID) ? NTAPS_LUMA : NTAPS_CHROMA;
    
    
      const int shift = iBit - 4 + MV_FRACTIONAL_BITS_INTERNAL;