Skip to content
Snippets Groups Projects
DecLib.cpp 70.9 KiB
Newer Older
  • Learn to ignore specific revisions
  •     m_cInterPred.init( &m_cRdCost, sps->getChromaFormatIdc() );
    
    #endif
    
    Taoran Lu's avatar
    Taoran Lu committed
        if (sps->getUseReshaper())
        {
    
          m_cReshaper.createDec(sps->getBitDepth(CHANNEL_TYPE_LUMA));
    
    #if !JVET_O0041_FRAME_FIELD_SEI
    
          // Check if any new Picture Timing SEI has arrived
          SEIMessages pictureTimingSEIs = getSeisByType(m_SEIs, SEI::PICTURE_TIMING);
          if (pictureTimingSEIs.size()>0)
          {
            SEIPictureTiming* pictureTiming = (SEIPictureTiming*) *(pictureTimingSEIs.begin());
            isField    = (pictureTiming->m_picStruct == 1) || (pictureTiming->m_picStruct == 2) || (pictureTiming->m_picStruct == 9) || (pictureTiming->m_picStruct == 10) || (pictureTiming->m_picStruct == 11) || (pictureTiming->m_picStruct == 12);
            isTopField = (pictureTiming->m_picStruct == 1) || (pictureTiming->m_picStruct == 9) || (pictureTiming->m_picStruct == 11);
          }
    
    #else
          // Check if any new Frame Field Info SEI has arrived
          SEIMessages frameFieldSEIs = getSeisByType(m_SEIs, SEI::FRAME_FIELD_INFO);
          if (frameFieldSEIs.size()>0)
          {
            SEIFrameFieldInfo* ff = (SEIFrameFieldInfo*) *(frameFieldSEIs.begin());
            isField    = ff->m_fieldPicFlag;
            isTopField = isField && (!ff->m_bottomFieldFlag);
          }
    #endif
    
        }
    
        //Set Field/Frame coding mode
        m_pcPic->fieldPic = isField;
        m_pcPic->topField = isTopField;
    
        // transfer any SEI messages that have been received to the picture
        m_pcPic->SEIs = m_SEIs;
        m_SEIs.clear();
    
        // Recursive structure
        m_cCuDecoder.init( &m_cTrQuant, &m_cIntraPred, &m_cInterPred );
    
    Taoran Lu's avatar
    Taoran Lu committed
        if (sps->getUseReshaper())
        {
          m_cCuDecoder.initDecCuReshaper(&m_cReshaper, sps->getChromaFormatIdc());
        }
    
    #if MAX_TB_SIZE_SIGNALLING
    
        m_cTrQuant.init( nullptr, sps->getMaxTbSize(), false, false, false, false );
    
        m_cTrQuant.init( nullptr, MAX_TB_SIZEY, false, false, false, false );
    
    
        // RdCost
        m_cRdCost.setCostMode ( COST_STANDARD_LOSSY ); // not used in decoder side RdCost stuff -> set to default
    
        m_cSliceDecoder.create();
    
    
        if( sps->getALFEnabledFlag() )
    
    #if JVET_O1164_PS
          m_cALF.create( pps->getPicWidthInLumaSamples(), pps->getPicHeightInLumaSamples(), sps->getChromaFormatIdc(), sps->getMaxCUWidth(), sps->getMaxCUHeight(), sps->getMaxCodingDepth(), sps->getBitDepths().recon );
    #else
    
          m_cALF.create( sps->getPicWidthInLumaSamples(), sps->getPicHeightInLumaSamples(), sps->getChromaFormatIdc(), sps->getMaxCUWidth(), sps->getMaxCUHeight(), sps->getMaxCodingDepth(), sps->getBitDepths().recon );
    
        }
      }
      else
      {
        // make the slice-pilot a real slice, and set up the slice-pilot for the next slice
        m_pcPic->allocateNewSlice();
        CHECK(m_pcPic->slices.size() != (size_t)(m_uiSliceSegmentIdx + 1), "Invalid number of slices");
        m_apcSlicePilot = m_pcPic->swapSliceObject(m_apcSlicePilot, m_uiSliceSegmentIdx);
    
        Slice *pSlice = m_pcPic->slices[m_uiSliceSegmentIdx]; // we now have a real slice.
    
        const SPS *sps = pSlice->getSPS();
        const PPS *pps = pSlice->getPPS();
    
        APS** apss = pSlice->getAlfAPSs();
        APS *lmcsAPS = pSlice->getLmcsAPS();
    
    #if JVET_O0299_APS_SCALINGLIST
        APS *scalinglistAPS = pSlice->getscalingListAPS();
    #endif
    
        // fix Parameter Sets, now that we have the real slice
        m_pcPic->cs->slice = pSlice;
        m_pcPic->cs->sps   = sps;
        m_pcPic->cs->pps   = pps;
    
        memcpy(m_pcPic->cs->alfApss, apss, sizeof(m_pcPic->cs->alfApss));
        m_pcPic->cs->lmcsAps = lmcsAPS;
    
    #if JVET_O0299_APS_SCALINGLIST
        m_pcPic->cs->scalinglistAps = scalinglistAPS;
    #endif
    
        m_pcPic->cs->pcv   = pps->pcv;
    
        // check that the current active PPS has not changed...
        if (m_parameterSetManager.getSPSChangedFlag(sps->getSPSId()) )
        {
          EXIT("Error - a new SPS has been decoded while processing a picture");
        }
        if (m_parameterSetManager.getPPSChangedFlag(pps->getPPSId()) )
        {
          EXIT("Error - a new PPS has been decoded while processing a picture");
        }
    
    #if JVET_O_MAX_NUM_ALF_APS_8
        for (int i = 0; i < ALF_CTB_MAX_NUM_APS; i++)
    #else
    
        for (int i = 0; i < MAX_NUM_APS; i++)
    
          APS* aps = m_parameterSetManager.getAPS(i, ALF_APS);
          if (aps && m_parameterSetManager.getAPSChangedFlag(i, ALF_APS))
    
          {
            EXIT("Error - a new APS has been decoded while processing a picture");
          }
        }
    
        if (lmcsAPS && m_parameterSetManager.getAPSChangedFlag(lmcsAPS->getAPSId(), LMCS_APS) )
        {
          EXIT("Error - a new LMCS APS has been decoded while processing a picture");
        }
    
    #if JVET_O0299_APS_SCALINGLIST
        if( scalinglistAPS && m_parameterSetManager.getAPSChangedFlag( scalinglistAPS->getAPSId(), SCALING_LIST_APS ) )
        {
          EXIT( "Error - a new SCALING LIST APS has been decoded while processing a picture" );
        }
    #endif
    
    #if JVET_O0299_APS_SCALINGLIST
        activateAPS(pSlice, m_parameterSetManager, apss, lmcsAPS, scalinglistAPS);
    #else
        activateAPS(pSlice, m_parameterSetManager, apss, lmcsAPS);
    #endif
    
        m_pcPic->cs->lmcsAps = lmcsAPS;
    #if JVET_O0299_APS_SCALINGLIST
        m_pcPic->cs->scalinglistAps = scalinglistAPS;
    #endif
    
    
        xParsePrefixSEImessages();
    
        // Check if any new SEI has arrived
         if(!m_SEIs.empty())
         {
           // Currently only decoding Unit SEI message occurring between VCL NALUs copied
           SEIMessages& picSEI = m_pcPic->SEIs;
           SEIMessages decodingUnitInfos = extractSeisByType( picSEI, SEI::DECODING_UNIT_INFO);
           picSEI.insert(picSEI.end(), decodingUnitInfos.begin(), decodingUnitInfos.end());
           deleteSEIs(m_SEIs);
         }
      }
    
    #if JVET_O0244_DELTA_POC
      Slice *pSlice = m_pcPic->slices[m_uiSliceSegmentIdx];
      const SPS *sps = pSlice->getSPS();
      const PPS *pps = pSlice->getPPS();
    
      if( !sps->getUseWP() )
      {
        CHECK( pps->getUseWP(), "When sps_weighted_pred_flag is equal to 0, the value of pps_weighted_pred_flag shall be equal to 0." );
      }
    
      if( !sps->getUseWPBiPred() )
      {
        CHECK( pps->getWPBiPred(), "When sps_weighted_bipred_flag is equal to 0, the value of pps_weighted_bipred_flag shall be equal to 0." );
      }
    #endif
    
    
    #if JVET_O1164_PS
    #if JVET_O0640_PICTURE_SIZE_CONSTRAINT
      CHECK( ( pps->getPicWidthInLumaSamples() % ( std::max( 8, int( sps->getMaxCUWidth() >> ( sps->getMaxCodingDepth() - 1 ) ) ) ) ) != 0, "Coded frame width must be a multiple of Max(8, the minimum unit size)" );
      CHECK( ( pps->getPicHeightInLumaSamples() % ( std::max( 8, int( sps->getMaxCUHeight() >> ( sps->getMaxCodingDepth() - 1 ) ) ) ) ) != 0, "Coded frame height must be a multiple of Max(8, the minimum unit size)" );
    #endif
    
      if( sps->getCTUSize() + 2 * ( 1 << sps->getLog2MinCodingBlockSize() ) > pps->getPicWidthInLumaSamples() )
      {    
        CHECK( sps->getWrapAroundEnabledFlag(), "Wraparound shall be disabled when the value of ( CtbSizeY / MinCbSizeY + 1) is less than or equal to ( pic_width_in_luma_samples / MinCbSizeY - 1 )" );
      }
    #endif
    
    }
    
    
    void DecLib::xParsePrefixSEIsForUnknownVCLNal()
    {
      while (!m_prefixSEINALUs.empty())
      {
        // do nothing?
        msg( NOTICE, "Discarding Prefix SEI associated with unknown VCL NAL unit.\n");
        delete m_prefixSEINALUs.front();
      }
      // TODO: discard following suffix SEIs as well?
    }
    
    
    void DecLib::xParsePrefixSEImessages()
    {
      while (!m_prefixSEINALUs.empty())
      {
        InputNALUnit &nalu=*m_prefixSEINALUs.front();
    
        m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_SEIs, nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), m_HRD, m_pDecodedSEIOutputStream );
    
    #else
        m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_SEIs, nalu.m_nalUnitType, nalu.m_temporalId, m_parameterSetManager.getActiveSPS(), m_HRD, m_pDecodedSEIOutputStream );
    #endif
    
        delete m_prefixSEINALUs.front();
        m_prefixSEINALUs.pop_front();
      }
    }
    
    
    bool DecLib::xDecodeSlice(InputNALUnit &nalu, int &iSkipFrame, int iPOCLastDisplay )
    {
      m_apcSlicePilot->initSlice(); // the slice pilot is an object to prepare for a new slice
                                    // it is not associated with picture, sps or pps structures.
    
    
    Vadim Seregin's avatar
    Vadim Seregin committed
      Picture* scaledRefPic[MAX_NUM_REF] = {};
    
      if (m_bFirstSliceInPicture)
      {
        m_uiSliceSegmentIdx = 0;
      }
      else
      {
        m_apcSlicePilot->copySliceInfo( m_pcPic->slices[m_uiSliceSegmentIdx-1] );
      }
    
    
      m_apcSlicePilot->setSliceCurStartCtuTsAddr(0);
      m_apcSlicePilot->setSliceCurEndCtuTsAddr(0);
      m_apcSlicePilot->setSliceCurStartBrickIdx(0);
      m_apcSlicePilot->setSliceCurEndBrickIdx(0);
    
      m_apcSlicePilot->setNalUnitType(nalu.m_nalUnitType);
      m_apcSlicePilot->setTLayer(nalu.m_temporalId);
    
    
    #if JVET_O0245_VPS_DPS_APS
      for( auto& naluTemporalId : m_accessUnitNals )
      {
        if( naluTemporalId.first != NAL_UNIT_DPS
          && naluTemporalId.first != NAL_UNIT_VPS
          && naluTemporalId.first != NAL_UNIT_SPS
          && naluTemporalId.first != NAL_UNIT_EOS
          && naluTemporalId.first != NAL_UNIT_EOB )
        {
          CHECK( naluTemporalId.second < nalu.m_temporalId, "TemporalId shall be greater than or equal to the TemporalId of the layer access unit containing the NAL unit" );
        }
      }
    #endif
    
    
    #if JVET_N0865_NONSYNTAX
      if (nalu.m_nalUnitType == NAL_UNIT_CODED_SLICE_GDR)
        CHECK(nalu.m_temporalId != 0, "Current GDR picture has TemporalId not equal to 0");
    #endif
    
    
      m_HLSReader.setBitstream( &nalu.getBitstream() );
      m_HLSReader.parseSliceHeader( m_apcSlicePilot, &m_parameterSetManager, m_prevTid0POC );
    
      // update independent slice index
      uint32_t uiIndependentSliceIdx = 0;
      if (!m_bFirstSliceInPicture)
      {
        uiIndependentSliceIdx = m_pcPic->slices[m_uiSliceSegmentIdx-1]->getIndependentSliceIdx();
          uiIndependentSliceIdx++;
      }
      m_apcSlicePilot->setIndependentSliceIdx(uiIndependentSliceIdx);
    
    
    #if K0149_BLOCK_STATISTICS
      PPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId());
      CHECK(pps == 0, "No PPS present");
      SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId());
      CHECK(sps == 0, "No SPS present");
    
      writeBlockStatisticsHeader(sps);
    #endif
    
    
      DTRACE_UPDATE( g_trace_ctx, std::make_pair( "poc", m_apcSlicePilot->getPOC() ) );
    
    
    #if JVET_O0610_DETECT_AUD
    #if JVET_N0865_NONSYNTAX
      if ((m_bFirstSliceInPicture ||
            m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ||
            m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) &&
          getNoOutputPriorPicsFlag())
    #else
        if ((m_bFirstSliceInPicture ||
              m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)
            && getNoOutputPriorPicsFlag() )
    #endif
        {
          checkNoOutputPriorPics(&m_cListPic);
          setNoOutputPriorPicsFlag (false);
        }
    #endif
    
    
      xUpdatePreviousTid0POC(m_apcSlicePilot);
    
      m_apcSlicePilot->setAssociatedIRAPPOC(m_pocCRA);
      m_apcSlicePilot->setAssociatedIRAPType(m_associatedIRAPType);
    
      //For inference of NoOutputOfPriorPicsFlag
    
    #if JVET_N0865_NONSYNTAX
      if (m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR)
    #else
    
    #if JVET_N0865_NONSYNTAX
        if ((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_bFirstSliceInSequence) ||
            (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_apcSlicePilot->getHandleCraAsCvsStartFlag()) || 
            (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR && m_bFirstSliceInSequence))
        {
          m_apcSlicePilot->setNoIncorrectPicOutputFlag(true);
        }
    #else
    
        if ((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_bFirstSliceInSequence) ||
            (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_apcSlicePilot->getHandleCraAsCvsStartFlag()))
    
    #if JVET_N0865_NONSYNTAX
        if (!m_bFirstSliceInBitstream &&
            (m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) &&
            m_apcSlicePilot->getNoIncorrectPicOutputFlag())
        {
          if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR)
          {
            m_apcSlicePilot->setNoOutputPriorPicsFlag(true);
          }
        }
    #else
    
        if (!m_bFirstSliceInBitstream && m_apcSlicePilot->getRapPicFlag() && m_apcSlicePilot->getNoRaslOutputFlag())
        {
          if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)
          {
            m_apcSlicePilot->setNoOutputPriorPicsFlag(true);
          }
        }
    
    #if JVET_N0865_NONSYNTAX
        if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR)
        {
          m_lastNoIncorrectPicOutputFlag = m_apcSlicePilot->getNoIncorrectPicOutputFlag();
        }
    #else
    
        if(m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)
        {
          m_craNoRaslOutputFlag = m_apcSlicePilot->getNoRaslOutputFlag();
        }
    
    #if JVET_N0865_NONSYNTAX
      if ((m_apcSlicePilot->getRapPicFlag() || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) && m_apcSlicePilot->getNoOutputPriorPicsFlag())
    #else
    
      if (m_apcSlicePilot->getRapPicFlag() && m_apcSlicePilot->getNoOutputPriorPicsFlag())
    
      {
        m_lastPOCNoOutputPriorPics = m_apcSlicePilot->getPOC();
        m_isNoOutputPriorPics = true;
      }
      else
      {
        m_isNoOutputPriorPics = false;
      }
    
      //For inference of PicOutputFlag
    
      if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL)
    
    #if JVET_N0865_NONSYNTAX
        if (m_lastNoIncorrectPicOutputFlag)
    #else
    
    #if JVET_N0865_NONSYNTAX
      if ((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) &&
          m_lastNoIncorrectPicOutputFlag)                     //Reset POC MSB when CRA or GDR has NoIncorrectPicOutputFlag equal to 1
    #else
    
      if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_craNoRaslOutputFlag) //Reset POC MSB when CRA has NoRaslOutputFlag equal to 1
    
      {
        PPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId());
        CHECK(pps == 0, "No PPS present");
        SPS *sps = m_parameterSetManager.getSPS(pps->getSPSId());
        CHECK(sps == 0, "No SPS present");
        int iMaxPOClsb = 1 << sps->getBitsForPOC();
        m_apcSlicePilot->setPOC( m_apcSlicePilot->getPOC() & (iMaxPOClsb - 1) );
        xUpdatePreviousTid0POC(m_apcSlicePilot);
      }
    
      // Skip pictures due to random access
    
      if (isRandomAccessSkipPicture(iSkipFrame, iPOCLastDisplay))
      {
        m_prevSliceSkipped = true;
        m_skippedPOC = m_apcSlicePilot->getPOC();
        return false;
      }
      // Skip TFD pictures associated with BLA/BLANT pictures
    
      // clear previous slice skipped flag
      m_prevSliceSkipped = false;
    
      //we should only get a different poc for a new picture (with CTU address==0)
      if(m_apcSlicePilot->getPOC() != m_prevPOC && !m_bFirstSliceInSequence && (m_apcSlicePilot->getSliceCurStartCtuTsAddr() != 0))
      {
        msg( WARNING, "Warning, the first slice of a picture might have been lost!\n");
      }
    
      // leave when a new picture is found
      if(m_apcSlicePilot->getSliceCurStartCtuTsAddr() == 0 && !m_bFirstSliceInPicture)
      {
        if (m_prevPOC >= m_pocRandomAccess)
        {
          DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 0 ) );
          m_prevPOC = m_apcSlicePilot->getPOC();
          return true;
        }
        m_prevPOC = m_apcSlicePilot->getPOC();
      }
      else
      {
        DTRACE_UPDATE( g_trace_ctx, std::make_pair( "final", 1 ) );
      }
    
      //detect lost reference picture and insert copy of earlier frame.
      {
        int lostPoc;
    
    Philip Cowan's avatar
    Philip Cowan committed
      #if JVET_O0241
        int refPicIndex;
        while ((lostPoc = m_apcSlicePilot->checkThatAllRefPicsAreAvailable(m_cListPic, m_apcSlicePilot->getRPL0(), 0, true, &refPicIndex)) > 0)
        {
    #if JVET_N0865_GRA2GDR
          if ( ( (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) || (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA) ) && m_apcSlicePilot->getNoIncorrectPicOutputFlag() )
    #else
          if (((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GRA) || (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)) && m_apcSlicePilot->getNoIncorrectPicOutputFlag())
    #endif
          {
    
            xCreateUnavailablePicture(lostPoc - 1, m_apcSlicePilot->getRPL0()->isRefPicLongterm(refPicIndex));
          }
          else
          {
            xCreateLostPicture(lostPoc - 1);
          }
        }
        while ((lostPoc = m_apcSlicePilot->checkThatAllRefPicsAreAvailable(m_cListPic, m_apcSlicePilot->getRPL0(), 0, true, &refPicIndex)) > 0)
        {
    #if JVET_N0865_GRA2GDR
          if (((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GDR) || (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)) && m_apcSlicePilot->getNoIncorrectPicOutputFlag())
    #else
          if (((m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_GRA) || (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)) && m_apcSlicePilot->getNoIncorrectPicOutputFlag())
    #endif
          {
    
            xCreateUnavailablePicture(lostPoc - 1, m_apcSlicePilot->getRPL0()->isRefPicLongterm(refPicIndex));
          }
          else
          {
            xCreateLostPicture(lostPoc - 1);
          }
        }
    #else
    
    Hendry's avatar
    Hendry committed
        while ((lostPoc = m_apcSlicePilot->checkThatAllRefPicsAreAvailable(m_cListPic, m_apcSlicePilot->getRPL0(), 0, true)) > 0)
          xCreateLostPicture(lostPoc - 1);
        while ((lostPoc = m_apcSlicePilot->checkThatAllRefPicsAreAvailable(m_cListPic, m_apcSlicePilot->getRPL1(), 1, true)) > 0)
          xCreateLostPicture(lostPoc - 1);
    
    Philip Cowan's avatar
    Philip Cowan committed
    #endif
    
      }
    
        m_prevPOC = m_apcSlicePilot->getPOC();
    
      if (m_bFirstSliceInPicture)
      {
        xUpdateRasInit(m_apcSlicePilot);
      }
    
      // actual decoding starts here
      xActivateParameterSets();
    
      m_bFirstSliceInSequence = false;
      m_bFirstSliceInBitstream  = false;
    
    
      Slice* pcSlice = m_pcPic->slices[m_uiSliceSegmentIdx];
      pcSlice->setPic( m_pcPic );
      m_pcPic->poc         = pcSlice->getPOC();
      m_pcPic->layer       = pcSlice->getTLayer();
      m_pcPic->referenced  = true;
      m_pcPic->layer       = nalu.m_temporalId;
    
    
    #if JVET_O0143_BOTTOM_RIGHT_BRICK_IDX_DELTA
      if (pcSlice->getPPS()->getRectSliceFlag())
      {
        int sliceIdx = pcSlice->getSliceIndex();
        int topLeft = pcSlice->getPic()->brickMap->getTopLeftBrickIdx(sliceIdx);
        int bottomRight = pcSlice->getPic()->brickMap->getBottomRightBrickIdx(sliceIdx);
    
        pcSlice->setSliceCurStartBrickIdx(topLeft);
        pcSlice->setSliceCurEndBrickIdx(bottomRight);
        pcSlice->setSliceCurStartCtuTsAddr(pcSlice->getSliceCurStartBrickIdx());
      }
    #endif
    
    
      // When decoding the slice header, the stored start and end addresses were actually RS addresses, not TS addresses.
      // Now, having set up the maps, convert them to the correct form.
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      const BrickMap& tileMap = *(m_pcPic->brickMap);
    
      const uint32_t numberOfCtusInFrame = m_pcPic->cs->pcv->sizeInCtus;
    
      uint32_t startCtuIdx = 0;
      while (pcSlice->getSliceCurStartBrickIdx() != tileMap.getBrickIdxBsMap(startCtuIdx) && startCtuIdx < numberOfCtusInFrame)
      {
        startCtuIdx++;
      }
      uint32_t endCtuIdx = startCtuIdx;
      while (pcSlice->getSliceCurEndBrickIdx() != tileMap.getBrickIdxBsMap(endCtuIdx) && endCtuIdx < numberOfCtusInFrame)
      {
        endCtuIdx++;
      }
      if (endCtuIdx == numberOfCtusInFrame)
        EXIT("Cannot find the last CTU index of the current slice");
    
    
      while ( (endCtuIdx < numberOfCtusInFrame) && (pcSlice->getSliceCurEndBrickIdx() == tileMap.getBrickIdxBsMap(endCtuIdx)) )
    
      {
        endCtuIdx++;
      }
      if (pcSlice->getSliceCurEndBrickIdx() != tileMap.getBrickIdxBsMap(endCtuIdx - 1))
        EXIT("Cannot find the last CTU index of the current slice");
    
      pcSlice->setSliceCurStartCtuTsAddr(startCtuIdx);
      pcSlice->setSliceCurEndCtuTsAddr(endCtuIdx);
    
    Hendry's avatar
    Hendry committed
      pcSlice->checkCRA(pcSlice->getRPL0(), pcSlice->getRPL1(), m_pocCRA, m_associatedIRAPType, m_cListPic);
      pcSlice->constructRefPicList(m_cListPic);
    
      pcSlice->scaleRefPicList( scaledRefPic, m_parameterSetManager.getAPSs(), pcSlice->getLmcsAPS(), pcSlice->getscalingListAPS(), true );
    
      pcSlice->scaleRefPicList( scaledRefPic, m_parameterSetManager.getAPSs(), pcSlice->getLmcsAPS(), true );
    
        if (!pcSlice->isIntra())
        {
          bool bLowDelay = true;
          int  iCurrPOC  = pcSlice->getPOC();
          int iRefIdx = 0;
    
          for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; iRefIdx++)
          {
            if ( pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx)->getPOC() > iCurrPOC )
            {
              bLowDelay = false;
            }
          }
          if (pcSlice->isInterB())
          {
            for (iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; iRefIdx++)
            {
              if ( pcSlice->getRefPic(REF_PIC_LIST_1, iRefIdx)->getPOC() > iCurrPOC )
              {
                bLowDelay = false;
              }
            }
          }
    
          pcSlice->setCheckLDC(bLowDelay);
        }
    
    
        if (pcSlice->getSPS()->getUseSMVD() && pcSlice->getCheckLDC() == false
    
    #if JVET_O0284_CONDITION_SMVD_MVDL1ZEROFLAG
          && pcSlice->getMvdL1ZeroFlag() == false
    #endif
    
        {
          int currPOC = pcSlice->getPOC();
    
          int forwardPOC = currPOC;
    
    Daniel's avatar
    Daniel committed
          int backwardPOC = currPOC;
    
          int ref = 0;
          int refIdx0 = -1;
          int refIdx1 = -1;
    
          // search nearest forward POC in List 0
          for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ )
          {
            int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();
    
            const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_0, ref)->longTerm;
            if ( poc < currPOC && (poc > forwardPOC || refIdx0 == -1) && !isRefLongTerm )
    
            if ( poc < currPOC && (poc > forwardPOC || refIdx0 == -1) )
    
            {
              forwardPOC = poc;
              refIdx0 = ref;
            }
          }
    
          // search nearest backward POC in List 1
          for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ )
          {
            int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();
    
            const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_1, ref)->longTerm;
            if ( poc > currPOC && (poc < backwardPOC || refIdx1 == -1) && !isRefLongTerm )
    
    Daniel's avatar
    Daniel committed
            if ( poc > currPOC && (poc < backwardPOC || refIdx1 == -1) )
    
    Daniel's avatar
    Daniel committed
              backwardPOC = poc;
    
    Daniel's avatar
    Daniel committed
          if ( !(forwardPOC < currPOC && backwardPOC > currPOC) )
    
          {
            forwardPOC = currPOC;
    
    Daniel's avatar
    Daniel committed
            backwardPOC = currPOC;
    
            refIdx0 = -1;
            refIdx1 = -1;
    
            // search nearest backward POC in List 0
            for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_0 ); ref++ )
            {
              int poc = pcSlice->getRefPic( REF_PIC_LIST_0, ref )->getPOC();
    
              const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_0, ref)->longTerm;
              if ( poc > currPOC && (poc < backwardPOC || refIdx0 == -1) && !isRefLongTerm )
    
    Daniel's avatar
    Daniel committed
              if ( poc > currPOC && (poc < backwardPOC || refIdx0 == -1) )
    
    Daniel's avatar
    Daniel committed
                backwardPOC = poc;
    
                refIdx0 = ref;
              }
            }
    
            // search nearest forward POC in List 1
            for ( ref = 0; ref < pcSlice->getNumRefIdx( REF_PIC_LIST_1 ); ref++ )
            {
              int poc = pcSlice->getRefPic( REF_PIC_LIST_1, ref )->getPOC();
    
              const bool isRefLongTerm = pcSlice->getRefPic(REF_PIC_LIST_1, ref)->longTerm;
              if ( poc < currPOC && (poc > forwardPOC || refIdx1 == -1) && !isRefLongTerm )
    
              if ( poc < currPOC && (poc > forwardPOC || refIdx1 == -1) )
    
    Daniel's avatar
    Daniel committed
          if ( forwardPOC < currPOC && backwardPOC > currPOC )
    
          {
            pcSlice->setBiDirPred( true, refIdx0, refIdx1 );
          }
          else
          {
            pcSlice->setBiDirPred( false, -1, -1 );
          }
        }
        else
        {
          pcSlice->setBiDirPred( false, -1, -1 );
        }
    
    
    #if JVET_N0494_DRAP
        SEIMessages drapSEIs = getSeisByType(m_pcPic->SEIs, SEI::DEPENDENT_RAP_INDICATION );
        if (!drapSEIs.empty())
        {
          msg( NOTICE, "Dependent RAP indication SEI decoded\n");
          pcSlice->setDRAP(true);
          pcSlice->setLatestDRAPPOC(pcSlice->getPOC());
        }
        pcSlice->checkConformanceForDRAP(nalu.m_temporalId);
    #endif
    
    #if JVET_O0299_APS_SCALINGLIST
      if( pcSlice->getSPS()->getScalingListFlag() )
      {
        ScalingList scalingList;
        if( pcSlice->getscalingListPresentFlag() )
        {
          APS* scalingListAPS = pcSlice->getscalingListAPS();
          scalingList = scalingListAPS->getScalingList();
        }
        else
        {
          scalingList.setDefaultScalingList();
        }
        quant->setScalingListDec( scalingList );
        quant->setUseScalingList( true );
      }
      else
      {
        quant->setUseScalingList( false );
      }
    #else
    
      if(pcSlice->getSPS()->getScalingListFlag())
      {
        ScalingList scalingList;
        if(pcSlice->getPPS()->getScalingListPresentFlag())
        {
          scalingList = pcSlice->getPPS()->getScalingList();
        }
        else if (pcSlice->getSPS()->getScalingListPresentFlag())
        {
          scalingList = pcSlice->getSPS()->getScalingList();
        }
        else
        {
          scalingList.setDefaultScalingList();
        }
        quant->setScalingListDec(scalingList);
        quant->setUseScalingList(true);
      }
      else
      {
        quant->setUseScalingList(false);
      }
    
    Taoran Lu's avatar
    Taoran Lu committed
      if (pcSlice->getSPS()->getUseReshaper())
      {
    
    #if JVET_O0428_LMCS_CLEANUP
        if (m_bFirstSliceInPicture)
          m_sliceLmcsApsId = -1;
    #endif
    
        if (pcSlice->getLmcsEnabledFlag())
        {
          APS* lmcsAPS = pcSlice->getLmcsAPS();
    
          if (m_sliceLmcsApsId == -1)
    
          {
            m_sliceLmcsApsId = lmcsAPS->getAPSId();
          }
          else
          {
            CHECK(lmcsAPS->getAPSId() != m_sliceLmcsApsId, "same APS ID shall be used for all slices in one picture");
          }
    #endif
    
          SliceReshapeInfo& sInfo = lmcsAPS->getReshaperAPSInfo();
          SliceReshapeInfo& tInfo = m_cReshaper.getSliceReshaperInfo();
          tInfo.reshaperModelMaxBinIdx = sInfo.reshaperModelMaxBinIdx;
          tInfo.reshaperModelMinBinIdx = sInfo.reshaperModelMinBinIdx;
          memcpy(tInfo.reshaperModelBinCWDelta, sInfo.reshaperModelBinCWDelta, sizeof(int)*(PIC_CODE_CW_BINS));
          tInfo.maxNbitsNeededDeltaCW = sInfo.maxNbitsNeededDeltaCW;
          tInfo.setUseSliceReshaper(pcSlice->getLmcsEnabledFlag());
          tInfo.setSliceReshapeChromaAdj(pcSlice->getLmcsChromaResidualScaleFlag());
          tInfo.setSliceReshapeModelPresentFlag(true);
        }
        else
        {
          SliceReshapeInfo& tInfo = m_cReshaper.getSliceReshaperInfo();
          tInfo.setUseSliceReshaper(false);
          tInfo.setSliceReshapeChromaAdj(false);
          tInfo.setSliceReshapeModelPresentFlag(false);
        }
        if (pcSlice->getLmcsEnabledFlag())
    
    Taoran Lu's avatar
    Taoran Lu committed
        {
          m_cReshaper.constructReshaper();
        }
        else
        {
          m_cReshaper.setReshapeFlag(false);
        }
    
    Taoran Lu's avatar
    Taoran Lu committed
        if ((pcSlice->getSliceType() == I_SLICE) && m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
    
    Taoran Lu's avatar
    Taoran Lu committed
        {
          m_cReshaper.setCTUFlag(false);
          m_cReshaper.setRecReshaped(true);
        }
        else
        {
          if (m_cReshaper.getSliceReshaperInfo().getUseSliceReshaper())
          {
            m_cReshaper.setCTUFlag(true);
            m_cReshaper.setRecReshaped(true);
          }
          else
          {
            m_cReshaper.setCTUFlag(false);
            m_cReshaper.setRecReshaped(false);
          }
        }
    
    #if JVET_O1109_UNFIY_CRS
        m_cReshaper.setVPDULoc(-1, -1);
    #endif
    
    Taoran Lu's avatar
    Taoran Lu committed
      }
      else
      {
        m_cReshaper.setCTUFlag(false);
        m_cReshaper.setRecReshaped(false);
      }
    
    Tobias Hinz's avatar
    Tobias Hinz committed
      m_cSliceDecoder.decompressSlice( pcSlice, &( nalu.getBitstream() ), ( m_pcPic->poc == getDebugPOC() ? getDebugCTU() : -1 ) );
    
    #if JVET_O1164_RPR
      pcSlice->freeScaledRefPicList( scaledRefPic );
    #endif
    
    
      return false;
    }
    
    void DecLib::xDecodeVPS( InputNALUnit& nalu )
    {
      VPS* vps = new VPS();
      m_HLSReader.setBitstream( &nalu.getBitstream() );
    
    
    #if JVET_O0245_VPS_DPS_APS
      CHECK( nalu.m_temporalId, "The value of TemporalId of VPS NAL units shall be equal to 0" );
    #endif
    
    
    Karsten Suehring's avatar
    Karsten Suehring committed
      delete vps;
    
    void DecLib::xDecodeDPS( InputNALUnit& nalu )
    {
      DPS* dps = new DPS();
      m_HLSReader.setBitstream( &nalu.getBitstream() );
    
    
    #if JVET_O0245_VPS_DPS_APS
      CHECK( nalu.m_temporalId, "The value of TemporalId of DPS NAL units shall be equal to 0" );
    #endif
    
    
      m_HLSReader.parseDPS( dps );
      m_parameterSetManager.storeDPS( dps, nalu.getBitstream().getFifo() );
    }
    
    
    void DecLib::xDecodeSPS( InputNALUnit& nalu )
    {
      SPS* sps = new SPS();
      m_HLSReader.setBitstream( &nalu.getBitstream() );
    
    
    #if JVET_O0245_VPS_DPS_APS
      CHECK( nalu.m_temporalId, "The value of TemporalId of SPS NAL units shall be equal to 0" );
    #endif
    
    
      m_HLSReader.parseSPS( sps );
      DTRACE( g_trace_ctx, D_QP_PER_CTU, "CTU Size: %dx%d", sps->getMaxCUWidth(), sps->getMaxCUHeight() );
    
      m_parameterSetManager.storeSPS( sps, nalu.getBitstream().getFifo() );
    
    }
    
    void DecLib::xDecodePPS( InputNALUnit& nalu )
    {
      PPS* pps = new PPS();
      m_HLSReader.setBitstream( &nalu.getBitstream() );
    
      m_HLSReader.parsePPS( pps, &m_parameterSetManager );
    
    #if JVET_O0245_VPS_DPS_APS
      pps->setLayerId( nalu.m_nuhLayerId );
      pps->setTemporalId( nalu.m_temporalId );
    #endif
    
      m_parameterSetManager.storePPS( pps, nalu.getBitstream().getFifo() );
    }
    
    
    Hendry's avatar
    Hendry committed
    void DecLib::xDecodeAPS(InputNALUnit& nalu)
    {
      APS* aps = new APS();
      m_HLSReader.setBitstream(&nalu.getBitstream());
      m_HLSReader.parseAPS(aps);
    
      aps->setTemporalId(nalu.m_temporalId);
    
    #if JVET_O0245_VPS_DPS_APS
      aps->setLayerId( nalu.m_nuhLayerId );
      m_parameterSetManager.checkAuApsContent( aps, m_accessUnitApsNals );  
    #endif
    
    Hendry's avatar
    Hendry committed
      m_parameterSetManager.storeAPS(aps, nalu.getBitstream().getFifo());
    }
    
    bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay)
    {
      bool ret;
      // ignore all NAL units of layers > 0
    
      if (getTargetDecLayer() >= 0 && nalu.m_nuhLayerId != getTargetDecLayer()) //TBC: ignore bitstreams whose nuh_layer_id is not the target layer id
    
      {
        msg( WARNING, "Warning: found NAL unit with nuh_layer_id equal to %d. Ignoring.\n", nalu.m_nuhLayerId);
        return false;
      }
    
    
    #if JVET_O0245_VPS_DPS_APS
      m_accessUnitNals.push_back( std::pair<NalUnitType, int>( nalu.m_nalUnitType, nalu.m_temporalId ) );
    #endif
    
    
      switch (nalu.m_nalUnitType)
      {
        case NAL_UNIT_VPS:
          xDecodeVPS( nalu );
          return false;
    
    
        case NAL_UNIT_DPS:
          xDecodeDPS( nalu );
          return false;
    
    
        case NAL_UNIT_SPS:
          xDecodeSPS( nalu );
          return false;
    
        case NAL_UNIT_PPS:
          xDecodePPS( nalu );
          return false;
    
    Hendry's avatar
    Hendry committed
        case NAL_UNIT_APS:
          xDecodeAPS(nalu);
          return false;
    
    
        case NAL_UNIT_PREFIX_SEI:
          // Buffer up prefix SEI messages until SPS of associated VCL is known.
          m_prefixSEINALUs.push_back(new InputNALUnit(nalu));
          return false;
    
        case NAL_UNIT_SUFFIX_SEI:
          if (m_pcPic)
          {
    
            m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_pcPic->SEIs, nalu.m_nalUnitType, m_parameterSetManager.getActiveSPS(), m_HRD, m_pDecodedSEIOutputStream );
    
    #else
            m_seiReader.parseSEImessage( &(nalu.getBitstream()), m_pcPic->SEIs, nalu.m_nalUnitType, nalu.m_temporalId, m_parameterSetManager.getActiveSPS(), m_HRD, m_pDecodedSEIOutputStream );
    #endif
    
          }
          else
          {
            msg( NOTICE, "Note: received suffix SEI but no picture currently active.\n");
          }
          return false;
    
    
        case NAL_UNIT_CODED_SLICE_TRAIL:
        case NAL_UNIT_CODED_SLICE_STSA:
        case NAL_UNIT_CODED_SLICE_IDR_W_RADL:
        case NAL_UNIT_CODED_SLICE_IDR_N_LP:
        case NAL_UNIT_CODED_SLICE_CRA:
    
    #if JVET_N0865_NONSYNTAX
        case NAL_UNIT_CODED_SLICE_GDR:
    #endif
    
        case NAL_UNIT_CODED_SLICE_RADL:
        case NAL_UNIT_CODED_SLICE_RASL:
    
          ret = xDecodeSlice(nalu, iSkipFrame, iPOCLastDisplay);
    #if JVET_J0090_MEMORY_BANDWITH_MEASURE
          if ( ret )
          {
            m_cacheModel.reportFrame( );
            m_cacheModel.accumulateFrame( );
            m_cacheModel.clear( );
          }
    #endif
          return ret;
    
        case NAL_UNIT_EOS:
          m_associatedIRAPType = NAL_UNIT_INVALID;
          m_pocCRA = 0;
          m_pocRandomAccess = MAX_INT;
          m_prevPOC = MAX_INT;
          m_prevSliceSkipped = false;
          m_skippedPOC = 0;
          return false;
    
        case NAL_UNIT_ACCESS_UNIT_DELIMITER:
          {
            AUDReader audReader;
            uint32_t picType;
            audReader.parseAccessUnitDelimiter(&(nalu.getBitstream()),picType);
    
    #if JVET_O0245_VPS_DPS_APS
            // vectors clearing shall be moved to the right place if mandatory AUD starting an AU is removed
            m_accessUnitNals.clear();
            m_accessUnitApsNals.clear();
            m_accessUnitNals.push_back( std::pair<NalUnitType, int>( NAL_UNIT_ACCESS_UNIT_DELIMITER, nalu.m_temporalId ) );
    #endif
    
    #if JVET_O0610_DETECT_AUD
    
            return !m_bFirstSliceInPicture;
    
    #else
            msg( NOTICE, "Note: found NAL_UNIT_ACCESS_UNIT_DELIMITER\n");
            return false;
    #endif