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(); }
void FrameEncoder::compressFrame() { PPAScopeEvent(FrameEncoder_compressFrame); int64_t startCompressTime = x265_mdate(); TEncEntropy* entropyCoder = getEntropyCoder(0); TComSlice* slice = m_pic->getSlice(); m_nalCount = 0; int qp = slice->getSliceQp(); double lambda = 0; if (slice->getSliceType() == I_SLICE) { lambda = X265_MAX(1, x265_lambda2_tab_I[qp]); } else { lambda = X265_MAX(1, x265_lambda2_non_I[qp]); } // for RDO // in RdCost there is only one lambda because the luma and chroma bits are not separated, // instead we weight the distortion of chroma. int qpc; int chromaQPOffset = slice->getPPS()->getChromaCbQpOffset() + slice->getSliceQpDeltaCb(); qpc = Clip3(0, 57, qp + chromaQPOffset); double cbWeight = pow(2.0, (qp - g_chromaScale[qpc])); // takes into account of the chroma qp mapping and chroma qp Offset chromaQPOffset = slice->getPPS()->getChromaCrQpOffset() + slice->getSliceQpDeltaCr(); qpc = Clip3(0, 57, qp + chromaQPOffset); double crWeight = pow(2.0, (qp - g_chromaScale[qpc])); // takes into account of the chroma qp mapping and chroma qp Offset double chromaLambda = lambda / crWeight; TComPicYuv *fenc = slice->getPic()->getPicYuvOrg(); for (int i = 0; i < m_numRows; i++) { m_rows[i].m_search.setQPLambda(qp, lambda, chromaLambda); m_rows[i].m_search.m_me.setSourcePlane(fenc->getLumaAddr(), fenc->getStride()); m_rows[i].m_rdCost.setLambda(lambda); m_rows[i].m_rdCost.setCbDistortionWeight(cbWeight); m_rows[i].m_rdCost.setCrDistortionWeight(crWeight); } m_frameFilter.m_sao.lumaLambda = lambda; m_frameFilter.m_sao.chromaLambda = chromaLambda; switch (slice->getSliceType()) { case I_SLICE: m_frameFilter.m_sao.depth = 0; break; case P_SLICE: m_frameFilter.m_sao.depth = 1; break; case B_SLICE: m_frameFilter.m_sao.depth = 2 + !slice->isReferenced(); break; } slice->setSliceQpDelta(0); slice->setSliceQpDeltaCb(0); slice->setSliceQpDeltaCr(0); int numSubstreams = m_cfg->param.bEnableWavefront ? m_pic->getPicSym()->getFrameHeightInCU() : 1; // TODO: these two items can likely be FrameEncoder member variables to avoid re-allocs TComOutputBitstream* bitstreamRedirect = new TComOutputBitstream; TComOutputBitstream* outStreams = new TComOutputBitstream[numSubstreams]; if (m_cfg->getUseASR() && !slice->isIntra()) { int pocCurr = slice->getPOC(); int maxSR = m_cfg->param.searchRange; int numPredDir = slice->isInterP() ? 1 : 2; for (int dir = 0; dir <= numPredDir; dir++) { for (int refIdx = 0; refIdx < slice->getNumRefIdx(dir); refIdx++) { int refPOC = slice->getRefPic(dir, refIdx)->getPOC(); int newSR = Clip3(8, maxSR, (maxSR * ADAPT_SR_SCALE * abs(pocCurr - refPOC) + 4) >> 3); for (int i = 0; i < m_numRows; i++) { m_rows[i].m_search.setAdaptiveSearchRange(dir, refIdx, newSR); } } } }
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; }
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; }