Skip to content
Snippets Groups Projects
DecLib.cpp 45.3 KiB
Newer Older
  • Learn to ignore specific revisions
  •   {
        msg( WARNING, "Warning, the first slice of a picture might have been lost!\n");
      }
    
      // leave when a new picture is found
    #if HEVC_DEPENDENT_SLICES
      if (!m_apcSlicePilot->getDependentSliceSegmentFlag() && (m_apcSlicePilot->getSliceCurStartCtuTsAddr() == 0 && !m_bFirstSliceInPicture) )
    #else
      if(m_apcSlicePilot->getSliceCurStartCtuTsAddr() == 0 && !m_bFirstSliceInPicture)
    #endif
      {
        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;
        while((lostPoc=m_apcSlicePilot->checkThatAllRefPicsAreAvailable(m_cListPic, m_apcSlicePilot->getRPS(), true, m_pocRandomAccess)) > 0)
        {
          xCreateLostPicture(lostPoc-1);
        }
      }
    
    #if HEVC_DEPENDENT_SLICES
      if (!m_apcSlicePilot->getDependentSliceSegmentFlag())
      {
    #endif
        m_prevPOC = m_apcSlicePilot->getPOC();
    #if HEVC_DEPENDENT_SLICES
      }
    #endif
    
      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;
    
      // 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.
    #if HEVC_TILES_WPP
      const TileMap& tileMap = *(m_pcPic->tileMap);
    #endif
    #if HEVC_DEPENDENT_SLICES
    #if HEVC_TILES_WPP
      pcSlice->setSliceSegmentCurStartCtuTsAddr( tileMap.getCtuRsToTsAddrMap(pcSlice->getSliceSegmentCurStartCtuTsAddr()) );
      pcSlice->setSliceSegmentCurEndCtuTsAddr( tileMap.getCtuRsToTsAddrMap(pcSlice->getSliceSegmentCurEndCtuTsAddr()) );
    #endif
      if(!pcSlice->getDependentSliceSegmentFlag())
      {
    #endif
    #if HEVC_TILES_WPP
        pcSlice->setSliceCurStartCtuTsAddr( tileMap.getCtuRsToTsAddrMap(pcSlice->getSliceCurStartCtuTsAddr()) );
        pcSlice->setSliceCurEndCtuTsAddr( tileMap.getCtuRsToTsAddrMap(pcSlice->getSliceCurEndCtuTsAddr()) );
    #endif
    #if HEVC_DEPENDENT_SLICES
      }
    #endif
    
    
    #if HEVC_DEPENDENT_SLICES
      if (!pcSlice->getDependentSliceSegmentFlag())
      {
    #endif
        pcSlice->checkCRA(pcSlice->getRPS(), m_pocCRA, m_associatedIRAPType, m_cListPic );
        // Set reference list
        pcSlice->setRefPicList( m_cListPic, true, 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);
        }
    
        //---------------
        pcSlice->setRefPOCList();
    
    #if HEVC_DEPENDENT_SLICES
      }
    #endif
    
    #if HEVC_USE_SCALING_LISTS
      Quant *quant = m_cTrQuant.getQuant();
    
      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);
      }
    #endif
    
    
      if (pcSlice->getSPS()->getSpsNext().getCPRMode() && pcSlice->getEnableTMVPFlag())
      {
        CHECK(pcSlice->getRefPic(RefPicList(pcSlice->isInterB() ? 1 - pcSlice->getColFromL0Flag() : 0), pcSlice->getColRefIdx())->getPOC() == pcSlice->getPOC(), "curr ref picture cannot be collocated picture");
      }
    
    
    
      //  Decode a picture
      m_cSliceDecoder.decompressSlice( pcSlice, &(nalu.getBitstream()) );
    
      m_bFirstSliceInPicture = false;
    
    Xiaozhong Xu's avatar
    Xiaozhong Xu committed
      if (pcSlice->getSPS()->getSpsNext().getCPRMode())
      {
        pcSlice->getPic()->longTerm = false;
      }
    
      m_uiSliceSegmentIdx++;
    
      return false;
    }
    
    #if HEVC_VPS
    void DecLib::xDecodeVPS( InputNALUnit& nalu )
    {
      VPS* vps = new VPS();
      m_HLSReader.setBitstream( &nalu.getBitstream() );
      m_HLSReader.parseVPS( vps );
      m_parameterSetManager.storeVPS( vps, nalu.getBitstream().getFifo() );
    }
    #endif
    
    void DecLib::xDecodeSPS( InputNALUnit& nalu )
    {
      SPS* sps = new SPS();
      m_HLSReader.setBitstream( &nalu.getBitstream() );
      m_HLSReader.parseSPS( sps );
      m_parameterSetManager.storeSPS( sps, nalu.getBitstream().getFifo() );
    
      DTRACE( g_trace_ctx, D_QP_PER_CTU, "CTU Size: %dx%d", sps->getMaxCUWidth(), sps->getMaxCUHeight() );
    }
    
    void DecLib::xDecodePPS( InputNALUnit& nalu )
    {
      PPS* pps = new PPS();
      m_HLSReader.setBitstream( &nalu.getBitstream() );
      m_HLSReader.parsePPS( pps );
      m_parameterSetManager.storePPS( pps, nalu.getBitstream().getFifo() );
    }
    
    bool DecLib::decode(InputNALUnit& nalu, int& iSkipFrame, int& iPOCLastDisplay)
    {
      bool ret;
      // ignore all NAL units of layers > 0
      if (nalu.m_nuhLayerId > 0)
      {
        msg( WARNING, "Warning: found NAL unit with nuh_layer_id equal to %d. Ignoring.\n", nalu.m_nuhLayerId);
        return false;
      }
    
      switch (nalu.m_nalUnitType)
      {
    #if HEVC_VPS
        case NAL_UNIT_VPS:
          xDecodeVPS( nalu );
          return false;
    #endif
    
        case NAL_UNIT_SPS:
          xDecodeSPS( nalu );
          return false;
    
        case NAL_UNIT_PPS:
          xDecodePPS( 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_pDecodedSEIOutputStream );
          }
          else
          {
            msg( NOTICE, "Note: received suffix SEI but no picture currently active.\n");
          }
          return false;
    
        case NAL_UNIT_CODED_SLICE_TRAIL_R:
        case NAL_UNIT_CODED_SLICE_TRAIL_N:
        case NAL_UNIT_CODED_SLICE_TSA_R:
        case NAL_UNIT_CODED_SLICE_TSA_N:
        case NAL_UNIT_CODED_SLICE_STSA_R:
        case NAL_UNIT_CODED_SLICE_STSA_N:
        case NAL_UNIT_CODED_SLICE_BLA_W_LP:
        case NAL_UNIT_CODED_SLICE_BLA_W_RADL:
        case NAL_UNIT_CODED_SLICE_BLA_N_LP:
        case NAL_UNIT_CODED_SLICE_IDR_W_RADL:
        case NAL_UNIT_CODED_SLICE_IDR_N_LP:
        case NAL_UNIT_CODED_SLICE_CRA:
        case NAL_UNIT_CODED_SLICE_RADL_N:
        case NAL_UNIT_CODED_SLICE_RADL_R:
        case NAL_UNIT_CODED_SLICE_RASL_N:
        case NAL_UNIT_CODED_SLICE_RASL_R:
          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);
            msg( NOTICE, "Note: found NAL_UNIT_ACCESS_UNIT_DELIMITER\n");
            return false;
          }
    
        case NAL_UNIT_EOB:
          return false;
    
        case NAL_UNIT_FILLER_DATA:
          {
            FDReader fdReader;
            uint32_t size;
            fdReader.parseFillerData(&(nalu.getBitstream()),size);
            msg( NOTICE, "Note: found NAL_UNIT_FILLER_DATA with %u bytes payload.\n", size);
            return false;
          }
    
        case NAL_UNIT_RESERVED_VCL_N10:
        case NAL_UNIT_RESERVED_VCL_R11:
        case NAL_UNIT_RESERVED_VCL_N12:
        case NAL_UNIT_RESERVED_VCL_R13:
        case NAL_UNIT_RESERVED_VCL_N14:
        case NAL_UNIT_RESERVED_VCL_R15:
    
        case NAL_UNIT_RESERVED_IRAP_VCL22:
        case NAL_UNIT_RESERVED_IRAP_VCL23:
    
        case NAL_UNIT_RESERVED_VCL24:
        case NAL_UNIT_RESERVED_VCL25:
        case NAL_UNIT_RESERVED_VCL26:
        case NAL_UNIT_RESERVED_VCL27:
        case NAL_UNIT_RESERVED_VCL28:
        case NAL_UNIT_RESERVED_VCL29:
        case NAL_UNIT_RESERVED_VCL30:
        case NAL_UNIT_RESERVED_VCL31:
    #if !HEVC_VPS
        case NAL_UNIT_RESERVED_32:
    #endif
          msg( NOTICE, "Note: found reserved VCL NAL unit.\n");
          xParsePrefixSEIsForUnknownVCLNal();
          return false;
    
        case NAL_UNIT_RESERVED_NVCL41:
        case NAL_UNIT_RESERVED_NVCL42:
        case NAL_UNIT_RESERVED_NVCL43:
        case NAL_UNIT_RESERVED_NVCL44:
        case NAL_UNIT_RESERVED_NVCL45:
        case NAL_UNIT_RESERVED_NVCL46:
        case NAL_UNIT_RESERVED_NVCL47:
          msg( NOTICE, "Note: found reserved NAL unit.\n");
          return false;
        case NAL_UNIT_UNSPECIFIED_48:
        case NAL_UNIT_UNSPECIFIED_49:
        case NAL_UNIT_UNSPECIFIED_50:
        case NAL_UNIT_UNSPECIFIED_51:
        case NAL_UNIT_UNSPECIFIED_52:
        case NAL_UNIT_UNSPECIFIED_53:
        case NAL_UNIT_UNSPECIFIED_54:
        case NAL_UNIT_UNSPECIFIED_55:
        case NAL_UNIT_UNSPECIFIED_56:
        case NAL_UNIT_UNSPECIFIED_57:
        case NAL_UNIT_UNSPECIFIED_58:
        case NAL_UNIT_UNSPECIFIED_59:
        case NAL_UNIT_UNSPECIFIED_60:
        case NAL_UNIT_UNSPECIFIED_61:
        case NAL_UNIT_UNSPECIFIED_62:
        case NAL_UNIT_UNSPECIFIED_63:
          msg( NOTICE, "Note: found unspecified NAL unit.\n");
          return false;
        default:
          THROW( "Invalid NAL unit type" );
          break;
      }
    
      return false;
    }
    
    /** Function for checking if picture should be skipped because of association with a previous BLA picture
     *  This function skips all TFD pictures that follow a BLA picture in decoding order and precede it in output order.
     */
    bool DecLib::isSkipPictureForBLA( int& iPOCLastDisplay )
    {
      if( ( m_associatedIRAPType == NAL_UNIT_CODED_SLICE_BLA_N_LP || m_associatedIRAPType == NAL_UNIT_CODED_SLICE_BLA_W_LP || m_associatedIRAPType == NAL_UNIT_CODED_SLICE_BLA_W_RADL ) &&
            m_apcSlicePilot->getPOC() < m_pocCRA && ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N ) )
      {
        iPOCLastDisplay++;
        return true;
      }
      return false;
    }
    
    /** Function for checking if picture should be skipped because of random access. This function checks the skipping of pictures in the case of -s option random access.
     *  All pictures prior to the random access point indicated by the counter iSkipFrame are skipped.
     *  It also checks the type of Nal unit type at the random access point.
     *  If the random access point is CRA/CRANT/BLA/BLANT, TFD pictures with POC less than the POC of the random access point are skipped.
     *  If the random access point is IDR all pictures after the random access point are decoded.
     *  If the random access point is none of the above, a warning is issues, and decoding of pictures with POC
     *  equal to or greater than the random access point POC is attempted. For non IDR/CRA/BLA random
     *  access point there is no guarantee that the decoder will not crash.
     */
    bool DecLib::isRandomAccessSkipPicture( int& iSkipFrame, int& iPOCLastDisplay )
    {
      if (iSkipFrame)
      {
        iSkipFrame--;   // decrement the counter
        return true;
      }
      else if (m_pocRandomAccess == MAX_INT) // start of random access point, m_pocRandomAccess has not been set yet.
      {
        if (   m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA
            || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP
            || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP
            || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL )
        {
          // set the POC random access since we need to skip the reordered pictures in the case of CRA/CRANT/BLA/BLANT.
          m_pocRandomAccess = m_apcSlicePilot->getPOC();
        }
        else if ( m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP )
        {
          m_pocRandomAccess = -MAX_INT; // no need to skip the reordered pictures in IDR, they are decodable.
        }
        else
        {
          if(!m_warningMessageSkipPicture)
          {
            msg( WARNING, "\nWarning: this is not a valid random access point and the data is discarded until the first CRA picture");
            m_warningMessageSkipPicture = true;
          }
          return true;
        }
      }
      // skip the reordered pictures, if necessary
      else if (m_apcSlicePilot->getPOC() < m_pocRandomAccess && (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N))
      {
        iPOCLastDisplay++;
        return true;
      }
      // if we reach here, then the picture is not skipped.
      return false;
    }
    
    
    
    
    //! \}