Skip to content
Snippets Groups Projects
IntraSearch.cpp 589 KiB
Newer Older
  • Learn to ignore specific revisions
  • #if JVET_AJ0249_NEURAL_NETWORK_BASED
                  for (int j = 0; j < (isNnIn ? ((numCand > 1) ? 1 : numCand) : ((numCand > 2) ? 2 : numCand)); j++)
    #else
    
                  for (int j = 0; j < numCand; j++)
    
                  {
                    bool     mostProbableModeIncluded = false;
                    ModeInfo mostProbableMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiPreds[j]);
    
    
    #if JVET_AK0059_MDIP
                    int mpmIdx = -1;
                    for (int i = 0; i < numModesForFullRD; i++)
                    {
                      mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]);
                      if(mostProbableModeIncluded)
                      {
                        mpmIdx = i;
                        break;
                      }
                    }
                    const double thresholdMpm = 1.1;
                    if (!mostProbableModeIncluded)
                    {
                      if(testMdip)
                      {
                        if(j==0 && m_mpm0SadHad < m_dSavedSadHadMdip * thresholdMpm)
                        {
                          numModesForFullRD++;
                          uiRdModeList.push_back(mostProbableMode);
                          candCostList.push_back(0); 
                        }
                      }
                      else
                      {
                        numModesForFullRD++;
                        uiRdModeList.push_back(mostProbableMode);
                        candCostList.push_back(0);
                      }
                    }
                    else
                    {
                      if(testMdip)
                      {
                        if(j==0 && m_mpm0SadHad >= m_dSavedSadHadMdip * thresholdMpm)
                        {
                          uiRdModeList.erase(uiRdModeList.begin() + mpmIdx);
                          candCostList.erase(candCostList.begin() + mpmIdx);
                          numModesForFullRD--;
                        }
                      }
                    }
    #else
    
                    for (int i = 0; i < numModesForFullRD; i++)
    
                      mostProbableModeIncluded |= (mostProbableMode == uiRdModeList[i]);
    
                    }
                    if (!mostProbableModeIncluded)
                    {
    
                      numModesForFullRD++;
                      uiRdModeList.push_back(mostProbableMode);
                      candCostList.push_back(0);
                    }
    
                  }
                  if (saveDataForISP)
                  {
                    // we add the MPMs to the list that contains only regular intra modes
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
                    for (int j = 0; j < ((numCand > 2) ? 2 : numCand); j++)
    #else
    
                    for (int j = 0; j < numCand; j++)
    
                    {
                      bool     mostProbableModeIncluded = false;
                      ModeInfo mostProbableMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, uiPreds[j]);
    
                      for (int i = 0; i < m_ispCandListHor.size(); i++)
                      {
                        mostProbableModeIncluded |= (mostProbableMode == m_ispCandListHor[i]);
                      }
                      if (!mostProbableModeIncluded)
                      {
                        m_ispCandListHor.push_back(mostProbableMode);
                      }
    
    #if JVET_AJ0112_REGRESSION_SGPM
    
              if (m_pcEncCfg->getUseFastLFNST() && LFNSTLoadFlag && mtsUsageFlag == 1)
              {
                if (m_bestModeCostValid[0])
                {
                  numModesForFullRD = 0;
                  uiRdModeList.clear();
                  std::vector<std::pair<ModeInfo, double>> modeInfoWithDCT2Cost(m_savedNumRdModes[0]);
                  for (int i = 0; i < m_savedNumRdModes[0]; i++)
                  {
                    modeInfoWithDCT2Cost[i] = { m_savedRdModeList[0][i], m_modeCostStore[0][i] };
                  }
                  std::stable_sort(modeInfoWithDCT2Cost.begin(), modeInfoWithDCT2Cost.end(), [](const std::pair<ModeInfo, double> & l, const std::pair<ModeInfo, double> & r) {return l.second < r.second; });
    
                  // **Reorder the modes** and skip checking the modes with much larger R-D cost than the best mode
                  for (int i = 0; i < m_savedNumRdModes[0]; i++)
                  {
                    if (modeInfoWithDCT2Cost[i].second <= 1.3 * modeInfoWithDCT2Cost[0].second)
                    {
                      uiRdModeList.push_back(modeInfoWithDCT2Cost[i].first);
                      numModesForFullRD++;
                    }
                  }
                }
                else
                {
                  // Restore the modes to be checked with RD
                  numModesForFullRD = m_savedNumRdModes[0];
                  uiRdModeList.resize(numModesForFullRD);
                  std::copy_n(m_savedRdModeList[0], m_savedNumRdModes[0], uiRdModeList.begin());
                  candCostList.resize(numModesForFullRD);
                }
              }
    #endif
    
            else
            {
              THROW("Full search not supported for MIP");
            }
    
    #if JVET_AH0103_LOW_DELAY_LFNST_NSPT
            if( spsIntraLfnstEnabled && mtsUsageFlag == 1 )
    #else
    
            if (sps.getUseLFNST() && mtsUsageFlag == 1)
    
            {
              // Store the modes to be checked with RD
    
    #if JVET_AJ0061_TIMD_MERGE
              if (!cu.mtsFlag && !cu.lfnstIdx)
              {
                static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> uiRdModeListNoTimdMrl = uiRdModeList;
                for (int i = (int)uiRdModeList.size() - 1; i >= 0 ; i--)
                {
                  int refIdx = uiRdModeListNoTimdMrl.at(i).mRefId;
                  int mode = uiRdModeListNoTimdMrl.at(i).modeId;
                  if ( refIdx > 0 && mode == TIMD_IDX )
                  {
                    uiRdModeListNoTimdMrl.erase(uiRdModeListNoTimdMrl.begin() + i);
                  }
                }
                m_savedNumRdModes[lfnstIdx] = (int)uiRdModeList.size() - ((int)uiRdModeList.size() - (int)uiRdModeListNoTimdMrl.size());
                std::copy_n(uiRdModeListNoTimdMrl.begin(), m_savedNumRdModes[lfnstIdx], m_savedRdModeList[lfnstIdx]);
              }
              else
              {
                m_savedNumRdModes[lfnstIdx] = numModesForFullRD;
                std::copy_n(uiRdModeList.begin(), numModesForFullRD, m_savedRdModeList[lfnstIdx]);
              }
    #else
    
              m_savedNumRdModes[lfnstIdx] = numModesForFullRD;
              std::copy_n(uiRdModeList.begin(), numModesForFullRD, m_savedRdModeList[lfnstIdx]);
    
          else   // mtsUsage = 2 (here we potentially reduce the number of modes that will be full-RD checked)
    
            if ((m_pcEncCfg->getUseFastLFNST() || !cu.slice->isIntra()) && m_bestModeCostValid[lfnstIdx])
            {
              numModesForFullRD = 0;
    
    #if JVET_W0103_INTRA_MTS
              double thresholdSkipMode = 1.0 + ((cu.lfnstIdx > 0) ? 0.1 : 0.8) * (1.4 / sqrt((double)(width * height)));
    
              std::vector<std::pair<ModeInfo, double>> modeInfoWithDCT2Cost(m_savedNumRdModes[0]);
    
              for (int i = 0; i < m_savedNumRdModes[0]; i++)
              {
    
                modeInfoWithDCT2Cost[i] = { m_savedRdModeList[0][i], m_modeCostStore[0][i] };
    
              std::stable_sort(modeInfoWithDCT2Cost.begin(), modeInfoWithDCT2Cost.end(), [](const std::pair<ModeInfo, double> & l, const std::pair<ModeInfo, double> & r) {return l.second < r.second; });
    
              // **Reorder the modes** and skip checking the modes with much larger R-D cost than the best mode
    
              for (int i = 0; i < m_savedNumRdModes[0]; i++)
              {
    
                if (modeInfoWithDCT2Cost[i].second <= thresholdSkipMode * modeInfoWithDCT2Cost[0].second)
    
                  uiRdModeList.push_back(modeInfoWithDCT2Cost[i].first);
    
                  numModesForFullRD++;
                }
              }
    #else
    
              double thresholdSkipMode = 1.0 + ((cu.lfnstIdx > 0) ? 0.1 : 1.0) * (1.4 / sqrt((double) (width * height)));
    
              // Skip checking the modes with much larger R-D cost than the best mode
              for (int i = 0; i < m_savedNumRdModes[lfnstIdx]; i++)
    
                if (m_modeCostStore[lfnstIdx][i] <= thresholdSkipMode * m_bestModeCostStore[lfnstIdx])
                {
                  uiRdModeList.push_back(m_savedRdModeList[lfnstIdx][i]);
                  numModesForFullRD++;
                }
    
    #endif
    #if JVET_AJ0061_TIMD_MERGE
              timdModes = m_uiSavedRdModeListTimd;
              timdCosts = m_uiSavedModeCostTimd;
              if (cu.mtsFlag)
              {
                for (int i = (int)timdModes.size() - 1; i >= 0; i--)
                {
                  if (timdModes[i].modeId == TIMDM_IDX)
                  {
                    timdModes.erase(timdModes.begin() + i);
                    timdCosts.erase(timdCosts.begin() + i);
                  }
                }
              }
              numTimdSatd = (int)timdModes.size();
    
            else   // this is necessary because we skip the candidates list calculation, since it was already obtained for
                   // the DCT-II. Now we load it
            {
              // Restore the modes to be checked with RD
              numModesForFullRD = m_savedNumRdModes[lfnstIdx];
              uiRdModeList.resize(numModesForFullRD);
              std::copy_n(m_savedRdModeList[lfnstIdx], m_savedNumRdModes[lfnstIdx], uiRdModeList.begin());
    
              candCostList.resize(numModesForFullRD);
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if ENABLE_DIMD
    
    #if JVET_AJ0061_TIMD_MERGE
          bool isDimdValid = cu.slice->getSPS()->getUseDimd() && !m_skipDimdMode;
    #else
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          bool isDimdValid = cu.slice->getSPS()->getUseDimd();
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          if (isDimdValid)
          {
            cu.dimd = false;
            ModeInfo m = ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, DIMD_IDX );
            uiRdModeList.push_back(m);
    
    Jie's avatar
    Jie committed
    #if !JVET_V0087_DIMD_NO_ISP
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            if (testISP)
            {
              m.ispMod = HOR_INTRA_SUBPARTITIONS;
              m_ispCandListHor.push_back(m);
              m.ispMod = VER_INTRA_SUBPARTITIONS;
              m_ispCandListVer.push_back(m);
            }
    
    Jie's avatar
    Jie committed
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          }
    #else
    
          CHECK(numModesForFullRD != uiRdModeList.size(), "Inconsistent state!");
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    #if JVET_AH0076_OBIC
          cu.obicFlag = false;
    
    #if JVET_AJ0061_TIMD_MERGE
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
          if (testObic && !m_skipObicMode && !isNnIn)
    #else
    
          if (testObic && !m_skipObicMode)
    
    #endif
    #else
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
          if (testObic && !isNnIn)
    
          {
            ModeInfo m = ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, OBIC_IDX );
            uiRdModeList.push_back(m);
          }
    #endif
    
    
    #if JVET_AH0209_PDP
          if( pdpSaveFlag )
          {
            std::memcpy(m_pdpIntraPredBufIP, m_pdpIntraPredBuf, sizeof(m_pdpIntraPredBufIP));
          }
    #endif
    
    
    #if JVET_AJ0061_TIMD_MERGE
          cu.timdMrg = 0;
          if (testTimdMerge && !cu.mtsFlag /* No MTS loop for Timd-Mrg CUs, as they inherit transform type from their cands*/)
          {
            int iNum = std::min(NUM_TIMD_MERGE_MODES, cu.timdMrgCand);
            for (int idx = 0; idx < iNum; idx++)
            {
              if (cu.timdMrgList[idx][0] != INVALID_TIMD_IDX && !m_skipTimdMode[TimdMrg])
              {
    
    #if JVET_AK0061_PDP_MPM
                if (pdpPredEligible) 
                {
                  bool pdpPredCostSmall = false;
                  for (int idx = 0; idx < m_mpmSavedPdpModeList.size() && !pdpPredCostSmall; ++idx) 
                  {
                    for (int i = 0; i < uiRdModeList.size() && !pdpPredCostSmall; ++i) 
                    {
                      if (m_mpmSavedPdpModeList[idx] == uiRdModeList[i]) 
                      {
                        continue;
                      }
                      if (m_mpmSavedPdpRdList[idx] <= m_timdMergeRdModeList.second)
                      {
                        pdpPredCostSmall = true;
                        break;
                      }
                    }
                    if (pdpPredCostSmall) 
                    {
                      ModeInfo m = m_mpmSavedPdpModeList[idx];
                      uiRdModeList.push_back(m);
                      break;
                    }
                  }
                  if (!pdpPredCostSmall)
                  {
                    ModeInfo m = ModeInfo(false, false, 0, NOT_INTRA_SUBPARTITIONS, TIMDM_IDX + idx);
                    uiRdModeList.push_back(m);
                  }
                }
                else 
                {
    #endif
    
                ModeInfo m = ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, TIMDM_IDX + idx );
                uiRdModeList.push_back(m);
    
          // after this point, don't use numModesForFullRD
          // PBINTRA fast
          if (m_pcEncCfg->getUsePbIntraFast() && !cs.slice->isIntra() && uiRdModeList.size() < numModesAvailable
              && !cs.slice->getDisableSATDForRD() && (mtsUsageFlag != 2 || lfnstIdx > 0))
    
            double   pbintraRatio = (lfnstIdx > 0) ? 1.25 : PBINTRA_RATIO;
            int      maxSize      = -1;
            ModeInfo bestMipMode;
            int      bestMipIdx = -1;
            for (int idx = 0; idx < uiRdModeList.size(); idx++)
    
              if (uiRdModeList[idx].mipFlg)
              {
                bestMipMode = uiRdModeList[idx];
                bestMipIdx  = idx;
                break;
              }
    
            const int numHadCand = 3;
            for (int k = numHadCand - 1; k >= 0; k--)
    
              if (candHadList.size() < (k + 1) || candHadList[k] > cs.interHad * pbintraRatio)
    
                maxSize = k;
    
            if (maxSize > 0)
    
              uiRdModeList.resize(std::min<size_t>(uiRdModeList.size(), maxSize));
    
    #if JVET_AH0103_LOW_DELAY_LFNST_NSPT
              if( spsIntraLfnstEnabled && mtsUsageFlag == 1 )
    #else
    
              if (sps.getUseLFNST() && mtsUsageFlag == 1)
    
              {
                // Update also the number of stored modes to avoid partial fill of mode storage
                m_savedNumRdModes[lfnstIdx] = std::min<int32_t>(int32_t(uiRdModeList.size()), m_savedNumRdModes[lfnstIdx]);
              }
    
    
              if (bestMipIdx >= 0)
              {
                if (uiRdModeList.size() <= bestMipIdx)
                {
                  uiRdModeList.push_back(bestMipMode);
                }
              }
              if (saveDataForISP)
              {
                m_ispCandListHor.resize(std::min<size_t>(m_ispCandListHor.size(), maxSize));
              }
    
            if (maxSize == 0)
            {
              cs.dist     = std::numeric_limits<Distortion>::max();
              cs.interHad = 0;
    
              //===== reset context models =====
    
              return false;
            }
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
        if (isShapeHandledPnn)
        {
          ModeInfo currMode(false, false, 0, NOT_INTRA_SUBPARTITIONS, PNN_IDX);
          uiRdModeList.insert(uiRdModeList.begin(), currMode);
          idxShift++;
          if (cu.lfnstIdx && isAllowedMultiple(width, height))
          {
            uiRdModeList.insert(uiRdModeList.begin(), currMode);
            idxShift++;
          }
          if (spsIntraLfnstEnabled)
          {
            idxPnnBackwardCompatibility = static_cast<int>(uiRdModeList.size());
          }
        }
    #endif
    
    #if JVET_Y0142_ADAPT_INTRA_MTS
    
    #if JVET_AH0103_LOW_DELAY_LFNST_NSPT
    
        if( spsIntraLfnstEnabled && m_modesForMTS.size() == 0 && cu.mtsFlag 
    #if AHG7_MTS_TOOLOFF_CFG
          && sps.getUseMTSExt()
    #endif
          )
    
        if (sps.getUseLFNST() && m_modesForMTS.size() == 0 && cu.mtsFlag
    #if AHG7_MTS_TOOLOFF_CFG
          && sps.getUseMTSExt()
    #endif
          )
    
        {
          return false;
        }
    #endif
    
        int numNonISPModes = (int)uiRdModeList.size();
    
    Keming Cao's avatar
    Keming Cao committed
    #if JVET_W0123_TIMD_FUSION
    
    #if !JVET_AJ0061_TIMD_MERGE
    
    Keming Cao's avatar
    Keming Cao committed
        bool isTimdValid = cu.slice->getSPS()->getUseTimd();
        if (cu.lwidth() * cu.lheight() > 1024 && cu.slice->getSliceType() == I_SLICE)
        {
          isTimdValid = false;
        }
        if (isTimdValid)
    
    #else
        if (isTimdValid && !m_skipTimdMode[Timd])
    #endif
    
    Keming Cao's avatar
    Keming Cao committed
        {
          cu.timd = false;
    
    #if JVET_AJ0146_TIMDSAD
          cu.timdSad = false;
    #endif
    
    Keming Cao's avatar
    Keming Cao committed
          uiRdModeList.push_back( ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, TIMD_IDX ) );
          numNonISPModes++;
    
    Keming Cao's avatar
    Keming Cao committed
          if (lfnstIdx == 0 && !cu.mtsFlag)
          {
    
    #if JVET_AH0065_RELAX_LINE_BUFFER
            bool isFirstLineOfCtu = pu.block(COMPONENT_Y).y == 0;
            int  numOfPassesExtendRef = ((!sps.getUseMRL() || isFirstLineOfCtu) ? 1 : 3);
    #else
    
    Keming Cao's avatar
    Keming Cao committed
            bool isFirstLineOfCtu     = (((pu.block(COMPONENT_Y).y) & ((pu.cs->sps)->getMaxCUWidth() - 1)) == 0);
    
    #if JVET_Y0116_EXTENDED_MRL_LIST
            int  numOfPassesExtendRef = 3;
            if (!sps.getUseMRL() || isFirstLineOfCtu) 
            {
              numOfPassesExtendRef = 1;
            }
            else
            {
              bool checkLineOutsideCtu[2];
              for (int mrlIdx = 1; mrlIdx < 3; mrlIdx++)
              {
                bool isLineOutsideCtu =
                  ((cu.block(COMPONENT_Y).y) % ((cu.cs->sps)->getMaxCUWidth()) <= MULTI_REF_LINE_IDX[mrlIdx]) ? true
                                                                                                              : false;
                checkLineOutsideCtu[mrlIdx-1] = isLineOutsideCtu;
              }
              if (checkLineOutsideCtu[0]) 
              {
                numOfPassesExtendRef = 1;
              }
              else
              {
                if (checkLineOutsideCtu[1] && !checkLineOutsideCtu[0])
                {
                  numOfPassesExtendRef = 2;
                }
              }
            }
    #else
    
    Keming Cao's avatar
    Keming Cao committed
            int  numOfPassesExtendRef = ((!sps.getUseMRL() || isFirstLineOfCtu) ? 1 : MRL_NUM_REF_LINES);
    
    Keming Cao's avatar
    Keming Cao committed
            for (int mRefNum = 1; mRefNum < numOfPassesExtendRef; mRefNum++)
            {
              int multiRefIdx = MULTI_REF_LINE_IDX[mRefNum];
    
    #if JVET_AJ0061_TIMD_MERGE
              TimdMode mode = getTimdMode(false, multiRefIdx);
              if (!m_skipTimdMode[mode])
              {
                uiRdModeList.push_back( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, TIMD_IDX ) );
                numNonISPModes++;
              }
    #else
    
    Keming Cao's avatar
    Keming Cao committed
              uiRdModeList.push_back( ModeInfo( false, false, multiRefIdx, NOT_INTRA_SUBPARTITIONS, TIMD_IDX ) );
              numNonISPModes++;
    
    Keming Cao's avatar
    Keming Cao committed
        }
    #endif
    
          // we reserve positions for ISP in the common full RD list
    
    #if JVET_AH0103_LOW_DELAY_LFNST_NSPT
          const int maxNumRDModesISP = spsIntraLfnstEnabled ? 16 * NUM_LFNST_NUM_PER_SET : 16;
    #else
    
          const int maxNumRDModesISP = sps.getUseLFNST() ? 16 * NUM_LFNST_NUM_PER_SET : 16;
    
          m_curIspLfnstIdx = 0;
    
          for (int i = 0; i < maxNumRDModesISP; i++)
    
            uiRdModeList.push_back( ModeInfo( false, false, 0, INTRA_SUBPARTITIONS_RESERVED, 0 ) );
    
    Keming Cao's avatar
    Keming Cao committed
    #if JVET_W0123_TIMD_FUSION
    
    #if JVET_AJ0061_TIMD_MERGE
        if (isTimdValid && !m_skipTimdMode[Timd] && sps.getUseISP() && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize()) && lfnstIdx == 0 && !cu.mtsFlag)
    #else
    
        if (isTimdValid && sps.getUseISP() && CU::canUseISP(width, height, cu.cs->sps->getMaxTbSize()) && lfnstIdx == 0 && !cu.mtsFlag)
    
    Keming Cao's avatar
    Keming Cao committed
        {
          uiRdModeList.push_back( ModeInfo( false, false, 0, HOR_INTRA_SUBPARTITIONS, TIMD_IDX ) );
          uiRdModeList.push_back( ModeInfo( false, false, 0, VER_INTRA_SUBPARTITIONS, TIMD_IDX ) );
        }
    
    Keming Cao's avatar
    Keming Cao committed
    #endif
    
        ModeInfo       uiBestPUMode;
    
        int            bestBDPCMMode = 0;
        double         bestCostNonBDPCM = MAX_DOUBLE;
    
    #if INTRA_TRANS_ENC_OPT
        double         bestISPCostTested = MAX_DOUBLE;
        ISPType        bestISPModeTested = NOT_INTRA_SUBPARTITIONS;
    #endif
    
        CodingStructure *csTemp = m_pTempCS[gp_sizeIdxInfo->idxFrom( cu.lwidth() )][gp_sizeIdxInfo->idxFrom( cu.lheight() )];
        CodingStructure *csBest = m_pBestCS[gp_sizeIdxInfo->idxFrom( cu.lwidth() )][gp_sizeIdxInfo->idxFrom( cu.lheight() )];
    
        csTemp->slice = cs.slice;
        csBest->slice = cs.slice;
        csTemp->initStructData();
        csBest->initStructData();
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if !INTRA_RM_SMALL_BLOCK_SIZE_CONSTRAINTS
    
        csTemp->picture = cs.picture;
        csBest->picture = cs.picture;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
        // just to be sure
        numModesForFullRD = ( int ) uiRdModeList.size();
    
        TUIntraSubPartitioner subTuPartitioner( partitioner );
    
        if ( testISP )
        {
          m_modeCtrl->setIspCost( MAX_DOUBLE );
          m_modeCtrl->setMtsFirstPassNoIspCost( MAX_DOUBLE );
        }
        int bestLfnstIdx = cu.lfnstIdx;
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
        double costRdPnn = MAX_DOUBLE;
        bool isFirstScanned = true;
    #endif
    
        for (int mode = isSecondColorSpace ? 0 : -2 * int(testBDPCM); mode < (int)uiRdModeList.size(); mode++)
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
          const int idxInModeCostStore = mode - idxShift;
          if (spsIntraLfnstEnabled && isShapeHandledPnn && mode == idxPnnBackwardCompatibility && m_globalBestCostStore > costRdPnn)
          {
            m_globalBestCostStore = costRdPnn;
          }
    
    #endif
    #if JVET_AK0217_INTRA_MTSS
          if (mode >= 0)
          {
            m_pcTrQuant->setLfnstIntraModeIdx(cu.lfnstIdx, mode);
          }
    
          // set CU/PU to luma prediction mode
          ModeInfo uiOrgMode;
    
          if (sps.getUseColorTrans() && !m_pcEncCfg->getRGBFormatFlag() && isSecondColorSpace && mode)
          {
            continue;
          }
    
          if (mode < 0 || (isSecondColorSpace && m_savedBDPCMModeFirstColorSpace[m_savedRdModeIdx][mode]))
    
            cu.bdpcmMode = mode < 0 ? -mode : m_savedBDPCMModeFirstColorSpace[m_savedRdModeIdx][mode];
    
            uiOrgMode = ModeInfo( false, false, 0, NOT_INTRA_SUBPARTITIONS, cu.bdpcmMode == 2 ? VER_IDX : HOR_IDX );
    
            uiOrgMode = uiRdModeList[mode];
          }
    
          if (!cu.bdpcmMode && uiRdModeList[mode].ispMod == INTRA_SUBPARTITIONS_RESERVED)
    
          {
            if (mode == numNonISPModes)   // the list needs to be sorted only once
    
              if (m_pcEncCfg->getUseFastISP())
    
    Keming Cao's avatar
    Keming Cao committed
    #if JVET_W0123_TIMD_FUSION
    
    #if JVET_AJ0146_TIMDSAD
                if (bestTimdMode || bestTimdModeSad)
    #else
    
    Keming Cao's avatar
    Keming Cao committed
                if (bestTimdMode)
    
    Keming Cao's avatar
    Keming Cao committed
                {
                  m_modeCtrl->setBestPredModeDCT2(MAP131TO67(uiBestPUMode.modeId));
                }
                else
                {
                  m_modeCtrl->setBestPredModeDCT2(uiBestPUMode.modeId);
                }
    #else
    
                m_modeCtrl->setBestPredModeDCT2(uiBestPUMode.modeId);
    
    Keming Cao's avatar
    Keming Cao committed
    #endif
    
    Keming Cao's avatar
    Keming Cao committed
    #if JVET_W0123_TIMD_FUSION
              ModeInfo tempBestPUMode = uiBestPUMode;
    
    #if JVET_AJ0146_TIMDSAD
              if (bestTimdMode || bestTimdModeSad)
    #else
    
    Keming Cao's avatar
    Keming Cao committed
              if (bestTimdMode)
    
    Keming Cao's avatar
    Keming Cao committed
              {
                tempBestPUMode.modeId = MAP131TO67(tempBestPUMode.modeId);
              }
              if (!xSortISPCandList(bestCurrentCost, csBest->cost, tempBestPUMode))
    #else
    
              if (!xSortISPCandList(bestCurrentCost, csBest->cost, uiBestPUMode))
    
    Keming Cao's avatar
    Keming Cao committed
    #endif
    
    #if AHG7_LN_TOOLOFF_CFG
            xGetNextISPMode( uiRdModeList[ mode ], ( mode > 0 ? &uiRdModeList[ mode - 1 ] : nullptr ), Size( width, height ), sps.getUseLFNSTExt(), sps.getUseNSPT() );
    #else
    
            xGetNextISPMode(uiRdModeList[mode], (mode > 0 ? &uiRdModeList[mode - 1] : nullptr), Size(width, height));
    
            if (uiRdModeList[mode].ispMod == INTRA_SUBPARTITIONS_RESERVED)
            {
              continue;
    
    #if JVET_AK0059_MDIP
            if(testMdip && uiRdModeList[mode].modeId == cu.mdipMode)
            { 
              uiRdModeList[mode].modeId = MDIP_IDX;
            }
            else if(uiRdModeList[mode].modeId < NUM_LUMA_MODE && m_includeExcludingMode[uiRdModeList[mode].modeId])
            {
              continue;
            }
    #endif
    
            cu.lfnstIdx = m_curIspLfnstIdx;
            uiOrgMode   = uiRdModeList[mode];
          }
    
    #if ENABLE_DIMD && INTRA_TRANS_ENC_OPT
    
          if ((m_pcEncCfg->getIntraPeriod() == 1) && cu.slice->getSPS()->getUseDimd() && mode >= 0 && !cu.dimdBlending && uiOrgMode.ispMod == 0 && uiOrgMode.mRefId == 0 && uiOrgMode.modeId != TIMD_IDX && uiOrgMode.modeId != DIMD_IDX
    #if JVET_AH0076_OBIC
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
            && (isNnIn ? true : uiOrgMode.modeId != OBIC_IDX)
    #else
    
            && uiOrgMode.modeId != OBIC_IDX
    
    #if JVET_AJ0061_TIMD_MERGE
            && uiOrgMode.modeId != TIMDM_IDX
    
    #endif
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
            && uiOrgMode.modeId != PNN_IDX
    
    #endif
    #if JVET_AJ0146_TIMDSAD
            && uiOrgMode.modeId != TIMDSAD_IDX
            && !uiOrgMode.tmpFlag
    
    #if JVET_AJ0061_TIMD_MERGE
            bool modeDuplicated = (uiOrgMode.modeId == cu.dimdMode) && !m_skipDimdMode;
    #else
    
            bool modeDuplicated = (uiOrgMode.modeId == cu.dimdMode);
    
            if (modeDuplicated)
            {
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
              m_modeCostStore[lfnstIdx][idxInModeCostStore] = MAX_DOUBLE / 2.0;
    #else
    
    Sunmi Yoo's avatar
    Sunmi Yoo committed
              m_modeCostStore[lfnstIdx][mode] = MAX_DOUBLE / 2.0;
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if ENABLE_DIMD
          cu.dimd = false;
          if( mode >= 0 && uiOrgMode.modeId == DIMD_IDX ) /*to check*/
          {
    
    #if JVET_AH0076_OBIC
            if (m_skipDimdLfnstMtsPass)
            {
    
    #if !JVET_AJ0061_TIMD_MERGE
    
              CHECK(!cu.lfnstIdx && !cu.mtsFlag, "invalid logic");
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            uiOrgMode.modeId = cu.dimdMode;
            cu.dimd = true;
          }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
    #if JVET_AH0076_OBIC
          cu.obicFlag = false;
          if( mode >= 0 && uiOrgMode.modeId == OBIC_IDX) /*to check*/
          {
            if (m_skipObicLfnstMtsPass)
            {
    
    #if !JVET_AJ0061_TIMD_MERGE
    
              CHECK(!cu.lfnstIdx && !cu.mtsFlag, "invalid logic");
    
              continue;
            }
            cu.obicFlag = true;
            cu.dimd = true;
            uiOrgMode.modeId = cu.obicMode[0];
            pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.modeId;
            pu.multiRefIdx = 0;
          }
    #endif
    
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
          if (mode >= 0 && uiOrgMode.modeId == PNN_IDX && m_skipNnLfnstMtsPass)
          {
            continue;
          }
    #endif
    
    #if JVET_AC0105_DIRECTIONAL_PLANAR
          cu.plIdx = 0;
          if (mode >= 0 && uiOrgMode.modeId == PL_HOR_IDX)
          {
            if (cu.ispMode)
            {
              continue;
            }
            uiOrgMode.modeId = PLANAR_IDX;
            cu.plIdx         = 1;
          }
          if (mode >= 0 && uiOrgMode.modeId == PL_VER_IDX)
          {
            if (cu.ispMode)
            {
              continue;
            }
            uiOrgMode.modeId = PLANAR_IDX;
            cu.plIdx         = 2;
          }
    #endif
    
    fan wang's avatar
    fan wang committed
    #if JVET_AB0155_SGPM
          cu.sgpm = uiOrgMode.sgpmFlag;
          if (cu.sgpm)
          {
    
    #if JVET_AJ0112_REGRESSION_SGPM
            if (m_skipSgpmLfnstMtsPass)
            {
              CHECK(!cu.lfnstIdx && !cu.mtsFlag, "invalid logic");
              continue;
            }
    #endif
    
    fan wang's avatar
    fan wang committed
            uiOrgMode.modeId = uiOrgMode.sgpmMode0;
            cu.sgpmSplitDir  = uiOrgMode.sgpmSplitDir;
            cu.sgpmMode0     = uiOrgMode.sgpmMode0;
            cu.sgpmMode1     = uiOrgMode.sgpmMode1;
    
    #if JVET_AG0152_SGPM_ITMP_IBC
            cu.sgpmBv0 = uiOrgMode.sgpmBv0;
            cu.sgpmBv1 = uiOrgMode.sgpmBv1;
    
    #endif
    #if JVET_AJ0112_REGRESSION_SGPM
            cu.blendModel = uiOrgMode.sgpmBlendModel;
    
    fan wang's avatar
    fan wang committed
            cu.sgpmIdx       = uiOrgMode.sgpmIdx;
    
    #if JVET_AG0152_SGPM_ITMP_IBC
            pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.sgpmMode0 >= SGPM_BV_START_IDX ? 0 : uiOrgMode.sgpmMode0;
            pu.intraDir1[CHANNEL_TYPE_LUMA] = uiOrgMode.sgpmMode1 >= SGPM_BV_START_IDX ? 0 : uiOrgMode.sgpmMode1;
    #else
    
    fan wang's avatar
    fan wang committed
            pu.intraDir1[CHANNEL_TYPE_LUMA] = uiOrgMode.sgpmMode1;
    
    fan wang's avatar
    fan wang committed
          }
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #if JVET_V0130_INTRA_TMP
          cu.tmpFlag = uiOrgMode.tmpFlag;
    
    #if JVET_AK0076_EXTENDED_OBMC_IBC
          cu.obmcFlag = enableOBMC;
    #endif
    
    #if JVET_AD0086_ENHANCED_INTRA_TMP
          cu.tmpIdx = uiOrgMode.tmpIdx;
          cu.tmpFusionFlag = uiOrgMode.tmpFusionFlag;
          cu.tmpFlmFlag = uiOrgMode.tmpFlmFlag;
    
    #if JVET_AG0136_INTRA_TMP_LIC
          cu.tmpLicFlag = uiOrgMode.tmpLicFlag;
          cu.ibcLicFlag = uiOrgMode.tmpLicFlag;
          cu.ibcLicIdx = uiOrgMode.tmpLicIdc;
    #endif
    
          if (cu.tmpFlag)
          {
            cu.tmpIsSubPel = uiOrgMode.tmpIsSubPel;
            cu.tmpSubPelIdx = uiOrgMode.tmpSubPelIdx;
    
    #if JVET_AH0200_INTRA_TMP_BV_REORDER
            cu.tmpFracIdx    = uiOrgMode.tmpFracIdx;
    #endif
          }
    #if JVET_AH0200_INTRA_TMP_BV_REORDER
          else
          {
            cu.tmpFracIdx    = -1;
    
    #if JVET_W0103_INTRA_MTS
    
    #if !JVET_AC0115_INTRA_TMP_DIMD_MTS_LFNST
    
          if (cu.tmpFlag && cu.mtsFlag) continue;
    #endif
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
          cu.mipFlag                     = uiOrgMode.mipFlg;
    
          pu.mipTransposedFlag           = uiOrgMode.mipTrFlg;
    
          cu.ispMode                     = uiOrgMode.ispMod;
          pu.multiRefIdx                 = uiOrgMode.mRefId;
          pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.modeId;
    
    #if JVET_AG0058_EIP
          cu.eipFlag = (mode >= 0) && (uiOrgMode.modeId >= EIP_IDX) && (uiOrgMode.modeId < EIP_IDX + std::max(NUM_DERIVED_EIP, MAX_MERGE_EIP));
          if (cu.eipFlag)
          {
    
    #if JVET_AJ0082_MM_EIP
            if (m_skipEipLfnstMtsPass)
            {
              cu.eipFlag = false;
              CHECK(!cu.lfnstIdx && !cu.mtsFlag, "invalid logic");
              continue;
            }
    #endif
    
            cu.eipMerge = uiOrgMode.mipTrFlg;
            pu.intraDir[0] = uiOrgMode.modeId - EIP_IDX;
            cu.eipModel = cu.eipMerge ? m_eipMergeModel[pu.intraDir[0]] : m_eipModel[pu.intraDir[0]];
    
    #if JVET_AJ0082_MM_EIP
            cu.eipMmFlag = (!cu.eipMerge) && (pu.intraDir[0] >= m_numSigEip);
            if(cu.eipMmFlag)
            {
              pu.intraDir[0] -= m_numSigEip;
            }
    
            if (cu.eipModel.eipDimdMode == -1)
    
            {
              const auto modeIdx = cu.eipMmFlag ? (pu.intraDir[0] + m_numSigEip): pu.intraDir[0];
              if(cu.eipMerge)
              {
                PelBuf eipSaveBuf(m_eipMergePredBuf[modeIdx], pu.Y());
                cu.eipModel.eipDimdMode = m_eipMergeModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu
    
    #if JVET_AI0050_INTER_MTSS || JVET_AK0187_IMPLICIT_MTS_LUT_EXTENSION
    
                  , cu.dimdDerivedIntraDir2nd
    #endif
                );
                CHECK(modeIdx >= NUM_EIP_MERGE_SIGNAL, "modeIdx >= NUM_EIP_MERGE_SIGNAL");
    
    #if JVET_AK0217_INTRA_MTSS || JVET_AK0187_IMPLICIT_MTS_LUT_EXTENSION
                cu.eipModel.eipDimdMode2nd = cu.dimdDerivedIntraDir2nd;
                m_eipMergeModel[ modeIdx ].eipDimdMode2nd = cu.dimdDerivedIntraDir2nd;
    #endif
    
              }
              else
              {
                PelBuf eipSaveBuf(m_eipPredBuf[modeIdx], pu.Y());
                cu.eipModel.eipDimdMode = m_eipModel[modeIdx].eipDimdMode = deriveIpmForTransform(eipSaveBuf, cu
    
    #if JVET_AI0050_INTER_MTSS || JVET_AK0187_IMPLICIT_MTS_LUT_EXTENSION
    
                  , cu.dimdDerivedIntraDir2nd
    #endif
                );
                CHECK(modeIdx >= NUM_DERIVED_EIP, "modeIdx >= NUM_DERIVED_EIP");
    
    #if JVET_AK0217_INTRA_MTSS || JVET_AK0187_IMPLICIT_MTS_LUT_EXTENSION
                cu.eipModel.eipDimdMode2nd = cu.dimdDerivedIntraDir2nd;
                m_eipModel[ modeIdx ].eipDimdMode2nd = cu.dimdDerivedIntraDir2nd;
    #endif
    
    Keming Cao's avatar
    Keming Cao committed
    #if JVET_W0123_TIMD_FUSION
          cu.timd = false;
    
    #if JVET_AJ0146_TIMDSAD
          cu.timdSad = false;
    #endif
    
    #if JVET_AJ0061_TIMD_MERGE
          cu.timdMrg = 0;
    #endif
    
    Keming Cao's avatar
    Keming Cao committed
          if (mode >= 0 && uiOrgMode.modeId == TIMD_IDX)
          {
            if (cu.ispMode)
            {
              cu.lfnstIdx = lfnstIdx;
    
    #if INTRA_TRANS_ENC_OPT
              if ((m_pcEncCfg->getIntraPeriod() == 1) && ((bestISPModeTested == HOR_INTRA_SUBPARTITIONS) || (bestISPModeTested == VER_INTRA_SUBPARTITIONS)))
              {
                if (cu.ispMode != bestISPModeTested)
                {
                  continue;
                }
              }
    #endif
    
    Keming Cao's avatar
    Keming Cao committed
              if (cu.ispMode == VER_INTRA_SUBPARTITIONS && uiBestPUMode.ispMod == 0 && !bestTimdMode)
              {
                continue;
              }
            }
    
    #if INTRA_TRANS_ENC_OPT
            else if (m_skipTimdLfnstMtsPass)
            {
    
    #if !JVET_AJ0061_TIMD_MERGE
    
              CHECK(!cu.lfnstIdx && !cu.mtsFlag, "invalid logic");
    
    Keming Cao's avatar
    Keming Cao committed
            uiOrgMode.modeId = cu.timdMode;
            pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.modeId;
            cu.timd = true;
    
    #if JVET_AJ0146_TIMDSAD
            cu.timdSad = false;
    #endif
          }
    #if JVET_AJ0146_TIMDSAD
          if (mode >= 0 && uiOrgMode.modeId == TIMDSAD_IDX)
          {
            cu.timd = true;
            cu.timdSad = true;
            uiOrgMode.modeId = cu.timdModeSad;
            pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.modeId;
    
    Keming Cao's avatar
    Keming Cao committed
          }
    #endif
    
    #if JVET_AB0157_TMRL
          cu.tmrlFlag = false;
          if (uiOrgMode.mRefId >= MAX_REF_LINE_IDX)
          {
            int tmrlListIdx = uiOrgMode.mRefId - MAX_REF_LINE_IDX;
            cu.tmrlListIdx = tmrlListIdx;
    
            pu.multiRefIdx = m_tmrlList[tmrlListIdx].multiRefIdx;
            pu.intraDir[0] = m_tmrlList[tmrlListIdx].intraDir;
    
            cu.tmrlFlag = true;
          }
    #endif
    
    #if JVET_AK0059_MDIP
          cu.mdip = false;
          if (mode >= 0 && uiOrgMode.modeId == MDIP_IDX)
          {
            cu.mdip = true;
            uiOrgMode.modeId = cu.mdipMode;
            pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.modeId;
          }
    #endif
    
    #if JVET_AJ0061_TIMD_MERGE
          cu.timdMrg = 0;
    
          if( mode >= 0 && uiOrgMode.modeId >= TIMDM_IDX && uiOrgMode.modeId < TIMDM_IDX + NUM_TIMD_MERGE_MODES + 1)
    
          {
            if (m_skipTimdMrgLfnstMtsPass)
            {
              continue;
            }
            cu.timdMrg = uiOrgMode.modeId - TIMDM_IDX + 1;
            cu.timd = true;
            uiOrgMode.modeId = cu.timdMrgList[uiOrgMode.modeId - TIMDM_IDX][0];
            pu.intraDir[CHANNEL_TYPE_LUMA] = uiOrgMode.modeId;
            pu.multiRefIdx = uiOrgMode.mRefId;
          }
    #endif
    
          CHECK(cu.mipFlag && pu.multiRefIdx, "Error: combination of MIP and MRL not supported");
    
    Keming Cao's avatar
    Keming Cao committed
    #if JVET_W0123_TIMD_FUSION
          if (!cu.timd)
          {
    #endif
            CHECK(pu.multiRefIdx && (pu.intraDir[0] == PLANAR_IDX),
                  "Error: combination of MRL and Planar mode not supported");
    #if JVET_W0123_TIMD_FUSION
          }
    
    #endif
    #if JVET_AJ0249_NEURAL_NETWORK_BASED
          if (pu.intraDir[CHANNEL_TYPE_LUMA] == PNN_IDX && cu.lfnstIdx && isAllowedMultiple(width, height))
          {
            if (isFirstScanned)
            {
              cu.lfnstSecFlag = false;
              isFirstScanned = false;
            }
            else
            {
              cu.lfnstSecFlag = true;
            }