Skip to content
Snippets Groups Projects
IntraSearch.cpp 116 KiB
Newer Older
  • Learn to ignore specific revisions
  •         double costTmp = std::numeric_limits<double>::max();
            if( distTmp < std::numeric_limits<Distortion>::max() )
            {
              uint64_t bits  = xGetIntraFracBitsQTChroma( currTU, COMPONENT_Cb );
              costTmp = m_pcRdCost->calcRdCost( bits, distTmp );
            }
    #else
    
            xIntraCodingTUBlock( currTU, COMPONENT_Cb, false, distTmp, 0 );
    
            uint64_t bits  = xGetIntraFracBitsQTChroma( currTU, COMPONENT_Cb );
            double costTmp = m_pcRdCost->calcRdCost( bits, distTmp );
    
            if( costTmp < bestCostCbCr )
            {
              bestCostCbCr  = costTmp;
              bestDistCbCr  = distTmp;
    
              bestJointCbCr = currTU.jointCbCr;
    
              // store data
              if( cbfMask != jointCbfMasksToTest.back() )
              {
    #if KEEP_PRED_AND_RESI_SIGNALS
                saveCS.getOrgResiBuf(cbArea).copyFrom(cs.getOrgResiBuf(cbArea));
                saveCS.getOrgResiBuf(crArea).copyFrom(cs.getOrgResiBuf(crArea));
    #endif
                saveCS.getPredBuf   (cbArea).copyFrom(cs.getPredBuf   (cbArea));
                saveCS.getPredBuf   (crArea).copyFrom(cs.getPredBuf   (crArea));
                if( keepResi )
                {
                  saveCS.getResiBuf (cbArea).copyFrom(cs.getResiBuf   (cbArea));
                  saveCS.getResiBuf (crArea).copyFrom(cs.getResiBuf   (crArea));
                }
                saveCS.getRecoBuf   (cbArea).copyFrom(cs.getRecoBuf   (cbArea));
                saveCS.getRecoBuf   (crArea).copyFrom(cs.getRecoBuf   (crArea));
    
                tmpTU.copyComponentFrom(currTU, COMPONENT_Cb);
                tmpTU.copyComponentFrom(currTU, COMPONENT_Cr);
    
                ctxBest = m_CABACEstimator->getCtx();
              }
              else
              {
                lastIsBest = true;
              }
    #else
    
              bestJointCbCr = 1;
    
          // Retrieve the best CU data (unless it was the very last one tested)
    
          if ( !( maxModesTested == 1 && jointCbfMasksToTest.empty() ) && !lastIsBest )
    #else
    
          if ( !(maxModesTested == 1 && !checkJointCbCr) && bestJointCbCr == 0 )
    
          {
    #if KEEP_PRED_AND_RESI_SIGNALS
            cs.getPredBuf   (cbArea).copyFrom(saveCS.getPredBuf   (cbArea));
            cs.getOrgResiBuf(cbArea).copyFrom(saveCS.getOrgResiBuf(cbArea));
            cs.getPredBuf   (crArea).copyFrom(saveCS.getPredBuf   (crArea));
            cs.getOrgResiBuf(crArea).copyFrom(saveCS.getOrgResiBuf(crArea));
    #endif
            cs.getPredBuf   (cbArea).copyFrom(saveCS.getPredBuf   (cbArea));
            cs.getPredBuf   (crArea).copyFrom(saveCS.getPredBuf   (crArea));
    
            if( keepResi )
            {
              cs.getResiBuf (cbArea).copyFrom(saveCS.getResiBuf   (cbArea));
              cs.getResiBuf (crArea).copyFrom(saveCS.getResiBuf   (crArea));
            }
            cs.getRecoBuf   (cbArea).copyFrom(saveCS.getRecoBuf   (cbArea));
            cs.getRecoBuf   (crArea).copyFrom(saveCS.getRecoBuf   (crArea));
    
            currTU.copyComponentFrom(tmpTU, COMPONENT_Cb);
            currTU.copyComponentFrom(tmpTU, COMPONENT_Cr);
    
            m_CABACEstimator->getCtx() = ctxBest;
          }
    
          // Copy results to the picture structures
          cs.picture->getRecoBuf(cbArea).copyFrom(cs.getRecoBuf(cbArea));
          cs.picture->getRecoBuf(crArea).copyFrom(cs.getRecoBuf(crArea));
          cs.picture->getPredBuf(cbArea).copyFrom(cs.getPredBuf(cbArea));
          cs.picture->getPredBuf(crArea).copyFrom(cs.getPredBuf(crArea));
    
          cbfs.cbf(COMPONENT_Cb) = TU::getCbf(currTU, COMPONENT_Cb);
          cbfs.cbf(COMPONENT_Cr) = TU::getCbf(currTU, COMPONENT_Cr);
    
          currTU.jointCbCr = ( (cbfs.cbf(COMPONENT_Cb) + cbfs.cbf(COMPONENT_Cr)) ? bestJointCbCr : 0 );
    
          currTU.jointCbCr = cbfs.cbf(COMPONENT_Cb) ? bestJointCbCr : 0;
    
          cs.dist         += bestDistCbCr;
    
        }
      }
      else
      {
        unsigned    numValidTBlocks   = ::getNumberValidTBlocks( *cs.pcv );
        ChromaCbfs  SplitCbfs         ( false );
    
        if( partitioner.canSplit( TU_MAX_TR_SPLIT, cs ) )
        {
          partitioner.splitCurrArea( TU_MAX_TR_SPLIT, cs );
        }
    
        else if( currTU.cu->ispMode )
        {
          partitioner.splitCurrArea( ispType, cs );
        }
    
          ChromaCbfs subCbfs = xRecurIntraChromaCodingQT( cs, partitioner, bestCostSoFar, ispType );
    
    
          for( uint32_t ch = COMPONENT_Cb; ch < numValidTBlocks; ch++ )
          {
            const ComponentID compID = ComponentID( ch );
            SplitCbfs.cbf( compID ) |= subCbfs.cbf( compID );
          }
        } while( partitioner.nextPart( cs ) );
    
        partitioner.exitCurrSplit();
    
    
        if( lumaUsesISP && cs.dist == MAX_UINT )
        {
          return cbfs;
        }
    
          if( !lumaUsesISP )
          {
            for( auto &ptu : cs.tus )
            {
              if( currArea.Cb().contains( ptu->Cb() ) || ( !ptu->Cb().valid() && currArea.Y().contains( ptu->Y() ) ) )
              {
                TU::setCbfAtDepth( *ptu, COMPONENT_Cb, currDepth, SplitCbfs.Cb );
                TU::setCbfAtDepth( *ptu, COMPONENT_Cr, currDepth, SplitCbfs.Cr );
              }
            }
          }
    
        }
      }
    
      return cbfs;
    }
    
    uint64_t IntraSearch::xFracModeBitsIntra(PredictionUnit &pu, const uint32_t &uiMode, const ChannelType &chType)
    {
      uint32_t orgMode = uiMode;
    
    
      if (!pu.mhIntraFlag)
    
      std::swap(orgMode, pu.intraDir[chType]);
    
      m_CABACEstimator->resetBits();
    
      if( isLuma( chType ) )
      {
    
        if (!pu.mhIntraFlag)
    
        {
          m_CABACEstimator->intra_luma_pred_mode(pu);
        }
    
      if ( !pu.mhIntraFlag )
    
      std::swap(orgMode, pu.intraDir[chType]);
    
      return m_CABACEstimator->getEstFracBits();
    }
    
    
    
    void IntraSearch::encPredIntraDPCM( const ComponentID &compID, PelBuf &pOrg, PelBuf &pDst, const uint32_t &uiDirMode )
    {
      CHECK( pOrg.buf == 0, "Encoder DPCM called without original buffer" );
    
      const int srcStride = m_topRefLength + 1;
      CPelBuf   pSrc = CPelBuf(getPredictorPtr(compID), srcStride, m_leftRefLength + 1);
    
      // Sample Adaptive intra-Prediction (SAP)
      if( uiDirMode == HOR_IDX )
      {
        // left column filled with reference samples, remaining columns filled with pOrg data
        for( int y = 0; y < pDst.height; y++ )
        {
          pDst.at( 0, y ) = pSrc.at( 0, 1 + y );
        }
        CPelBuf orgRest  = pOrg.subBuf( 0, 0, pOrg.width - 1, pOrg.height );
        PelBuf  predRest = pDst.subBuf( 1, 0, pDst.width - 1, pDst.height );
    
        predRest.copyFrom( orgRest );
      }
      else // VER_IDX
      {
        // top row filled with reference samples, remaining rows filled with pOrg data
        for( int x = 0; x < pDst.width; x++ )
        {
          pDst.at( x, 0 ) = pSrc.at( 1 + x, 0 );
        }
        CPelBuf orgRest  = pOrg.subBuf( 0, 0, pOrg.width, pOrg.height - 1 );
        PelBuf  predRest = pDst.subBuf( 0, 1, pDst.width, pDst.height - 1 );
    
        predRest.copyFrom( orgRest );
      }
    }
    
    bool IntraSearch::useDPCMForFirstPassIntraEstimation( const PredictionUnit &pu, const uint32_t &uiDirMode )
    {
      return CU::isRDPCMEnabled( *pu.cu ) && pu.cu->transQuantBypass && (uiDirMode == HOR_IDX || uiDirMode == VER_IDX);
    }
    
    
    template<typename T, size_t N>
    void IntraSearch::reduceHadCandList(static_vector<T, N>& candModeList, static_vector<double, N>& candCostList, int& numModesForFullRD, const double thresholdHadCost, const double thresholdHadCostConv)
    {
      CHECKD(candModeList.size() != numModesForFullRD, "Error: list size");
      CHECKD(candCostList.size() != numModesForFullRD, "Error: list size");
      const int maxCandPerType = numModesForFullRD >> 1;
      static_vector<ModeInfo, FAST_UDI_MAX_RDMODE_NUM> tempRdModeList;
      static_vector<double, FAST_UDI_MAX_RDMODE_NUM> tempCandCostList;
      const double minCost = candCostList[0];
    
      int numConv = 0;
      for (int idx = 0; idx < candModeList.size(); idx++)
      {
        ModeInfo uiOrgMode = candModeList[idx];
    
        if (!uiOrgMode.mipFlg) { numConv++; }
    
        if (uiOrgMode.mipFlg || (numConv <= maxCandPerType))
        {
          tempRdModeList.push_back(uiOrgMode);
          tempCandCostList.push_back(candCostList[idx]);
        }
        else if (candCostList[idx] < thresholdHadCostConv * minCost)
        {
          tempRdModeList.push_back(uiOrgMode);
          tempCandCostList.push_back(candCostList[idx]);
        }
      }
      candModeList = tempRdModeList;
      candCostList = tempCandCostList;
    
      int numMip = 0;
      tempRdModeList.clear();
      tempCandCostList.clear();
      for (int idx = 0; idx < candModeList.size(); idx++)
      {
        ModeInfo uiOrgMode = candModeList[idx];
        if (uiOrgMode.mipFlg)
        {
          numMip++;
        }
        if (!uiOrgMode.mipFlg || (numMip <= maxCandPerType))
        {
          tempRdModeList.push_back(uiOrgMode);
          tempCandCostList.push_back(candCostList[idx]);
        }
        else if (candCostList[idx] < thresholdHadCost * minCost)
        {
          tempRdModeList.push_back(uiOrgMode);
          tempCandCostList.push_back(candCostList[idx]);
        }
      }
      candModeList = tempRdModeList;
      candCostList = tempCandCostList;
      numModesForFullRD = int(candModeList.size());
    }