Skip to content
Snippets Groups Projects
EncLib.cpp 77.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • Karsten Suehring's avatar
    Karsten Suehring committed
        pps.setBrickSplittingPresentFlag(false);
      }
      else
      {
        pps.setBrickSplittingPresentFlag(true);
    
        std::vector<bool> brickSplitFlag (numTiles, false);
        std::vector<bool> uniformBrickSpacingFlag (numTiles, false);
        std::vector<int>  brickHeightMinus1 (numTiles, 0);
    
        std::vector<int> numBrickRowsMinus2(numTiles, 0);
    
    Karsten Suehring's avatar
    Karsten Suehring committed
        std::vector<std::vector<int>>  brickRowHeightMinus1 (numTiles);
    
        for (auto &brickSplit: m_brickSplitMap)
        {
          int tileIdx = brickSplit.first;
          CHECK ( tileIdx >= numTiles, "Brick split specified for undefined tile");
    
          brickSplitFlag[tileIdx]           = true;
          uniformBrickSpacingFlag [tileIdx] = brickSplit.second.m_uniformSplit;
          if (uniformBrickSpacingFlag [tileIdx])
          {
            brickHeightMinus1[tileIdx]=brickSplit.second.m_uniformHeight - 1;
          }
          else
          {
    
            numBrickRowsMinus2[tileIdx] = brickSplit.second.m_numSplits - 1;
    
    Karsten Suehring's avatar
    Karsten Suehring committed
            brickRowHeightMinus1[tileIdx].resize(brickSplit.second.m_numSplits);
            for (int i=0; i<brickSplit.second.m_numSplits; i++)
            {
              brickRowHeightMinus1[tileIdx][i]=brickSplit.second.m_brickHeight[i] - 1;
            }
          }
        }
        pps.setBrickSplitFlag(brickSplitFlag);
        pps.setUniformBrickSpacingFlag(uniformBrickSpacingFlag);
        pps.setBrickHeightMinus1(brickHeightMinus1);
    
        pps.setNumBrickRowsMinus2(numBrickRowsMinus2);
    
    Karsten Suehring's avatar
    Karsten Suehring committed
        pps.setBrickRowHeightMinus1(brickRowHeightMinus1);
    
        // check brick dimensions
        std::vector<uint32_t> tileRowHeight (m_iNumRowsMinus1+1);
        int picHeightInCtus = (getSourceHeight() + m_maxCUHeight - 1) / m_maxCUHeight;
    
        // calculate all tile row heights
        if( pps.getUniformTileSpacingFlag() )
        {
          //set width and height for each (uniform) tile
          for(int row=0; row < m_iNumRowsMinus1 + 1; row++)
          {
            tileRowHeight[row] = (row+1)*picHeightInCtus/(m_iNumRowsMinus1+1)   - (row*picHeightInCtus)/(m_iNumRowsMinus1 + 1);
          }
        }
        else
        {
          tileRowHeight[ m_iNumRowsMinus1 ] = picHeightInCtus;
    
          for( int j = 0; j < m_iNumRowsMinus1; j++ )
    
    Karsten Suehring's avatar
    Karsten Suehring committed
          {
            tileRowHeight[ j ] = pps.getTileRowHeight( j );
            tileRowHeight[ m_iNumRowsMinus1 ]  =  tileRowHeight[ m_iNumRowsMinus1 ] - pps.getTileRowHeight( j );
          }
        }
    
        // check brick splits for each tile
        for (int tileIdx=0; tileIdx < numTiles; tileIdx++)
        {
    
          const int tileY = tileIdx / (m_iNumColumnsMinus1 + 1);
    
    
          tileHeight[tileIdx] = tileRowHeight[tileY];
    
          if (tileHeight[tileIdx] <= 1)
          {
            CHECK(pps.getBrickSplitFlag(tileIdx) != 0, "The value of brick_split_flag[ i ] shall be 0 if tileHeight <= 1");
          }
    
    Karsten Suehring's avatar
    Karsten Suehring committed
          if (pps.getBrickSplitFlag(tileIdx))
          {
    
            if (tileHeight[tileIdx] <= 2)
            {
              CHECK(pps.getUniformBrickSpacingFlag(tileIdx) != 1, "The value of uniform_brick_spacing_flag[ i ] shall be 1 if tileHeight <= 2");
            }
    
    Karsten Suehring's avatar
    Karsten Suehring committed
            if (pps.getUniformBrickSpacingFlag(tileIdx))
            {
    
              CHECK((pps.getBrickHeightMinus1(tileIdx) + 1) >= tileHeight[tileIdx], "Brick height larger than or equal to tile height");
    
    Karsten Suehring's avatar
    Karsten Suehring committed
            }
            else
            {
              int cumulativeHeight=0;
    
              for (int i = 0; i <= pps.getNumBrickRowsMinus2(tileIdx); i++)
    
    Karsten Suehring's avatar
    Karsten Suehring committed
              {
                cumulativeHeight += pps.getBrickRowHeightMinus1(tileIdx, i) + 1;
              }
    
              CHECK(cumulativeHeight >= tileHeight[tileIdx], "Cumulative brick height larger than or equal to tile height");
    
    }
    
    void  EncCfg::xCheckGSParameters()
    {
      int   iWidthInCU = ( m_iSourceWidth%m_maxCUWidth ) ? m_iSourceWidth/m_maxCUWidth + 1 : m_iSourceWidth/m_maxCUWidth;
      int   iHeightInCU = ( m_iSourceHeight%m_maxCUHeight ) ? m_iSourceHeight/m_maxCUHeight + 1 : m_iSourceHeight/m_maxCUHeight;
      uint32_t  uiCummulativeColumnWidth = 0;
      uint32_t  uiCummulativeRowHeight = 0;
    
    
      if (m_tileUniformSpacingFlag && m_uniformTileColsWidthMinus1 == -1)
      {
        EXIT("Uniform tiles specified with unspecified or invalid UniformTileColsWidthMinus1 value");
      }
      if (m_tileUniformSpacingFlag && m_uniformTileRowHeightMinus1 == -1)
      {
        EXIT("Uniform tiles specified with unspecified or invalid UniformTileRowHeightMinus1 value");
      }
      if (m_tileUniformSpacingFlag && m_uniformTileColsWidthMinus1 >= iWidthInCU)
      {
        EXIT("UniformTileColsWidthMinus1 too large");
      }
      if (m_tileUniformSpacingFlag && m_uniformTileRowHeightMinus1 >= iHeightInCU)
      {
        EXIT("UniformTileRowHeightMinus1 too large");
      }
    
    
      //check the column relative parameters
      if( m_iNumColumnsMinus1 >= (1<<(LOG2_MAX_NUM_COLUMNS_MINUS1+1)) )
      {
        EXIT( "The number of columns is larger than the maximum allowed number of columns." );
      }
    
      if( m_iNumColumnsMinus1 >= iWidthInCU )
      {
        EXIT( "The current picture can not have so many columns." );
      }
    
      if( m_iNumColumnsMinus1 && !m_tileUniformSpacingFlag )
      {
        for(int i=0; i<m_iNumColumnsMinus1; i++)
        {
          uiCummulativeColumnWidth += m_tileColumnWidth[i];
        }
    
        if( uiCummulativeColumnWidth >= iWidthInCU )
        {
          EXIT( "The width of the column is too large." );
        }
      }
    
      //check the row relative parameters
      if( m_iNumRowsMinus1 >= (1<<(LOG2_MAX_NUM_ROWS_MINUS1+1)) )
      {
        EXIT( "The number of rows is larger than the maximum allowed number of rows." );
      }
    
      if( m_iNumRowsMinus1 >= iHeightInCU )
      {
        EXIT( "The current picture can not have so many rows." );
      }
    
      if( m_iNumRowsMinus1 && !m_tileUniformSpacingFlag )
      {
        for(int i=0; i<m_iNumRowsMinus1; i++)
        {
          uiCummulativeRowHeight += m_tileRowHeight[i];
        }
    
        if( uiCummulativeRowHeight >= iHeightInCU )
        {
          EXIT( "The height of the row is too large." );
        }
      }
    }
    
    
    void EncLib::setParamSetChanged(int spsId, int ppsId)
    {
      m_ppsMap.setChangedFlag(ppsId);
      m_spsMap.setChangedFlag(spsId);
    }
    
    Hendry's avatar
    Hendry committed
    bool EncLib::APSNeedsWriting(int apsId)
    {
    
      bool isChanged = m_apsMap.getChangedFlag(apsId);
    
    Hendry's avatar
    Hendry committed
      m_apsMap.clearChangedFlag(apsId);
    
    Hendry's avatar
    Hendry committed
    }
    
    bool EncLib::PPSNeedsWriting(int ppsId)
    {
      bool bChanged=m_ppsMap.getChangedFlag(ppsId);
      m_ppsMap.clearChangedFlag(ppsId);
      return bChanged;
    }
    
    bool EncLib::SPSNeedsWriting(int spsId)
    {
      bool bChanged=m_spsMap.getChangedFlag(spsId);
      m_spsMap.clearChangedFlag(spsId);
      return bChanged;
    }
    
    
    void EncLib::checkPltStats( Picture* pic )
    {
      int totalArea = 0;
      int pltArea = 0;
      for (auto apu : pic->cs->pus)
      {
        for (int i = 0; i < MAX_NUM_TBLOCKS; ++i)
        {
          int puArea = apu->blocks[i].width * apu->blocks[i].height;
          if (apu->blocks[i].width > 0 && apu->blocks[i].height > 0)
          {
            totalArea += puArea;
            if (CU::isPLT(*apu->cu) || CU::isIBC(*apu->cu))
            {
              pltArea += puArea;
            }
            break;
          }
    
        }
      }
      if (pltArea * PLT_FAST_RATIO < totalArea)
      {
        m_doPlt = false;
      }
      else
      {
        m_doPlt = true;
      }
    }
    
    
    #if X0038_LAMBDA_FROM_QP_CAPABILITY
    int EncCfg::getQPForPicture(const uint32_t gopIndex, const Slice *pSlice) const
    {
      const int lumaQpBDOffset = pSlice->getSPS()->getQpBDOffset(CHANNEL_TYPE_LUMA);
      int qp;
    
      if (getCostMode()==COST_LOSSLESS_CODING)
      {
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #if JVET_AHG14_LOSSLESS
        qp = LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP - ( ( pSlice->getSPS()->getBitDepth( CHANNEL_TYPE_LUMA ) - 8 ) * 6 );
    #else
    
        qp=LOSSLESS_AND_MIXED_LOSSLESS_RD_COST_TEST_QP;
    
    Tung Nguyen's avatar
    Tung Nguyen committed
    #endif
    
      }
      else
      {
        const SliceType sliceType=pSlice->getSliceType();
    
        qp = getBaseQP();
    
        // switch at specific qp and keep this qp offset
        static int appliedSwitchDQQ = 0; /* TODO: MT */
        if( pSlice->getPOC() == getSwitchPOC() )
        {
          appliedSwitchDQQ = getSwitchDQP();
        }
        qp += appliedSwitchDQQ;
    
    #if QP_SWITCHING_FOR_PARALLEL
        const int* pdQPs = getdQPs();
        if ( pdQPs )
        {
    
          qp += pdQPs[pSlice->getPOC() / (m_compositeRefEnabled ? 2 : 1)];
    
        }
    #endif
    
        if(sliceType==I_SLICE)
        {
          qp += getIntraQPOffset();
        }
        else
        {
    #if SHARP_LUMA_DELTA_QP
          // Only adjust QP when not lossless
          if (!(( getMaxDeltaQP() == 0 ) && (!getLumaLevelToDeltaQPMapping().isEnabled()) && (qp == -lumaQpBDOffset ) && (pSlice->getPPS()->getTransquantBypassEnabledFlag())))
    #else
          if (!(( getMaxDeltaQP() == 0 ) && (qp == -lumaQpBDOffset ) && (pSlice->getPPS()->getTransquantBypassEnabledFlag())))
    #endif
    
          {
            const GOPEntry &gopEntry=getGOPEntry(gopIndex);
            // adjust QP according to the QP offset for the GOP entry.
            qp +=gopEntry.m_QPOffset;
    
            // adjust QP according to QPOffsetModel for the GOP entry.
            double dqpOffset=qp*gopEntry.m_QPOffsetModelScale+gopEntry.m_QPOffsetModelOffset+0.5;
            int qpOffset = (int)floor(Clip3<double>(0.0, 3.0, dqpOffset));
            qp += qpOffset ;
          }
        }
    
    #if !QP_SWITCHING_FOR_PARALLEL
        // modify QP if a fractional QP was originally specified, cause dQPs to be 0 or 1.
        const int* pdQPs = getdQPs();
        if ( pdQPs )
        {
          qp += pdQPs[ pSlice->getPOC() ];
        }
    #endif
      }
      qp = Clip3( -lumaQpBDOffset, MAX_QP, qp );
      return qp;
    }
    #endif