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); } } }
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; }