Skip to content
Snippets Groups Projects
InterSearch.h 68.9 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-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     InterSearch.h
        \brief    inter search class (header)
     */
    
    #ifndef __INTERSEARCH__
    #define __INTERSEARCH__
    
    // Include files
    #include "CABACWriter.h"
    #include "EncCfg.h"
    
    #include "CommonLib/MotionInfo.h"
    #include "CommonLib/InterPrediction.h"
    #include "CommonLib/TrQuant.h"
    #include "CommonLib/Unit.h"
    #include "CommonLib/UnitPartitioner.h"
    #include "CommonLib/RdCost.h"
    
    #if JVET_V0094_BILATERAL_FILTER || JVET_X0071_CHROMA_BILATERAL_FILTER
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #include "CommonLib/BilateralFilter.h"
    #endif
    
    Yu Han's avatar
    Yu Han committed
    #include "CommonLib/IbcHashMap.h"
    
    #include "CommonLib/Hash.h"
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    #include <unordered_map>
    #include <vector>
    
    Taoran Lu's avatar
    Taoran Lu committed
    #include "EncReshape.h"
    
    //! \ingroup EncoderLib
    //! \{
    
    // ====================================================================================================================
    // Class definition
    // ====================================================================================================================
    
    static const uint32_t MAX_NUM_REF_LIST_ADAPT_SR = 2;
    static const uint32_t MAX_IDX_ADAPT_SR          = 33;
    static const uint32_t NUM_MV_PREDICTORS         = 3;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
    struct BlkRecord
    {
      std::unordered_map<Mv, Distortion> bvRecord;
    };
    
    struct AffineMVInfo
    {
      Mv  affMVs[2][33][3];
      int x, y, w, h;
    };
    
    
    struct BlkUniMvInfo
    {
      Mv uniMvs[2][33];
      int x, y, w, h;
    };
    
    
      Mv acMvAffine4Para[2][3];
    
      Mv acMvAffine6Para[2][3];
      int16_t affine4ParaRefIdx[2];
      int16_t affine6ParaRefIdx[2];
      Distortion hevcCost[3];
      Distortion affineCost[3];
      bool affine4ParaAvail;
      bool affine6ParaAvail;
    } EncAffineMotion;
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if MERGE_ENC_OPT
    struct ModeInfo
    {
      uint32_t mergeCand;
      bool     isRegularMerge;
      bool     isMMVD;
      bool     isCIIP;
    #if CIIP_PDPC
      bool     isCiipPDPC;
    
    #if JVET_AG0135_AFFINE_CIIP
      bool     isCiipAffine;
    #endif
    
    #if JVET_X0141_CIIP_TIMD_TM && JVET_W0123_TIMD_FUSION
      int      intraMode;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
      bool     isAffine;
    #if AFFINE_MMVD
      bool     isAffineMmvd;
    #endif
    #if TM_MRG
      bool     isTMMrg;
    
    Han Huang's avatar
    Han Huang committed
    #endif
    
    #if JVET_AG0276_LIC_FLAG_SIGNALING
      bool     isTMMrgOppositeLic;
      bool     isOppositeLic;
      bool     isAffOppositeLic;
    #endif
    
    Han Huang's avatar
    Han Huang committed
    #if JVET_X0049_ADAPT_DMVR
      bool     isBMMrg;
      uint8_t  bmDir;
    
    #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
      bool isAffBMMrg;
      uint8_t affBMDir;
    #endif
    
    #if JVET_AA0070_RRIBC
      int rribcFlipType;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
      bool     isGeo;
      uint8_t     geoSplitDir;
      uint8_t     geoMergeIdx0;
      uint8_t     geoMergeIdx1;
    #if ENABLE_OBMC
      bool      isOBMC;
    #endif
      ModeInfo() : mergeCand(0), isRegularMerge(false), isMMVD(false)
        , isCIIP(false)
    #if CIIP_PDPC
        , isCiipPDPC(false)
    
    #if JVET_AG0135_AFFINE_CIIP
        , isCiipAffine(false)
    #endif
    
    #if JVET_X0141_CIIP_TIMD_TM && JVET_W0123_TIMD_FUSION
        , intraMode(0)
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
        , isAffine(false)
    #if AFFINE_MMVD
        , isAffineMmvd(false)
    #endif
    #if TM_MRG
        , isTMMrg(false)
    #endif
    
    #if JVET_AG0276_LIC_FLAG_SIGNALING
        , isTMMrgOppositeLic(false)
        , isOppositeLic(false)
        , isAffOppositeLic(false)
    #endif
    
    Han Huang's avatar
    Han Huang committed
    #if JVET_X0049_ADAPT_DMVR
        , isBMMrg(false)
        , bmDir(0)
    
    #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
        , isAffBMMrg(false)
        , affBMDir(0)
    #endif
    
    #if JVET_AA0070_RRIBC
        , rribcFlipType(0)
    
    Han Huang's avatar
    Han Huang committed
    #endif
      , isGeo(false), geoSplitDir(0), geoMergeIdx0(0), geoMergeIdx1(0)
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if ENABLE_OBMC
        , isOBMC(false)
    #endif
      {}
      ModeInfo(const uint32_t mergeCand, const bool isRegularMerge, const bool isMMVD, const bool isCIIP
    #if CIIP_PDPC
        , const bool isCiipPDPC
    
    #if JVET_AG0135_AFFINE_CIIP
        , const bool isCiipAffine
    #endif
    
    #if JVET_X0141_CIIP_TIMD_TM && JVET_W0123_TIMD_FUSION
        , const int intraMode
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
        , const bool isAffine
    #if ENABLE_OBMC
        , const bool isOBMC = false
    #endif
    #if AFFINE_MMVD
        , const bool isAffineMmvd = false
    #endif
    #if TM_MRG
        , const bool isTMMrg = false
    
    #endif
    #if JVET_AG0276_LIC_FLAG_SIGNALING
        , const bool isTMMrgOppositeLic = false
        , const bool isOppositeLic = false
        , const bool isAffOppositeLic = false
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
      ) :
        mergeCand(mergeCand), isRegularMerge(isRegularMerge), isMMVD(isMMVD), isCIIP(isCIIP)
    #if CIIP_PDPC
        , isCiipPDPC(isCiipPDPC)
    
    #if JVET_AG0135_AFFINE_CIIP
        , isCiipAffine(isCiipAffine)
    #endif
    
    #if JVET_X0141_CIIP_TIMD_TM && JVET_W0123_TIMD_FUSION
        , intraMode(intraMode)
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
        , isAffine(isAffine)
    #if AFFINE_MMVD
        , isAffineMmvd(isAffineMmvd)
    #endif
    #if TM_MRG
        , isTMMrg(isTMMrg)
    
    #if JVET_AG0276_LIC_FLAG_SIGNALING
        , isTMMrgOppositeLic(isTMMrgOppositeLic)
        , isOppositeLic(isOppositeLic)
        , isAffOppositeLic(isAffOppositeLic)
    #endif
    
    #if JVET_X0049_ADAPT_DMVR
        , isBMMrg( false )
        , bmDir( 0 )
    
    #endif
    #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
        , isAffBMMrg(false)
        , affBMDir(0)
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
        , isGeo(false), geoSplitDir(0), geoMergeIdx0(0), geoMergeIdx1(0)
    #if ENABLE_OBMC
        , isOBMC(false)
    #endif
      {}
      ModeInfo(const CodingUnit cu, const PredictionUnit pu)
      {
    #if AFFINE_MMVD
    
    #if JVET_Y0067_ENHANCED_MMVD_MVD_SIGN_PRED
        mergeCand = pu.afMmvdFlag ?  pu.afMmvdMergeIdx : pu.mergeIdx;
    
    #if JVET_AA0132_CONFIGURABLE_TM_TOOLS
        mergeCand = !pu.cs->sps->getUseTMMMVD() && pu.afMmvdFlag ? pu.afMmvdBaseIdx * ECM3_AF_MMVD_MAX_REFINE_NUM + pu.afMmvdStep * ECM3_AF_MMVD_OFFSET_DIR + pu.afMmvdDir : mergeCand;
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
        mergeCand = pu.afMmvdFlag ? pu.afMmvdBaseIdx * AF_MMVD_MAX_REFINE_NUM + pu.afMmvdStep * AF_MMVD_OFFSET_DIR + pu.afMmvdDir : pu.mergeIdx;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #else
        mergeCand = pu.mergeIdx;
    #endif
        isRegularMerge = pu.regularMergeFlag;
        isMMVD = pu.mmvdMergeFlag || cu.mmvdSkip;
        isCIIP = pu.ciipFlag;
    #if CIIP_PDPC
        isCiipPDPC = pu.ciipPDPC;
    
    #if JVET_AG0135_AFFINE_CIIP
        isCiipAffine = pu.ciipAffine;
    #endif
    
    #if JVET_X0141_CIIP_TIMD_TM && JVET_W0123_TIMD_FUSION
        intraMode = pu.intraDir[0];
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
        isAffine = cu.affine;
    #if AFFINE_MMVD
        isAffineMmvd = pu.afMmvdFlag;
    #endif
    #if TM_MRG
        isTMMrg = pu.tmMergeFlag;
    
    Han Huang's avatar
    Han Huang committed
    #endif
    
    #if JVET_AG0276_LIC_FLAG_SIGNALING
        isTMMrgOppositeLic = pu.tmMergeFlagOppositeLic;
        isOppositeLic = pu.mergeOppositeLic;
        isAffOppositeLic = pu.affineOppositeLic;
    #endif
    
    Han Huang's avatar
    Han Huang committed
    #if JVET_X0049_ADAPT_DMVR
        isBMMrg = pu.bmMergeFlag;
        bmDir = pu.bmDir;
    
    #if JVET_AD0182_AFFINE_DMVR_PLUS_EXTENSIONS
        isAffBMMrg = pu.affBMMergeFlag;
        affBMDir = pu.affBMDir;
    #endif
    
    #if JVET_AA0070_RRIBC
        rribcFlipType = cu.rribcFlipType;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
        isGeo = cu.geoFlag;
        geoSplitDir = pu.geoSplitDir;
        geoMergeIdx0 = pu.geoMergeIdx0;
        geoMergeIdx1 = pu.geoMergeIdx1;
    #if ENABLE_OBMC
        isOBMC = cu.obmcFlag;
    
    #endif
    #if JVET_AG0112_REGRESSION_BASED_GPM_BLENDING
        CHECK(cu.geoBlendFlag && (pu.geoMergeIdx0 != pu.mergeIdx || pu.geoMergeIdx0 != mergeCand),"ModeInfo() failed.");
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
      }
    };
    #endif
    
    
    #if JVET_AC0112_IBC_CIIP
    struct ModeIbcInfo
    {
    #if JVET_AC0112_IBC_GPM
      uint32_t mergeCand;
      bool     isCIIP;
      int      dirIdx;
      bool     isIbcGpm;
      int      mergeIdx0;
      int      mergeIdx1;
      int      splitDir;
      int      bldIdx;
      int      combIdx;
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
      ModeIbcInfo() : mergeCand(0), isCIIP(false), dirIdx(0), isIbcGpm(false), mergeIdx0(MAX_UCHAR), mergeIdx1(MAX_UCHAR), splitDir(0), bldIdx(0), combIdx(0)
    #else
    
      ModeIbcInfo() : mergeCand(0), isCIIP(false), dirIdx(0), isIbcGpm(false), mergeIdx0(0), mergeIdx1(0), splitDir(0), bldIdx(0), combIdx(0)
    
      {}
      ModeIbcInfo(const uint32_t mergeCand, const bool isCIIP, const int dirIdx, const bool isIbcGpm, const int mergeIdx0, const int mergeIdx1, const int splitDir, const int bldIdx, const int combIdx
      ) :
        mergeCand(mergeCand), isCIIP(isCIIP), dirIdx(dirIdx), isIbcGpm(isIbcGpm), mergeIdx0(mergeIdx0), mergeIdx1(mergeIdx1), splitDir(splitDir), bldIdx(bldIdx), combIdx(combIdx)
      {}
      ModeIbcInfo(const CodingUnit cu, const PredictionUnit pu)
      {
        mergeCand = pu.mergeIdx;
        isCIIP = pu.ibcCiipFlag;
        dirIdx = pu.ibcCiipIntraIdx;
        isIbcGpm = pu.ibcGpmFlag;
        mergeIdx0 = pu.ibcGpmMergeIdx0;
        mergeIdx1 = pu.ibcGpmMergeIdx1;
        splitDir = pu.ibcGpmSplitDir;
        bldIdx = pu.ibcGpmBldIdx;
      }
    #else
      uint32_t mergeCand;
      bool     isCIIP;
      int      dirIdx;
      ModeIbcInfo() : mergeCand(0), isCIIP(false), dirIdx(0)
      {}
      ModeIbcInfo(const uint32_t mergeCand, const bool isCIIP, const int dirIdx
      ) :
        mergeCand(mergeCand), isCIIP(isCIIP), dirIdx(dirIdx)
      {}
      ModeIbcInfo(const CodingUnit cu, const PredictionUnit pu)
      {
        mergeCand = pu.mergeIdx;
        isCIIP = pu.ibcCiipFlag;
        dirIdx = pu.ibcCiipIntraIdx;
      }
    #endif
    };
    #endif
    
    #if JVET_AC0112_IBC_GPM && !JVET_AC0112_IBC_CIIP
    struct ModeIbcInfo
    {
      uint32_t mergeCand;
      bool     isIbcGpm;
      int      mergeIdx0;
      int      mergeIdx1;
      int      splitDir;
      int      bldIdx;
      int      combIdx;
      ModeIbcInfo() : mergeCand(0), isIbcGpm(false), mergeIdx0(0), mergeIdx1(0), splitDir(0), bldIdx(0), combIdx(0)
      {}
      ModeIbcInfo(const uint32_t mergeCand, const bool isIbcGpm, const int mergeIdx0, const int mergeIdx1, const int splitDir, const int bldIdx, const int combIdx
      ) :
        mergeCand(mergeCand), isIbcGpm(isIbcGpm), mergeIdx0(mergeIdx0), mergeIdx1(mergeIdx1), splitDir(splitDir), bldIdx(bldIdx), combIdx(combIdx)
      {}
      ModeIbcInfo(const CodingUnit cu, const PredictionUnit pu)
      {
        mergeCand = pu.mergeIdx;
        isIbcGpm = pu.ibcGpmFlag;
        mergeIdx0 = pu.ibcGpmMergeIdx0;
        mergeIdx1 = pu.ibcGpmMergeIdx1;
        splitDir = pu.ibcGpmSplitDir;
        bldIdx = pu.ibcGpmBldIdx;
      }
    };
    #endif
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if INTER_LIC
    class EncFastLICCtrl
    {
      double m_amvpRdBeforeLIC[NUM_IMV_MODES];
    
    public:
      EncFastLICCtrl() { init(); }
    
      void init()
      {
        m_amvpRdBeforeLIC[IMV_OFF ] = std::numeric_limits<double>::max();
        m_amvpRdBeforeLIC[IMV_FPEL] = std::numeric_limits<double>::max();
        m_amvpRdBeforeLIC[IMV_4PEL] = std::numeric_limits<double>::max();
        m_amvpRdBeforeLIC[IMV_HPEL] = std::numeric_limits<double>::max();
      }
    
      bool skipRDCheckForLIC( bool isLIC
                             , int imv, double curBestRd
                             , uint32_t cuNumPel
      )
      {
        bool skipLIC = false;
        if (isLIC)
        {
          skipLIC |= skipLicBasedOnBestAmvpRDBeforeLIC(imv, curBestRd);
          skipLIC |= (cuNumPel < LIC_MIN_CU_PIXELS);
        }
        return skipLIC;
      }
    
    public:
      void setBestAmvpRDBeforeLIC(const CodingUnit& cu, double curCuRdCost)
      {
    
        m_amvpRdBeforeLIC[cu.imv] = !cu.firstPU->mergeFlag && cu.predMode != MODE_IBC && !cu.licFlag ? std::min(curCuRdCost, m_amvpRdBeforeLIC[cu.imv]) : m_amvpRdBeforeLIC[cu.imv];
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      }
    private:
      bool skipLicBasedOnBestAmvpRDBeforeLIC(uint8_t curCuimvIdx, double curBestRdCost)
      {
        return m_amvpRdBeforeLIC[curCuimvIdx] != std::numeric_limits<double>::max()
            && m_amvpRdBeforeLIC[curCuimvIdx] > curBestRdCost * LIC_AMVP_SKIP_TH;
      }
    };
    #endif
    
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
    template <int N>
    struct SrchCostBv
    {
      static const int maxSize  = N;
      static const int capacity = (N) + 1;
    
      uint32_t   cnt;
      bool       enableFracIBC;         // Just to make sure cfg-off results and macro-off results will match
      bool       enableMultiCandSrch;   // True: search best fracBv among best N integer BVs; False: search best fracBv among best integer BVs and best fracBv of previous round
      Distortion costList  [capacity];
      Mv         mvList    [capacity];
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
      int        mergeIdxList[capacity];
    #endif
    
      uint8_t    imvList   [capacity];
      uint8_t    mvpIdxList[capacity];
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
      int        bvTypeList[capacity];
    #endif
    #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
    
    #if JVET_AE0078_IBC_LIC_EXTENSION
      bool       skipLicSrch[capacity];
      int        bvLicIdx[capacity];
    #endif
    
    
      SrchCostBv()
      : cnt                 (0)
      , enableFracIBC       (false)
      , enableMultiCandSrch (false)
      {
        mvList[maxSize].setZero();
      }
    
      void init(bool resetHistoryMv = false, bool _enableFracIBC = false)
      {
        cnt = 0;
        enableFracIBC       = _enableFracIBC;
        enableMultiCandSrch = _enableFracIBC;
        if (resetHistoryMv)
        {
          mvList[maxSize].setZero();
    
    #if JVET_AE0159_FIBC
          bvFilter[maxSize] = false;
    
    #endif
    #if JVET_AE0078_IBC_LIC_EXTENSION
          bvLicIdx[maxSize] = 0;
          skipLicSrch[maxSize] = false;
    
        }
      }
    
      void cutoff(double ratio)
      {
        if (N >= 2)
        {
          if (cnt >= 2)
          {
            double th = ratio * (double)costList[0];
    
            for (int i = 1; i < cnt; ++i)
            {
              if ((double)costList[i] > th)
              {
                cnt = i;
                return;
              }
            }
          }
        }
      }
    
      int find(int mvx, int mvy
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
             , int mergeIdx
    #endif
    
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
             , int bvType
    #endif
    #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
             , bool bvFlip
    
    #endif
    #if JVET_AE0078_IBC_LIC_EXTENSION
             , int bvLic
    
    #endif
      )
      {
        for (int i = 0; i < (int)cnt; ++i)
        {
          if (mvList[i].getHor() == mvx && mvList[i].getVer() == mvy
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
            && mergeIdxList[i] == mergeIdx
    #endif
    
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
            && bvTypeList[i] == bvType
    #endif
    #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
            && bvFlipList[i] == bvFlip
    
    #endif
    #if JVET_AE0078_IBC_LIC_EXTENSION
            && bvLicIdx[i] == bvLic
    
    #endif
            )
          {
            return i;
          }
        }
        return NOT_VALID;
      }
    
      void  replaceAt(uint32_t idxSrc, uint32_t idxDst)
      {
        if (idxSrc != idxDst)
        {
          costList  [idxDst] = costList  [idxSrc];
          mvList    [idxDst] = mvList    [idxSrc];
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
          mergeIdxList[idxDst] = mergeIdxList[idxSrc];
    #endif
    
          imvList   [idxDst] = imvList   [idxSrc];
          mvpIdxList[idxDst] = mvpIdxList[idxSrc];
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
          bvTypeList[idxDst] = bvTypeList[idxSrc];
    #endif
    #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
          bvFlipList[idxDst] = bvFlipList[idxSrc];
    
    #endif
    #if JVET_AE0078_IBC_LIC_EXTENSION
          bvLicIdx[idxDst] = bvLicIdx[idxSrc];
    
          skipLicSrch[idxDst] = skipLicSrch[idxSrc];
    
    #endif
    #if JVET_AE0159_FIBC
          bvFilter[idxDst] = bvFilter[idxSrc];
    
    #endif
        }
      }
    
      int  insert(Distortion cost, int mvx, int mvy
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
                , int mergeIdx
    #endif
    
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
                , int bvType = 0
    #endif
    #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
                , bool bvFlip = true
    
    #endif
    #if JVET_AE0078_IBC_LIC_EXTENSION
                , int bvLic = 0
    
    #endif
      )
      {
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
        // Ignore 1-D BV's
        if (bvType != 0)
        {
          return NOT_VALID;
        }
    #endif
    #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
        bvFlip = bvType == 0 ? false : bvFlip;
    #endif
    
        // Find insertion index
        int insertIdx = NOT_VALID;
        for (int i = 0; i < (int)cnt; ++i)
        {
          if (cost <= costList[i])
          {
            if (cost == costList[i])
            {
              if (mvList[i].getHor() == mvx && mvList[i].getVer() == mvy
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
                && mergeIdxList[i] == mergeIdx
    #endif
    
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
                && bvTypeList[i] == bvType
    #endif
    #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
                && bvFlipList[i] == bvFlip
    
    #endif
    #if JVET_AE0078_IBC_LIC_EXTENSION
                && bvLicIdx[i] == bvLic
    
    #endif
                )
              {
                return NOT_VALID;
              }
            }
            else
            {
              insertIdx = i;
              break;
            }
          }
        }
    
        // Do insertion
        auto setAt = [&](uint32_t idx)
        {
          costList[idx] = cost;
          mvList[idx].set(mvx, mvy);
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
          mergeIdxList[idx] = mergeIdx;
    #endif
    
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
          bvTypeList[idx] = bvType;
    #endif
    #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
          bvFlipList[idx] = bvFlip;
    
    #endif
    #if JVET_AE0078_IBC_LIC_EXTENSION
          bvLicIdx[idx] = bvLic;
    
    #endif
    #if JVET_AE0159_FIBC
          bvFilter[idx] = false;
    
    #endif
        };
    
        auto replaceNext = [&](uint32_t idx)
        {
          costList[idx + 1] = costList[idx];
          mvList[idx + 1].set(mvList[idx].getHor(), mvList[idx].getVer());
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
          mergeIdxList[idx + 1] = mergeIdxList[idx];
    #endif
    
    #if JVET_AA0070_RRIBC || JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV
          bvTypeList[idx + 1] = bvTypeList[idx];
    #endif
    #if JVET_AC0060_IBC_BVP_CLUSTER_RRIBC_BVD_SIGN_DERIV && JVET_AA0070_RRIBC
          bvFlipList[idx + 1] = bvFlipList[idx];
    
    #endif
    #if JVET_AE0078_IBC_LIC_EXTENSION
          bvLicIdx[idx + 1] = bvLicIdx[idx];
    
    #endif
    #if JVET_AE0159_FIBC
          bvFilter[idx + 1] = bvFilter[idx];
    
    #endif
        };
    
        if (insertIdx != NOT_VALID)
        {
          for (int i = (cnt < N ? cnt - 1 : N - 2); i >= insertIdx; --i)
          {
            replaceNext(i);
          }
          setAt(insertIdx);
    
          if (cnt < N)
          {
            ++cnt;
          }
          return insertIdx;
        }
        else if (cnt < N)
        {
          insertIdx = cnt;
          setAt(insertIdx);
    
          ++cnt;
          return insertIdx;
        }
        else
        {
          return NOT_VALID;
        }
      }
    };
    
    typedef SrchCostBv<4> SrchCostIntBv;
    #endif
    
    
    class InterSearch : public InterPrediction, AffineGradientSearch
    
    {
    private:
      EncModeCtrl     *m_modeCtrl;
    
      PelStorage      m_tmpPredStorage              [NUM_REF_PIC_LIST_01];
      PelStorage      m_tmpStorageLCU;
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
      PelStorage      m_tmpStorageCUflipH;
      PelStorage      m_tmpStorageCUflipV;
    public:
      SrchCostIntBv   m_bestSrchCostIntBv;
    
    #if JVET_AE0159_FIBC || JVET_AE0078_IBC_LIC_EXTENSION
    
      SrchCostIntBv   m_bestSrchCostIbcFilter;
    #endif
    
      PelStorage      m_tmpAffiStorage;
      Pel*            m_tmpAffiError;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if AFFINE_ENC_OPT
      Pel*            m_tmpAffiDeri[2];
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    #if JVET_AC0112_IBC_CIIP
      PelStorage      m_ibcCiipBuffer;
    #endif
    #if JVET_AC0112_IBC_CIIP || JVET_AC0112_IBC_LIC
    #if JVET_AA0070_RRIBC
      AMVPInfo        m_amvpInfo[3];
      AMVPInfo        m_amvpInfo4Pel[3];
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
      AMVPInfo        m_amvpInfoHPel[3];
      AMVPInfo        m_amvpInfoQPel[3];
    #endif
    
    #else
      AMVPInfo        m_amvpInfo;
      AMVPInfo        m_amvpInfo4Pel;
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
      AMVPInfo        m_amvpInfoHPel;
      AMVPInfo        m_amvpInfoQPel;
    #endif
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
      Pel**           m_amvpMergeBuffer;
      MergeCtx        m_amvpMergeCtx;
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    
    #if MULTI_HYP_PRED
      MergeCtx        m_geoMrgCtx;
    
    #if JVET_AD0213_LIC_IMP
      int             m_mhpMrgTempBufSet;
      PelUnitBuf      m_mhpMrgTempBuf[GEO_MAX_NUM_UNI_CANDS];
      PelUnitBuf      m_mhpMrgTempBufLic[GEO_MAX_NUM_UNI_CANDS];
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      bool            m_mhpMrgTempBufSet;
      PelUnitBuf      m_mhpMrgTempBuf[GEO_MAX_NUM_UNI_CANDS];
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      PelUnitBuf      m_mhpTempBuf[GEO_MAX_TRY_WEIGHTED_SAD];
      int             m_mhpTempBufCounter;
    #endif
    
    
      CodingStructure ****m_pSplitCS;
      CodingStructure ****m_pFullCS;
    
      CodingStructure **m_pSaveCS;
    
      ClpRng          m_lumaClpRng;
    
      uint32_t        m_estWeightIdxBits[BCW_NUM];
      BcwMotionParam  m_uniMotions;
    
      bool            m_affineModeSelected;
    
    #if JVET_AD0213_LIC_IMP
      bool            m_doAffineLic;
    #if TM_AMVP
      bool            updateMvNeeded;
      bool            updateL1ZeroFlagMvNeeded;
      bool            updateSMVDMvNeeded;
      bool            isBDOFNotNeeded;
      AMVPInfo        *amvpCand0;
      AMVPInfo        *amvpCand1;
      AMVPInfo        *amvpCand0Lic;
      AMVPInfo        *amvpCand1Lic;
      int             mvpIdx0;
      int             mvpIdx1;
    #endif
    #endif
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      std::unordered_map< Position, std::unordered_map< Size, BlkRecord> > m_ctuRecord;
    
    #if JVET_AA0070_RRIBC
      Distortion      minCostProj;
    #endif
    
      AffineMVInfo       *m_affMVList;
      int             m_affMVListIdx;
      int             m_affMVListSize;
      int             m_affMVListMaxSize;
    
      BlkUniMvInfo*   m_uniMvList;
      int             m_uniMvListIdx;
      int             m_uniMvListSize;
      int             m_uniMvListMaxSize;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if INTER_LIC
      BlkUniMvInfo*   m_uniMvListLIC;
      int             m_uniMvListIdxLIC;
      int             m_uniMvListSizeLIC;
    
    #endif
    #if JVET_AG0098_AMVP_WITH_SBTMVP
      bool*           m_amvpSbTmvpBufValid;
      MotionInfo*     m_amvpSbTmvpMotionBuf;
      Position        m_amvpSbTmvpBufTLPos;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
      Distortion      m_hevcCost;
    
      EncAffineMotion m_affineMotion;
    
      PatentBvCand    m_defaultCachedBvs;
    
    #if JVET_AE0059_INTER_CCCM
      Pel             **m_interCccmStorage;
    #endif
    
    #if JVET_AF0073_INTER_CCP_MERGE
      Pel             **m_interCcpMergeStorage;
    #endif
    
    #if JVET_AE0169_BIPREDICTIVE_IBC
      Distortion      m_bestBvpSADHADCost;
    #endif
    
    protected:
      // interface to option
      EncCfg*         m_pcEncCfg;
    
      // interface to classes
    
    #if JVET_V0094_BILATERAL_FILTER || JVET_X0071_CHROMA_BILATERAL_FILTER
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      BilateralFilter* m_bilateralFilter;
    #endif
    
    #if JVET_AG0276_NLIC
    public:
    
    Taoran Lu's avatar
    Taoran Lu committed
      EncReshape*     m_pcReshape;
    
    protected:
    #else
      EncReshape*     m_pcReshape;
    #endif
    
    
      // ME parameters
      int             m_iSearchRange;
      int             m_bipredSearchRange; // Search range for bi-prediction
      MESearchMethod  m_motionEstimationSearchMethod;
      int             m_aaiAdaptSR                  [MAX_NUM_REF_LIST_ADAPT_SR][MAX_IDX_ADAPT_SR];
    
      // RD computation
      CABACWriter*    m_CABACEstimator;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      CtxCache*       m_ctxCache;
    
    #if JVET_AA0133_INTER_MTS_OPT
      double          m_globalBestLumaCost;
      double          m_bestDCT2PassLumaCost;
    #endif
    
      RefPicList      m_currRefPicList;
      int             m_currRefPicIndex;
    
      bool            m_skipFracME;
    
      int             m_numHashMVStoreds[NUM_REF_PIC_LIST_01][MAX_NUM_REF];
      Mv              m_hashMVStoreds[NUM_REF_PIC_LIST_01][MAX_NUM_REF][5];
    
    #if JVET_Y0129_MVD_SIGNAL_AMVP_MERGE_MODE
      uint32_t            m_auiMVPIdxCost               [AMVP_MAX_NUM_CANDS+1][AMVP_MAX_NUM_CANDS+1+1]; //th array bounds
    #else
    
      uint32_t            m_auiMVPIdxCost               [AMVP_MAX_NUM_CANDS+1][AMVP_MAX_NUM_CANDS+1]; //th array bounds
    
    
      Mv              m_integerMv2Nx2N              [NUM_REF_PIC_LIST_01][MAX_NUM_REF];
    
      bool            m_isInitialized;
    
    
      Mv              m_acBVs[2 * IBC_NUM_CANDIDATES];
      unsigned int    m_numBVs;
    
      bool            m_useCompositeRef;
    
      Distortion      m_estMinDistSbt[NUMBER_SBT_MODE + 1]; // estimated minimum SSE value of the PU if using a SBT mode
      uint8_t         m_sbtRdoOrder[NUMBER_SBT_MODE];       // order of SBT mode in RDO
      bool            m_skipSbtAll;                         // to skip all SBT modes for the current PU
      uint8_t         m_histBestSbt;                        // historical best SBT mode for PU of certain SSE values
      uint8_t         m_histBestMtsIdx;                     // historical best MTS idx  for PU of certain SSE values
    
      bool            m_clipMvInSubPic;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if INTER_LIC
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      EncFastLICCtrl  m_fastLicCtrl;
    #endif
    
    #if JVET_AF0073_INTER_CCP_MERGE
      bool m_isInterCcpModelReady;
      int  m_validNum;
      CCPModelCandidate m_interCcpMergeList[MAX_CCP_CAND_LIST_SIZE];
    #endif
    
    #if JVET_X0083_BM_AMVP_MERGE_MODE
    public:
      Distortion      m_amvpOnlyCost;
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    
    public:
    #if MULTI_HYP_PRED
    
    #if JVET_AD0213_LIC_IMP
      void             initMHPTmpBuffer(PelStorage* mergeTmpBuffer, PelStorage* mergeTmpBuffer2, int maxNumMergeCandidates,
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      void             initMHPTmpBuffer(PelStorage* mergeTmpBuffer, int maxNumMergeCandidates,
    
    Vadim Seregin's avatar
    Vadim Seregin committed
        PelStorage* mhpTmpBuffer, int maxNumStoredMhpCandidates,
        const UnitArea localUnitArea)
      {
    
    #if JVET_AD0213_LIC_IMP
        m_mhpMrgTempBufSet = 0;
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
        m_mhpMrgTempBufSet = false;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
        for (uint8_t mergeCand = 0; mergeCand < maxNumMergeCandidates; mergeCand++)
        {
          m_mhpMrgTempBuf[mergeCand] = mergeTmpBuffer[mergeCand].getBuf(localUnitArea);
    
    #if JVET_AD0213_LIC_IMP
          m_mhpMrgTempBufLic[mergeCand] = mergeTmpBuffer2[mergeCand].getBuf(localUnitArea);
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
        }
        for (uint8_t i = 0; i < maxNumStoredMhpCandidates; i++)
        {
          m_mhpTempBuf[i] = mhpTmpBuffer[i].getBuf(localUnitArea);
        }
        m_mhpTempBufCounter = 0;
      }
    
    #if JVET_AD0213_LIC_IMP
      void             setGeoTmpBuffer(int setId)
      {
        m_mhpMrgTempBufSet = setId;
      }
      void             setGeoTmpBuffer(MergeCtx geoMrgCtx, int setId)
      {
        m_mhpMrgTempBufSet = setId;
        m_geoMrgCtx = geoMrgCtx;
      }
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      void             setGeoTmpBuffer()
      {
        m_mhpMrgTempBufSet = true;
      }
      void             setGeoTmpBuffer(MergeCtx geoMrgCtx)
      {
        m_mhpMrgTempBufSet = true;
        m_geoMrgCtx = geoMrgCtx;
      }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    #if JVET_AI0183_MVP_EXTENSION
      MotionInfo      m_subPuMiBuf[SUB_BUFFER_SIZE][(MAX_CU_SIZE * MAX_CU_SIZE) >> (MIN_CU_LOG2 << 1)];
    #endif
    
      InterSearch();
      virtual ~InterSearch();
    
      void init                         ( EncCfg*        pcEncCfg,
    
    #if JVET_V0094_BILATERAL_FILTER || JVET_X0071_CHROMA_BILATERAL_FILTER
    
    Vadim Seregin's avatar
    Vadim Seregin committed
                                         BilateralFilter* bilateralFilter,
    #endif
    
                                          TrQuant*       pcTrQuant,
                                          int            iSearchRange,
                                          int            bipredSearchRange,
                                          MESearchMethod motionEstimationSearchMethod,
    
                                          bool           useCompositeRef,
    
                                          const uint32_t     maxCUWidth,
                                          const uint32_t     maxCUHeight,
                                          const uint32_t     maxTotalCUDepth,
                                          RdCost*        pcRdCost,
                                          CABACWriter*   CABACEstimator,
                                          CtxCache*      ctxCache
    
    Taoran Lu's avatar
    Taoran Lu committed
                                         , EncReshape*   m_pcReshape
    
    #if JVET_Z0153_IBC_EXT_REF
                                        , const uint32_t curPicWidthY
    
    #if JVET_AJ0172_IBC_ITMP_ALIGN_REF_AREA
                                        , const uint32_t curPicHeightY 
    #endif
    
      void       calcMinDistSbt         ( CodingStructure &cs, const CodingUnit& cu, const uint8_t sbtAllowed );
      uint8_t    skipSbtByRDCost        ( int width, int height, int mtDepth, uint8_t sbtIdx, uint8_t sbtPos, double bestCost, Distortion distSbtOff, double costSbtOff, bool rootCbfSbtOff );
      bool       getSkipSbtAll          ()                 { return m_skipSbtAll; }
      void       setSkipSbtAll          ( bool skipAll )   { m_skipSbtAll = skipAll; }
      uint8_t    getSbtRdoOrder         ( uint8_t idx )    { assert( m_sbtRdoOrder[idx] < NUMBER_SBT_MODE ); assert( (uint32_t)( m_estMinDistSbt[m_sbtRdoOrder[idx]] >> 2 ) < ( MAX_UINT >> 1 ) ); return m_sbtRdoOrder[idx]; }
      Distortion getEstDistSbt          ( uint8_t sbtMode) { return m_estMinDistSbt[sbtMode]; }
      void       initTuAnalyzer         ()                 { m_estMinDistSbt[NUMBER_SBT_MODE] = std::numeric_limits<uint64_t>::max(); m_skipSbtAll = false; }