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 ¤tTile = *(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 } }
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; }