Skip to content
Snippets Groups Projects
IntraSearch.cpp 322 KiB
Newer Older
  • Learn to ignore specific revisions
  •     }
      }
    
      int mode1 = PLANAR_IDX;
      int mode2 = bestNormalIntraAngle;
    
      ModeInfo refMode = origHadList.at(0);
      auto* destListPtr = &m_ispCandListHor;
    
    
      if (m_pcEncCfg->getUseFastISP() && bestISPModeInRelCU != -1) //RelCU intra mode
      {
    
        destListPtr->push_back(
          ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, bestISPModeInRelCU));
    
        modeIsInList[bestISPModeInRelCU] = true;
      }
      // Planar
    
    #if JVET_W0103_INTRA_MTS
      // push planar later when FastISP is on.
      if (!m_pcEncCfg->getUseFastISP() && !modeIsInList[mode1])
    #else
    
      if (!modeIsInList[mode1])
    
      {
        destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode1));
        modeIsInList[mode1] = true;
      }
    
      // Best angle in regular intra
      if (mode2 != -1 && !modeIsInList[mode2])
      {
        destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode2));
        modeIsInList[mode2] = true;
      }
      // Remaining regular intra modes that were full RD tested (except DC, which is added after the angles from regular intra)
      int dcModeIndex = -1;
      for (int remModeIdx = 0; remModeIdx < m_regIntraRDListWithCosts.size(); remModeIdx++)
      {
        int currentMode = m_regIntraRDListWithCosts.at(remModeIdx).modeId;
        if (currentMode != mode1 && currentMode != mode2 && !modeIsInList[currentMode])
        {
          if (currentMode > DC_IDX)
          {
            destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, currentMode));
            modeIsInList[currentMode] = true;
          }
          else if (currentMode == DC_IDX)
          {
            dcModeIndex = remModeIdx;
          }
        }
      }
    
    #if JVET_W0103_INTRA_MTS
      // Planar (after angular modes when FastISP is on)
      if (!modeIsInList[mode1])
      {
        destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, mode1));
        modeIsInList[mode1] = true;
      }
    #endif
    
      // DC is added after the angles from regular intra
      if (dcModeIndex != -1 && !modeIsInList[DC_IDX])
      {
        destListPtr->push_back(ModeInfo(refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, DC_IDX));
        modeIsInList[DC_IDX] = true;
      }
    
      // We add extra candidates to the list that will only be tested if ISP is likely to win
      for (int j = 0; j < NUM_LFNST_NUM_PER_SET; j++)
      {
        m_ispTestedModes[j].numOrigModesToTest = (int)destListPtr->size();
    
    #if JVET_W0103_INTRA_MTS
        if (m_pcEncCfg->getUseFastISP() && m_numModesISPRDO != -1 && destListPtr->size() > m_numModesISPRDO)
        {
          m_ispTestedModes[j].numOrigModesToTest = m_numModesISPRDO;
        }
    #endif
    
      const int addedModesFromHadList = 3;
      int       newModesAdded = 0;
    
      for (int k = 0; k < origHadList.size(); k++)
      {
        if (newModesAdded == addedModesFromHadList)
        {
          break;
        }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
        if (
    
    Jie's avatar
    Jie committed
    #if ENABLE_DIMD && !JVET_V0087_DIMD_NO_ISP
    
    Vadim Seregin's avatar
    Vadim Seregin committed
          origHadList.at(k).modeId == DIMD_IDX ||
    
    Keming Cao's avatar
    Keming Cao committed
    #endif
    #if JVET_W0123_TIMD_FUSION
          origHadList.at(k).modeId == TIMD_IDX ||
    
    #endif
    #if JVET_AC0105_DIRECTIONAL_PLANAR
          origHadList.at(k).modeId == PL_HOR_IDX || origHadList.at(k).modeId == PL_VER_IDX ||
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    	!modeIsInList[origHadList.at(k).modeId])
    
          destListPtr->push_back( ModeInfo( refMode.mipFlg, refMode.mipTrFlg, refMode.mRefId, refMode.ispMod, origHadList.at(k).modeId ) );
    
      if (m_pcEncCfg->getUseFastISP() && bestISPModeInRelCU != -1)
      {
        destListPtr->resize(1);
      }
    
    
      // Copy modes to other split-type list
      m_ispCandListVer = m_ispCandListHor;
      for (int i = 0; i < m_ispCandListVer.size(); i++)
      {
        m_ispCandListVer[i].ispMod = VER_INTRA_SUBPARTITIONS;
      }
    
      // Reset the tested modes information to 0
    
      for (int j = 0; j < NUM_LFNST_NUM_PER_SET; j++)
      {
        for (int i = 0; i < m_ispCandListHor.size(); i++)
        {
          m_ispTestedModes[j].clearISPModeInfo(m_ispCandListHor[i].modeId);
        }
      }
      return true;
    }
    
    void IntraSearch::xSortISPCandListLFNST()
    {
      //It resorts the list of intra mode candidates for lfnstIdx > 0 by checking the RD costs for lfnstIdx = 0
      ISPTestedModesInfo& ispTestedModesRef = m_ispTestedModes[0];
      for (int splitIdx = 0; splitIdx < NUM_INTRA_SUBPARTITIONS_MODES - 1; splitIdx++)
      {
        ISPType ispMode = splitIdx ? VER_INTRA_SUBPARTITIONS : HOR_INTRA_SUBPARTITIONS;
        if (!m_ispTestedModes[m_curIspLfnstIdx].splitIsFinished[splitIdx] && ispTestedModesRef.testedModes[splitIdx].size() > 1)
        {
          auto& candList   = ispMode == HOR_INTRA_SUBPARTITIONS ? m_ispCandListHor : m_ispCandListVer;
          int bestModeId   = candList[1].modeId > DC_IDX ? candList[1].modeId : -1;
          int bestSubParts = candList[1].modeId > DC_IDX ? ispTestedModesRef.getNumCompletedSubParts(ispMode, bestModeId) : -1;
          double bestCost  = candList[1].modeId > DC_IDX ? ispTestedModesRef.getRDCost(ispMode, bestModeId) : MAX_DOUBLE;
          for (int i = 0; i < candList.size(); i++)
          {
    
    Jie's avatar
    Jie committed
    #if ENABLE_DIMD && !JVET_V0087_DIMD_NO_ISP
    
    Vadim Seregin's avatar
    Vadim Seregin committed
            if( candList[i].modeId == DIMD_IDX )
            {
              continue;
            }
    
    Keming Cao's avatar
    Keming Cao committed
    #endif
    #if JVET_W0123_TIMD_FUSION
            if( candList[i].modeId == TIMD_IDX )
            {
              continue;
            }
    
    #endif
    #if JVET_AC0105_DIRECTIONAL_PLANAR
            if (candList[i].modeId == PL_HOR_IDX || candList[i].modeId == PL_VER_IDX)
            {
              continue;
            }
    
    Vadim Seregin's avatar
    Vadim Seregin committed
    #endif
    
            const int candSubParts = ispTestedModesRef.getNumCompletedSubParts(ispMode, candList[i].modeId);
            const double candCost = ispTestedModesRef.getRDCost(ispMode, candList[i].modeId);
            if (candSubParts > bestSubParts || candCost < bestCost)
            {
              bestModeId = candList[i].modeId;
              bestCost = candCost;
              bestSubParts = candSubParts;
            }
          }
    
          if (bestModeId != -1)
          {
            if (bestModeId != candList[0].modeId)
            {
              auto prevMode = candList[0];
              candList[0].modeId = bestModeId;
              for (int i = 1; i < candList.size(); i++)
              {
                auto nextMode = candList[i];
                candList[i] = prevMode;
                if (nextMode.modeId == bestModeId)
                {
                  break;
                }
                prevMode = nextMode;
              }
            }
          }
        }
      }
    
    bool IntraSearch::updateISPStatusFromRelCU( double bestNonISPCostCurrCu, ModeInfo bestNonISPModeCurrCu, int& bestISPModeInRelCU )
    {
      //It compares the data of a related CU with the current CU to cancel or reduce the ISP tests
      bestISPModeInRelCU = -1;
      if (m_modeCtrl->getRelatedCuIsValid())
      {
        double bestNonISPCostRelCU = m_modeCtrl->getBestDCT2NonISPCostRelCU();
        double costRatio           = bestNonISPCostCurrCu / bestNonISPCostRelCU;
        bool   bestModeRelCuIsMip  = (m_modeCtrl->getIspPredModeValRelCU() >> 5) & 0x1;
        bool   bestModeCurrCuIsMip = bestNonISPModeCurrCu.mipFlg;
        int    relatedCuIntraMode  = m_modeCtrl->getIspPredModeValRelCU() >> 9;
        bool   isSameTypeOfMode    = (bestModeRelCuIsMip && bestModeCurrCuIsMip) || (!bestModeRelCuIsMip && !bestModeCurrCuIsMip);
        bool   bothModesAreAngular = bestNonISPModeCurrCu.modeId > DC_IDX && relatedCuIntraMode > DC_IDX;
        bool   modesAreComparable  = isSameTypeOfMode && (bestModeCurrCuIsMip || bestNonISPModeCurrCu.modeId == relatedCuIntraMode || (bothModesAreAngular && abs(relatedCuIntraMode - (int)bestNonISPModeCurrCu.modeId) <= 5));
        int    status              = m_modeCtrl->getIspPredModeValRelCU();
    
        if ((status & 0x3) == 0x3) //ISP was not selected in the relCU
        {
          double bestNonDCT2Cost = m_modeCtrl->getBestNonDCT2Cost();
          double ratioWithNonDCT2 = bestNonDCT2Cost / bestNonISPCostRelCU;
          double margin = ratioWithNonDCT2 < 0.95 ? 0.2 : 0.1;
    
          if (costRatio > 1 - margin && costRatio < 1 + margin && modesAreComparable)
          {
            for (int lfnstVal = 0; lfnstVal < NUM_LFNST_NUM_PER_SET; lfnstVal++)
            {
              m_ispTestedModes[lfnstVal].splitIsFinished[HOR_INTRA_SUBPARTITIONS - 1] = true;
              m_ispTestedModes[lfnstVal].splitIsFinished[VER_INTRA_SUBPARTITIONS - 1] = true;
            }
            return false;
          }
        }
        else if ((status & 0x3) == 0x1) //ISP was selected in the relCU
        {
          double margin = 0.05;
    
          if (costRatio > 1 - margin && costRatio < 1 + margin && modesAreComparable)
          {
            int  ispSplitIdx = (m_modeCtrl->getIspPredModeValRelCU() >> 2) & 0x1;
            bool lfnstIdxIsNot0 = (bool)((m_modeCtrl->getIspPredModeValRelCU() >> 3) & 0x1);
            bool lfnstIdxIs2 = (bool)((m_modeCtrl->getIspPredModeValRelCU() >> 4) & 0x1);
            int  lfnstIdx = !lfnstIdxIsNot0 ? 0 : lfnstIdxIs2 ? 2 : 1;
            bestISPModeInRelCU = (int)m_modeCtrl->getBestISPIntraModeRelCU();
    
            for (int splitIdx = 0; splitIdx < NUM_INTRA_SUBPARTITIONS_MODES - 1; splitIdx++)
            {
              for (int lfnstVal = 0; lfnstVal < NUM_LFNST_NUM_PER_SET; lfnstVal++)
              {
                if (lfnstVal == lfnstIdx && splitIdx == ispSplitIdx)
                {
                  continue;
                }
                m_ispTestedModes[lfnstVal].splitIsFinished[splitIdx] = true;
              }
            }
    
            bool stopNonDCT2Transforms = (bool)((m_modeCtrl->getIspPredModeValRelCU() >> 6) & 0x1);
            m_modeCtrl->setStopNonDCT2Transforms(stopNonDCT2Transforms);
          }
        }
        else
        {
          THROW("Wrong ISP relCU status");
        }
      }
    
      return true;
    }
    
    void IntraSearch::xFinishISPModes()
    {
    
      //Continue to the next lfnst index
    
      m_curIspLfnstIdx++;
    
      if (m_curIspLfnstIdx < NUM_LFNST_NUM_PER_SET)
      {
        //Check if LFNST is applicable
        if (m_curIspLfnstIdx == 1)
        {
          bool canTestLFNST = false;
          for (int lfnstIdx = 1; lfnstIdx < NUM_LFNST_NUM_PER_SET; lfnstIdx++)
          {
            canTestLFNST |= !m_ispTestedModes[lfnstIdx].splitIsFinished[HOR_INTRA_SUBPARTITIONS - 1] || !m_ispTestedModes[lfnstIdx].splitIsFinished[VER_INTRA_SUBPARTITIONS - 1];
          }
          if (canTestLFNST)
          {
            //Construct the intra modes candidates list for the lfnst > 0 cases
            xSortISPCandListLFNST();
          }
        }
      }
    }