Void TDecSlice::decompressSlice(TComInputBitstream** ppcSubstreams, TComPic* pcPic, TDecSbac* pcSbacDecoder)
{
  TComSlice* pcSlice                 = pcPic->getSlice(pcPic->getCurrSliceIdx());

  const Int  startCtuTsAddr          = pcSlice->getSliceSegmentCurStartCtuTsAddr();
  const Int  startCtuRsAddr          = pcPic->getPicSym()->getCtuTsToRsAddrMap(startCtuTsAddr);
  const UInt numCtusInFrame          = pcPic->getNumberOfCtusInFrame();

  const UInt frameWidthInCtus        = pcPic->getPicSym()->getFrameWidthInCtus();
  const Bool depSliceSegmentsEnabled = pcSlice->getPPS()->getDependentSliceSegmentsEnabledFlag();
  const Bool wavefrontsEnabled       = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag();

  m_pcEntropyDecoder->setEntropyDecoder ( pcSbacDecoder  );
  m_pcEntropyDecoder->setBitstream      ( ppcSubstreams[0] );
  m_pcEntropyDecoder->resetEntropy      (pcSlice);

  // decoder doesn't need prediction & residual frame buffer
  pcPic->setPicYuvPred( 0 );
  pcPic->setPicYuvResi( 0 );

#if ENC_DEC_TRACE
  g_bJustDoIt = g_bEncDecTraceEnable;
#endif
  DTRACE_CABAC_VL( g_nSymbolCounter++ );
  DTRACE_CABAC_T( "\tPOC: " );
  DTRACE_CABAC_V( pcPic->getPOC() );
  DTRACE_CABAC_T( "\n" );

#if ENC_DEC_TRACE
  g_bJustDoIt = g_bEncDecTraceDisable;
#endif

  // The first CTU of the slice is the first coded substream, but the global substream number, as calculated by getSubstreamForCtuAddr may be higher.
  // This calculates the common offset for all substreams in this slice.
  const UInt subStreamOffset=pcPic->getSubstreamForCtuAddr(startCtuRsAddr, true, pcSlice);


  if (depSliceSegmentsEnabled)
  {
    // modify initial contexts with previous slice segment if this is a dependent slice.
    const UInt startTileIdx=pcPic->getPicSym()->getTileIdxMap(startCtuRsAddr);
    const TComTile *pCurrentTile=pcPic->getPicSym()->getTComTile(startTileIdx);
    const UInt firstCtuRsAddrOfTile = pCurrentTile->getFirstCtuRsAddr();

    if( pcSlice->getDependentSliceSegmentFlag() && startCtuRsAddr != firstCtuRsAddrOfTile)
    {
      if ( pCurrentTile->getTileWidthInCtus() >= 2 || !wavefrontsEnabled)
      {
        pcSbacDecoder->loadContexts(&m_lastSliceSegmentEndContextState);
      }
    }
  }

  // for every CTU in the slice segment...

  Bool isLastCtuOfSliceSegment = false;
  for( UInt ctuTsAddr = startCtuTsAddr; !isLastCtuOfSliceSegment && ctuTsAddr < numCtusInFrame; ctuTsAddr++)
  {
    const UInt ctuRsAddr = pcPic->getPicSym()->getCtuTsToRsAddrMap(ctuTsAddr);
    const TComTile &currentTile = *(pcPic->getPicSym()->getTComTile(pcPic->getPicSym()->getTileIdxMap(ctuRsAddr)));
    const UInt firstCtuRsAddrOfTile = currentTile.getFirstCtuRsAddr();
    const UInt tileXPosInCtus = firstCtuRsAddrOfTile % frameWidthInCtus;
    const UInt tileYPosInCtus = firstCtuRsAddrOfTile / frameWidthInCtus;
    const UInt ctuXPosInCtus  = ctuRsAddr % frameWidthInCtus;
    const UInt ctuYPosInCtus  = ctuRsAddr / frameWidthInCtus;
    const UInt uiSubStrm=pcPic->getSubstreamForCtuAddr(ctuRsAddr, true, pcSlice)-subStreamOffset;
    TComDataCU* pCtu = pcPic->getCtu( ctuRsAddr );
    pCtu->initCtu( pcPic, ctuRsAddr );

    m_pcEntropyDecoder->setBitstream( ppcSubstreams[uiSubStrm] );

    // set up CABAC contexts' state for this CTU
    if (ctuRsAddr == firstCtuRsAddrOfTile)
    {
      if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset
      {
        m_pcEntropyDecoder->resetEntropy(pcSlice);
      }
    }
    else if (ctuXPosInCtus == tileXPosInCtus && wavefrontsEnabled)
    {
      // Synchronize cabac probabilities with upper-right CTU if it's available and at the start of a line.
      if (ctuTsAddr != startCtuTsAddr) // if it is the first CTU, then the entropy coder has already been reset
      {
        m_pcEntropyDecoder->resetEntropy(pcSlice);
      }
      TComDataCU *pCtuUp = pCtu->getCtuAbove();
      if ( pCtuUp && ((ctuRsAddr%frameWidthInCtus+1) < frameWidthInCtus)  )
      {
        TComDataCU *pCtuTR = pcPic->getCtu( ctuRsAddr - frameWidthInCtus + 1 );
        if ( pCtu->CUIsFromSameSliceAndTile(pCtuTR) )
        {
          // Top-right is available, so use it.
          pcSbacDecoder->loadContexts( &m_entropyCodingSyncContextState );
        }
      }
    }

#if ENC_DEC_TRACE
    g_bJustDoIt = g_bEncDecTraceEnable;
#endif

    if ( pcSlice->getSPS()->getUseSAO() )
    {
      SAOBlkParam& saoblkParam = (pcPic->getPicSym()->getSAOBlkParam())[ctuRsAddr];
      Bool bIsSAOSliceEnabled = false;
      Bool sliceEnabled[MAX_NUM_COMPONENT];
      for(Int comp=0; comp < MAX_NUM_COMPONENT; comp++)
      {
        ComponentID compId=ComponentID(comp);
        sliceEnabled[compId] = pcSlice->getSaoEnabledFlag(toChannelType(compId)) && (comp < pcPic->getNumberValidComponents());
        if (sliceEnabled[compId]) bIsSAOSliceEnabled=true;
        saoblkParam[compId].modeIdc = SAO_MODE_OFF;
      }
      if (bIsSAOSliceEnabled)
      {
        Bool leftMergeAvail = false;
        Bool aboveMergeAvail= false;

        //merge left condition
        Int rx = (ctuRsAddr % frameWidthInCtus);
        if(rx > 0)
        {
          leftMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-1);
        }
        //merge up condition
        Int ry = (ctuRsAddr / frameWidthInCtus);
        if(ry > 0)
        {
          aboveMergeAvail = pcPic->getSAOMergeAvailability(ctuRsAddr, ctuRsAddr-frameWidthInCtus);
        }
#if SVC_EXTENSION
        pcSbacDecoder->parseSAOBlkParam( saoblkParam, m_saoMaxOffsetQVal, sliceEnabled, leftMergeAvail, aboveMergeAvail);
#else
        pcSbacDecoder->parseSAOBlkParam( saoblkParam, sliceEnabled, leftMergeAvail, aboveMergeAvail);
#endif      
      }
    }

    m_pcCuDecoder->decodeCtu     ( pCtu, isLastCtuOfSliceSegment );
    m_pcCuDecoder->decompressCtu ( pCtu );

#if ENC_DEC_TRACE
    g_bJustDoIt = g_bEncDecTraceDisable;
#endif

    //Store probabilities of second CTU in line into buffer
    if ( ctuXPosInCtus == tileXPosInCtus+1 && wavefrontsEnabled)
    {
      m_entropyCodingSyncContextState.loadContexts( pcSbacDecoder );
    }

    // Should the sub-stream/stream be terminated after this CTU?
    // (end of slice-segment, end of tile, end of wavefront-CTU-row)
    if (isLastCtuOfSliceSegment ||
         (  ctuXPosInCtus + 1 == tileXPosInCtus + currentTile.getTileWidthInCtus() &&
          ( ctuYPosInCtus + 1 == tileYPosInCtus + currentTile.getTileHeightInCtus() || wavefrontsEnabled)
         )
       )
    {
      UInt binVal;
      pcSbacDecoder->parseTerminatingBit( binVal );
      assert( binVal );
#if DECODER_CHECK_SUBSTREAM_AND_SLICE_TRAILING_BYTES
      pcSbacDecoder->parseRemainingBytes(!isLastCtuOfSliceSegment);
#endif

      if (isLastCtuOfSliceSegment)
      {
        if(!pcSlice->getDependentSliceSegmentFlag())
        {
          pcSlice->setSliceCurEndCtuTsAddr( ctuTsAddr+1 );
        }
        pcSlice->setSliceSegmentCurEndCtuTsAddr( ctuTsAddr+1 );
        break;
      }
    }
  }

  assert(isLastCtuOfSliceSegment == true);


  if( depSliceSegmentsEnabled )
  {
    m_lastSliceSegmentEndContextState.loadContexts( pcSbacDecoder );//ctx end of dep.slice
  }

}
예제 #2
0
Bool TDecTop::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.

    if (m_bFirstSliceInPicture)
    {
        m_uiSliceIdx = 0;
    }
    else
    {
        m_apcSlicePilot->copySliceInfo( m_pcPic->getPicSym()->getSlice(m_uiSliceIdx-1) );
    }
    m_apcSlicePilot->setSliceIdx(m_uiSliceIdx);

    m_apcSlicePilot->setNalUnitType(nalu.m_nalUnitType);
    Bool nonReferenceFlag = (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_TRAIL_N ||
                             m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_N   ||
                             m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_STSA_N  ||
                             m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N  ||
                             m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_N);
    m_apcSlicePilot->setTemporalLayerNonReferenceFlag(nonReferenceFlag);
    m_apcSlicePilot->setReferenced(true); // Putting this as true ensures that picture is referenced the first time it is in an RPS
    m_apcSlicePilot->setTLayerInfo(nalu.m_temporalId);

#if ENC_DEC_TRACE
    const UInt64 originalSymbolCount = g_nSymbolCounter;
#endif

    m_cEntropyDecoder.decodeSliceHeader (m_apcSlicePilot, &m_parameterSetManager);

    // set POC for dependent slices in skipped pictures
    if(m_apcSlicePilot->getDependentSliceSegmentFlag() && m_prevSliceSkipped)
    {
        m_apcSlicePilot->setPOC(m_skippedPOC);
    }

    m_apcSlicePilot->setAssociatedIRAPPOC(m_pocCRA);
    m_apcSlicePilot->setAssociatedIRAPType(m_associatedIRAPType);

    //For inference of NoOutputOfPriorPicsFlag
    if (m_apcSlicePilot->getRapPicFlag())
    {
        if ((m_apcSlicePilot->getNalUnitType() >= NAL_UNIT_CODED_SLICE_BLA_W_LP && m_apcSlicePilot->getNalUnitType() <= NAL_UNIT_CODED_SLICE_IDR_N_LP) ||
                (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_bFirstSliceInSequence) ||
                (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_apcSlicePilot->getHandleCraAsBlaFlag()))
        {
            m_apcSlicePilot->setNoRaslOutputFlag(true);
        }
        //the inference for NoOutputPriorPicsFlag
        if (!m_bFirstSliceInBitstream && m_apcSlicePilot->getRapPicFlag() && m_apcSlicePilot->getNoRaslOutputFlag())
        {
            if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)
            {
                m_apcSlicePilot->setNoOutputPriorPicsFlag(true);
            }
        }
        else
        {
            m_apcSlicePilot->setNoOutputPriorPicsFlag(false);
        }

        if(m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)
        {
            m_craNoRaslOutputFlag = m_apcSlicePilot->getNoRaslOutputFlag();
        }
    }
    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_N || m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_RASL_R)
    {
        if ( m_craNoRaslOutputFlag )
        {
            m_apcSlicePilot->setPicOutputFlag(false);
        }
    }

    if (m_apcSlicePilot->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA && m_craNoRaslOutputFlag) //Reset POC MSB when CRA has NoRaslOutputFlag equal to 1
    {
        TComPPS *pps = m_parameterSetManager.getPPS(m_apcSlicePilot->getPPSId());
        assert (pps != 0);
        TComSPS *sps = m_parameterSetManager.getSPS(pps->getSPSId());
        assert (sps != 0);
        Int iMaxPOClsb = 1 << sps->getBitsForPOC();
        m_apcSlicePilot->setPOC( m_apcSlicePilot->getPOC() & (iMaxPOClsb - 1) );
    }

    // 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
    if (isSkipPictureForBLA(iPOCLastDisplay))
    {
        m_prevSliceSkipped = true;
        m_skippedPOC = m_apcSlicePilot->getPOC();
        return false;
    }

    // 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->getDependentSliceSegmentFlag() && m_apcSlicePilot->getPOC()!=m_prevPOC && !m_bFirstSliceInSequence && (m_apcSlicePilot->getSliceCurStartCtuTsAddr() != 0))
    {
        printf ("Warning, the first slice of a picture might have been lost!\n");
    }

    // exit when a new picture is found
    if (!m_apcSlicePilot->getDependentSliceSegmentFlag() && (m_apcSlicePilot->getSliceCurStartCtuTsAddr() == 0 && !m_bFirstSliceInPicture) )
    {
        if (m_prevPOC >= m_pocRandomAccess)
        {
            m_prevPOC = m_apcSlicePilot->getPOC();
#if ENC_DEC_TRACE
            //rewind the trace counter since we didn't actually decode the slice
            g_nSymbolCounter = originalSymbolCount;
#endif
            return true;
        }
        m_prevPOC = m_apcSlicePilot->getPOC();
    }

    //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 (!m_apcSlicePilot->getDependentSliceSegmentFlag())
    {
        m_prevPOC = m_apcSlicePilot->getPOC();
    }

    // actual decoding starts here
    xActivateParameterSets();

    m_bFirstSliceInSequence = false;
    m_bFirstSliceInBitstream  = false;


    TComSlice* pcSlice = m_pcPic->getPicSym()->getSlice(m_uiSliceIdx);

    // 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.
    pcSlice->setSliceSegmentCurStartCtuTsAddr( m_pcPic->getPicSym()->getCtuRsToTsAddrMap(pcSlice->getSliceSegmentCurStartCtuTsAddr()) );
    pcSlice->setSliceSegmentCurEndCtuTsAddr( m_pcPic->getPicSym()->getCtuRsToTsAddrMap(pcSlice->getSliceSegmentCurEndCtuTsAddr()) );
    if(!pcSlice->getDependentSliceSegmentFlag())
    {
        pcSlice->setSliceCurStartCtuTsAddr(m_pcPic->getPicSym()->getCtuRsToTsAddrMap(pcSlice->getSliceCurStartCtuTsAddr()));
        pcSlice->setSliceCurEndCtuTsAddr(m_pcPic->getPicSym()->getCtuRsToTsAddrMap(pcSlice->getSliceCurEndCtuTsAddr()));
    }

    m_pcPic->setTLayer(nalu.m_temporalId);

    if (!pcSlice->getDependentSliceSegmentFlag())
    {
        pcSlice->checkCRA(pcSlice->getRPS(), m_pocCRA, m_associatedIRAPType, m_cListPic );
        // Set reference list
        pcSlice->setRefPicList( m_cListPic, true );

        // For generalized B
        // note: maybe not existed case (always L0 is copied to L1 if L1 is empty)
        if (pcSlice->isInterB() && pcSlice->getNumRefIdx(REF_PIC_LIST_1) == 0)
        {
            Int iNumRefIdx = pcSlice->getNumRefIdx(REF_PIC_LIST_0);
            pcSlice->setNumRefIdx        ( REF_PIC_LIST_1, iNumRefIdx );

            for (Int iRefIdx = 0; iRefIdx < iNumRefIdx; iRefIdx++)
            {
                pcSlice->setRefPic(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx), REF_PIC_LIST_1, iRefIdx);
            }
        }
        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();
    }

    m_pcPic->setCurrSliceIdx(m_uiSliceIdx);
    if(pcSlice->getSPS()->getScalingListFlag())
    {
        TComScalingList scalingList;
        if(pcSlice->getPPS()->getScalingListPresentFlag())
        {
            scalingList = pcSlice->getPPS()->getScalingList();
        }
        else if (pcSlice->getSPS()->getScalingListPresentFlag())
        {
            scalingList = pcSlice->getSPS()->getScalingList();
        }
        else
        {
            scalingList.setDefaultScalingList();
        }
        m_cTrQuant.setScalingListDec(scalingList, pcSlice->getSPS()->getChromaFormatIdc());
        m_cTrQuant.setUseScalingList(true);
    }
    else
    {
        m_cTrQuant.setFlatScalingList(pcSlice->getSPS()->getChromaFormatIdc());
        m_cTrQuant.setUseScalingList(false);
    }

    //  Decode a picture
    m_cGopDecoder.decompressSlice(nalu.m_Bitstream, m_pcPic);

    m_bFirstSliceInPicture = false;
    m_uiSliceIdx++;

    return false;
}