Skip to content
Snippets Groups Projects
Slice.cpp 88.8 KiB
Newer Older
  • Learn to ignore specific revisions
  • /* The copyright in this software is being made available under the BSD
     * License, included below. This software may be subject to other third party
     * and contributor rights, including patent rights, and no such rights are
     * granted under this license.
     *
    
     * Copyright (c) 2010-2019, ITU/ISO/IEC
    
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions are met:
     *
     *  * Redistributions of source code must retain the above copyright notice,
     *    this list of conditions and the following disclaimer.
     *  * Redistributions in binary form must reproduce the above copyright notice,
     *    this list of conditions and the following disclaimer in the documentation
     *    and/or other materials provided with the distribution.
     *  * Neither the name of the ITU/ISO/IEC nor the names of its contributors may
     *    be used to endorse or promote products derived from this software without
     *    specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
     * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
     * THE POSSIBILITY OF SUCH DAMAGE.
     */
    
    /** \file     Slice.cpp
        \brief    slice header and SPS class
    */
    
    #include "CommonDef.h"
    #include "Unit.h"
    #include "Slice.h"
    #include "Picture.h"
    #include "dtrace_next.h"
    
    
    #include "UnitTools.h"
    
    
    //! \ingroup CommonLib
    //! \{
    
    Slice::Slice()
    : m_iPPSId                        ( -1 )
    , m_PicOutputFlag                 ( true )
    , m_iPOC                          ( 0 )
    , m_iLastIDR                      ( 0 )
    , m_iAssociatedIRAP               ( 0 )
    , m_iAssociatedIRAPType           ( NAL_UNIT_INVALID )
    
    Hendry's avatar
    Hendry committed
    , m_rpl0Idx                       ( -1 )
    , m_rpl1Idx                       ( -1 )
    
    , m_eNalUnitType                  ( NAL_UNIT_CODED_SLICE_IDR_W_RADL )
    , m_eSliceType                    ( I_SLICE )
    , m_iSliceQp                      ( 0 )
    , m_ChromaQpAdjEnabled            ( false )
    , m_deblockingFilterDisable       ( false )
    , m_deblockingFilterOverrideFlag  ( false )
    , m_deblockingFilterBetaOffsetDiv2( 0 )
    , m_deblockingFilterTcOffsetDiv2  ( 0 )
    , m_pendingRasInit                ( false )
    , m_depQuantEnabledFlag           ( false )
    , m_signDataHidingEnabledFlag     ( false )
    , m_bCheckLDC                     ( false )
    
    , m_dps                           ( nullptr )
    
    , m_pcSPS                         ( NULL )
    , m_pcPPS                         ( NULL )
    , m_pcPic                         ( NULL )
    , m_colFromL0Flag                 ( true )
    , m_noOutputPriorPicsFlag         ( false )
    
    , m_noIncorrectPicOutputFlag      ( false )
    
    , m_handleCraAsCvsStartFlag            ( false )
    
    , m_maxNumAffineMergeCand         ( 0 )
    
    , m_maxNumTriangleCand            ( 0 )
    
    Yan Zhang's avatar
    Yan Zhang committed
    , m_maxNumIBCMergeCand            ( 0 )
    
    , m_disFracMMVD                   ( false )
    
    , m_disBdofDmvrFlag               ( false )
    
    , m_uiTLayer                      ( 0 )
    , m_bTLayerSwitchingFlag          ( false )
    , m_sliceMode                     ( NO_SLICES )
    , m_sliceArgument                 ( 0 )
    , m_sliceCurStartCtuTsAddr        ( 0 )
    , m_sliceCurEndCtuTsAddr          ( 0 )
    , m_independentSliceIdx           ( 0 )
    , m_nextSlice                     ( false )
    , m_sliceBits                     ( 0 )
    , m_bFinalized                    ( false )
    , m_bTestWeightPred               ( false )
    , m_bTestWeightBiPred             ( false )
    , m_substreamSizes                ( )
    , m_cabacInitFlag                 ( false )
    
    , m_jointCbCrSignFlag             ( false )
    
    , m_bLMvdL1Zero                   ( false )
    , m_LFCrossSliceBoundaryFlag      ( false )
    , m_enableTMVPFlag                ( true )
    , m_encCABACTableIdx              (I_SLICE)
    , m_iProcessingStartTime          ( 0 )
    , m_dProcessingTime               ( 0 )
    
    , m_splitConsOverrideFlag         ( false )
    , m_uiMinQTSize                   ( 0 )
    
    Remy Foray's avatar
    Remy Foray committed
    , m_uiMaxMTTHierarchyDepth                  ( 0 )
    
    , m_uiMaxTTSize                   ( 0 )
    , m_uiMinQTSizeIChroma            ( 0 )
    
    Remy Foray's avatar
    Remy Foray committed
    , m_uiMaxMTTHierarchyDepthIChroma           ( 0 )
    
    , m_uiMaxBTSizeIChroma            ( 0 )
    , m_uiMaxTTSizeIChroma            ( 0 )
    
    , m_lmcsApsId                    ( -1 )
    , m_lmcsAps                      (nullptr)
    , m_tileGroupLmcsEnabledFlag     (false)
    , m_tileGroupLmcsChromaResidualScaleFlag (false)
    
    , m_scalingListApsId             ( -1 )
    , m_scalingListAps               ( nullptr )
    , m_tileGroupscalingListPresentFlag ( false )
    
    , m_nonReferencePicFlag          ( 0 )
    
    {
      for(uint32_t i=0; i<NUM_REF_PIC_LIST_01; i++)
      {
        m_aiNumRefIdx[i] = 0;
      }
    
      for (uint32_t component = 0; component < MAX_NUM_COMPONENT; component++)
      {
        m_lambdas            [component] = 0.0;
        m_iSliceChromaQpDelta[component] = 0;
      }
    
      m_iSliceChromaQpDelta[JOINT_CbCr] = 0;
    
    
      initEqualRef();
    
      for ( int idx = 0; idx < MAX_NUM_REF; idx++ )
      {
        m_list1IdxToList0Idx[idx] = -1;
      }
    
      for(int iNumCount = 0; iNumCount < MAX_NUM_REF; iNumCount++)
      {
        for(uint32_t i=0; i<NUM_REF_PIC_LIST_01; i++)
        {
          m_apcRefPicList [i][iNumCount] = NULL;
          m_aiRefPOCList  [i][iNumCount] = 0;
        }
      }
    
      resetWpScaling();
      initWpAcDcParam();
    
      for(int ch=0; ch < MAX_NUM_CHANNEL_TYPE; ch++)
      {
        m_saoEnabledFlag[ch] = false;
      }
    
    
      memset(m_alfApss, 0, sizeof(m_alfApss));
    
    }
    
    Slice::~Slice()
    {
    }
    
    
    void Slice::initSlice()
    {
      for(uint32_t i=0; i<NUM_REF_PIC_LIST_01; i++)
      {
        m_aiNumRefIdx[i]      = 0;
      }
      m_colFromL0Flag = true;
    
      m_colRefIdx = 0;
      initEqualRef();
    
      m_bCheckLDC = false;
    
    
      m_symRefIdx[0] = -1;
      m_symRefIdx[1] = -1;
    
    
      for (uint32_t component = 0; component < MAX_NUM_COMPONENT; component++)
      {
        m_iSliceChromaQpDelta[component] = 0;
      }
    
      m_iSliceChromaQpDelta[JOINT_CbCr] = 0;
    
      m_maxNumAffineMergeCand = AFFINE_MRG_MAX_NUM_CANDS;
    
    Yan Zhang's avatar
    Yan Zhang committed
      m_maxNumIBCMergeCand = IBC_MRG_MAX_NUM_CANDS;
    
      m_disFracMMVD          = false;
    
      m_disBdofDmvrFlag      = false;
    
      m_substreamSizes.clear();
      m_cabacInitFlag        = false;
    
      m_enableDRAPSEI        = false;
      m_useLTforDRAP         = false;
      m_isDRAP               = false;
      m_latestDRAPPOC        = MAX_INT;
    
    }
    
    void Slice::setDefaultClpRng( const SPS& sps )
    {
      m_clpRngs.comp[COMPONENT_Y].min = m_clpRngs.comp[COMPONENT_Cb].min  = m_clpRngs.comp[COMPONENT_Cr].min = 0;
      m_clpRngs.comp[COMPONENT_Y].max                                     = (1<< sps.getBitDepth(CHANNEL_TYPE_LUMA))-1;
      m_clpRngs.comp[COMPONENT_Y].bd  = sps.getBitDepth(CHANNEL_TYPE_LUMA);
      m_clpRngs.comp[COMPONENT_Y].n   = 0;
      m_clpRngs.comp[COMPONENT_Cb].max = m_clpRngs.comp[COMPONENT_Cr].max = (1<< sps.getBitDepth(CHANNEL_TYPE_CHROMA))-1;
      m_clpRngs.comp[COMPONENT_Cb].bd  = m_clpRngs.comp[COMPONENT_Cr].bd  = sps.getBitDepth(CHANNEL_TYPE_CHROMA);
      m_clpRngs.comp[COMPONENT_Cb].n   = m_clpRngs.comp[COMPONENT_Cr].n   = 0;
      m_clpRngs.used = m_clpRngs.chroma = false;
    }
    
    
    bool Slice::getRapPicFlag() const
    {
      return getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
          || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP
    
        || getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA;
    
    }
    
    
    void  Slice::sortPicList        (PicList& rcListPic)
    {
      Picture*    pcPicExtract;
      Picture*    pcPicInsert;
    
      PicList::iterator    iterPicExtract;
      PicList::iterator    iterPicExtract_1;
      PicList::iterator    iterPicInsert;
    
      for (int i = 1; i < (int)(rcListPic.size()); i++)
      {
        iterPicExtract = rcListPic.begin();
        for (int j = 0; j < i; j++)
        {
          iterPicExtract++;
        }
        pcPicExtract = *(iterPicExtract);
    
        iterPicInsert = rcListPic.begin();
        while (iterPicInsert != iterPicExtract)
        {
          pcPicInsert = *(iterPicInsert);
          if (pcPicInsert->getPOC() >= pcPicExtract->getPOC())
          {
            break;
          }
    
          iterPicInsert++;
        }
    
        iterPicExtract_1 = iterPicExtract;    iterPicExtract_1++;
    
        //  swap iterPicExtract and iterPicInsert, iterPicExtract = curr. / iterPicInsert = insertion position
        rcListPic.insert( iterPicInsert, iterPicExtract, iterPicExtract_1 );
        rcListPic.erase( iterPicExtract );
      }
    }
    
    Picture* Slice::xGetRefPic (PicList& rcListPic, int poc)
    {
      PicList::iterator  iterPic = rcListPic.begin();
      Picture*           pcPic   = *(iterPic);
    
      while ( iterPic != rcListPic.end() )
      {
        if(pcPic->getPOC() == poc)
        {
          break;
        }
        iterPic++;
        pcPic = *(iterPic);
      }
      return  pcPic;
    }
    
    
    Picture* Slice::xGetLongTermRefPic( PicList& rcListPic, int poc, bool pocHasMsb)
    {
      PicList::iterator  iterPic = rcListPic.begin();
      Picture*           pcPic   = *(iterPic);
      Picture*           pcStPic = pcPic;
    
      int pocCycle = 1 << getSPS()->getBitsForPOC();
      if (!pocHasMsb)
      {
        poc = poc & (pocCycle - 1);
      }
    
      while ( iterPic != rcListPic.end() )
      {
        pcPic = *(iterPic);
        if (pcPic && pcPic->getPOC()!=this->getPOC() && pcPic->referenced)
        {
          int picPoc = pcPic->getPOC();
          if (!pocHasMsb)
          {
            picPoc = picPoc & (pocCycle - 1);
          }
    
          if (poc == picPoc)
          {
            if(pcPic->longTerm)
            {
              return pcPic;
            }
            else
            {
              pcStPic = pcPic;
            }
            break;
          }
        }
    
        iterPic++;
      }
    
      return pcStPic;
    }
    
    void Slice::setRefPOCList       ()
    {
      for (int iDir = 0; iDir < NUM_REF_PIC_LIST_01; iDir++)
      {
        for (int iNumRefIdx = 0; iNumRefIdx < m_aiNumRefIdx[iDir]; iNumRefIdx++)
        {
          m_aiRefPOCList[iDir][iNumRefIdx] = m_apcRefPicList[iDir][iNumRefIdx]->getPOC();
        }
      }
    
    }
    
    void Slice::setList1IdxToList0Idx()
    {
      int idxL0, idxL1;
      for ( idxL1 = 0; idxL1 < getNumRefIdx( REF_PIC_LIST_1 ); idxL1++ )
      {
        m_list1IdxToList0Idx[idxL1] = -1;
        for ( idxL0 = 0; idxL0 < getNumRefIdx( REF_PIC_LIST_0 ); idxL0++ )
        {
          if ( m_apcRefPicList[REF_PIC_LIST_0][idxL0]->getPOC() == m_apcRefPicList[REF_PIC_LIST_1][idxL1]->getPOC() )
          {
            m_list1IdxToList0Idx[idxL1] = idxL0;
            break;
          }
        }
      }
    }
    
    
    Hendry's avatar
    Hendry committed
    void Slice::constructRefPicList(PicList& rcListPic)
    {
      ::memset(m_bIsUsedAsLongTerm, 0, sizeof(m_bIsUsedAsLongTerm));
      if (m_eSliceType == I_SLICE)
      {
        ::memset(m_apcRefPicList, 0, sizeof(m_apcRefPicList));
        ::memset(m_aiNumRefIdx, 0, sizeof(m_aiNumRefIdx));
        return;
      }
    
      Picture*  pcRefPic = NULL;
      uint32_t numOfActiveRef = 0;
      //construct L0
      numOfActiveRef = getNumRefIdx(REF_PIC_LIST_0);
      for (int ii = 0; ii < numOfActiveRef; ii++)
      {
        if (!m_pRPL0->isRefPicLongterm(ii))
        {
          pcRefPic = xGetRefPic(rcListPic, getPOC() - m_pRPL0->getRefPicIdentifier(ii));
          pcRefPic->longTerm = false;
        }
        else
        {
          int pocBits = getSPS()->getBitsForPOC();
          int pocMask = (1 << pocBits) - 1;
          int ltrpPoc = m_pRPL0->getRefPicIdentifier(ii) & pocMask;
          ltrpPoc += m_localRPL0.getDeltaPocMSBPresentFlag(ii) ? (pocMask + 1) * m_localRPL0.getDeltaPocMSBCycleLT(ii) : 0;
          pcRefPic = xGetLongTermRefPic(rcListPic, ltrpPoc, m_localRPL0.getDeltaPocMSBPresentFlag(ii));
          pcRefPic->longTerm = true;
        }
        pcRefPic->extendPicBorder();
        m_apcRefPicList[REF_PIC_LIST_0][ii] = pcRefPic;
        m_bIsUsedAsLongTerm[REF_PIC_LIST_0][ii] = pcRefPic->longTerm;
      }
    
      //construct L1
      numOfActiveRef = getNumRefIdx(REF_PIC_LIST_1);
      for (int ii = 0; ii < numOfActiveRef; ii++)
      {
        if (!m_pRPL1->isRefPicLongterm(ii))
        {
          pcRefPic = xGetRefPic(rcListPic, getPOC() - m_pRPL1->getRefPicIdentifier(ii));
          pcRefPic->longTerm = false;
        }
        else
        {
          int pocBits = getSPS()->getBitsForPOC();
          int pocMask = (1 << pocBits) - 1;
          int ltrpPoc = m_pRPL1->getRefPicIdentifier(ii) & pocMask;
          ltrpPoc += m_localRPL1.getDeltaPocMSBPresentFlag(ii) ? (pocMask + 1) * m_localRPL1.getDeltaPocMSBCycleLT(ii) : 0;
          pcRefPic = xGetLongTermRefPic(rcListPic, ltrpPoc, m_localRPL1.getDeltaPocMSBPresentFlag(ii));
          pcRefPic->longTerm = true;
        }
        pcRefPic->extendPicBorder();
        m_apcRefPicList[REF_PIC_LIST_1][ii] = pcRefPic;
        m_bIsUsedAsLongTerm[REF_PIC_LIST_1][ii] = pcRefPic->longTerm;
      }
    }
    
    
    void Slice::initEqualRef()
    {
      for (int iDir = 0; iDir < NUM_REF_PIC_LIST_01; iDir++)
      {
        for (int iRefIdx1 = 0; iRefIdx1 < MAX_NUM_REF; iRefIdx1++)
        {
          for (int iRefIdx2 = iRefIdx1; iRefIdx2 < MAX_NUM_REF; iRefIdx2++)
          {
            m_abEqualRef[iDir][iRefIdx1][iRefIdx2] = m_abEqualRef[iDir][iRefIdx2][iRefIdx1] = (iRefIdx1 == iRefIdx2? true : false);
          }
        }
      }
    }
    
    void Slice::checkColRefIdx(uint32_t curSliceSegmentIdx, const Picture* pic)
    {
      int i;
      Slice* curSlice = pic->slices[curSliceSegmentIdx];
      int currColRefPOC =  curSlice->getRefPOC( RefPicList(1 - curSlice->getColFromL0Flag()), curSlice->getColRefIdx());
    
      for(i=curSliceSegmentIdx-1; i>=0; i--)
      {
        const Slice* preSlice = pic->slices[i];
        if(preSlice->getSliceType() != I_SLICE)
        {
          const int preColRefPOC  = preSlice->getRefPOC( RefPicList(1 - preSlice->getColFromL0Flag()), preSlice->getColRefIdx());
          if(currColRefPOC != preColRefPOC)
          {
            THROW("Collocated_ref_idx shall always be the same for all slices of a coded picture!");
          }
          else
          {
            break;
          }
        }
      }
    }
    
    
    Hendry's avatar
    Hendry committed
    void Slice::checkCRA(const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1, int& pocCRA, NalUnitType& associatedIRAPType, PicList& rcListPic)
    {
      if (pocCRA < MAX_UINT && getPOC() > pocCRA)
      {
        uint32_t numRefPic = pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures();
        for (int i = 0; i < numRefPic; i++)
        {
          if (!pRPL0->isRefPicLongterm(i))
          {
            CHECK(getPOC() - pRPL0->getRefPicIdentifier(i) < pocCRA, "Invalid state");
          }
          else
          {
            CHECK(xGetLongTermRefPic(rcListPic, pRPL0->getRefPicIdentifier(i), pRPL0->getDeltaPocMSBPresentFlag(i))->getPOC() < pocCRA, "Invalid state");
          }
        }
        numRefPic = pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures();
        for (int i = 0; i < numRefPic; i++)
        {
          if (!pRPL1->isRefPicLongterm(i))
          {
            CHECK(getPOC() - pRPL1->getRefPicIdentifier(i) < pocCRA, "Invalid state");
          }
          else
          {
            CHECK(xGetLongTermRefPic(rcListPic, pRPL1->getRefPicIdentifier(i), pRPL1->getDeltaPocMSBPresentFlag(i))->getPOC() < pocCRA, "Invalid state");
          }
        }
      }
      if (getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP) // IDR picture found
      {
        pocCRA = getPOC();
        associatedIRAPType = getNalUnitType();
      }
      else if (getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA) // CRA picture found
      {
        pocCRA = getPOC();
        associatedIRAPType = getNalUnitType();
      }
    }
    
    
    /** Function for marking the reference pictures when an IDR/CRA/CRANT/BLA/BLANT is encountered.
     * \param pocCRA POC of the CRA/CRANT/BLA/BLANT picture
     * \param bRefreshPending flag indicating if a deferred decoding refresh is pending
     * \param rcListPic reference to the reference picture list
     * This function marks the reference pictures as "unused for reference" in the following conditions.
     * If the nal_unit_type is IDR/BLA/BLANT, all pictures in the reference picture list
     * are marked as "unused for reference"
     *    If the nal_unit_type is BLA/BLANT, set the pocCRA to the temporal reference of the current picture.
     * Otherwise
     *    If the bRefreshPending flag is true (a deferred decoding refresh is pending) and the current
     *    temporal reference is greater than the temporal reference of the latest CRA/CRANT/BLA/BLANT picture (pocCRA),
     *    mark all reference pictures except the latest CRA/CRANT/BLA/BLANT picture as "unused for reference" and set
     *    the bRefreshPending flag to false.
     *    If the nal_unit_type is CRA/CRANT, set the bRefreshPending flag to true and pocCRA to the temporal
     *    reference of the current picture.
     * Note that the current picture is already placed in the reference list and its marking is not changed.
     * If the current picture has a nal_ref_idc that is not 0, it will remain marked as "used for reference".
     */
    void Slice::decodingRefreshMarking(int& pocCRA, bool& bRefreshPending, PicList& rcListPic, const bool bEfficientFieldIRAPEnabled)
    {
      Picture* rpcPic;
      int      pocCurr = getPOC();
    
    
      if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL
        || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP)  // IDR picture
    
      {
        // mark all pictures as not used for reference
        PicList::iterator        iterPic       = rcListPic.begin();
        while (iterPic != rcListPic.end())
        {
          rpcPic = *(iterPic);
          if (rpcPic->getPOC() != pocCurr)
          {
            rpcPic->referenced = false;
    
            rpcPic->getHashMap()->clearAll();
    
          }
          iterPic++;
        }
        if (bEfficientFieldIRAPEnabled)
        {
          bRefreshPending = true;
        }
      }
      else // CRA or No DR
      {
        if(bEfficientFieldIRAPEnabled && (getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL))
        {
          if (bRefreshPending==true && pocCurr > m_iLastIDR) // IDR reference marking pending
          {
            PicList::iterator        iterPic       = rcListPic.begin();
            while (iterPic != rcListPic.end())
            {
              rpcPic = *(iterPic);
              if (rpcPic->getPOC() != pocCurr && rpcPic->getPOC() != m_iLastIDR)
              {
                rpcPic->referenced = false;
    
                rpcPic->getHashMap()->clearAll();
    
              }
              iterPic++;
            }
            bRefreshPending = false;
          }
        }
        else
        {
          if (bRefreshPending==true && pocCurr > pocCRA) // CRA reference marking pending
          {
            PicList::iterator iterPic = rcListPic.begin();
            while (iterPic != rcListPic.end())
            {
              rpcPic = *(iterPic);
              if (rpcPic->getPOC() != pocCurr && rpcPic->getPOC() != pocCRA)
              {
                rpcPic->referenced = false;
    
                rpcPic->getHashMap()->clearAll();
    
              }
              iterPic++;
            }
            bRefreshPending = false;
          }
        }
        if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // CRA picture found
        {
          bRefreshPending = true;
          pocCRA = pocCurr;
        }
      }
    }
    
    void Slice::copySliceInfo(Slice *pSrc, bool cpyAlmostAll)
    {
      CHECK(!pSrc, "Source is NULL");
    
      int i, j, k;
    
      m_iPOC                 = pSrc->m_iPOC;
      m_eNalUnitType         = pSrc->m_eNalUnitType;
      m_eSliceType           = pSrc->m_eSliceType;
      m_iSliceQp             = pSrc->m_iSliceQp;
      m_iSliceQpBase         = pSrc->m_iSliceQpBase;
      m_ChromaQpAdjEnabled              = pSrc->m_ChromaQpAdjEnabled;
      m_deblockingFilterDisable         = pSrc->m_deblockingFilterDisable;
      m_deblockingFilterOverrideFlag    = pSrc->m_deblockingFilterOverrideFlag;
      m_deblockingFilterBetaOffsetDiv2  = pSrc->m_deblockingFilterBetaOffsetDiv2;
      m_deblockingFilterTcOffsetDiv2    = pSrc->m_deblockingFilterTcOffsetDiv2;
    
      for (i = 0; i < NUM_REF_PIC_LIST_01; i++)
      {
        m_aiNumRefIdx[i]     = pSrc->m_aiNumRefIdx[i];
      }
    
      for (i = 0; i < MAX_NUM_REF; i++)
      {
        m_list1IdxToList0Idx[i] = pSrc->m_list1IdxToList0Idx[i];
      }
    
      m_bCheckLDC             = pSrc->m_bCheckLDC;
      m_iSliceQpDelta        = pSrc->m_iSliceQpDelta;
    
      m_symRefIdx[0] = pSrc->m_symRefIdx[0];
      m_symRefIdx[1] = pSrc->m_symRefIdx[1];
    
    
      for (uint32_t component = 0; component < MAX_NUM_COMPONENT; component++)
      {
        m_iSliceChromaQpDelta[component] = pSrc->m_iSliceChromaQpDelta[component];
      }
    
      m_iSliceChromaQpDelta[JOINT_CbCr] = pSrc->m_iSliceChromaQpDelta[JOINT_CbCr];
    
      for (i = 0; i < NUM_REF_PIC_LIST_01; i++)
      {
        for (j = 0; j < MAX_NUM_REF; j++)
        {
          m_apcRefPicList[i][j]  = pSrc->m_apcRefPicList[i][j];
          m_aiRefPOCList[i][j]   = pSrc->m_aiRefPOCList[i][j];
          m_bIsUsedAsLongTerm[i][j] = pSrc->m_bIsUsedAsLongTerm[i][j];
        }
        m_bIsUsedAsLongTerm[i][MAX_NUM_REF] = pSrc->m_bIsUsedAsLongTerm[i][MAX_NUM_REF];
      }
      if( cpyAlmostAll ) m_iDepth = pSrc->m_iDepth;
    
      // access channel
    
    Hendry's avatar
    Hendry committed
      if (cpyAlmostAll) m_pRPL0 = pSrc->m_pRPL0;
      if (cpyAlmostAll) m_pRPL1 = pSrc->m_pRPL1;
    
      m_iLastIDR             = pSrc->m_iLastIDR;
    
      if( cpyAlmostAll ) m_pcPic  = pSrc->m_pcPic;
    
      m_colFromL0Flag        = pSrc->m_colFromL0Flag;
      m_colRefIdx            = pSrc->m_colRefIdx;
    
      if( cpyAlmostAll ) setLambdas(pSrc->getLambdas());
    
      for (i = 0; i < NUM_REF_PIC_LIST_01; i++)
      {
        for (j = 0; j < MAX_NUM_REF; j++)
        {
          for (k =0; k < MAX_NUM_REF; k++)
          {
            m_abEqualRef[i][j][k] = pSrc->m_abEqualRef[i][j][k];
          }
        }
      }
    
      m_uiTLayer                      = pSrc->m_uiTLayer;
      m_bTLayerSwitchingFlag          = pSrc->m_bTLayerSwitchingFlag;
    
      m_sliceMode                     = pSrc->m_sliceMode;
      m_sliceArgument                 = pSrc->m_sliceArgument;
      m_sliceCurStartCtuTsAddr        = pSrc->m_sliceCurStartCtuTsAddr;
      m_sliceCurEndCtuTsAddr          = pSrc->m_sliceCurEndCtuTsAddr;
      m_independentSliceIdx           = pSrc->m_independentSliceIdx;
      m_nextSlice                     = pSrc->m_nextSlice;
      m_clpRngs                       = pSrc->m_clpRngs;
      m_pendingRasInit                = pSrc->m_pendingRasInit;
    
      for ( uint32_t e=0 ; e<NUM_REF_PIC_LIST_01 ; e++ )
      {
        for ( uint32_t n=0 ; n<MAX_NUM_REF ; n++ )
        {
          memcpy(m_weightPredTable[e][n], pSrc->m_weightPredTable[e][n], sizeof(WPScalingParam)*MAX_NUM_COMPONENT );
        }
      }
    
      for( uint32_t ch = 0 ; ch < MAX_NUM_CHANNEL_TYPE; ch++)
      {
        m_saoEnabledFlag[ch] = pSrc->m_saoEnabledFlag[ch];
      }
    
      m_cabacInitFlag                 = pSrc->m_cabacInitFlag;
    
      m_jointCbCrSignFlag             = pSrc->m_jointCbCrSignFlag;
    
      memcpy(m_alfApss, pSrc->m_alfApss, sizeof(m_alfApss)); // this might be quite unsafe
    
      memcpy( m_tileGroupAlfEnabledFlag, pSrc->m_tileGroupAlfEnabledFlag, sizeof(m_tileGroupAlfEnabledFlag));
      m_tileGroupNumAps               = pSrc->m_tileGroupNumAps;
      m_tileGroupLumaApsId            = pSrc->m_tileGroupLumaApsId;
      m_tileGroupChromaApsId          = pSrc->m_tileGroupChromaApsId;
      m_disableSATDForRd              = pSrc->m_disableSATDForRd;
    
    
      m_bLMvdL1Zero                   = pSrc->m_bLMvdL1Zero;
      m_LFCrossSliceBoundaryFlag      = pSrc->m_LFCrossSliceBoundaryFlag;
      m_enableTMVPFlag                = pSrc->m_enableTMVPFlag;
      m_maxNumMergeCand               = pSrc->m_maxNumMergeCand;
    
      m_maxNumAffineMergeCand         = pSrc->m_maxNumAffineMergeCand;
    
      m_maxNumTriangleCand            = pSrc->m_maxNumTriangleCand;
    
    Yan Zhang's avatar
    Yan Zhang committed
      m_maxNumIBCMergeCand            = pSrc->m_maxNumIBCMergeCand;
    
      m_disFracMMVD                   = pSrc->m_disFracMMVD;
    
      m_disBdofDmvrFlag               = pSrc->m_disBdofDmvrFlag;
    
      if( cpyAlmostAll ) m_encCABACTableIdx  = pSrc->m_encCABACTableIdx;
    
      m_splitConsOverrideFlag         = pSrc->m_splitConsOverrideFlag;
      m_uiMinQTSize                   = pSrc->m_uiMinQTSize;
    
    Remy Foray's avatar
    Remy Foray committed
      m_uiMaxMTTHierarchyDepth                  = pSrc->m_uiMaxMTTHierarchyDepth;
    
      m_uiMaxTTSize                   = pSrc->m_uiMaxTTSize;
      m_uiMinQTSizeIChroma            = pSrc->m_uiMinQTSizeIChroma;
    
    Remy Foray's avatar
    Remy Foray committed
      m_uiMaxMTTHierarchyDepthIChroma           = pSrc->m_uiMaxMTTHierarchyDepthIChroma;
    
      m_uiMaxBTSizeIChroma            = pSrc->m_uiMaxBTSizeIChroma;
      m_uiMaxTTSizeIChroma            = pSrc->m_uiMaxTTSizeIChroma;
    
    
      m_depQuantEnabledFlag           = pSrc->m_depQuantEnabledFlag;
      m_signDataHidingEnabledFlag     = pSrc->m_signDataHidingEnabledFlag;
    
    
      m_tileGroupLmcsEnabledFlag = pSrc->m_tileGroupLmcsEnabledFlag;
      m_tileGroupLmcsChromaResidualScaleFlag = pSrc->m_tileGroupLmcsChromaResidualScaleFlag;
      m_lmcsAps = pSrc->m_lmcsAps;
      m_lmcsApsId = pSrc->m_lmcsApsId;
    
    
      m_tileGroupscalingListPresentFlag = pSrc->m_tileGroupscalingListPresentFlag;
      m_scalingListAps                  = pSrc->m_scalingListAps;
      m_scalingListApsId                = pSrc->m_scalingListApsId;
    
      for( int i = 0; i < NUM_REF_PIC_LIST_01; i ++ )
      {
        for (int j = 0; j < MAX_NUM_REF_PICS; j ++ )
        {
          m_scalingRatio[i][j]          = pSrc->m_scalingRatio[i][j];
        }
      }
    
    }
    
    
    /** Function for checking if this is a switching-point
    */
    bool Slice::isTemporalLayerSwitchingPoint(PicList& rcListPic) const
    {
      // loop through all pictures in the reference picture buffer
      PicList::iterator iterPic = rcListPic.begin();
      while ( iterPic != rcListPic.end())
      {
        const Picture* pcPic = *(iterPic++);
        if( pcPic->referenced && pcPic->poc != getPOC())
        {
          if( pcPic->layer >= getTLayer())
          {
            return false;
          }
        }
      }
      return true;
    }
    
    /** Function for checking if this is a STSA candidate
     */
    bool Slice::isStepwiseTemporalLayerSwitchingPointCandidate(PicList& rcListPic) const
    {
      PicList::iterator iterPic = rcListPic.begin();
      while ( iterPic != rcListPic.end())
      {
        const Picture* pcPic = *(iterPic++);
        if( pcPic->referenced &&  pcPic->usedByCurr && pcPic->poc != getPOC())
        {
          if( pcPic->layer >= getTLayer())
          {
            return false;
          }
        }
      }
      return true;
    }
    
    
    void Slice::checkLeadingPictureRestrictions(PicList& rcListPic) const
    {
      int nalUnitType = this->getNalUnitType();
    
      // When a picture is a leading picture, it shall be a RADL or RASL picture.
      if(this->getAssociatedIRAPPOC() > this->getPOC())
      {
        // Do not check IRAP pictures since they may get a POC lower than their associated IRAP
    
        if (nalUnitType < NAL_UNIT_CODED_SLICE_IDR_W_RADL ||
            nalUnitType > NAL_UNIT_CODED_SLICE_CRA)
    
          CHECK(nalUnitType != NAL_UNIT_CODED_SLICE_RASL &&
                nalUnitType != NAL_UNIT_CODED_SLICE_RADL, "Invalid NAL unit type");
    
        }
      }
    
      // When a picture is a trailing picture, it shall not be a RADL or RASL picture.
      if(this->getAssociatedIRAPPOC() < this->getPOC())
      {
    
        CHECK(nalUnitType == NAL_UNIT_CODED_SLICE_RASL ||
              nalUnitType == NAL_UNIT_CODED_SLICE_RADL, "Invalid NAL unit type");
    
      }
    
    
      // No RASL pictures shall be present in the bitstream that are associated with
      // an IDR picture.
    
      if (nalUnitType == NAL_UNIT_CODED_SLICE_RASL)
    
      {
        CHECK( this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_N_LP   ||
               this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL, "Invalid NAL unit type");
      }
    
      // No RADL pictures shall be present in the bitstream that are associated with
      // a BLA picture having nal_unit_type equal to BLA_N_LP or that are associated
      // with an IDR picture having nal_unit_type equal to IDR_N_LP.
    
      if (nalUnitType == NAL_UNIT_CODED_SLICE_RADL)
    
        CHECK (this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_N_LP, "Invalid NAL unit type");
    
      }
    
      // loop through all pictures in the reference picture buffer
      PicList::iterator iterPic = rcListPic.begin();
    
      while ( iterPic != rcListPic.end())
      {
        Picture* pcPic = *(iterPic++);
        if( ! pcPic->reconstructed)
        {
          continue;
        }
        if( pcPic->poc == this->getPOC())
        {
          continue;
        }
        const Slice* pcSlice = pcPic->slices[0];
    
        // Any picture that has PicOutputFlag equal to 1 that precedes an IRAP picture
        // in decoding order shall precede the IRAP picture in output order.
        // (Note that any picture following in output order would be present in the DPB)
        if(pcSlice->getPicOutputFlag() == 1 && !this->getNoOutputPriorPicsFlag())
        {
    
          if (nalUnitType == NAL_UNIT_CODED_SLICE_CRA ||
              nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP ||
              nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL)
    
          {
            CHECK(pcPic->poc >= this->getPOC(), "Invalid POC");
          }
        }
    
        // Any picture that has PicOutputFlag equal to 1 that precedes an IRAP picture
        // in decoding order shall precede any RADL picture associated with the IRAP
        // picture in output order.
    
        if(pcSlice->getPicOutputFlag() == 1)
    
          if (nalUnitType == NAL_UNIT_CODED_SLICE_RADL)
    
            // rpcPic precedes the IRAP in decoding order
            if(this->getAssociatedIRAPPOC() > pcSlice->getAssociatedIRAPPOC())
    
              // rpcPic must not be the IRAP picture
              if(this->getAssociatedIRAPPOC() != pcPic->poc)
    
                CHECK( pcPic->poc >= this->getPOC(), "Invalid POC");
    
        // When a picture is a leading picture, it shall precede, in decoding order,
        // all trailing pictures that are associated with the same IRAP picture.
    
        if ((nalUnitType == NAL_UNIT_CODED_SLICE_RASL || nalUnitType == NAL_UNIT_CODED_SLICE_RADL) &&
    
            (pcSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RASL && pcSlice->getNalUnitType() != NAL_UNIT_CODED_SLICE_RADL)  )
        {
          if (pcSlice->getAssociatedIRAPPOC() == this->getAssociatedIRAPPOC())
          {
            numLeadingPicsFound++;
    
            int limitNonLP = 0;
            if (pcSlice->getSPS()->getVuiParameters() && pcSlice->getSPS()->getVuiParameters()->getFieldSeqFlag())
              limitNonLP = 1;
            CHECK(pcPic->poc > this->getAssociatedIRAPPOC() && numLeadingPicsFound > limitNonLP, "Invalid POC");
    
        // Any RASL picture associated with a CRA or BLA picture shall precede any
        // RADL picture associated with the CRA or BLA picture in output order
        if (nalUnitType == NAL_UNIT_CODED_SLICE_RASL)
        {
          if ((this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_CRA) &&
              this->getAssociatedIRAPPOC() == pcSlice->getAssociatedIRAPPOC())
    
            if (pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL)
    
              CHECK( pcPic->poc <= this->getPOC(), "Invalid POC");
    
    
        // Any RASL picture associated with a CRA picture shall follow, in output
        // order, any IRAP picture that precedes the CRA picture in decoding order.
        if (nalUnitType == NAL_UNIT_CODED_SLICE_RASL)
    
          if(this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_CRA)
    
            if(pcSlice->getPOC() < this->getAssociatedIRAPPOC() &&
              (
                pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP   ||
                pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL ||
                pcSlice->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA))
    
              CHECK(this->getPOC() <= pcSlice->getPOC(), "Invalid POC");
    
    Hendry's avatar
    Hendry committed
    //Function for applying picture marking based on the Reference Picture List
    void Slice::applyReferencePictureListBasedMarking(PicList& rcListPic, const ReferencePictureList *pRPL0, const ReferencePictureList *pRPL1) const
    {
      int i, isReference;
      checkLeadingPictureRestrictions(rcListPic);
    
      bool isNeedToCheck = (this->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || this->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL) ? false : true;
    
      // loop through all pictures in the reference picture buffer
      PicList::iterator iterPic = rcListPic.begin();
      while (iterPic != rcListPic.end())
      {
        Picture* pcPic = *(iterPic++);
    
        if (!pcPic->referenced)
          continue;
    
        isReference = 0;
        // loop through all pictures in the Reference Picture Set
        // to see if the picture should be kept as reference picture
        for (i = 0; isNeedToCheck && !isReference && i<pRPL0->getNumberOfShorttermPictures() + pRPL0->getNumberOfLongtermPictures(); i++)
        {
          if (!(pRPL0->isRefPicLongterm(i)))
          {
            if (pcPic->poc == this->getPOC() - pRPL0->getRefPicIdentifier(i))
            {
              isReference = 1;
              pcPic->longTerm = false;
            }
          }
          else
          {
            int pocCycle = 1 << (pcPic->cs->sps->getBitsForPOC());
            int curPoc = pcPic->poc & (pocCycle - 1);
            if (pcPic->longTerm && curPoc == pRPL0->getRefPicIdentifier(i))
            {
              isReference = 1;
              pcPic->longTerm = true;
            }
          }
        }
        for (i = 0; isNeedToCheck && !isReference && i<pRPL1->getNumberOfShorttermPictures() + pRPL1->getNumberOfLongtermPictures(); i++)
        {
          if (!(pRPL1->isRefPicLongterm(i)))
          {
            if (pcPic->poc == this->getPOC() - pRPL1->getRefPicIdentifier(i))
            {
              isReference = 1;
              pcPic->longTerm = false;
            }
          }
          else
          {
            int pocCycle = 1 << (pcPic->cs->sps->getBitsForPOC());
            int curPoc = pcPic->poc & (pocCycle - 1);
            if (pcPic->longTerm && curPoc == pRPL1->getRefPicIdentifier(i))
            {
              isReference = 1;
              pcPic->longTerm = true;
            }
          }
        }
        // mark the picture as "unused for reference" if it is not in
        // the Reference Picture List
        if (pcPic->poc != this->getPOC() && isReference == 0)
        {
          pcPic->referenced = false;
          pcPic->longTerm = false;
        }
    
        // sanity checks
        if (pcPic->referenced)
        {
          //check that pictures of higher temporal layers are not used
          CHECK(pcPic->usedByCurr && !(pcPic->layer <= this->getTLayer()), "Invalid state");
        }
      }
    }
    
    int Slice::checkThatAllRefPicsAreAvailable(PicList& rcListPic, const ReferencePictureList *pRPL, int rplIdx, bool printErrors) const
    {
      Picture* rpcPic;
      int isAvailable = 0;