void DPB::prepareEncode(TComPic *pic) { PPAScopeEvent(DPB_prepareEncode); int pocCurr = pic->getSlice()->getPOC(); m_picList.pushFront(*pic); TComSlice* slice = pic->getSlice(); if (getNalUnitType(pocCurr, m_lastIDR, pic) == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType(pocCurr, m_lastIDR, pic) == NAL_UNIT_CODED_SLICE_IDR_N_LP) { m_lastIDR = pocCurr; } slice->setLastIDR(m_lastIDR); slice->setTemporalLayerNonReferenceFlag(!slice->isReferenced()); // Set the nal unit type slice->setNalUnitType(getNalUnitType(pocCurr, m_lastIDR, pic)); // If the slice is un-referenced, change from _R "referenced" to _N "non-referenced" NAL unit type if (slice->getTemporalLayerNonReferenceFlag()) { switch (slice->getNalUnitType()) { case NAL_UNIT_CODED_SLICE_TRAIL_R: slice->setNalUnitType(NAL_UNIT_CODED_SLICE_TRAIL_N); break; case NAL_UNIT_CODED_SLICE_RADL_R: slice->setNalUnitType(NAL_UNIT_CODED_SLICE_RADL_N); break; case NAL_UNIT_CODED_SLICE_RASL_R: slice->setNalUnitType(NAL_UNIT_CODED_SLICE_RASL_N); break; default: break; } } // Do decoding refresh marking if any decodingRefreshMarking(pocCurr, slice->getNalUnitType()); computeRPS(pocCurr, slice->isIRAP(), slice->getLocalRPS(), slice->getSPS()->getMaxDecPicBuffering(0)); slice->setRPS(slice->getLocalRPS()); slice->setRPSidx(-1); // Force use of RPS from slice, rather than from SPS applyReferencePictureSet(slice->getRPS(), pocCurr); // Mark pictures in m_piclist as unreferenced if they are not included in RPS arrangeLongtermPicturesInRPS(slice); slice->setNumRefIdx(REF_PIC_LIST_0, X265_MIN(m_maxRefL0, slice->getRPS()->getNumberOfNegativePictures())); // Ensuring L0 contains just the -ve POC slice->setNumRefIdx(REF_PIC_LIST_1, X265_MIN(m_maxRefL1, slice->getRPS()->getNumberOfPositivePictures())); slice->setRefPicList(m_picList); // Slice type refinement if ((slice->getSliceType() == B_SLICE) && (slice->getNumRefIdx(REF_PIC_LIST_1) == 0)) { slice->setSliceType(P_SLICE); } if (slice->getSliceType() == B_SLICE) { // TODO: Can we estimate this from lookahead? slice->setColFromL0Flag(0); bool bLowDelay = true; int curPOC = slice->getPOC(); int refIdx = 0; for (refIdx = 0; refIdx < slice->getNumRefIdx(REF_PIC_LIST_0) && bLowDelay; refIdx++) { if (slice->getRefPic(REF_PIC_LIST_0, refIdx)->getPOC() > curPOC) { bLowDelay = false; } } for (refIdx = 0; refIdx < slice->getNumRefIdx(REF_PIC_LIST_1) && bLowDelay; refIdx++) { if (slice->getRefPic(REF_PIC_LIST_1, refIdx)->getPOC() > curPOC) { bLowDelay = false; } } slice->setCheckLDC(bLowDelay); } else { slice->setCheckLDC(true); } slice->setRefPOCList(); slice->setEnableTMVPFlag(1); bool bGPBcheck = false; if (slice->getSliceType() == B_SLICE) { if (slice->getNumRefIdx(REF_PIC_LIST_0) == slice->getNumRefIdx(REF_PIC_LIST_1)) { bGPBcheck = true; for (int i = 0; i < slice->getNumRefIdx(REF_PIC_LIST_1); i++) { if (slice->getRefPOC(REF_PIC_LIST_1, i) != slice->getRefPOC(REF_PIC_LIST_0, i)) { bGPBcheck = false; break; } } } } slice->setMvdL1ZeroFlag(bGPBcheck); slice->setNextSlice(false); /* Increment reference count of all motion-referenced frames. This serves two purposes. First * it prevents the frame from being recycled, and second the referenced frames know how many * other FrameEncoders are using them for motion reference */ int numPredDir = slice->isInterP() ? 1 : slice->isInterB() ? 2 : 0; for (int l = 0; l < numPredDir; l++) { for (int ref = 0; ref < slice->getNumRefIdx(l); ref++) { TComPic *refpic = slice->getRefPic(l, ref); ATOMIC_INC(&refpic->m_countRefEncoders); } } }
Void TDecGop::decompressSlice(TComInputBitstream* pcBitstream, TComPic*& rpcPic) { TComSlice* pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx()); // Table of extracted substreams. // These must be deallocated AND their internal fifos, too. TComInputBitstream **ppcSubstreams = NULL; //-- For time output for each slice long iBeforeTime = clock(); UInt uiStartCUAddr = pcSlice->getSliceSegmentCurStartCUAddr(); UInt uiSliceStartCuAddr = pcSlice->getSliceCurStartCUAddr(); if(uiSliceStartCuAddr == uiStartCUAddr) { m_sliceStartCUAddress.push_back(uiSliceStartCuAddr); } m_pcSbacDecoder->init( (TDecBinIf*)m_pcBinCABAC ); m_pcEntropyDecoder->setEntropyDecoder (m_pcSbacDecoder); UInt uiNumSubstreams = pcSlice->getPPS()->getEntropyCodingSyncEnabledFlag() ? pcSlice->getNumEntryPointOffsets()+1 : pcSlice->getPPS()->getNumSubstreams(); // init each couple {EntropyDecoder, Substream} UInt *puiSubstreamSizes = pcSlice->getSubstreamSizes(); ppcSubstreams = new TComInputBitstream*[uiNumSubstreams]; m_pcSbacDecoders = new TDecSbac[uiNumSubstreams]; m_pcBinCABACs = new TDecBinCABAC[uiNumSubstreams]; for ( UInt ui = 0 ; ui < uiNumSubstreams ; ui++ ) { m_pcSbacDecoders[ui].init(&m_pcBinCABACs[ui]); ppcSubstreams[ui] = pcBitstream->extractSubstream(ui+1 < uiNumSubstreams ? puiSubstreamSizes[ui] : pcBitstream->getNumBitsLeft()); } for ( UInt ui = 0 ; ui+1 < uiNumSubstreams; ui++ ) { m_pcEntropyDecoder->setEntropyDecoder ( &m_pcSbacDecoders[uiNumSubstreams - 1 - ui] ); m_pcEntropyDecoder->setBitstream ( ppcSubstreams [uiNumSubstreams - 1 - ui] ); m_pcEntropyDecoder->resetEntropy (pcSlice); } m_pcEntropyDecoder->setEntropyDecoder ( m_pcSbacDecoder ); m_pcEntropyDecoder->setBitstream ( ppcSubstreams[0] ); m_pcEntropyDecoder->resetEntropy (pcSlice); if(uiSliceStartCuAddr == uiStartCUAddr) { m_LFCrossSliceBoundaryFlag.push_back( pcSlice->getLFCrossSliceBoundaryFlag()); } #if H_3D_NBDV if(pcSlice->getViewIndex() && !pcSlice->getIsDepth()) //Notes from QC: this condition shall be changed once the configuration is completed, e.g. in pcSlice->getSPS()->getMultiviewMvPredMode() || ARP in prev. HTM. Remove this comment once it is done. { Int iColPoc = pcSlice->getRefPOC(RefPicList(1-pcSlice->getColFromL0Flag()), pcSlice->getColRefIdx()); rpcPic->setNumDdvCandPics(rpcPic->getDisCandRefPictures(iColPoc)); } if(pcSlice->getViewIndex() && !pcSlice->getIsDepth() && !pcSlice->isIntra()) //Notes from QC: this condition shall be changed once the configuration is completed, e.g. in pcSlice->getSPS()->getMultiviewMvPredMode() || ARP in prev. HTM. Remove this comment once it is done. { rpcPic->checkTemporalIVRef(); } if(pcSlice->getIsDepth()) { rpcPic->checkTextureRef(); } #endif #if H_3D pcSlice->setDepthToDisparityLUTs(); #endif m_pcSbacDecoders[0].load(m_pcSbacDecoder); m_pcSliceDecoder->decompressSlice( ppcSubstreams, rpcPic, m_pcSbacDecoder, m_pcSbacDecoders); m_pcEntropyDecoder->setBitstream( ppcSubstreams[uiNumSubstreams-1] ); // deallocate all created substreams, including internal buffers. for (UInt ui = 0; ui < uiNumSubstreams; ui++) { ppcSubstreams[ui]->deleteFifo(); delete ppcSubstreams[ui]; } delete[] ppcSubstreams; delete[] m_pcSbacDecoders; m_pcSbacDecoders = NULL; delete[] m_pcBinCABACs; m_pcBinCABACs = NULL; m_dDecTime += (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC; }
Void TDecGop::filterPicture(TComPic*& rpcPic) { TComSlice* pcSlice = rpcPic->getSlice(rpcPic->getCurrSliceIdx()); //-- For time output for each slice long iBeforeTime = clock(); // deblocking filter Bool bLFCrossTileBoundary = pcSlice->getPPS()->getLoopFilterAcrossTilesEnabledFlag(); m_pcLoopFilter->setCfg(bLFCrossTileBoundary); m_pcLoopFilter->loopFilterPic( rpcPic ); if(pcSlice->getSPS()->getUseSAO()) { m_sliceStartCUAddress.push_back(rpcPic->getNumCUsInFrame()* rpcPic->getNumPartInCU()); rpcPic->createNonDBFilterInfo(m_sliceStartCUAddress, 0, &m_LFCrossSliceBoundaryFlag, rpcPic->getPicSym()->getNumTiles(), bLFCrossTileBoundary); } if( pcSlice->getSPS()->getUseSAO() ) { { SAOParam *saoParam = rpcPic->getPicSym()->getSaoParam(); saoParam->bSaoFlag[0] = pcSlice->getSaoEnabledFlag(); saoParam->bSaoFlag[1] = pcSlice->getSaoEnabledFlagChroma(); m_pcSAO->setSaoLcuBasedOptimization(1); m_pcSAO->createPicSaoInfo(rpcPic); m_pcSAO->SAOProcess(saoParam); m_pcSAO->PCMLFDisableProcess(rpcPic); m_pcSAO->destroyPicSaoInfo(); } } if(pcSlice->getSPS()->getUseSAO()) { rpcPic->destroyNonDBFilterInfo(); } #if H_3D rpcPic->compressMotion(2); #endif #if !H_3D rpcPic->compressMotion(); #endif Char c = (pcSlice->isIntra() ? 'I' : pcSlice->isInterP() ? 'P' : 'B'); if (!pcSlice->isReferenced()) c += 32; //-- For time output for each slice #if H_MV printf("\nLayer %2d POC %4d TId: %1d ( %c-SLICE, QP%3d ) ", pcSlice->getLayerId(), pcSlice->getPOC(), pcSlice->getTLayer(), c, pcSlice->getSliceQp() ); #else printf("\nPOC %4d TId: %1d ( %c-SLICE, QP%3d ) ", pcSlice->getPOC(), pcSlice->getTLayer(), c, pcSlice->getSliceQp() ); #endif m_dDecTime += (Double)(clock()-iBeforeTime) / CLOCKS_PER_SEC; printf ("[DT %6.3f] ", m_dDecTime ); m_dDecTime = 0; for (Int iRefList = 0; iRefList < 2; iRefList++) { printf ("[L%d ", iRefList); for (Int iRefIndex = 0; iRefIndex < pcSlice->getNumRefIdx(RefPicList(iRefList)); iRefIndex++) { #if H_MV if( pcSlice->getLayerId() != pcSlice->getRefLayerId( RefPicList(iRefList), iRefIndex ) ) { printf( "V%d ", pcSlice->getRefLayerId( RefPicList(iRefList), iRefIndex ) ); } else { #endif printf ("%d ", pcSlice->getRefPOC(RefPicList(iRefList), iRefIndex)); #if H_MV } #endif } printf ("] "); } if (m_decodedPictureHashSEIEnabled) { SEIMessages pictureHashes = getSeisByType(rpcPic->getSEIs(), SEI::DECODED_PICTURE_HASH ); const SEIDecodedPictureHash *hash = ( pictureHashes.size() > 0 ) ? (SEIDecodedPictureHash*) *(pictureHashes.begin()) : NULL; if (pictureHashes.size() > 1) { printf ("Warning: Got multiple decoded picture hash SEI messages. Using first."); } calcAndPrintHashStatus(*rpcPic->getPicYuvRec(), hash); } rpcPic->setOutputMark(true); rpcPic->setReconMark(true); m_sliceStartCUAddress.clear(); m_LFCrossSliceBoundaryFlag.clear(); }
Bool TDecTop::decode(InputNALUnit& nalu, Int& iSkipFrame, Int& iPOCLastDisplay) { TComPic*& pcPic = m_pcPic; #if E045_SLICE_COMMON_INFO_SHARING static TComPPS* pcNewPPS = NULL; #endif // Initialize entropy decoder m_cEntropyDecoder.setEntropyDecoder (&m_cCavlcDecoder); m_cEntropyDecoder.setBitstream (nalu.m_Bitstream); switch (nalu.m_UnitType) { case NAL_UNIT_SPS: m_cEntropyDecoder.decodeSPS( &m_cSPS ); #if ENABLE_ANAYSIS_OUTPUT TSysuAnalyzerOutput::getInstance()->writeOutSps( &m_cSPS ); #endif #if AMP for (Int i = 0; i < m_cSPS.getMaxCUDepth() - 1; i++) { // m_cSPS.setAMPAcc( i, m_cSPS.getUseAMP() ); m_cSPS.setAMPAcc( i, 1 ); } for (Int i = m_cSPS.getMaxCUDepth() - 1; i < m_cSPS.getMaxCUDepth(); i++) { m_cSPS.setAMPAcc( i, 0 ); } #endif // create ALF temporary buffer m_cAdaptiveLoopFilter.create( m_cSPS.getWidth(), m_cSPS.getHeight(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth ); #if MTK_SAO m_cSAO.create( m_cSPS.getWidth(), m_cSPS.getHeight(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth ); #endif #if PARALLEL_MERGED_DEBLK m_cLoopFilter.create( m_cSPS.getWidth(), m_cSPS.getHeight(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth ); #else m_cLoopFilter. create( g_uiMaxCUDepth ); #endif #if E045_SLICE_COMMON_INFO_SHARING createPPSBuffer(); #endif m_uiValidPS |= 1; return false; case NAL_UNIT_PPS: #if E045_SLICE_COMMON_INFO_SHARING pcNewPPS = getNewPPSBuffer(); #if SUB_LCU_DQP pcNewPPS->setSPS(&m_cSPS); #endif m_cEntropyDecoder.decodePPS( pcNewPPS ); if(pcNewPPS->getSharedPPSInfoEnabled()) { if(m_cSPS.getUseALF()) { m_cEntropyDecoder.decodeAlfParam( pcNewPPS->getSharedAlfParam()); } } signalNewPPSAvailable(); #else #if SUB_LCU_DQP m_cPPS.setSPS(&m_cSPS); #endif m_cEntropyDecoder.decodePPS( &m_cPPS ); #endif m_uiValidPS |= 2; return false; case NAL_UNIT_SEI: m_SEIs = new SEImessages; m_cEntropyDecoder.decodeSEI(*m_SEIs); return false; case NAL_UNIT_CODED_SLICE: case NAL_UNIT_CODED_SLICE_IDR: case NAL_UNIT_CODED_SLICE_CDR: { // make sure we already received both parameter sets assert( 3 == m_uiValidPS ); if (m_bFirstSliceInPicture) { m_apcSlicePilot->initSlice(); m_uiSliceIdx = 0; m_uiLastSliceIdx = 0; #if E045_SLICE_COMMON_INFO_SHARING if(hasNewPPS()) { m_pcPPS = pcNewPPS; updatePPSBuffer(); } #endif } m_apcSlicePilot->setSliceIdx(m_uiSliceIdx); // Read slice header m_apcSlicePilot->setSPS( &m_cSPS ); #if E045_SLICE_COMMON_INFO_SHARING m_apcSlicePilot->setPPS( m_pcPPS ); #else m_apcSlicePilot->setPPS( &m_cPPS ); #endif m_apcSlicePilot->setSliceIdx(m_uiSliceIdx); if (!m_bFirstSliceInPicture) { memcpy(m_apcSlicePilot, pcPic->getPicSym()->getSlice(m_uiSliceIdx-1), sizeof(TComSlice)); } m_apcSlicePilot->setNalUnitType(nalu.m_UnitType); m_apcSlicePilot->setReferenced(nalu.m_RefIDC != NAL_REF_IDC_PRIORITY_LOWEST); m_cEntropyDecoder.decodeSliceHeader (m_apcSlicePilot); if ( m_apcSlicePilot->getSymbolMode() ) { Int numBitsForByteAlignment = nalu.m_Bitstream->getNumBitsUntilByteAligned(); if ( numBitsForByteAlignment > 0 ) { UInt bitsForByteAlignment; nalu.m_Bitstream->read( numBitsForByteAlignment, bitsForByteAlignment ); assert( bitsForByteAlignment == ( ( 1 << numBitsForByteAlignment ) - 1 ) ); } } m_apcSlicePilot->setTLayerInfo(nalu.m_TemporalID); if (m_apcSlicePilot->isNextSlice() && m_apcSlicePilot->getPOC()!=m_uiPrevPOC && !m_bFirstSliceInSequence) { m_uiPrevPOC = m_apcSlicePilot->getPOC(); return true; } if (m_apcSlicePilot->isNextSlice()) m_uiPrevPOC = m_apcSlicePilot->getPOC(); m_bFirstSliceInSequence = false; if (m_apcSlicePilot->isNextSlice()) { // Skip pictures due to random access if (isRandomAccessSkipPicture(iSkipFrame, iPOCLastDisplay)) { return false; } } if (m_bFirstSliceInPicture) { // Buffer initialize for prediction. m_cPrediction.initTempBuff(); // Get a new picture buffer xGetNewPicBuffer (m_apcSlicePilot, pcPic); /* transfer any SEI messages that have been received to the picture */ pcPic->setSEIs(m_SEIs); m_SEIs = NULL; // Recursive structure m_cCuDecoder.create ( g_uiMaxCUDepth, g_uiMaxCUWidth, g_uiMaxCUHeight ); m_cCuDecoder.init ( &m_cEntropyDecoder, &m_cTrQuant, &m_cPrediction ); m_cTrQuant.init ( g_uiMaxCUWidth, g_uiMaxCUHeight, m_apcSlicePilot->getSPS()->getMaxTrSize()); m_cSliceDecoder.create( m_apcSlicePilot, m_apcSlicePilot->getSPS()->getWidth(), m_apcSlicePilot->getSPS()->getHeight(), g_uiMaxCUWidth, g_uiMaxCUHeight, g_uiMaxCUDepth ); } // Set picture slice pointer TComSlice* pcSlice = m_apcSlicePilot; Bool bNextSlice = pcSlice->isNextSlice(); if (m_bFirstSliceInPicture) { if(pcPic->getNumAllocatedSlice() != 1) { pcPic->clearSliceBuffer(); } } else { pcPic->allocateNewSlice(); } assert(pcPic->getNumAllocatedSlice() == (m_uiSliceIdx + 1)); m_apcSlicePilot = pcPic->getPicSym()->getSlice(m_uiSliceIdx); pcPic->getPicSym()->setSlice(pcSlice, m_uiSliceIdx); pcPic->setTLayer(nalu.m_TemporalID); if (bNextSlice) { // Do decoding refresh marking if any pcSlice->decodingRefreshMarking(m_uiPOCCDR, m_bRefreshPending, m_cListPic); // Set reference list pcSlice->setRefPicList( m_cListPic ); // HierP + GPB case if ( m_cSPS.getUseLDC() && pcSlice->isInterB() ) { if(pcSlice->getRefPicListCombinationFlag() && (pcSlice->getNumRefIdx(REF_PIC_LIST_0) > pcSlice->getNumRefIdx(REF_PIC_LIST_1))) { for (Int iRefIdx = 0; iRefIdx < pcSlice->getNumRefIdx(REF_PIC_LIST_1); iRefIdx++) { pcSlice->setRefPic(pcSlice->getRefPic(REF_PIC_LIST_0, iRefIdx), REF_PIC_LIST_1, iRefIdx); } } else { 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); } } } // 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 TMVP_ONE_LIST_CHECK if (pcSlice->isInterB()) { 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; } } 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); } #endif //--------------- pcSlice->setRefPOCList(); if(!pcSlice->getRefPicListModificationFlagLC()) { pcSlice->generateCombinedList(); } pcSlice->setNoBackPredFlag( false ); if ( pcSlice->getSliceType() == B_SLICE && !pcSlice->getRefPicListCombinationFlag()) { if ( pcSlice->getNumRefIdx(RefPicList( 0 ) ) == pcSlice->getNumRefIdx(RefPicList( 1 ) ) ) { pcSlice->setNoBackPredFlag( true ); int i; for ( i=0; i < pcSlice->getNumRefIdx(RefPicList( 1 ) ); i++ ) { if ( pcSlice->getRefPOC(RefPicList(1), i) != pcSlice->getRefPOC(RefPicList(0), i) ) { pcSlice->setNoBackPredFlag( false ); break; } } } } } pcPic->setCurrSliceIdx(m_uiSliceIdx); // Decode a picture #if REF_SETTING_FOR_LD m_cGopDecoder.decompressGop(nalu.m_Bitstream, pcPic, false, m_cListPic ); #else m_cGopDecoder.decompressGop(nalu.m_Bitstream, pcPic, false); #endif m_bFirstSliceInPicture = false; m_uiSliceIdx++; } break; default: assert (1); } return false; }