Skip to content
Snippets Groups Projects
EncSlice.cpp 81.9 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
        // terminate the sub-stream, if required (end of slice-segment, end of tile, end of wavefront-CTU-row):
        if( ctuTsAddr + 1 == boundingCtuTsAddr ||
             (  ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getTileWidthInCtus () &&
              ( ctuYPosInCtus + 1 == tileYPosInCtus + currentTile.getTileHeightInCtus() || wavefrontsEnabled )
             )
           )
        {
          m_CABACWriter->end_of_slice();
    
          // Byte-alignment in slice_data() when new tile
          pcSubstreams[uiSubStrm].writeByteAlignment();
    
          // write sub-stream size
          if( ctuTsAddr + 1 != boundingCtuTsAddr )
          {
            pcSlice->addSubstreamSize( (pcSubstreams[uiSubStrm].getNumberOfWrittenBits() >> 3) + pcSubstreams[uiSubStrm].countStartCodeEmulations() );
          }
        }
      } // CTU-loop
    
    #if HEVC_DEPENDENT_SLICES
      if( depSliceSegmentsEnabled )
      {
        m_lastSliceSegmentEndContextState = m_CABACWriter->getCtx();//ctx end of dep.slice
      }
    #endif
    
    #if HEVC_DEPENDENT_SLICES
      if (pcSlice->getPPS()->getCabacInitPresentFlag() && !pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag())
    #else
      if(pcSlice->getPPS()->getCabacInitPresentFlag())
    #endif
      {
        m_encCABACTableIdx = m_CABACWriter->getCtxInitId( *pcSlice );
      }
      else
      {
        m_encCABACTableIdx = pcSlice->getSliceType();
      }
      numBinsCoded = m_CABACWriter->getNumBins();
    
    }
    
    void EncSlice::calculateBoundingCtuTsAddrForSlice(uint32_t &startCtuTSAddrSlice, uint32_t &boundingCtuTSAddrSlice, bool &haveReachedTileBoundary,
                                                       Picture* pcPic, const int sliceMode, const int sliceArgument)
    {
      Slice* pcSlice = pcPic->slices[getSliceSegmentIdx()];
      const TileMap& tileMap = *( pcPic->tileMap );
      const PPS &pps         = *( pcSlice->getPPS() );
      const uint32_t numberOfCtusInFrame = pcPic->cs->pcv->sizeInCtus;
      boundingCtuTSAddrSlice=0;
      haveReachedTileBoundary=false;
    
      switch (sliceMode)
      {
        case FIXED_NUMBER_OF_CTU:
          {
            uint32_t ctuAddrIncrement    = sliceArgument;
            boundingCtuTSAddrSlice  = ((startCtuTSAddrSlice + ctuAddrIncrement) < numberOfCtusInFrame) ? (startCtuTSAddrSlice + ctuAddrIncrement) : numberOfCtusInFrame;
          }
          break;
        case FIXED_NUMBER_OF_BYTES:
          boundingCtuTSAddrSlice  = numberOfCtusInFrame; // This will be adjusted later if required.
          break;
        case FIXED_NUMBER_OF_TILES:
          {
            const uint32_t tileIdx        = tileMap.getTileIdxMap( tileMap.getCtuTsToRsAddrMap(startCtuTSAddrSlice) );
            const uint32_t tileTotalCount = (pps.getNumTileColumnsMinus1()+1) * (pps.getNumTileRowsMinus1()+1);
            uint32_t ctuAddrIncrement   = 0;
    
            for(uint32_t tileIdxIncrement = 0; tileIdxIncrement < sliceArgument; tileIdxIncrement++)
            {
              if((tileIdx + tileIdxIncrement) < tileTotalCount)
              {
                uint32_t tileWidthInCtus    = tileMap.tiles[tileIdx + tileIdxIncrement].getTileWidthInCtus();
                uint32_t tileHeightInCtus   = tileMap.tiles[tileIdx + tileIdxIncrement].getTileHeightInCtus();
                ctuAddrIncrement       += (tileWidthInCtus * tileHeightInCtus);
              }
            }
    
            boundingCtuTSAddrSlice  = ((startCtuTSAddrSlice + ctuAddrIncrement) < numberOfCtusInFrame) ? (startCtuTSAddrSlice + ctuAddrIncrement) : numberOfCtusInFrame;
          }
          break;
        default:
          boundingCtuTSAddrSlice    = numberOfCtusInFrame;
          break;
      }
    
      // Adjust for tiles and wavefronts.
      const bool wavefrontsAreEnabled = pps.getEntropyCodingSyncEnabledFlag();
    
      if ((sliceMode == FIXED_NUMBER_OF_CTU || sliceMode == FIXED_NUMBER_OF_BYTES) &&
          (pps.getNumTileRowsMinus1() > 0 || pps.getNumTileColumnsMinus1() > 0))
      {
        const uint32_t ctuRsAddr                   = tileMap.getCtuTsToRsAddrMap(startCtuTSAddrSlice);
        const uint32_t startTileIdx                = tileMap.getTileIdxMap(ctuRsAddr);
        const Tile& startingTile               = tileMap.tiles[startTileIdx];
        const uint32_t  tileStartTsAddr            = tileMap.getCtuRsToTsAddrMap(startingTile.getFirstCtuRsAddr());
        const uint32_t  tileStartWidth             = startingTile.getTileWidthInCtus();
        const uint32_t  tileStartHeight            = startingTile.getTileHeightInCtus();
        const uint32_t tileLastTsAddr_excl        = tileStartTsAddr + tileStartWidth*tileStartHeight;
        const uint32_t tileBoundingCtuTsAddrSlice = tileLastTsAddr_excl;
        const uint32_t ctuColumnOfStartingTile     = ((startCtuTSAddrSlice-tileStartTsAddr)%tileStartWidth);
        if (wavefrontsAreEnabled && ctuColumnOfStartingTile!=0)
        {
          // WPP: if a slice does not start at the beginning of a CTB row, it must end within the same CTB row
          const uint32_t numberOfCTUsToEndOfRow            = tileStartWidth - ctuColumnOfStartingTile;
          const uint32_t wavefrontTileBoundingCtuAddrSlice = startCtuTSAddrSlice + numberOfCTUsToEndOfRow;
          if (wavefrontTileBoundingCtuAddrSlice < boundingCtuTSAddrSlice)
          {
            boundingCtuTSAddrSlice = wavefrontTileBoundingCtuAddrSlice;
          }
        }
    
        if (tileBoundingCtuTsAddrSlice < boundingCtuTSAddrSlice)
        {
          boundingCtuTSAddrSlice = tileBoundingCtuTsAddrSlice;
          haveReachedTileBoundary = true;
        }
      }
      else if ((sliceMode == FIXED_NUMBER_OF_CTU || sliceMode == FIXED_NUMBER_OF_BYTES) && wavefrontsAreEnabled && ((startCtuTSAddrSlice % pcPic->cs->pcv->widthInCtus) != 0))
      {
        // Adjust for wavefronts (no tiles).
        // WPP: if a slice does not start at the beginning of a CTB row, it must end within the same CTB row
    
        boundingCtuTSAddrSlice = std::min(boundingCtuTSAddrSlice, startCtuTSAddrSlice - (startCtuTSAddrSlice % pcPic->cs->pcv->widthInCtus) + (pcPic->cs->pcv->widthInCtus));
    
      }
    }
    
    /** Determines the starting and bounding CTU address of current slice / dependent slice
     * \param [out] startCtuTsAddr
     * \param [out] boundingCtuTsAddr
     * \param [in]  pcPic
    
     * Updates startCtuTsAddr, boundingCtuTsAddr with appropriate CTU address
     */
    void EncSlice::xDetermineStartAndBoundingCtuTsAddr  ( uint32_t& startCtuTsAddr, uint32_t& boundingCtuTsAddr, Picture* pcPic )
    {
      Slice* pcSlice                 = pcPic->slices[getSliceSegmentIdx()];
    
      // Non-dependent slice
      uint32_t startCtuTsAddrSlice           = pcSlice->getSliceCurStartCtuTsAddr();
      bool haveReachedTileBoundarySlice  = false;
      uint32_t boundingCtuTsAddrSlice;
      calculateBoundingCtuTsAddrForSlice(startCtuTsAddrSlice, boundingCtuTsAddrSlice, haveReachedTileBoundarySlice, pcPic,
                                         m_pcCfg->getSliceMode(), m_pcCfg->getSliceArgument());
      pcSlice->setSliceCurEndCtuTsAddr(   boundingCtuTsAddrSlice );
      pcSlice->setSliceCurStartCtuTsAddr( startCtuTsAddrSlice    );
    
    #if HEVC_DEPENDENT_SLICES
      // Dependent slice
      uint32_t startCtuTsAddrSliceSegment          = pcSlice->getSliceSegmentCurStartCtuTsAddr();
      bool haveReachedTileBoundarySliceSegment = false;
      uint32_t boundingCtuTsAddrSliceSegment;
      calculateBoundingCtuTsAddrForSlice(startCtuTsAddrSliceSegment, boundingCtuTsAddrSliceSegment, haveReachedTileBoundarySliceSegment, pcPic,
                                         m_pcCfg->getSliceSegmentMode(), m_pcCfg->getSliceSegmentArgument());
      if (boundingCtuTsAddrSliceSegment>boundingCtuTsAddrSlice)
      {
        boundingCtuTsAddrSliceSegment = boundingCtuTsAddrSlice;
      }
      pcSlice->setSliceSegmentCurEndCtuTsAddr( boundingCtuTsAddrSliceSegment );
      pcSlice->setSliceSegmentCurStartCtuTsAddr(startCtuTsAddrSliceSegment);
    
      // Make a joint decision based on reconstruction and dependent slice bounds
    
      startCtuTsAddr    = std::max(startCtuTsAddrSlice, startCtuTsAddrSliceSegment);
    
      boundingCtuTsAddr = boundingCtuTsAddrSliceSegment;
    #else
      startCtuTsAddr = startCtuTsAddrSlice;
      boundingCtuTsAddr = boundingCtuTsAddrSlice;
    #endif
    }
    
    double EncSlice::xGetQPValueAccordingToLambda ( double lambda )
    {
      return 4.2005*log(lambda) + 13.7122;
    }
    
    //! \}