Skip to content
Snippets Groups Projects
IntraSearch.cpp 565 KiB
Newer Older
  • Learn to ignore specific revisions
  •   bool ispCanBeUsed   = sps.getUseISP() && cu.mtsFlag == 0 && cu.lfnstIdx == 0 && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize());
      bool saveDataForISP = ispCanBeUsed && (!colorTransformIsEnabled || isFirstColorSpace);
      bool testISP        = ispCanBeUsed && (!colorTransformIsEnabled || !cu.colorTransform);
    
    fan wang's avatar
    fan wang committed
    
    #if JVET_AB0155_SGPM
      const bool sgpmAllowed = sps.getUseSgpm() && isLuma(partitioner.chType);
      bool testSgpm = sgpmAllowed && cu.lwidth() >= GEO_MIN_CU_SIZE_EX && cu.lheight() >= GEO_MIN_CU_SIZE_EX
                      && cu.lwidth() <= GEO_MAX_CU_SIZE_EX && cu.lheight() <= GEO_MAX_CU_SIZE_EX
                      && cu.lwidth() < 8 * cu.lheight() && cu.lheight() < 8 * cu.lwidth() && cu.lx() && cu.ly()
                      && cu.lwidth() * cu.lheight() >= SGPM_MIN_PIX;
    #endif
    
    #if JVET_AG0058_EIP
      bool testEip = isLuma(partitioner.chType) && sps.getUseEip() && (getAllowedEip(cu, COMPONENT_Y) || getAllowedEipMerge(cu, COMPONENT_Y));
      bool eipSaveFlag = (cu.lfnstIdx == 0 && cu.mtsFlag == 0);
    
    #if JVET_AJ0082_MM_EIP
      double eipCost = MAX_DOUBLE;
      bool setSkipEipControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
    #if JVET_AI0136_ADAPTIVE_DUAL_TREE
      CodedCUInfo *relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfoPtr(partitioner.currArea());
      testEip &= !relatedCU->skipEip;
    #else
      CodedCUInfo &relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfo(partitioner.currArea());
      testEip &= !relatedCU.skipEip;
    #endif
      double eipBestSatdCost = MAX_DOUBLE;
      bool isEipModeTested = false;
    #endif
    
    #if JVET_AJ0146_TIMDSAD
      bool testTimdSad = CU::allowTimdSad(cu) && cu.timdModeSad != INVALID_TIMD_IDX;
      bool timdSadSaveFlag = (cu.lfnstIdx == 0 && cu.mtsFlag == 0);
    #if !JVET_AJ0061_TIMD_MERGE  
      bool testTimd = cu.slice->getSPS()->getUseTimd() && !(cu.lwidth() * cu.lheight() > 1024 && cu.slice->getSliceType() == I_SLICE);
      bool timdSaveFlag = (cu.lfnstIdx == 0 && cu.mtsFlag == 0);
    #endif
    #endif
    
    #if JVET_W0103_INTRA_MTS 
      if (testISP && m_pcEncCfg->getUseFastISP())
      {
        m_numModesISPRDO = -1;
        testISP &= testISPforCurrCU(cu);
      }
    #endif
    
      if ( saveDataForISP )
    
        //reset the intra modes lists variables
        m_ispCandListHor.clear();
        m_ispCandListVer.clear();
    
        //reset the variables used for the tests
    
        m_regIntraRDListWithCosts.clear();
    
        int numTotalPartsHor = (int)width  >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_VERT_SPLIT));
        int numTotalPartsVer = (int)height >> floorLog2(CU::getISPSplitDim(width, height, TU_1D_HORZ_SPLIT));
    
        m_ispTestedModes[0].init( numTotalPartsHor, numTotalPartsVer );
        //the total number of subpartitions is modified to take into account the cases where LFNST cannot be combined with ISP due to size restrictions
    
    #if JVET_AH0103_LOW_DELAY_LFNST_NSPT
        numTotalPartsHor = spsIntraLfnstEnabled && CU::canUseLfnstWithISP( cu.Y(), HOR_INTRA_SUBPARTITIONS ) ? numTotalPartsHor : 0;
        numTotalPartsVer = spsIntraLfnstEnabled && CU::canUseLfnstWithISP( cu.Y(), VER_INTRA_SUBPARTITIONS ) ? numTotalPartsVer : 0;
    #else
    
        numTotalPartsHor = sps.getUseLFNST() && CU::canUseLfnstWithISP(cu.Y(), HOR_INTRA_SUBPARTITIONS) ? numTotalPartsHor : 0;
        numTotalPartsVer = sps.getUseLFNST() && CU::canUseLfnstWithISP(cu.Y(), VER_INTRA_SUBPARTITIONS) ? numTotalPartsVer : 0;
    
        for (int j = 1; j < NUM_LFNST_NUM_PER_SET; j++)
        {
          m_ispTestedModes[j].init(numTotalPartsHor, numTotalPartsVer);
        }
    
    #if INTRA_TRANS_ENC_OPT
      double regAngCost = MAX_DOUBLE;
      bool setSkipTimdControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
      double timdAngCost = MAX_DOUBLE;
    
    #if JVET_AJ0112_REGRESSION_SGPM
      double sgpmCost = MAX_DOUBLE;
      bool setSkipSgpmControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
    #endif
    
    #if JVET_AJ0061_TIMD_MERGE
      bool setSkipTimdMrgControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
      double timdMrgAngCost[NUM_TIMD_MERGE_MODES];
      for (int i = 0; i < NUM_TIMD_MERGE_MODES; i++)
      {
        timdMrgAngCost[i] = MAX_DOUBLE;
      }
      bool testTimd = cu.slice->getSPS()->getUseTimd();
      if (cu.lwidth() * cu.lheight() > 1024 && cu.slice->getSliceType() == I_SLICE)
      {
        testTimd = false;
      }
      bool testTimdMerge = testTimd && PU::canTimdMerge(*cu.firstPU) && cu.timdMrgList[0][0] != INVALID_TIMD_IDX;
      bool testTimdMrl = false;
    #endif
    
    #if JVET_AH0076_OBIC
      double obicAngCost = MAX_DOUBLE, dimdAngCost = MAX_DOUBLE;
      bool setSkipDimdControl = (m_pcEncCfg->getIntraPeriod() == 1) && !cu.lfnstIdx && !cu.mtsFlag;
    
    #endif
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
      double regAngCostSupp = MAX_DOUBLE;
      const bool setSkipNnControl = m_pcEncCfg->getIntraPeriod() == 1 && !cu.lfnstIdx && !cu.mtsFlag;
      double nnAngCost = MAX_DOUBLE;
    
      const bool testBDPCM = sps.getBDPCMEnabledFlag() && CU::bdpcmAllowed(cu, ComponentID(partitioner.chType)) && cu.mtsFlag == 0 && cu.lfnstIdx == 0;
    
      static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiHadModeList;
    
      static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostList;
    
      static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candHadList;
    
    #if JVET_AJ0061_TIMD_MERGE
      double mipHadCostStore[MAX_NUM_MIP_MODE] = { MAX_DOUBLE };
    #endif
    
      bool validReturn = false;
    
    #if JVET_AH0200_INTRA_TMP_BV_REORDER
        double tmpBestSatdCost = MAX_DOUBLE;
    
    #if JVET_AI0136_ADAPTIVE_DUAL_TREE
        CodedCUInfo *relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfoPtr(partitioner.currArea());
    #else
    
        CodedCUInfo &relatedCU = ((EncModeCtrlMTnoRQT *) m_modeCtrl)->getBlkInfo(partitioner.currArea());
    
        CHECK(pu.cu != &cu, "PU is not contained in the CU");
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    
    
        //===== determine set of modes to be tested (using prediction signal only) =====
        int numModesAvailable = NUM_LUMA_MODE; // total number of Intra modes
    
        const bool fastMip    = sps.getUseMIP() && m_pcEncCfg->getUseFastMIP();
    
        const bool mipAllowed = sps.getUseMIP() && isLuma(partitioner.chType) && ((cu.lfnstIdx == 0) || allowLfnstWithMip(cu.firstPU->lumaSize()));
    
        const bool testMip = mipAllowed && !(cu.lwidth() > (8 * cu.lheight()) || cu.lheight() > (8 * cu.lwidth()));
    
        const bool supportedMipBlkSize = pu.lwidth() <= MIP_MAX_WIDTH && pu.lheight() <= MIP_MAX_HEIGHT;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if JVET_V0130_INTRA_TMP
        const bool tpmAllowed = sps.getUseIntraTMP() && isLuma(partitioner.chType) && ((cu.lfnstIdx == 0) || allowLfnstWithTmp());
        const bool testTpm = tpmAllowed && (cu.lwidth() <= sps.getIntraTMPMaxSize() && cu.lheight() <= sps.getIntraTMPMaxSize());
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    
        static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeList;
    
    Karsten Suehring's avatar
    Karsten Suehring committed
        numModesForFullRD = g_aucIntraModeNumFast_UseMPM_2D[uiWidthBit - MIN_CU_LOG2][uiHeightBit - MIN_CU_LOG2];
    
    #if JVET_AJ0146_TIMDSAD
        bool modList = cu.slice->getSPS()->getUseTimd() && cu.slice->getSliceType() == I_SLICE;
        if (modList)
        {
          numModesForFullRD++;
        }
    #endif
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
        if (m_pcEncCfg->getIBCFastMethod() & IBC_FAST_METHOD_NONSCC)
        {
          numModesForFullRD = (numModesForFullRD > 1) ? (numModesForFullRD - 1) : numModesForFullRD;
        }
    #endif
    
    #if INTRA_FULL_SEARCH
        numModesForFullRD = numModesAvailable;
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if ENABLE_DIMD
        bool bestDimdMode = false;
    
    Keming Cao's avatar
    Keming Cao committed
    #endif
    
    #if JVET_AH0076_OBIC
        bool bestObicMode = false;
        int bestMipDimd = 0;
    #endif
    
    #if JVET_AJ0112_REGRESSION_SGPM
        int bestSgpmDimd = 0;
    #endif
    
    Keming Cao's avatar
    Keming Cao committed
    #if JVET_W0123_TIMD_FUSION
        bool bestTimdMode = false;
    
    #if JVET_AJ0146_TIMDSAD
        bool bestTimdModeSad = false;
    #endif	
    
    #if JVET_AJ0061_TIMD_MERGE
        int bestTimdMrgMode = 0;
        int bestTimdTrType[2] = { TransType::DCT2, TransType::DCT2 };
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    #if JVET_AC0105_DIRECTIONAL_PLANAR
        uint8_t bestPlMode = 0;
    #endif
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
        bool bestLfnstSecFlag = false;
    #endif
    
    fan wang's avatar
    fan wang committed
    #if JVET_AB0155_SGPM
        bool bestSgpmMode = false;
        const CompArea &area = pu.Y();
        CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
    #endif
    
    #if JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST 
        int intraTmpDimdMode = 0;
    #endif 
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
        const bool isShapeHandledPnn = isNnIn && IntraPredictionNN::hasPnnPrediction(cu);
        int idxShift = 0;
        int idxPnnBackwardCompatibility = -MAX_INT;
    #endif
    
        if (isSecondColorSpace)
        {
          uiRdModeList.clear();
          if (m_numSavedRdModeFirstColorSpace[m_savedRdModeIdx] > 0)
          {
            for (int i = 0; i < m_numSavedRdModeFirstColorSpace[m_savedRdModeIdx]; i++)
            {
              uiRdModeList.push_back(m_savedRdModeFirstColorSpace[m_savedRdModeIdx][i]);
            }
          }
    
          if (mtsUsageFlag != 2)
    
    fan wang's avatar
    fan wang committed
    #if JVET_AB0155_SGPM
    
    #if JVET_AH0076_OBIC
            if ((testSgpm && SGPMSaveFlag) || obicSaveFlag || dimdSaveFlag)
    #else
    
    fan wang's avatar
    fan wang committed
            if (testSgpm && SGPMSaveFlag)
    
    fan wang's avatar
    fan wang committed
            {
    
    #if JVET_AG0152_SGPM_ITMP_IBC
              for (int i = 0; i < NUM_LUMA_MODE + SGPM_NUM_BVS; i++)
    #else
    
    fan wang's avatar
    fan wang committed
              for (int i = 0; i < NUM_LUMA_MODE; i++)
    
    fan wang's avatar
    fan wang committed
              {
                m_intraModeReady[i] = 0;
              }
            }
    #endif
    
            // this should always be true
            CHECK(!pu.Y().valid(), "PU is not valid");
    
    #if !JVET_AB0157_TMRL || JVET_AD0082_TMRL_CONFIG
    
    #if JVET_AH0065_RELAX_LINE_BUFFER
            bool isFirstLineOfCtu = pu.block(COMPONENT_Y).y == 0;
    #else
    
            bool isFirstLineOfCtu     = (((pu.block(COMPONENT_Y).y) & ((pu.cs->sps)->getMaxCUWidth() - 1)) == 0);
    
    #if JVET_Y0116_EXTENDED_MRL_LIST
            int  numOfPassesExtendRef = MRL_NUM_REF_LINES;
            if (!sps.getUseMRL() || isFirstLineOfCtu) 
            {
              numOfPassesExtendRef = 1;
            }
            else
            {
              bool checkLineOutsideCtu[MRL_NUM_REF_LINES - 1];
              for (int mrlIdx = 1; mrlIdx < MRL_NUM_REF_LINES; mrlIdx++)
              {
    
    #if JVET_AH0065_RELAX_LINE_BUFFER
                bool isLineOutsideCtu = (cu.block(COMPONENT_Y).y <= MULTI_REF_LINE_IDX[mrlIdx]) ? true : false;
    #else
    
                bool isLineOutsideCtu =
                  ((cu.block(COMPONENT_Y).y) % ((cu.cs->sps)->getMaxCUWidth()) <= MULTI_REF_LINE_IDX[mrlIdx]) ? true
    
                checkLineOutsideCtu[mrlIdx-1] = isLineOutsideCtu;
              }
              if (checkLineOutsideCtu[0]) 
              {
                numOfPassesExtendRef = 1;
              }
              else
              {
                for (int mrlIdx = MRL_NUM_REF_LINES - 2; mrlIdx > 0; mrlIdx--)
                {
                  if (checkLineOutsideCtu[mrlIdx] && !checkLineOutsideCtu[mrlIdx - 1])
                  {
                    numOfPassesExtendRef = mrlIdx + 1;
                    break;
                  }
                }
              }
            }
    #else
    
            int  numOfPassesExtendRef = ((!sps.getUseMRL() || isFirstLineOfCtu) ? 1 : MRL_NUM_REF_LINES);
    
            pu.multiRefIdx            = 0;
    
    #if JVET_AB0157_TMRL
            cu.tmrlFlag = false;
    #endif
    
            if (numModesForFullRD != numModesAvailable)
    
              CHECK(numModesForFullRD >= numModesAvailable, "Too many modes for full RD search");
    
    fan wang's avatar
    fan wang committed
    #if !JVET_AB0155_SGPM
    
              const CompArea &area = pu.Y();
    
    fan wang's avatar
    fan wang committed
    #endif
    
              PelBuf piOrg  = cs.getOrgBuf(area);
              PelBuf piPred = cs.getPredBuf(area);
    
              DistParam distParamSad;
              DistParam distParamHad;
    
              if (cu.slice->getLmcsEnabledFlag() && m_pcReshape->getCTUFlag())
    
    fan wang's avatar
    fan wang committed
    #if !JVET_AB0155_SGPM
    
                CompArea tmpArea(COMPONENT_Y, area.chromaFormat, Position(0, 0), area.size());
    
    fan wang's avatar
    fan wang committed
    #endif
    
                PelBuf   tmpOrg = m_tmpStorageLCU.getBuf(tmpArea);
    
    Vadim Seregin's avatar
    Vadim Seregin committed
                tmpOrg.rspSignal( piOrg, m_pcReshape->getFwdLUT() );
    
                m_pcRdCost->setDistParam(distParamSad, tmpOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y,
                                         false);   // Use SAD cost
                m_pcRdCost->setDistParam(distParamHad, tmpOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y,
                                         true);   // Use HAD (SATD) cost
    
                m_pcRdCost->setDistParam(distParamSad, piOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y,
                                         false);   // Use SAD cost
                m_pcRdCost->setDistParam(distParamHad, piOrg, piPred, sps.getBitDepth(CHANNEL_TYPE_LUMA), COMPONENT_Y,
                                         true);   // Use HAD (SATD) cost
    
              distParamSad.applyWeight = false;
              distParamHad.applyWeight = false;
    
              if (testMip && supportedMipBlkSize)
              {
                numModesForFullRD += fastMip
                                       ? std::max(numModesForFullRD, floorLog2(std::min(pu.lwidth(), pu.lheight())) - 1)
                                       : numModesForFullRD;
              }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if JVET_V0130_INTRA_TMP
    
    #if JVET_AB0130_ITMP_SAMPLING
              if (testTpm && !m_pcEncCfg->getUseFastIntraTMP())
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
              if( testTpm )
    
    Vadim Seregin's avatar
    Vadim Seregin committed
              {
                numModesForFullRD += 1; // testing tpm
              }
    
    #if JVET_AG0136_INTRA_TMP_LIC 
              if( testTpm && m_pcEncCfg->getItmpLicMode())
              {
                numModesForFullRD += 1; // testing lic itmp
              }
    
    #endif
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
              if (isNnIn)
              {
                numModesForFullRD += 1;
              }
    
    #if JVET_AJ0146_TIMDSAD
              const int numHadCand = (testMip ? 2 : 1) * 3 + (modList ? 1 : 0) + testTpm;
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
              const int numHadCand = (testMip ? 2 : 1) * 3 + testTpm;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
              
              cu.tmpFlag = false;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #else
    
              const int numHadCand = (testMip ? 2 : 1) * 3;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    fan wang's avatar
    fan wang committed
    #if JVET_AB0155_SGPM
              static_vector<SgpmInfo, SGPM_NUM> sgpmInfoList;
              static_vector<double, SGPM_NUM>   sgpmCostList;
    
    #if JVET_AG0152_SGPM_ITMP_IBC
              int                               sgpmNeededMode[NUM_LUMA_MODE + SGPM_NUM_BVS] = { 0 };
    #else
    
    fan wang's avatar
    fan wang committed
              int                               sgpmNeededMode[NUM_LUMA_MODE] = {0};
    
    fan wang's avatar
    fan wang committed
    
              if (testSgpm && SGPMSaveFlag)
              {
                deriveSgpmModeOrdered(bestCS->picture->getRecoBuf(area), area, cu, sgpmInfoList, sgpmCostList);
    
    fan wang's avatar
    fan wang committed
                for (int sgpmIdx = 0; sgpmIdx < SGPM_NUM; sgpmIdx++)
                {
                  int      sgpmMode[2];
                  sgpmMode[0]                 = sgpmInfoList[sgpmIdx].sgpmMode0;
                  sgpmMode[1]                 = sgpmInfoList[sgpmIdx].sgpmMode1;
                  sgpmNeededMode[sgpmMode[0]] = 1;
                  sgpmNeededMode[sgpmMode[1]] = 1;
                }
              }
    #endif
    
    
    #if JVET_AH0076_OBIC
              int dimdNeededMode[NUM_LUMA_MODE] = {0};
              if (obicSaveFlag)
              {
                for (int idx = 0; idx < OBIC_FUSION_NUM; idx++)
                {
                  int iMode = cu.obicMode[idx];
                  if (iMode < 0)
                  {
                    continue;
                  }
                  dimdNeededMode[iMode] = 1;
                }
              }
              if (dimdSaveFlag)
              {
                if (cu.dimdBlending)
                {
                  for (int dimdIdx = 0; dimdIdx < DIMD_FUSION_NUM - 1; dimdIdx++)
                  {
                    int dimdMode = (dimdIdx == 0 ? cu.dimdMode : cu.dimdBlendMode[dimdIdx-1]);
                    if (dimdMode <= 0)
                    {
                      break;
                    }
                    dimdNeededMode[dimdMode] = 1;
                  }
                  dimdNeededMode[PLANAR_IDX] = 1;
                }
              }
    #endif
              
    
    #if JVET_AB0157_TMRL
              double tmrlCostList[MRL_LIST_SIZE]{ MAX_DOUBLE };
    #endif
    
    #if JVET_AC0105_DIRECTIONAL_PLANAR
              double dirPlanarCostList[2]{ MAX_DOUBLE };
    #endif
    
              //*** Derive (regular) candidates using Hadamard
              cu.mipFlag = false;
    
              //===== init pattern for luma prediction =====
    
    #if JVET_AB0157_INTRA_FUSION && JVET_AB0155_SGPM
              initIntraPatternChType(cu, pu.Y(), true, 0, false);
    #elif JVET_AB0157_INTRA_FUSION
    
              initIntraPatternChType(cu, pu.Y(), true, false);
    #else
    
              initIntraPatternChType(cu, pu.Y(), true);
    
              bool bSatdChecked[NUM_INTRA_MODE];
              memset(bSatdChecked, 0, sizeof(bSatdChecked));
    
              if (!LFNSTLoadFlag)
              {
                for (int modeIdx = 0; modeIdx < numModesAvailable; modeIdx++)
                {
                  uint32_t   uiMode    = modeIdx;
                  Distortion minSadHad = 0;
    
                  // Skip checking extended Angular modes in the first round of SATD
                  if (uiMode > DC_IDX && (uiMode & 1))
                  {
                    continue;
    
                  bSatdChecked[uiMode] = true;
    
                  pu.intraDir[0] = modeIdx;
    
                  initPredIntraParams(pu, pu.Y(), sps);
    
    #if JVET_AB0157_INTRA_FUSION
                  predIntraAng(COMPONENT_Y, piPred, pu, false);
    #else
    
                  predIntraAng(COMPONENT_Y, piPred, pu);
    
    #if JVET_AH0209_PDP
                  bool pdpMode = false;
    
                  if( pdpSaveFlag )
                  {
                    const int sizeKey = (width << 8) + height;
                    const int sizeIdx = g_size.find(sizeKey) != g_size.end() ? g_size[sizeKey] : -1;
                    const int m = sizeIdx > 12 ? 2 : 0;
                    const int s = sizeIdx > 12 ? 4 : 2;
                    if (sizeIdx >= 0 && m_refAvailable && pu.cu->cs->sps->getUsePDP() && !(modeIdx > 1 && modeIdx % s != m))
                    {
                      PelBuf predBuf(m_pdpIntraPredBuf[uiMode], tmpArea);
                      predBuf.copyFrom(piPred);
                      m_pdpIntraPredReady[modeIdx] = true;
                      pdpMode = true;
                    }
                  }
                  
                  if( !pdpMode )
                  {
    #endif
    
    fan wang's avatar
    fan wang committed
    #if JVET_AB0155_SGPM
                  if (testSgpm && SGPMSaveFlag && sgpmNeededMode[uiMode])
                  {
    
    fan wang's avatar
    fan wang committed
                    predBuf.copyFrom(piPred);
                    m_intraModeReady[uiMode] = 1;
                  }
    #endif
    
    #if JVET_AH0076_OBIC
                  if ((obicSaveFlag || dimdSaveFlag) && dimdNeededMode[uiMode] && !m_intraModeReady[uiMode])
                  {
    
                    predBuf.copyFrom(piPred);
                    m_intraModeReady[uiMode] = 1;
                  }
    #endif
    
                  // Use the min between SAD and HAD as the cost criterion
    
                  // SAD is scaled by 2 to align with the scaling of HAD
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                  Distortion sadCost = distParamSad.distFunc(distParamSad);
                  minSadHad += std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
    #else
    
                  minSadHad += std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
    
                  uint64_t fracModeBits = xFracModeBitsIntra(pu, uiMode, CHANNEL_TYPE_LUMA);
    
                  double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                  m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
    #endif
    
                  DTRACE(g_trace_ctx, D_INTRA_COST, "IntraHAD: %u, %llu, %f (%d)\n", minSadHad, fracModeBits, cost, uiMode);
    
                  updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiMode), cost, uiRdModeList,
    
                                 candCostList, numModesForFullRD);
    
                  updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiMode), double(minSadHad),
    
    #if JVET_AC0105_DIRECTIONAL_PLANAR
                bool testDirPlanar = isLuma(partitioner.chType);
                if (testDirPlanar)
                {
                  for (int dirPlanarModeIdx = 0; dirPlanarModeIdx < 2; dirPlanarModeIdx++)
                  {
                    cu.sgpm        = false;
                    cu.ispMode     = 0;
                    cu.tmpFlag     = false;
                    cu.tmrlFlag    = false;
                    pu.multiRefIdx = 0;
                    cu.mipFlag     = false;
                    pu.intraDir[0] = PLANAR_IDX;
                    cu.plIdx       = dirPlanarModeIdx + 1;
    
                    initPredIntraParams(pu, pu.Y(), sps);
    #if JVET_AB0157_INTRA_FUSION
                    predIntraAng(COMPONENT_Y, piPred, pu, false);
    #else
                    predIntraAng(COMPONENT_Y, piPred, pu);
    #endif
    
                    // Use the min between SAD and SATD as the cost criterion
                    // SAD is scaled by 2 to align with the scaling of HAD
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                    Distortion sadCost = distParamSad.distFunc(distParamSad);
                    Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
    #else
    
                    Distortion minSadHad =
                      std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
    
                    uint64_t fracModeBits = xFracModeBitsIntra(pu, PLANAR_IDX, CHANNEL_TYPE_LUMA);
                    double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                    m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
    #endif
    
                    updateCandList(
                      ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, dirPlanarModeIdx ? PL_VER_IDX : PL_HOR_IDX), cost,
    
                      uiRdModeList, candCostList, numModesForFullRD);
    
                    updateCandList(
                      ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, dirPlanarModeIdx ? PL_VER_IDX : PL_HOR_IDX),
    
                      double(minSadHad), uiHadModeList, candHadList, numHadCand);
    
                    dirPlanarCostList[dirPlanarModeIdx] = cost;
                  }
                }
                cu.plIdx = 0;
    #endif
    
                if (!sps.getUseMIP() && LFNSTSaveFlag)
                {
                  // save found best modes
                  m_uiSavedNumRdModesLFNST = numModesForFullRD;
                  m_uiSavedRdModeListLFNST = uiRdModeList;
    
                  m_dSavedModeCostLFNST    = candCostList;
    
                  // PBINTRA fast
                  m_uiSavedHadModeListLFNST = uiHadModeList;
    
                  LFNSTSaveFlag             = false;
                }
              }   // NSSTFlag
              if (!sps.getUseMIP() && LFNSTLoadFlag)
    
                // restore saved modes
                numModesForFullRD = m_uiSavedNumRdModesLFNST;
                uiRdModeList      = m_uiSavedRdModeListLFNST;
    
                candCostList      = m_dSavedModeCostLFNST;
    
                // PBINTRA fast
                uiHadModeList = m_uiSavedHadModeListLFNST;
    
              }   // !LFNSTFlag
    
              if (!(sps.getUseMIP() && LFNSTLoadFlag))
              {
                static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> parentCandList = uiRdModeList;
    
                // Second round of SATD for extended Angular modes
                for (int modeIdx = 0; modeIdx < numModesForFullRD; modeIdx++)
                {
                  unsigned parentMode = parentCandList[modeIdx].modeId;
                  if (parentMode > (DC_IDX + 1) && parentMode < (NUM_LUMA_MODE - 1))
                  {
                    for (int subModeIdx = -1; subModeIdx <= 1; subModeIdx += 2)
                    {
                      unsigned mode = parentMode + subModeIdx;
    
                      if (!bSatdChecked[mode])
                      {
                        pu.intraDir[0] = mode;
    
                        initPredIntraParams(pu, pu.Y(), sps);
    
    #if JVET_AB0157_INTRA_FUSION
                        predIntraAng(COMPONENT_Y, piPred, pu, false);
    #else
    
                        predIntraAng(COMPONENT_Y, piPred, pu);
    
    fan wang's avatar
    fan wang committed
    #if JVET_AB0155_SGPM
                        if (testSgpm && SGPMSaveFlag && sgpmNeededMode[mode])
                        {
    
    fan wang's avatar
    fan wang committed
                          predBuf.copyFrom(piPred);
                          m_intraModeReady[mode] = 1;
                        }
    #endif
    
    #if JVET_AH0076_OBIC
                        if ((obicSaveFlag || dimdSaveFlag) && dimdNeededMode[mode] && !m_intraModeReady[mode])
                        {
    
                          predBuf.copyFrom(piPred);
                          m_intraModeReady[mode] = 1;
                        }
    #endif
    
    
                        // Use the min between SAD and SATD as the cost criterion
                        // SAD is scaled by 2 to align with the scaling of HAD
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                        Distortion sadCost = distParamSad.distFunc(distParamSad);
                        Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
    #else
    
                        Distortion minSadHad =
                          std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
    
                        uint64_t fracModeBits = xFracModeBitsIntra(pu, mode, CHANNEL_TYPE_LUMA);
    
                        double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                        m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
    #endif
    
                        updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, mode), cost, uiRdModeList,
    
                                       candCostList, numModesForFullRD);
    
                        updateCandList(ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, mode), double(minSadHad),
    
    
                        bSatdChecked[mode] = true;
                      }
                    }
                  }
                }
                if (saveDataForISP)
    
                  // we save the regular intra modes list
                  m_ispCandListHor = uiRdModeList;
                }
    
    #if !JVET_AB0157_TMRL || JVET_AD0082_TMRL_CONFIG
    
                pu.multiRefIdx    = 1;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if SECONDARY_MPM
                const int numMPMs = NUM_PRIMARY_MOST_PROBABLE_MODES;
    #else
    
                const int numMPMs = NUM_MOST_PROBABLE_MODES;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !SECONDARY_MPM
    
                PU::getIntraMPMs(pu, multiRefMPM);
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    #endif
    #if JVET_AB0157_TMRL
    
    #if !JVET_AD0082_TMRL_CONFIG
    
                cu.tmrlFlag = true;
    
                if (CU::allowTmrl(cu))
                {
    
    #if JVET_AD0082_TMRL_CONFIG
                  cu.tmrlFlag = true;
    #endif
    
                  for (auto multiRefIdx : EXT_REF_LINE_IDX)
                  {
                    pu.multiRefIdx = multiRefIdx;
                    initIntraPatternChType(cu, pu.Y(), true);
    
                    for (auto i = 0; i < MRL_LIST_SIZE; i++)
                    {
    
                      if (m_tmrlList[i].multiRefIdx != multiRefIdx)
    
                      pu.intraDir[0] = m_tmrlList[i].intraDir;
    
                      cu.tmrlListIdx = i;
                      uint32_t uiMode = i + MAX_REF_LINE_IDX;
    
                      initPredIntraParams(pu, pu.Y(), *(pu.cs->sps));
                      predIntraAng(COMPONENT_Y, piPred, pu);
    
                      // Use the min between SAD and SATD as the cost criterion
                        // SAD is scaled by 2 to align with the scaling of HAD
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                      Distortion sadCost = distParamSad.distFunc(distParamSad);
                      Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
    #else
    
                      Distortion minSadHad =
                        std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
    
                      uint64_t fracModeBits = xFracModeBitsIntra(pu, pu.intraDir[0], CHANNEL_TYPE_LUMA);
    
                      double cost = (double)minSadHad + (double)fracModeBits * sqrtLambdaForFirstPass;
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                      m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
    #endif
    
                      updateCandList(ModeInfo(false, false, uiMode, NOT_INTRA_SUBPARTITIONS, 0), cost, uiRdModeList,
    
                        candCostList, numModesForFullRD);
    
                      updateCandList(ModeInfo(false, false, uiMode, NOT_INTRA_SUBPARTITIONS, 0), double(minSadHad),
    
    #if JVET_AB0157_TMRL
                      tmrlCostList[i] = cost;
    #endif
                    }
                  }
    
    #if JVET_AD0082_TMRL_CONFIG
                  cu.tmrlFlag = false;
    #endif
    
    #endif
    #if !JVET_AB0157_TMRL || JVET_AD0082_TMRL_CONFIG
    #if JVET_AD0082_TMRL_CONFIG
                else
                {
    #endif
    
                for (int mRefNum = 1; mRefNum < numOfPassesExtendRef; mRefNum++)
                {
                  int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
    
                  pu.multiRefIdx = multiRefIdx;
                  {
    
    #if JVET_AB0157_INTRA_FUSION && JVET_AB0155_SGPM
                    initIntraPatternChType(cu, pu.Y(), true, 0, false);
    #elif JVET_AB0157_INTRA_FUSION
    
                    initIntraPatternChType(cu, pu.Y(), true, false);
    #else
    
                    initIntraPatternChType(cu, pu.Y(), true);
    
                  }
                  for (int x = 1; x < numMPMs; x++)
                  {
                    uint32_t mode = multiRefMPM[x];
                    {
                      pu.intraDir[0] = mode;
                      initPredIntraParams(pu, pu.Y(), sps);
    
    
    #if JVET_AB0157_INTRA_FUSION
                      predIntraAng(COMPONENT_Y, piPred, pu, false);
    #else
    
                      predIntraAng(COMPONENT_Y, piPred, pu);
    
    
                      // Use the min between SAD and SATD as the cost criterion
                      // SAD is scaled by 2 to align with the scaling of HAD
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                      Distortion sadCost = distParamSad.distFunc(distParamSad);
                      Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
    #else
    
                      Distortion minSadHad =
                        std::min(distParamSad.distFunc(distParamSad) * 2, distParamHad.distFunc(distParamHad));
    
                      uint64_t fracModeBits = xFracModeBitsIntra(pu, mode, CHANNEL_TYPE_LUMA);
    
                      double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
    
    #if JVET_AD0208_IBC_ADAPT_FOR_CAM_CAPTURED_CONTENTS
                      m_bestIntraSADCost = std::min(m_bestIntraSADCost, cost - (double)minSadHad + (double)sadCost);
    #endif
    
                      updateCandList(ModeInfo(false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, mode), cost, uiRdModeList,
    
                                     candCostList, numModesForFullRD);
    
                      updateCandList(ModeInfo(false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, mode), double(minSadHad),
    
    #if JVET_AD0082_TMRL_CONFIG
                }
    #endif
    
    
    #if JVET_AJ0061_TIMD_MERGE
                const int numTool = 2; // Timd, TimdMrl
                bool isTimd, isTimdMrl;
                /*-------------*/
                /*    TIMD     */
                int numPassTimd = (testTimd ? 1 : 0) + (testTimdMerge ? 1 : 0);
                CHECK(!testTimd && testTimdMerge, "something went wrong");
                
                /*-------------*/
                /*  TIMD-MRL   */
                bool isFirstLineOfCtu = pu.block(COMPONENT_Y).y == 0;
                bool isTimdMrlAllowed = (lfnstIdx == 0 && !cu.mtsFlag) && isTimdValid;
                numOfPassesExtendRef = !isTimdMrlAllowed ? 0 : (((!sps.getUseMRL() || isFirstLineOfCtu) ? 1 : 3) - 1);
    
                const int numToolPass[numTool] = { numPassTimd, numOfPassesExtendRef};
                
                // Shared variables
                int multiRefIdx;
                uint8_t intraDir = 0;
                uint32_t modeId = 0;
                uint8_t modeRefIdx = 0;
                
                ModeInfo currMode;
                for (int tool = 0; tool < numTool; tool++)
                {
                  isTimd      = tool == 0;
                  isTimdMrl   = tool == 1;
                  
                  for (int pass = 0; pass < numToolPass[tool]; pass++)
                  {
                    if (isTimd)
                    {
                      cu.timd = true;
    
    #if JVET_AJ0146_TIMDSAD
                      cu.timdSad = false;
    #endif				  
    
                      cu.timdMrg = pass == 1;
                      intraDir = !cu.timdMrg ? cu.timdMode : cu.timdMrgList[0][0];
                      modeId = !cu.timdMrg ? TIMD_IDX : TIMDM_IDX;
                      modeRefIdx = 0;
                      multiRefIdx = 0;
                    }
    
                    if (isTimdMrl)
                    {
                      multiRefIdx = MULTI_REF_LINE_IDX[pass + 1];
                      modeRefIdx = multiRefIdx;
                      intraDir = cu.timdMode;
                      modeId = TIMD_IDX;
                      cu.timd = true;
    
    #if JVET_AJ0146_TIMDSAD
                      cu.timdSad = false;
    #endif				  
    
                      cu.timdMrg = false;
                      testTimdMrl = true;
                    }
    
                    // PU/CU init
                    pu.intraDir[0] = intraDir;
                    pu.cu->tmrlFlag = false;
                    pu.multiRefIdx = multiRefIdx;
                    pu.cu->timd = isTimd || isTimdMrl;
    
    #if JVET_AJ0146_TIMDSAD
                    pu.cu->timdSad = false;
    #endif
    
                    // Init intra pattern
                    initIntraPatternChType(cu, pu.Y());
    
                    // Init IPM parameters
                    initPredIntraParams(pu, pu.Y(), sps);
    
                    // Prediction
                    predIntraAng(COMPONENT_Y, piPred, pu);
                    
                    // Cost calculation
                    Distortion sadCost = distParamSad.distFunc(distParamSad);
                    Distortion minSadHad = std::min(sadCost * 2, distParamHad.distFunc(distParamHad));
    
                    loadStartStates();
                    uint64_t fracModeBits = xFracModeBitsIntra(pu, intraDir, CHANNEL_TYPE_LUMA);
    
                    double cost = (double) minSadHad + (double) fracModeBits * sqrtLambdaForFirstPass;
                    currMode = ModeInfo(false, false, modeRefIdx, NOT_INTRA_SUBPARTITIONS, modeId);
                    // Update lists
                    numTimdSatd++;
                    timdModes.push_back(currMode);
                    timdCosts.push_back(cost);
                    timdSadCosts.push_back(static_cast<double>(minSadHad));
                    TimdMode mode = getTimdMode(cu.timdMrg, multiRefIdx);
                    PelBuf timdSaveBuf(m_timdPredBuf[mode], pu.Y());
                    timdSaveBuf.copyFrom(piPred);
                    m_satdCostTIMD[mode][0] = static_cast<uint64_t>(cost);
                    m_satdCostTIMD[mode][1] = minSadHad;
                  }
                }
                cu.tmrlFlag = false;           
                cu.timd = false;
                cu.timdMrg = false;
    #endif
    
    
                CHECKD(uiRdModeList.size() != numModesForFullRD, "Error: RD mode list size");
    
    #if JVET_V0130_INTRA_TMP && JVET_AB0130_ITMP_SAMPLING
                // derive TPM candidate using hadamard
                if (testTpm)
                {
                  cu.tmpFlag = true;
                  cu.mipFlag = false;
                  pu.multiRefIdx = 0;
    
    
    #if JVET_AD0086_ENHANCED_INTRA_TMP
                  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListTmp;
    
                  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostListTmp;
    
                  int foundCandiNum = 0;
                  bool bsuccessfull = 0;
    
    #endif
    #if JVET_AH0200_INTRA_TMP_BV_REORDER
                  int adjustedTMPNonLicBvNum = TMP_REFINE_NONLIC_BV_NUM;
                  int adjustedTmpLicBvNum = TMP_REFINE_LIC_BV_NUM;
                  if(m_pcEncCfg->getIntraPeriod() != 1)
                  {
                    adjustedTMPNonLicBvNum = 10;
                    adjustedTmpLicBvNum = 4;
                  }
                  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListFracTmp;
                  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostListFracTmp;
                  Distortion backupMinSadHad[MTMP_NUM];
                  Distortion backupSadCost[MTMP_NUM];
                  Distortion backupLicMinSadHad[MTMP_NUM][4];
                  Distortion backupLicSadCost[MTMP_NUM][4];
                  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListLicFracTmp;
                  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostListLicFracTmp;
                  static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListTmpLic;
                  static_vector<double, FAST_UDI_MAX_RDMODE_NUM> candCostListTmpLic;
    
                  CodingUnit cuCopy = cu;
    
    #if JVET_W0069_TMP_BOUNDARY
                  RefTemplateType templateType = getRefTemplateType(cuCopy, cuCopy.blocks[COMPONENT_Y]);
                  if (templateType != NO_TEMPLATE)
    #else
                  if (isRefTemplateAvailable(cuCopy, cuCopy.blocks[COMPONENT_Y]))
    #endif
                  {
    
    #if JVET_AD0086_ENHANCED_INTRA_TMP
                    cu.tmpIsSubPel = 0;
    
    #if JVET_AG0136_INTRA_TMP_LIC
                    cu.tmpSubPelIdx = -1;
    #else
    
    #endif
    #if JVET_AH0200_INTRA_TMP_BV_REORDER
                    cu.tmpFracIdx   = 0;
                    int numModesForFracIntraTmp = numModesForFullRD + adjustedTMPNonLicBvNum;
    
    #if JVET_AI0136_ADAPTIVE_DUAL_TREE
                    if(relatedCU && relatedCU->skipFracTmp)
    #else
    
                    {
                      numModesForFracIntraTmp = numModesForFullRD;
                    }
                    if(m_tmpNumCand > 0)
                    {
                      for(int idxInList=0; idxInList < uiRdModeList.size(); idxInList++)
                      {
                        if(cu.lwidth() * cu.lheight() > TMP_SKIP_REFINE_THRESHOLD)
                        {
                          break;
                        }
                        updateCandList(uiRdModeList[idxInList], candCostList[idxInList], uiRdModeListFracTmp, candCostListFracTmp, numModesForFracIntraTmp);
                      }
                    }
    
                    int numModesForLicFracIntraTmp = numModesForFullRD + adjustedTmpLicBvNum;
    
    #if JVET_AI0136_ADAPTIVE_DUAL_TREE
                    if(relatedCU && relatedCU->skipFracTmp)
    #else
    
                    {
                      numModesForLicFracIntraTmp = numModesForFullRD;
                    }
                    if(m_tmpNumCandUseMR > 0)
                    {
                      for(int idxInList=0; idxInList < uiRdModeList.size(); idxInList++)
                      {
                        if(cu.lwidth() * cu.lheight() > TMP_SKIP_REFINE_THRESHOLD)
                        {
                          break;
                        }
                        updateCandList(uiRdModeList[idxInList], candCostList[idxInList], uiRdModeListLicFracTmp, candCostListLicFracTmp, numModesForLicFracIntraTmp);
                      }
                    }