Mercurial > hg > forks > libbpg
diff jctvc/TLibCommon/TComSlice.cpp @ 0:772086c29cc7
Initial import.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Wed, 16 Nov 2016 11:16:33 +0200 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jctvc/TLibCommon/TComSlice.cpp Wed Nov 16 11:16:33 2016 +0200 @@ -0,0 +1,2417 @@ +/* The copyright in this software is being made available under the BSD + * License, included below. This software may be subject to other third party + * and contributor rights, including patent rights, and no such rights are + * granted under this license. + * + * Copyright (c) 2010-2014, ITU/ISO/IEC + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * * Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * * Neither the name of the ITU/ISO/IEC nor the names of its contributors may + * be used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** \file TComSlice.cpp + \brief slice header and SPS class +*/ + +#include "CommonDef.h" +#include "TComSlice.h" +#include "TComPic.h" +#include "TLibEncoder/TEncSbac.h" +//#include "TLibDecoder/TDecSbac.h" + + +//! \ingroup TLibCommon +//! \{ + +TComSlice::TComSlice() +: m_iPPSId ( -1 ) +, m_PicOutputFlag ( true ) +, m_iPOC ( 0 ) +, m_iLastIDR ( 0 ) +, m_iAssociatedIRAP ( 0 ) +, m_iAssociatedIRAPType ( NAL_UNIT_INVALID ) +, m_pcRPS ( 0 ) +, m_LocalRPS ( ) +, m_iBDidx ( 0 ) +, m_RefPicListModification ( ) +, m_eNalUnitType ( NAL_UNIT_CODED_SLICE_IDR_W_RADL ) +, m_eSliceType ( I_SLICE ) +, m_iSliceQp ( 0 ) +, m_dependentSliceSegmentFlag ( false ) +#if ADAPTIVE_QP_SELECTION +, m_iSliceQpBase ( 0 ) +#endif +, m_ChromaQpAdjEnabled ( false ) +, m_deblockingFilterDisable ( false ) +, m_deblockingFilterOverrideFlag ( false ) +, m_deblockingFilterBetaOffsetDiv2( 0 ) +, m_deblockingFilterTcOffsetDiv2 ( 0 ) +, m_bCheckLDC ( false ) +, m_iSliceQpDelta ( 0 ) +, m_iDepth ( 0 ) +, m_bRefenced ( false ) +, m_pcVPS ( NULL ) +, m_pcSPS ( NULL ) +, m_pcPPS ( NULL ) +, m_pcPic ( NULL ) +#if ADAPTIVE_QP_SELECTION +, m_pcTrQuant ( NULL ) +#endif +, m_colFromL0Flag ( 1 ) +, m_noOutputPriorPicsFlag ( false ) +, m_noRaslOutputFlag ( false ) +, m_handleCraAsBlaFlag ( false ) +, m_colRefIdx ( 0 ) +, m_maxNumMergeCand ( 0 ) +, m_uiTLayer ( 0 ) +, m_bTLayerSwitchingFlag ( false ) +, m_sliceMode ( NO_SLICES ) +, m_sliceArgument ( 0 ) +, m_sliceCurStartCtuTsAddr ( 0 ) +, m_sliceCurEndCtuTsAddr ( 0 ) +, m_sliceIdx ( 0 ) +, m_sliceSegmentMode ( NO_SLICES ) +, m_sliceSegmentArgument ( 0 ) +, m_sliceSegmentCurStartCtuTsAddr ( 0 ) +, m_sliceSegmentCurEndCtuTsAddr ( 0 ) +, m_nextSlice ( false ) +, m_nextSliceSegment ( false ) +, m_sliceBits ( 0 ) +, m_sliceSegmentBits ( 0 ) +, m_bFinalized ( false ) +, m_substreamSizes ( ) +, m_scalingList ( NULL ) +, m_cabacInitFlag ( false ) +, m_bLMvdL1Zero ( false ) +, m_temporalLayerNonReferenceFlag ( false ) +, m_LFCrossSliceBoundaryFlag ( false ) +, m_enableTMVPFlag ( true ) +{ + for(UInt i=0; i<NUM_REF_PIC_LIST_01; i++) + { + m_aiNumRefIdx[i] = 0; + } + + for (UInt component = 0; component < MAX_NUM_COMPONENT; component++) + { + m_lambdas [component] = 0.0; + m_iSliceChromaQpDelta[component] = 0; + } + + initEqualRef(); + + for ( Int idx = 0; idx < MAX_NUM_REF; idx++ ) + { + m_list1IdxToList0Idx[idx] = -1; + } + + for(Int iNumCount = 0; iNumCount < MAX_NUM_REF; iNumCount++) + { + for(UInt i=0; i<NUM_REF_PIC_LIST_01; i++) + { + m_apcRefPicList [i][iNumCount] = NULL; + m_aiRefPOCList [i][iNumCount] = 0; + } + } + + resetWpScaling(); + initWpAcDcParam(); + + for(Int ch=0; ch < MAX_NUM_CHANNEL_TYPE; ch++) + { + m_saoEnabledFlag[ch] = false; + } +} + +TComSlice::~TComSlice() +{ +} + + +Void TComSlice::initSlice() +{ + for(UInt i=0; i<NUM_REF_PIC_LIST_01; i++) + { + m_aiNumRefIdx[i] = 0; + } + m_colFromL0Flag = 1; + + m_colRefIdx = 0; + initEqualRef(); + + m_bCheckLDC = false; + + for (UInt component = 0; component < MAX_NUM_COMPONENT; component++) m_iSliceChromaQpDelta[component] = 0; + + m_maxNumMergeCand = MRG_MAX_NUM_CANDS; + + m_bFinalized=false; + + m_substreamSizes.clear(); + m_cabacInitFlag = false; + m_enableTMVPFlag = true; +} + +Bool TComSlice::getRapPicFlag() +{ + return getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL + || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP + || getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA; +} + + +Void TComSlice::sortPicList (TComList<TComPic*>& rcListPic) +{ + TComPic* pcPicExtract; + TComPic* pcPicInsert; + + TComList<TComPic*>::iterator iterPicExtract; + TComList<TComPic*>::iterator iterPicExtract_1; + TComList<TComPic*>::iterator iterPicInsert; + + for (Int i = 1; i < (Int)(rcListPic.size()); i++) + { + iterPicExtract = rcListPic.begin(); + for (Int j = 0; j < i; j++) iterPicExtract++; + pcPicExtract = *(iterPicExtract); + pcPicExtract->setCurrSliceIdx(0); + + iterPicInsert = rcListPic.begin(); + while (iterPicInsert != iterPicExtract) + { + pcPicInsert = *(iterPicInsert); + pcPicInsert->setCurrSliceIdx(0); + if (pcPicInsert->getPOC() >= pcPicExtract->getPOC()) + { + break; + } + + iterPicInsert++; + } + + iterPicExtract_1 = iterPicExtract; iterPicExtract_1++; + + // swap iterPicExtract and iterPicInsert, iterPicExtract = curr. / iterPicInsert = insertion position + rcListPic.insert (iterPicInsert, iterPicExtract, iterPicExtract_1); + rcListPic.erase (iterPicExtract); + } +} + +TComPic* TComSlice::xGetRefPic (TComList<TComPic*>& rcListPic, Int poc) +{ + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + TComPic* pcPic = *(iterPic); + while ( iterPic != rcListPic.end() ) + { + if(pcPic->getPOC() == poc) + { + break; + } + iterPic++; + pcPic = *(iterPic); + } + return pcPic; +} + + +TComPic* TComSlice::xGetLongTermRefPic(TComList<TComPic*>& rcListPic, Int poc, Bool pocHasMsb) +{ + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + TComPic* pcPic = *(iterPic); + TComPic* pcStPic = pcPic; + + Int pocCycle = 1 << getSPS()->getBitsForPOC(); + if (!pocHasMsb) + { + poc = poc & (pocCycle - 1); + } + + while ( iterPic != rcListPic.end() ) + { + pcPic = *(iterPic); + if (pcPic && pcPic->getPOC()!=this->getPOC() && pcPic->getSlice( 0 )->isReferenced()) + { + Int picPoc = pcPic->getPOC(); + if (!pocHasMsb) + { + picPoc = picPoc & (pocCycle - 1); + } + + if (poc == picPoc) + { + if(pcPic->getIsLongTerm()) + { + return pcPic; + } + else + { + pcStPic = pcPic; + } + break; + } + } + + iterPic++; + } + + return pcStPic; +} + +Void TComSlice::setRefPOCList () +{ + for (Int iDir = 0; iDir < NUM_REF_PIC_LIST_01; iDir++) + { + for (Int iNumRefIdx = 0; iNumRefIdx < m_aiNumRefIdx[iDir]; iNumRefIdx++) + { + m_aiRefPOCList[iDir][iNumRefIdx] = m_apcRefPicList[iDir][iNumRefIdx]->getPOC(); + } + } + +} + +Void TComSlice::setList1IdxToList0Idx() +{ + Int idxL0, idxL1; + for ( idxL1 = 0; idxL1 < getNumRefIdx( REF_PIC_LIST_1 ); idxL1++ ) + { + m_list1IdxToList0Idx[idxL1] = -1; + for ( idxL0 = 0; idxL0 < getNumRefIdx( REF_PIC_LIST_0 ); idxL0++ ) + { + if ( m_apcRefPicList[REF_PIC_LIST_0][idxL0]->getPOC() == m_apcRefPicList[REF_PIC_LIST_1][idxL1]->getPOC() ) + { + m_list1IdxToList0Idx[idxL1] = idxL0; + break; + } + } + } +} + +Void TComSlice::setRefPicList( TComList<TComPic*>& rcListPic, Bool checkNumPocTotalCurr ) +{ + if (!checkNumPocTotalCurr) + { + if (m_eSliceType == I_SLICE) + { + ::memset( m_apcRefPicList, 0, sizeof (m_apcRefPicList)); + ::memset( m_aiNumRefIdx, 0, sizeof ( m_aiNumRefIdx )); + + return; + } + + m_aiNumRefIdx[REF_PIC_LIST_0] = getNumRefIdx(REF_PIC_LIST_0); + m_aiNumRefIdx[REF_PIC_LIST_1] = getNumRefIdx(REF_PIC_LIST_1); + } + + TComPic* pcRefPic= NULL; + static const UInt MAX_NUM_NEGATIVE_PICTURES=16; + TComPic* RefPicSetStCurr0[MAX_NUM_NEGATIVE_PICTURES]; + TComPic* RefPicSetStCurr1[MAX_NUM_NEGATIVE_PICTURES]; + TComPic* RefPicSetLtCurr[MAX_NUM_NEGATIVE_PICTURES]; + UInt NumPocStCurr0 = 0; + UInt NumPocStCurr1 = 0; + UInt NumPocLtCurr = 0; + Int i; + + for(i=0; i < m_pcRPS->getNumberOfNegativePictures(); i++) + { + if(m_pcRPS->getUsed(i)) + { + pcRefPic = xGetRefPic(rcListPic, getPOC()+m_pcRPS->getDeltaPOC(i)); + pcRefPic->setIsLongTerm(0); + pcRefPic->getPicYuvRec()->extendPicBorder(); + RefPicSetStCurr0[NumPocStCurr0] = pcRefPic; + NumPocStCurr0++; + pcRefPic->setCheckLTMSBPresent(false); + } + } + + for(; i < m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures(); i++) + { + if(m_pcRPS->getUsed(i)) + { + pcRefPic = xGetRefPic(rcListPic, getPOC()+m_pcRPS->getDeltaPOC(i)); + pcRefPic->setIsLongTerm(0); + pcRefPic->getPicYuvRec()->extendPicBorder(); + RefPicSetStCurr1[NumPocStCurr1] = pcRefPic; + NumPocStCurr1++; + pcRefPic->setCheckLTMSBPresent(false); + } + } + + for(i = m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures()+m_pcRPS->getNumberOfLongtermPictures()-1; i > m_pcRPS->getNumberOfNegativePictures()+m_pcRPS->getNumberOfPositivePictures()-1 ; i--) + { + if(m_pcRPS->getUsed(i)) + { + pcRefPic = xGetLongTermRefPic(rcListPic, m_pcRPS->getPOC(i), m_pcRPS->getCheckLTMSBPresent(i)); + pcRefPic->setIsLongTerm(1); + pcRefPic->getPicYuvRec()->extendPicBorder(); + RefPicSetLtCurr[NumPocLtCurr] = pcRefPic; + NumPocLtCurr++; + } + if(pcRefPic==NULL) + { + pcRefPic = xGetLongTermRefPic(rcListPic, m_pcRPS->getPOC(i), m_pcRPS->getCheckLTMSBPresent(i)); + } + pcRefPic->setCheckLTMSBPresent(m_pcRPS->getCheckLTMSBPresent(i)); + } + + // ref_pic_list_init + TComPic* rpsCurrList0[MAX_NUM_REF+1]; + TComPic* rpsCurrList1[MAX_NUM_REF+1]; + Int numPocTotalCurr = NumPocStCurr0 + NumPocStCurr1 + NumPocLtCurr; + + if (checkNumPocTotalCurr) + { + // The variable NumPocTotalCurr is derived as specified in subclause 7.4.7.2. It is a requirement of bitstream conformance that the following applies to the value of NumPocTotalCurr: + // - If the current picture is a BLA or CRA picture, the value of NumPocTotalCurr shall be equal to 0. + // - Otherwise, when the current picture contains a P or B slice, the value of NumPocTotalCurr shall not be equal to 0. + if (getRapPicFlag()) + { + assert(numPocTotalCurr == 0); + } + + if (m_eSliceType == I_SLICE) + { + ::memset( m_apcRefPicList, 0, sizeof (m_apcRefPicList)); + ::memset( m_aiNumRefIdx, 0, sizeof ( m_aiNumRefIdx )); + + return; + } + + assert(numPocTotalCurr > 0); + + m_aiNumRefIdx[0] = getNumRefIdx(REF_PIC_LIST_0); + m_aiNumRefIdx[1] = getNumRefIdx(REF_PIC_LIST_1); + } + + Int cIdx = 0; + for ( i=0; i<NumPocStCurr0; i++, cIdx++) + { + rpsCurrList0[cIdx] = RefPicSetStCurr0[i]; + } + for ( i=0; i<NumPocStCurr1; i++, cIdx++) + { + rpsCurrList0[cIdx] = RefPicSetStCurr1[i]; + } + for ( i=0; i<NumPocLtCurr; i++, cIdx++) + { + rpsCurrList0[cIdx] = RefPicSetLtCurr[i]; + } + assert(cIdx == numPocTotalCurr); + + if (m_eSliceType==B_SLICE) + { + cIdx = 0; + for ( i=0; i<NumPocStCurr1; i++, cIdx++) + { + rpsCurrList1[cIdx] = RefPicSetStCurr1[i]; + } + for ( i=0; i<NumPocStCurr0; i++, cIdx++) + { + rpsCurrList1[cIdx] = RefPicSetStCurr0[i]; + } + for ( i=0; i<NumPocLtCurr; i++, cIdx++) + { + rpsCurrList1[cIdx] = RefPicSetLtCurr[i]; + } + assert(cIdx == numPocTotalCurr); + } + + ::memset(m_bIsUsedAsLongTerm, 0, sizeof(m_bIsUsedAsLongTerm)); + + for (Int rIdx = 0; rIdx < m_aiNumRefIdx[REF_PIC_LIST_0]; rIdx ++) + { + cIdx = m_RefPicListModification.getRefPicListModificationFlagL0() ? m_RefPicListModification.getRefPicSetIdxL0(rIdx) : rIdx % numPocTotalCurr; + assert(cIdx >= 0 && cIdx < numPocTotalCurr); + m_apcRefPicList[REF_PIC_LIST_0][rIdx] = rpsCurrList0[ cIdx ]; + m_bIsUsedAsLongTerm[REF_PIC_LIST_0][rIdx] = ( cIdx >= NumPocStCurr0 + NumPocStCurr1 ); + } + if ( m_eSliceType != B_SLICE ) + { + m_aiNumRefIdx[REF_PIC_LIST_1] = 0; + ::memset( m_apcRefPicList[REF_PIC_LIST_1], 0, sizeof(m_apcRefPicList[REF_PIC_LIST_1])); + } + else + { + for (Int rIdx = 0; rIdx < m_aiNumRefIdx[REF_PIC_LIST_1]; rIdx ++) + { + cIdx = m_RefPicListModification.getRefPicListModificationFlagL1() ? m_RefPicListModification.getRefPicSetIdxL1(rIdx) : rIdx % numPocTotalCurr; + assert(cIdx >= 0 && cIdx < numPocTotalCurr); + m_apcRefPicList[REF_PIC_LIST_1][rIdx] = rpsCurrList1[ cIdx ]; + m_bIsUsedAsLongTerm[REF_PIC_LIST_1][rIdx] = ( cIdx >= NumPocStCurr0 + NumPocStCurr1 ); + } + } +} + +Int TComSlice::getNumRpsCurrTempList() +{ + Int numRpsCurrTempList = 0; + + if (m_eSliceType == I_SLICE) + { + return 0; + } + for(UInt i=0; i < m_pcRPS->getNumberOfNegativePictures()+ m_pcRPS->getNumberOfPositivePictures() + m_pcRPS->getNumberOfLongtermPictures(); i++) + { + if(m_pcRPS->getUsed(i)) + { + numRpsCurrTempList++; + } + } + return numRpsCurrTempList; +} + +Void TComSlice::initEqualRef() +{ + for (Int iDir = 0; iDir < NUM_REF_PIC_LIST_01; iDir++) + { + for (Int iRefIdx1 = 0; iRefIdx1 < MAX_NUM_REF; iRefIdx1++) + { + for (Int iRefIdx2 = iRefIdx1; iRefIdx2 < MAX_NUM_REF; iRefIdx2++) + { + m_abEqualRef[iDir][iRefIdx1][iRefIdx2] = m_abEqualRef[iDir][iRefIdx2][iRefIdx1] = (iRefIdx1 == iRefIdx2? true : false); + } + } + } +} + +Void TComSlice::checkColRefIdx(UInt curSliceIdx, TComPic* pic) +{ + Int i; + TComSlice* curSlice = pic->getSlice(curSliceIdx); + Int currColRefPOC = curSlice->getRefPOC( RefPicList(1 - curSlice->getColFromL0Flag()), curSlice->getColRefIdx()); + TComSlice* preSlice; + Int preColRefPOC; + for(i=curSliceIdx-1; i>=0; i--) + { + preSlice = pic->getSlice(i); + if(preSlice->getSliceType() != I_SLICE) + { + preColRefPOC = preSlice->getRefPOC( RefPicList(1 - preSlice->getColFromL0Flag()), preSlice->getColRefIdx()); + if(currColRefPOC != preColRefPOC) + { + printf("Collocated_ref_idx shall always be the same for all slices of a coded picture!\n"); + exit(EXIT_FAILURE); + } + else + { + break; + } + } + } +} + +Void TComSlice::checkCRA(TComReferencePictureSet *pReferencePictureSet, Int& pocCRA, NalUnitType& associatedIRAPType, TComList<TComPic *>& rcListPic) +{ + for(Int i = 0; i < pReferencePictureSet->getNumberOfNegativePictures()+pReferencePictureSet->getNumberOfPositivePictures(); i++) + { + if(pocCRA < MAX_UINT && getPOC() > pocCRA) + { + assert(getPOC()+pReferencePictureSet->getDeltaPOC(i) >= pocCRA); + } + } + for(Int i = pReferencePictureSet->getNumberOfNegativePictures()+pReferencePictureSet->getNumberOfPositivePictures(); i < pReferencePictureSet->getNumberOfPictures(); i++) + { + if(pocCRA < MAX_UINT && getPOC() > pocCRA) + { + if (!pReferencePictureSet->getCheckLTMSBPresent(i)) + { + assert(xGetLongTermRefPic(rcListPic, pReferencePictureSet->getPOC(i), false)->getPOC() >= pocCRA); + } + else + { + assert(pReferencePictureSet->getPOC(i) >= pocCRA); + } + } + } + if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) // IDR picture found + { + pocCRA = getPOC(); + associatedIRAPType = getNalUnitType(); + } + else if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // CRA picture found + { + pocCRA = getPOC(); + associatedIRAPType = getNalUnitType(); + } + else if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP ) // BLA picture found + { + pocCRA = getPOC(); + associatedIRAPType = getNalUnitType(); + } +} + +/** Function for marking the reference pictures when an IDR/CRA/CRANT/BLA/BLANT is encountered. + * \param pocCRA POC of the CRA/CRANT/BLA/BLANT picture + * \param bRefreshPending flag indicating if a deferred decoding refresh is pending + * \param rcListPic reference to the reference picture list + * This function marks the reference pictures as "unused for reference" in the following conditions. + * If the nal_unit_type is IDR/BLA/BLANT, all pictures in the reference picture list + * are marked as "unused for reference" + * If the nal_unit_type is BLA/BLANT, set the pocCRA to the temporal reference of the current picture. + * Otherwise + * If the bRefreshPending flag is true (a deferred decoding refresh is pending) and the current + * temporal reference is greater than the temporal reference of the latest CRA/CRANT/BLA/BLANT picture (pocCRA), + * mark all reference pictures except the latest CRA/CRANT/BLA/BLANT picture as "unused for reference" and set + * the bRefreshPending flag to false. + * If the nal_unit_type is CRA/CRANT, set the bRefreshPending flag to true and pocCRA to the temporal + * reference of the current picture. + * Note that the current picture is already placed in the reference list and its marking is not changed. + * If the current picture has a nal_ref_idc that is not 0, it will remain marked as "used for reference". + */ +Void TComSlice::decodingRefreshMarking(Int& pocCRA, Bool& bRefreshPending, TComList<TComPic*>& rcListPic) +{ + TComPic* rpcPic; + Int pocCurr = getPOC(); + + if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP + || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL + || getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP ) // IDR or BLA picture + { + // mark all pictures as not used for reference + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while (iterPic != rcListPic.end()) + { + rpcPic = *(iterPic); + rpcPic->setCurrSliceIdx(0); + if (rpcPic->getPOC() != pocCurr) rpcPic->getSlice(0)->setReferenced(false); + iterPic++; + } + if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL + || getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP ) + { + pocCRA = pocCurr; + } +#if EFFICIENT_FIELD_IRAP + bRefreshPending = true; +#endif + } + else // CRA or No DR + { +#if EFFICIENT_FIELD_IRAP + if(getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL) + { + if (bRefreshPending==true && pocCurr > m_iLastIDR) // IDR reference marking pending + { + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while (iterPic != rcListPic.end()) + { + rpcPic = *(iterPic); + if (rpcPic->getPOC() != pocCurr && rpcPic->getPOC() != m_iLastIDR) + { + rpcPic->getSlice(0)->setReferenced(false); + } + iterPic++; + } + bRefreshPending = false; + } + } + else + { +#endif + if (bRefreshPending==true && pocCurr > pocCRA) // CRA reference marking pending + { + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while (iterPic != rcListPic.end()) + { + rpcPic = *(iterPic); + if (rpcPic->getPOC() != pocCurr && rpcPic->getPOC() != pocCRA) + { + rpcPic->getSlice(0)->setReferenced(false); + } + iterPic++; + } + bRefreshPending = false; + } +#if EFFICIENT_FIELD_IRAP + } +#endif + if ( getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA ) // CRA picture found + { + bRefreshPending = true; + pocCRA = pocCurr; + } + } +} + +Void TComSlice::copySliceInfo(TComSlice *pSrc) +{ + assert( pSrc != NULL ); + + Int i, j, k; + + m_iPOC = pSrc->m_iPOC; + m_eNalUnitType = pSrc->m_eNalUnitType; + m_eSliceType = pSrc->m_eSliceType; + m_iSliceQp = pSrc->m_iSliceQp; +#if ADAPTIVE_QP_SELECTION + m_iSliceQpBase = pSrc->m_iSliceQpBase; +#endif + m_ChromaQpAdjEnabled = pSrc->m_ChromaQpAdjEnabled; + m_deblockingFilterDisable = pSrc->m_deblockingFilterDisable; + m_deblockingFilterOverrideFlag = pSrc->m_deblockingFilterOverrideFlag; + m_deblockingFilterBetaOffsetDiv2 = pSrc->m_deblockingFilterBetaOffsetDiv2; + m_deblockingFilterTcOffsetDiv2 = pSrc->m_deblockingFilterTcOffsetDiv2; + + for (i = 0; i < NUM_REF_PIC_LIST_01; i++) + { + m_aiNumRefIdx[i] = pSrc->m_aiNumRefIdx[i]; + } + + for (i = 0; i < MAX_NUM_REF; i++) + { + m_list1IdxToList0Idx[i] = pSrc->m_list1IdxToList0Idx[i]; + } + + m_bCheckLDC = pSrc->m_bCheckLDC; + m_iSliceQpDelta = pSrc->m_iSliceQpDelta; + for (UInt component = 0; component < MAX_NUM_COMPONENT; component++) m_iSliceChromaQpDelta[component] = pSrc->m_iSliceChromaQpDelta[component]; + for (i = 0; i < NUM_REF_PIC_LIST_01; i++) + { + for (j = 0; j < MAX_NUM_REF; j++) + { + m_apcRefPicList[i][j] = pSrc->m_apcRefPicList[i][j]; + m_aiRefPOCList[i][j] = pSrc->m_aiRefPOCList[i][j]; + m_bIsUsedAsLongTerm[i][j] = pSrc->m_bIsUsedAsLongTerm[i][j]; + } + m_bIsUsedAsLongTerm[i][MAX_NUM_REF] = pSrc->m_bIsUsedAsLongTerm[i][MAX_NUM_REF]; + } + m_iDepth = pSrc->m_iDepth; + + // referenced slice + m_bRefenced = pSrc->m_bRefenced; + + // access channel + m_pcSPS = pSrc->m_pcSPS; + m_pcPPS = pSrc->m_pcPPS; + m_pcRPS = pSrc->m_pcRPS; + m_iLastIDR = pSrc->m_iLastIDR; + + m_pcPic = pSrc->m_pcPic; + + m_colFromL0Flag = pSrc->m_colFromL0Flag; + m_colRefIdx = pSrc->m_colRefIdx; + + setLambdas(pSrc->getLambdas()); + + for (i = 0; i < NUM_REF_PIC_LIST_01; i++) + { + for (j = 0; j < MAX_NUM_REF; j++) + { + for (k =0; k < MAX_NUM_REF; k++) + { + m_abEqualRef[i][j][k] = pSrc->m_abEqualRef[i][j][k]; + } + } + } + + m_uiTLayer = pSrc->m_uiTLayer; + m_bTLayerSwitchingFlag = pSrc->m_bTLayerSwitchingFlag; + + m_sliceMode = pSrc->m_sliceMode; + m_sliceArgument = pSrc->m_sliceArgument; + m_sliceCurStartCtuTsAddr = pSrc->m_sliceCurStartCtuTsAddr; + m_sliceCurEndCtuTsAddr = pSrc->m_sliceCurEndCtuTsAddr; + m_sliceIdx = pSrc->m_sliceIdx; + m_sliceSegmentMode = pSrc->m_sliceSegmentMode; + m_sliceSegmentArgument = pSrc->m_sliceSegmentArgument; + m_sliceSegmentCurStartCtuTsAddr = pSrc->m_sliceSegmentCurStartCtuTsAddr; + m_sliceSegmentCurEndCtuTsAddr = pSrc->m_sliceSegmentCurEndCtuTsAddr; + m_nextSlice = pSrc->m_nextSlice; + m_nextSliceSegment = pSrc->m_nextSliceSegment; + + for ( UInt e=0 ; e<NUM_REF_PIC_LIST_01 ; e++ ) + { + for ( UInt n=0 ; n<MAX_NUM_REF ; n++ ) + { + memcpy(m_weightPredTable[e][n], pSrc->m_weightPredTable[e][n], sizeof(WPScalingParam)*MAX_NUM_COMPONENT ); + } + } + + for( UInt ch = 0 ; ch < MAX_NUM_CHANNEL_TYPE; ch++) + { + m_saoEnabledFlag[ch] = pSrc->m_saoEnabledFlag[ch]; + } + + m_cabacInitFlag = pSrc->m_cabacInitFlag; + + m_bLMvdL1Zero = pSrc->m_bLMvdL1Zero; + m_LFCrossSliceBoundaryFlag = pSrc->m_LFCrossSliceBoundaryFlag; + m_enableTMVPFlag = pSrc->m_enableTMVPFlag; + m_maxNumMergeCand = pSrc->m_maxNumMergeCand; +} + + +Int TComSlice::m_prevTid0POC = 0; + +/** Function for setting the slice's temporal layer ID and corresponding temporal_layer_switching_point_flag. + * \param uiTLayer Temporal layer ID of the current slice + * The decoder calls this function to set temporal_layer_switching_point_flag for each temporal layer based on + * the SPS's temporal_id_nesting_flag and the parsed PPS. Then, current slice's temporal layer ID and + * temporal_layer_switching_point_flag is set accordingly. + */ +Void TComSlice::setTLayerInfo( UInt uiTLayer ) +{ + m_uiTLayer = uiTLayer; +} + +/** Function for checking if this is a switching-point +*/ +Bool TComSlice::isTemporalLayerSwitchingPoint(TComList<TComPic*>& rcListPic) +{ + TComPic* rpcPic; + // loop through all pictures in the reference picture buffer + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); + if(rpcPic->getSlice(0)->isReferenced() && rpcPic->getPOC() != getPOC()) + { + if(rpcPic->getTLayer() >= getTLayer()) + { + return false; + } + } + } + return true; +} + +/** Function for checking if this is a STSA candidate + */ +Bool TComSlice::isStepwiseTemporalLayerSwitchingPointCandidate(TComList<TComPic*>& rcListPic) +{ + TComPic* rpcPic; + + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); + if(rpcPic->getSlice(0)->isReferenced() && (rpcPic->getUsedByCurr()==true) && rpcPic->getPOC() != getPOC()) + { + if(rpcPic->getTLayer() >= getTLayer()) + { + return false; + } + } + } + return true; +} + + +Void TComSlice::checkLeadingPictureRestrictions(TComList<TComPic*>& rcListPic) +{ + TComPic* rpcPic; + + Int nalUnitType = this->getNalUnitType(); + + // When a picture is a leading picture, it shall be a RADL or RASL picture. + if(this->getAssociatedIRAPPOC() > this->getPOC()) + { + // Do not check IRAP pictures since they may get a POC lower than their associated IRAP + if(nalUnitType < NAL_UNIT_CODED_SLICE_BLA_W_LP || + nalUnitType > NAL_UNIT_RESERVED_IRAP_VCL23) + { + assert(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R || + nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R); + } + } + + // When a picture is a trailing picture, it shall not be a RADL or RASL picture. + if(this->getAssociatedIRAPPOC() < this->getPOC()) + { + assert(nalUnitType != NAL_UNIT_CODED_SLICE_RASL_N && + nalUnitType != NAL_UNIT_CODED_SLICE_RASL_R && + nalUnitType != NAL_UNIT_CODED_SLICE_RADL_N && + nalUnitType != NAL_UNIT_CODED_SLICE_RADL_R); + } + + // No RASL pictures shall be present in the bitstream that are associated + // with a BLA picture having nal_unit_type equal to BLA_W_RADL or BLA_N_LP. + if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R) + { + assert(this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_BLA_W_RADL && + this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_BLA_N_LP); + } + + // No RASL pictures shall be present in the bitstream that are associated with + // an IDR picture. + if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R) + { + assert(this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_IDR_N_LP && + this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_IDR_W_RADL); + } + + // No RADL pictures shall be present in the bitstream that are associated with + // a BLA picture having nal_unit_type equal to BLA_N_LP or that are associated + // with an IDR picture having nal_unit_type equal to IDR_N_LP. + if(nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R) + { + assert(this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_BLA_N_LP && + this->getAssociatedIRAPType() != NAL_UNIT_CODED_SLICE_IDR_N_LP); + } + + // loop through all pictures in the reference picture buffer + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); +#if BUGFIX_INTRAPERIOD + if(!rpcPic->getReconMark()) + { + continue; + } +#endif + if (rpcPic->getPOC() == this->getPOC()) + { + continue; + } + + // Any picture that has PicOutputFlag equal to 1 that precedes an IRAP picture + // in decoding order shall precede the IRAP picture in output order. + // (Note that any picture following in output order would be present in the DPB) + if(rpcPic->getSlice(0)->getPicOutputFlag() == 1 && !this->getNoOutputPriorPicsFlag()) + { + if(nalUnitType == NAL_UNIT_CODED_SLICE_BLA_N_LP || + nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_LP || + nalUnitType == NAL_UNIT_CODED_SLICE_BLA_W_RADL || + nalUnitType == NAL_UNIT_CODED_SLICE_CRA || + nalUnitType == NAL_UNIT_CODED_SLICE_IDR_N_LP || + nalUnitType == NAL_UNIT_CODED_SLICE_IDR_W_RADL) + { + assert(rpcPic->getPOC() < this->getPOC()); + } + } + + // Any picture that has PicOutputFlag equal to 1 that precedes an IRAP picture + // in decoding order shall precede any RADL picture associated with the IRAP + // picture in output order. + if(rpcPic->getSlice(0)->getPicOutputFlag() == 1) + { + if((nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R)) + { + // rpcPic precedes the IRAP in decoding order + if(this->getAssociatedIRAPPOC() > rpcPic->getSlice(0)->getAssociatedIRAPPOC()) + { + // rpcPic must not be the IRAP picture + if(this->getAssociatedIRAPPOC() != rpcPic->getPOC()) + { + assert(rpcPic->getPOC() < this->getPOC()); + } + } + } + } + + // When a picture is a leading picture, it shall precede, in decoding order, + // all trailing pictures that are associated with the same IRAP picture. + if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R || + nalUnitType == NAL_UNIT_CODED_SLICE_RADL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RADL_R) + { + if(rpcPic->getSlice(0)->getAssociatedIRAPPOC() == this->getAssociatedIRAPPOC()) + { + // rpcPic is a picture that preceded the leading in decoding order since it exist in the DPB + // rpcPic would violate the constraint if it was a trailing picture + assert(rpcPic->getPOC() <= this->getAssociatedIRAPPOC()); + } + } + + // Any RASL picture associated with a CRA or BLA picture shall precede any + // RADL picture associated with the CRA or BLA picture in output order + if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R) + { + if((this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || + this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || + this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || + this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_CRA) && + this->getAssociatedIRAPPOC() == rpcPic->getSlice(0)->getAssociatedIRAPPOC()) + { + if(rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_N || + rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_RADL_R) + { + assert(rpcPic->getPOC() > this->getPOC()); + } + } + } + + // Any RASL picture associated with a CRA picture shall follow, in output + // order, any IRAP picture that precedes the CRA picture in decoding order. + if(nalUnitType == NAL_UNIT_CODED_SLICE_RASL_N || + nalUnitType == NAL_UNIT_CODED_SLICE_RASL_R) + { + if(this->getAssociatedIRAPType() == NAL_UNIT_CODED_SLICE_CRA) + { + if(rpcPic->getSlice(0)->getPOC() < this->getAssociatedIRAPPOC() && + (rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_N_LP || + rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_LP || + rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_BLA_W_RADL || + rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_N_LP || + rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR_W_RADL || + rpcPic->getSlice(0)->getNalUnitType() == NAL_UNIT_CODED_SLICE_CRA)) + { + assert(this->getPOC() > rpcPic->getSlice(0)->getPOC()); + } + } + } + } +} + + + +/** Function for applying picture marking based on the Reference Picture Set in pReferencePictureSet. +*/ +Void TComSlice::applyReferencePictureSet( TComList<TComPic*>& rcListPic, TComReferencePictureSet *pReferencePictureSet) +{ + TComPic* rpcPic; + Int i, isReference; + + checkLeadingPictureRestrictions(rcListPic); + + // loop through all pictures in the reference picture buffer + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); + + if(!rpcPic->getSlice( 0 )->isReferenced()) + { + continue; + } + + isReference = 0; + // loop through all pictures in the Reference Picture Set + // to see if the picture should be kept as reference picture + for(i=0;i<pReferencePictureSet->getNumberOfPositivePictures()+pReferencePictureSet->getNumberOfNegativePictures();i++) + { + if(!rpcPic->getIsLongTerm() && rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getPOC() + pReferencePictureSet->getDeltaPOC(i)) + { + isReference = 1; + rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i)); + rpcPic->setIsLongTerm(0); + } + } + for(;i<pReferencePictureSet->getNumberOfPictures();i++) + { + if(pReferencePictureSet->getCheckLTMSBPresent(i)==true) + { + if(rpcPic->getIsLongTerm() && (rpcPic->getPicSym()->getSlice(0)->getPOC()) == pReferencePictureSet->getPOC(i)) + { + isReference = 1; + rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i)); + } + } + else + { + Int pocCycle = 1<<rpcPic->getPicSym()->getSlice(0)->getSPS()->getBitsForPOC(); + Int curPoc = rpcPic->getPicSym()->getSlice(0)->getPOC() & (pocCycle-1); + Int refPoc = pReferencePictureSet->getPOC(i) & (pocCycle-1); + if(rpcPic->getIsLongTerm() && curPoc == refPoc) + { + isReference = 1; + rpcPic->setUsedByCurr(pReferencePictureSet->getUsed(i)); + } + } + + } + // mark the picture as "unused for reference" if it is not in + // the Reference Picture Set + if(rpcPic->getPicSym()->getSlice(0)->getPOC() != this->getPOC() && isReference == 0) + { + rpcPic->getSlice( 0 )->setReferenced( false ); + rpcPic->setUsedByCurr(0); + rpcPic->setIsLongTerm(0); + } + //check that pictures of higher temporal layers are not used + assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getUsedByCurr()==0||rpcPic->getTLayer()<=this->getTLayer()); + //check that pictures of higher or equal temporal layer are not in the RPS if the current picture is a TSA picture + if(this->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_R || this->getNalUnitType() == NAL_UNIT_CODED_SLICE_TSA_N) + { + assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getTLayer()<this->getTLayer()); + } + //check that pictures marked as temporal layer non-reference pictures are not used for reference + if(rpcPic->getPicSym()->getSlice(0)->getPOC() != this->getPOC() && rpcPic->getTLayer()==this->getTLayer()) + { + assert(rpcPic->getSlice( 0 )->isReferenced()==0||rpcPic->getUsedByCurr()==0||rpcPic->getSlice( 0 )->getTemporalLayerNonReferenceFlag()==false); + } + } +} + +/** Function for applying picture marking based on the Reference Picture Set in pReferencePictureSet. +*/ +#if ALLOW_RECOVERY_POINT_AS_RAP +Int TComSlice::checkThatAllRefPicsAreAvailable( TComList<TComPic*>& rcListPic, TComReferencePictureSet *pReferencePictureSet, Bool printErrors, Int pocRandomAccess, Bool bUseRecoveryPoint) +#else +Int TComSlice::checkThatAllRefPicsAreAvailable( TComList<TComPic*>& rcListPic, TComReferencePictureSet *pReferencePictureSet, Bool printErrors, Int pocRandomAccess) +#endif +{ +#if ALLOW_RECOVERY_POINT_AS_RAP + Int atLeastOneUnabledByRecoveryPoint = 0; + Int atLeastOneFlushedByPreviousIDR = 0; +#endif + TComPic* rpcPic; + Int i, isAvailable; + Int atLeastOneLost = 0; + Int atLeastOneRemoved = 0; + Int iPocLost = 0; + + // loop through all long-term pictures in the Reference Picture Set + // to see if the picture should be kept as reference picture + for(i=pReferencePictureSet->getNumberOfNegativePictures()+pReferencePictureSet->getNumberOfPositivePictures();i<pReferencePictureSet->getNumberOfPictures();i++) + { + isAvailable = 0; + // loop through all pictures in the reference picture buffer + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); + if(pReferencePictureSet->getCheckLTMSBPresent(i)==true) + { + if(rpcPic->getIsLongTerm() && (rpcPic->getPicSym()->getSlice(0)->getPOC()) == pReferencePictureSet->getPOC(i) && rpcPic->getSlice(0)->isReferenced()) + { +#if ALLOW_RECOVERY_POINT_AS_RAP + if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) + { + isAvailable = 0; + } + else + { + isAvailable = 1; + } +#else + isAvailable = 1; +#endif + } + } + else + { + Int pocCycle = 1<<rpcPic->getPicSym()->getSlice(0)->getSPS()->getBitsForPOC(); + Int curPoc = rpcPic->getPicSym()->getSlice(0)->getPOC() & (pocCycle-1); + Int refPoc = pReferencePictureSet->getPOC(i) & (pocCycle-1); + if(rpcPic->getIsLongTerm() && curPoc == refPoc && rpcPic->getSlice(0)->isReferenced()) + { +#if ALLOW_RECOVERY_POINT_AS_RAP + if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) + { + isAvailable = 0; + } + else + { + isAvailable = 1; + } +#else + isAvailable = 1; +#endif + } + } + } + // if there was no such long-term check the short terms + if(!isAvailable) + { + iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); + + Int pocCycle = 1 << rpcPic->getPicSym()->getSlice(0)->getSPS()->getBitsForPOC(); + Int curPoc = rpcPic->getPicSym()->getSlice(0)->getPOC(); + Int refPoc = pReferencePictureSet->getPOC(i); + if (!pReferencePictureSet->getCheckLTMSBPresent(i)) + { + curPoc = curPoc & (pocCycle - 1); + refPoc = refPoc & (pocCycle - 1); + } + + if (rpcPic->getSlice(0)->isReferenced() && curPoc == refPoc) + { +#if ALLOW_RECOVERY_POINT_AS_RAP + if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) + { + isAvailable = 0; + } + else + { + isAvailable = 1; + rpcPic->setIsLongTerm(1); + break; + } +#else + isAvailable = 1; + rpcPic->setIsLongTerm(1); + break; +#endif + } + } + } + // report that a picture is lost if it is in the Reference Picture Set + // but not available as reference picture + if(isAvailable == 0) + { + if (this->getPOC() + pReferencePictureSet->getDeltaPOC(i) >= pocRandomAccess) + { + if(!pReferencePictureSet->getUsed(i) ) + { + if(printErrors) + { + printf("\nLong-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC() + pReferencePictureSet->getDeltaPOC(i)); + } + atLeastOneRemoved = 1; + } + else + { + if(printErrors) + { + printf("\nLong-term reference picture with POC = %3d is lost or not correctly decoded!", this->getPOC() + pReferencePictureSet->getDeltaPOC(i)); + } + atLeastOneLost = 1; + iPocLost=this->getPOC() + pReferencePictureSet->getDeltaPOC(i); + } + } +#if ALLOW_RECOVERY_POINT_AS_RAP + else if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess) + { + atLeastOneUnabledByRecoveryPoint = 1; + } + else if(bUseRecoveryPoint && (this->getAssociatedIRAPType()==NAL_UNIT_CODED_SLICE_IDR_N_LP || this->getAssociatedIRAPType()==NAL_UNIT_CODED_SLICE_IDR_W_RADL)) + { + atLeastOneFlushedByPreviousIDR = 1; + } +#endif + } + } + // loop through all short-term pictures in the Reference Picture Set + // to see if the picture should be kept as reference picture + for(i=0;i<pReferencePictureSet->getNumberOfNegativePictures()+pReferencePictureSet->getNumberOfPositivePictures();i++) + { + isAvailable = 0; + // loop through all pictures in the reference picture buffer + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); + + if(!rpcPic->getIsLongTerm() && rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getPOC() + pReferencePictureSet->getDeltaPOC(i) && rpcPic->getSlice(0)->isReferenced()) + { +#if ALLOW_RECOVERY_POINT_AS_RAP + if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) + { + isAvailable = 0; + } + else + { + isAvailable = 1; + } +#else + isAvailable = 1; +#endif + } + } + // report that a picture is lost if it is in the Reference Picture Set + // but not available as reference picture + if(isAvailable == 0) + { + if (this->getPOC() + pReferencePictureSet->getDeltaPOC(i) >= pocRandomAccess) + { + if(!pReferencePictureSet->getUsed(i) ) + { + if(printErrors) + { + printf("\nShort-term reference picture with POC = %3d seems to have been removed or not correctly decoded.", this->getPOC() + pReferencePictureSet->getDeltaPOC(i)); + } + atLeastOneRemoved = 1; + } + else + { + if(printErrors) + { + printf("\nShort-term reference picture with POC = %3d is lost or not correctly decoded!", this->getPOC() + pReferencePictureSet->getDeltaPOC(i)); + } + atLeastOneLost = 1; + iPocLost=this->getPOC() + pReferencePictureSet->getDeltaPOC(i); + } + } +#if ALLOW_RECOVERY_POINT_AS_RAP + else if(bUseRecoveryPoint && this->getPOC() > pocRandomAccess) + { + atLeastOneUnabledByRecoveryPoint = 1; + } + else if(bUseRecoveryPoint && (this->getAssociatedIRAPType()==NAL_UNIT_CODED_SLICE_IDR_N_LP || this->getAssociatedIRAPType()==NAL_UNIT_CODED_SLICE_IDR_W_RADL)) + { + atLeastOneFlushedByPreviousIDR = 1; + } +#endif + } + } + +#if ALLOW_RECOVERY_POINT_AS_RAP + if(atLeastOneUnabledByRecoveryPoint || atLeastOneFlushedByPreviousIDR) + { + return -1; + } +#endif + if(atLeastOneLost) + { + return iPocLost+1; + } + if(atLeastOneRemoved) + { + return -2; + } + else + { + return 0; + } +} + +/** Function for constructing an explicit Reference Picture Set out of the available pictures in a referenced Reference Picture Set +*/ +#if ALLOW_RECOVERY_POINT_AS_RAP +Void TComSlice::createExplicitReferencePictureSetFromReference( TComList<TComPic*>& rcListPic, TComReferencePictureSet *pReferencePictureSet, Bool isRAP, Int pocRandomAccess, Bool bUseRecoveryPoint) +#else +Void TComSlice::createExplicitReferencePictureSetFromReference( TComList<TComPic*>& rcListPic, TComReferencePictureSet *pReferencePictureSet, Bool isRAP) +#endif +{ + TComPic* rpcPic; + Int i, j; + Int k = 0; + Int nrOfNegativePictures = 0; + Int nrOfPositivePictures = 0; + TComReferencePictureSet* pcRPS = this->getLocalRPS(); +#if EFFICIENT_FIELD_IRAP + Bool irapIsInRPS = false; +#endif + + // loop through all pictures in the Reference Picture Set + for(i=0;i<pReferencePictureSet->getNumberOfPictures();i++) + { + j = 0; + // loop through all pictures in the reference picture buffer + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + j++; + rpcPic = *(iterPic++); + + if(rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getPOC() + pReferencePictureSet->getDeltaPOC(i) && rpcPic->getSlice(0)->isReferenced()) + { + // This picture exists as a reference picture + // and should be added to the explicit Reference Picture Set + pcRPS->setDeltaPOC(k, pReferencePictureSet->getDeltaPOC(i)); + pcRPS->setUsed(k, pReferencePictureSet->getUsed(i) && (!isRAP)); +#if ALLOW_RECOVERY_POINT_AS_RAP + pcRPS->setUsed(k, pcRPS->getUsed(k) && !(bUseRecoveryPoint && this->getPOC() > pocRandomAccess && this->getPOC() + pReferencePictureSet->getDeltaPOC(i) < pocRandomAccess) ); +#endif + + if(pcRPS->getDeltaPOC(k) < 0) + { + nrOfNegativePictures++; + } + else + { +#if EFFICIENT_FIELD_IRAP + if(rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getAssociatedIRAPPOC() && this->getAssociatedIRAPPOC() == this->getPOC()+1) + { + irapIsInRPS = true; + } +#endif + nrOfPositivePictures++; + } + k++; + } + } + } + +#if EFFICIENT_FIELD_IRAP + Bool useNewRPS = false; + // if current picture is complimentary field associated to IRAP, add the IRAP to its RPS. + if(m_pcPic->isField() && !irapIsInRPS) + { + TComList<TComPic*>::iterator iterPic = rcListPic.begin(); + while ( iterPic != rcListPic.end()) + { + rpcPic = *(iterPic++); + if(rpcPic->getPicSym()->getSlice(0)->getPOC() == this->getAssociatedIRAPPOC() && this->getAssociatedIRAPPOC() == this->getPOC()+1) + { + pcRPS->setDeltaPOC(k, 1); + pcRPS->setUsed(k, true); + nrOfPositivePictures++; + k ++; + useNewRPS = true; + } + } + } +#endif + pcRPS->setNumberOfNegativePictures(nrOfNegativePictures); + pcRPS->setNumberOfPositivePictures(nrOfPositivePictures); + pcRPS->setNumberOfPictures(nrOfNegativePictures+nrOfPositivePictures); + // This is a simplistic inter rps example. A smarter encoder will look for a better reference RPS to do the + // inter RPS prediction with. Here we just use the reference used by pReferencePictureSet. + // If pReferencePictureSet is not inter_RPS_predicted, then inter_RPS_prediction is for the current RPS also disabled. + if (!pReferencePictureSet->getInterRPSPrediction() +#if EFFICIENT_FIELD_IRAP + || useNewRPS +#endif + ) + { + pcRPS->setInterRPSPrediction(false); + pcRPS->setNumRefIdc(0); + } + else + { + Int rIdx = this->getRPSidx() - pReferencePictureSet->getDeltaRIdxMinus1() - 1; + Int deltaRPS = pReferencePictureSet->getDeltaRPS(); + TComReferencePictureSet* pcRefRPS = this->getSPS()->getRPSList()->getReferencePictureSet(rIdx); + Int iRefPics = pcRefRPS->getNumberOfPictures(); + Int iNewIdc=0; + for(i=0; i<= iRefPics; i++) + { + Int deltaPOC = ((i != iRefPics)? pcRefRPS->getDeltaPOC(i) : 0); // check if the reference abs POC is >= 0 + Int iRefIdc = 0; + for (j=0; j < pcRPS->getNumberOfPictures(); j++) // loop through the pictures in the new RPS + { + if ( (deltaPOC + deltaRPS) == pcRPS->getDeltaPOC(j)) + { + if (pcRPS->getUsed(j)) + { + iRefIdc = 1; + } + else + { + iRefIdc = 2; + } + } + } + pcRPS->setRefIdc(i, iRefIdc); + iNewIdc++; + } + pcRPS->setInterRPSPrediction(true); + pcRPS->setNumRefIdc(iNewIdc); + pcRPS->setDeltaRPS(deltaRPS); + pcRPS->setDeltaRIdxMinus1(pReferencePictureSet->getDeltaRIdxMinus1() + this->getSPS()->getRPSList()->getNumberOfReferencePictureSets() - this->getRPSidx()); + } + + this->setRPS(pcRPS); + this->setRPSidx(-1); +} + +/** get AC and DC values for weighted pred + * \param *wp + * \returns Void + */ +Void TComSlice::getWpAcDcParam(WPACDCParam *&wp) +{ + wp = m_weightACDCParam; +} + +/** init AC and DC values for weighted pred + * \returns Void + */ +Void TComSlice::initWpAcDcParam() +{ + for(Int iComp = 0; iComp < MAX_NUM_COMPONENT; iComp++ ) + { + m_weightACDCParam[iComp].iAC = 0; + m_weightACDCParam[iComp].iDC = 0; + } +} + +/** get WP tables for weighted pred + * \param RefPicList + * \param iRefIdx + * \param *&WPScalingParam + * \returns Void + */ +Void TComSlice::getWpScaling( RefPicList e, Int iRefIdx, WPScalingParam *&wp ) +{ + assert (e<NUM_REF_PIC_LIST_01); + wp = m_weightPredTable[e][iRefIdx]; +} + +/** reset Default WP tables settings : no weight. + * \param WPScalingParam + * \returns Void + */ +Void TComSlice::resetWpScaling() +{ + for ( Int e=0 ; e<NUM_REF_PIC_LIST_01 ; e++ ) + { + for ( Int i=0 ; i<MAX_NUM_REF ; i++ ) + { + for ( Int yuv=0 ; yuv<MAX_NUM_COMPONENT ; yuv++ ) + { + WPScalingParam *pwp = &(m_weightPredTable[e][i][yuv]); + pwp->bPresentFlag = false; + pwp->uiLog2WeightDenom = 0; + pwp->uiLog2WeightDenom = 0; + pwp->iWeight = 1; + pwp->iOffset = 0; + } + } + } +} + +/** init WP table + * \returns Void + */ +Void TComSlice::initWpScaling() +{ + const Bool bUseHighPrecisionPredictionWeighting = getSPS()->getUseHighPrecisionPredictionWeighting(); + for ( Int e=0 ; e<NUM_REF_PIC_LIST_01 ; e++ ) + { + for ( Int i=0 ; i<MAX_NUM_REF ; i++ ) + { + for ( Int yuv=0 ; yuv<MAX_NUM_COMPONENT ; yuv++ ) + { + WPScalingParam *pwp = &(m_weightPredTable[e][i][yuv]); + if ( !pwp->bPresentFlag ) + { + // Inferring values not present : + pwp->iWeight = (1 << pwp->uiLog2WeightDenom); + pwp->iOffset = 0; + } + + const Int offsetScalingFactor = bUseHighPrecisionPredictionWeighting ? 1 : (1 << (g_bitDepth[toChannelType(ComponentID(yuv))]-8)); + + pwp->w = pwp->iWeight; + pwp->o = pwp->iOffset * offsetScalingFactor; //NOTE: This value of the ".o" variable is never used - .o is set immediately before it gets used + pwp->shift = pwp->uiLog2WeightDenom; + pwp->round = (pwp->uiLog2WeightDenom>=1) ? (1 << (pwp->uiLog2WeightDenom-1)) : (0); + } + } + } +} + +// ------------------------------------------------------------------------------------------------ +// Video parameter set (VPS) +// ------------------------------------------------------------------------------------------------ +TComVPS::TComVPS() +: m_VPSId ( 0) +, m_uiMaxTLayers ( 1) +, m_uiMaxLayers ( 1) +, m_bTemporalIdNestingFlag (false) +, m_numHrdParameters ( 0) +, m_maxNuhReservedZeroLayerId ( 0) +, m_hrdParameters (NULL) +, m_hrdOpSetIdx (NULL) +, m_cprmsPresentFlag (NULL) +{ + + for( Int i = 0; i < MAX_TLAYER; i++) + { + m_numReorderPics[i] = 0; + m_uiMaxDecPicBuffering[i] = 1; + m_uiMaxLatencyIncrease[i] = 0; + } +} + +TComVPS::~TComVPS() +{ + if( m_hrdParameters != NULL ) delete[] m_hrdParameters; + if( m_hrdOpSetIdx != NULL ) delete[] m_hrdOpSetIdx; + if( m_cprmsPresentFlag != NULL ) delete[] m_cprmsPresentFlag; +} + +// ------------------------------------------------------------------------------------------------ +// Sequence parameter set (SPS) +// ------------------------------------------------------------------------------------------------ + +TComSPS::TComSPS() +: m_SPSId ( 0) +, m_VPSId ( 0) +, m_chromaFormatIdc (CHROMA_420) +, m_uiMaxTLayers ( 1) +// Structure +, m_picWidthInLumaSamples (352) +, m_picHeightInLumaSamples (288) +, m_log2MinCodingBlockSize ( 0) +, m_log2DiffMaxMinCodingBlockSize(0) +, m_uiMaxCUWidth ( 32) +, m_uiMaxCUHeight ( 32) +, m_uiMaxCUDepth ( 3) +, m_bLongTermRefsPresent (false) +, m_uiQuadtreeTULog2MaxSize ( 0) +, m_uiQuadtreeTULog2MinSize ( 0) +, m_uiQuadtreeTUMaxDepthInter ( 0) +, m_uiQuadtreeTUMaxDepthIntra ( 0) +// Tool list +, m_usePCM (false) +, m_pcmLog2MaxSize ( 5) +, m_uiPCMLog2MinSize ( 7) +, m_useExtendedPrecision (false) +, m_useHighPrecisionPredictionWeighting(false) +, m_useResidualRotation (false) +, m_useSingleSignificanceMapContext(false) +, m_useGolombRiceParameterAdaptation(false) +, m_alignCABACBeforeBypass (false) +, m_bPCMFilterDisableFlag (false) +, m_disableIntraReferenceSmoothing(false) +, m_uiBitsForPOC ( 8) +, m_numLongTermRefPicSPS ( 0) +, m_uiMaxTrSize ( 32) +, m_bUseSAO (false) +, m_bTemporalIdNestingFlag (false) +, m_scalingListEnabledFlag (false) +, m_useStrongIntraSmoothing (false) +, m_vuiParametersPresentFlag (false) +, m_vuiParameters () +{ + for(Int ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++) + { + m_uiBitDepth [ch] = 8; + m_uiPCMBitDepth[ch] = 8; + m_qpBDOffset [ch] = 0; + } + + for ( Int i = 0; i < MAX_TLAYER; i++ ) + { + m_uiMaxLatencyIncrease[i] = 0; + m_uiMaxDecPicBuffering[i] = 1; + m_numReorderPics[i] = 0; + } + + for (UInt signallingModeIndex = 0; signallingModeIndex < NUMBER_OF_RDPCM_SIGNALLING_MODES; signallingModeIndex++) + { + m_useResidualDPCM[signallingModeIndex] = false; + } + + m_scalingList = new TComScalingList; + ::memset(m_ltRefPicPocLsbSps, 0, sizeof(m_ltRefPicPocLsbSps)); + ::memset(m_usedByCurrPicLtSPSFlag, 0, sizeof(m_usedByCurrPicLtSPSFlag)); +} + +TComSPS::~TComSPS() +{ + delete m_scalingList; + m_RPSList.destroy(); +} + +Void TComSPS::createRPSList( Int numRPS ) +{ + m_RPSList.destroy(); + m_RPSList.create(numRPS); +} + +Void TComSPS::setHrdParameters( UInt frameRate, UInt numDU, UInt bitRate, Bool randomAccess ) +{ + if( !getVuiParametersPresentFlag() ) + { + return; + } + + TComVUI *vui = getVuiParameters(); + TComHRD *hrd = vui->getHrdParameters(); + + TimingInfo *timingInfo = vui->getTimingInfo(); + timingInfo->setTimingInfoPresentFlag( true ); + switch( frameRate ) + { + case 24: + timingInfo->setNumUnitsInTick( 1125000 ); timingInfo->setTimeScale ( 27000000 ); + break; + case 25: + timingInfo->setNumUnitsInTick( 1080000 ); timingInfo->setTimeScale ( 27000000 ); + break; + case 30: + timingInfo->setNumUnitsInTick( 900900 ); timingInfo->setTimeScale ( 27000000 ); + break; + case 50: + timingInfo->setNumUnitsInTick( 540000 ); timingInfo->setTimeScale ( 27000000 ); + break; + case 60: + timingInfo->setNumUnitsInTick( 450450 ); timingInfo->setTimeScale ( 27000000 ); + break; + default: + timingInfo->setNumUnitsInTick( 1001 ); timingInfo->setTimeScale ( 60000 ); + break; + } + + Bool rateCnt = ( bitRate > 0 ); + hrd->setNalHrdParametersPresentFlag( rateCnt ); + hrd->setVclHrdParametersPresentFlag( rateCnt ); + + hrd->setSubPicCpbParamsPresentFlag( ( numDU > 1 ) ); + + if( hrd->getSubPicCpbParamsPresentFlag() ) + { + hrd->setTickDivisorMinus2( 100 - 2 ); // + hrd->setDuCpbRemovalDelayLengthMinus1( 7 ); // 8-bit precision ( plus 1 for last DU in AU ) + hrd->setSubPicCpbParamsInPicTimingSEIFlag( true ); + hrd->setDpbOutputDelayDuLengthMinus1( 5 + 7 ); // With sub-clock tick factor of 100, at least 7 bits to have the same value as AU dpb delay + } + else + { + hrd->setSubPicCpbParamsInPicTimingSEIFlag( false ); + } + + hrd->setBitRateScale( 4 ); // in units of 2~( 6 + 4 ) = 1,024 bps + hrd->setCpbSizeScale( 6 ); // in units of 2~( 4 + 4 ) = 1,024 bit + hrd->setDuCpbSizeScale( 6 ); // in units of 2~( 4 + 4 ) = 1,024 bit + + hrd->setInitialCpbRemovalDelayLengthMinus1(15); // assuming 0.5 sec, log2( 90,000 * 0.5 ) = 16-bit + if( randomAccess ) + { + hrd->setCpbRemovalDelayLengthMinus1(5); // 32 = 2^5 (plus 1) + hrd->setDpbOutputDelayLengthMinus1 (5); // 32 + 3 = 2^6 + } + else + { + hrd->setCpbRemovalDelayLengthMinus1(9); // max. 2^10 + hrd->setDpbOutputDelayLengthMinus1 (9); // max. 2^10 + } + +/* + Note: only the case of "vps_max_temporal_layers_minus1 = 0" is supported. +*/ + Int i, j; + UInt bitrateValue, cpbSizeValue; + UInt duCpbSizeValue; + UInt duBitRateValue = 0; + + for( i = 0; i < MAX_TLAYER; i ++ ) + { + hrd->setFixedPicRateFlag( i, 1 ); + hrd->setPicDurationInTcMinus1( i, 0 ); + hrd->setLowDelayHrdFlag( i, 0 ); + hrd->setCpbCntMinus1( i, 0 ); + + bitrateValue = bitRate; + cpbSizeValue = bitRate; // 1 second + duCpbSizeValue = bitRate/numDU; + duBitRateValue = bitRate; + + for( j = 0; j < ( hrd->getCpbCntMinus1( i ) + 1 ); j ++ ) + { + hrd->setBitRateValueMinus1( i, j, 0, ( bitrateValue - 1 ) ); + hrd->setCpbSizeValueMinus1( i, j, 0, ( cpbSizeValue - 1 ) ); + hrd->setDuCpbSizeValueMinus1( i, j, 0, ( duCpbSizeValue - 1 ) ); + hrd->setCbrFlag( i, j, 0, ( j == 0 ) ); + + hrd->setBitRateValueMinus1( i, j, 1, ( bitrateValue - 1) ); + hrd->setCpbSizeValueMinus1( i, j, 1, ( cpbSizeValue - 1 ) ); + hrd->setDuCpbSizeValueMinus1( i, j, 1, ( duCpbSizeValue - 1 ) ); + hrd->setDuBitRateValueMinus1( i, j, 1, ( duBitRateValue - 1 ) ); + hrd->setCbrFlag( i, j, 1, ( j == 0 ) ); + } + } +} + +const Int TComSPS::m_winUnitX[]={1,2,2,1}; +const Int TComSPS::m_winUnitY[]={1,2,1,1}; + +TComPPS::TComPPS() +: m_PPSId (0) +, m_SPSId (0) +, m_picInitQPMinus26 (0) +, m_useDQP (false) +, m_bConstrainedIntraPred (false) +, m_bSliceChromaQpFlag (false) +, m_pcSPS (NULL) +, m_uiMaxCuDQPDepth (0) +, m_uiMinCuDQPSize (0) +, m_MaxCuChromaQpAdjDepth (0) +, m_MinCuChromaQpAdjSize (0) +, m_ChromaQpAdjTableSize (0) +, m_chromaCbQpOffset (0) +, m_chromaCrQpOffset (0) +, m_numRefIdxL0DefaultActive (1) +, m_numRefIdxL1DefaultActive (1) +, m_useCrossComponentPrediction (false) +, m_TransquantBypassEnableFlag (false) +, m_useTransformSkip (false) +, m_transformSkipLog2MaxSize (2) +, m_dependentSliceSegmentsEnabledFlag(false) +, m_tilesEnabledFlag (false) +, m_entropyCodingSyncEnabledFlag (false) +, m_loopFilterAcrossTilesEnabledFlag (true) +, m_uniformSpacingFlag (false) +, m_numTileColumnsMinus1 (0) +, m_numTileRowsMinus1 (0) +, m_numSubstreams (1) +, m_signHideFlag (0) +, m_cabacInitPresentFlag (false) +, m_encCABACTableIdx (I_SLICE) +, m_sliceHeaderExtensionPresentFlag (false) +, m_loopFilterAcrossSlicesEnabledFlag(false) +, m_listsModificationPresentFlag (0) +, m_numExtraSliceHeaderBits (0) +{ + m_scalingList = new TComScalingList; + for(Int ch=0; ch<MAX_NUM_CHANNEL_TYPE; ch++) + { + m_saoOffsetBitShift[ch] = 0; + } + m_ChromaQpAdjTable[0].u.comp.CbOffset = 0; + m_ChromaQpAdjTable[0].u.comp.CrOffset = 0; +} + +TComPPS::~TComPPS() +{ + delete m_scalingList; +} + +TComReferencePictureSet::TComReferencePictureSet() +: m_numberOfPictures (0) +, m_numberOfNegativePictures (0) +, m_numberOfPositivePictures (0) +, m_numberOfLongtermPictures (0) +, m_interRPSPrediction (0) +, m_deltaRIdxMinus1 (0) +, m_deltaRPS (0) +, m_numRefIdc (0) +{ + ::memset( m_deltaPOC, 0, sizeof(m_deltaPOC) ); + ::memset( m_POC, 0, sizeof(m_POC) ); + ::memset( m_used, 0, sizeof(m_used) ); + ::memset( m_refIdc, 0, sizeof(m_refIdc) ); +} + +TComReferencePictureSet::~TComReferencePictureSet() +{ +} + +Void TComReferencePictureSet::setUsed(Int bufferNum, Bool used) +{ + m_used[bufferNum] = used; +} + +Void TComReferencePictureSet::setDeltaPOC(Int bufferNum, Int deltaPOC) +{ + m_deltaPOC[bufferNum] = deltaPOC; +} + +Void TComReferencePictureSet::setNumberOfPictures(Int numberOfPictures) +{ + m_numberOfPictures = numberOfPictures; +} + +Int TComReferencePictureSet::getUsed(Int bufferNum) +{ + return m_used[bufferNum]; +} + +Int TComReferencePictureSet::getDeltaPOC(Int bufferNum) +{ + return m_deltaPOC[bufferNum]; +} + +Int TComReferencePictureSet::getNumberOfPictures() +{ + return m_numberOfPictures; +} + +Int TComReferencePictureSet::getPOC(Int bufferNum) +{ + return m_POC[bufferNum]; +} + +Void TComReferencePictureSet::setPOC(Int bufferNum, Int POC) +{ + m_POC[bufferNum] = POC; +} + +Bool TComReferencePictureSet::getCheckLTMSBPresent(Int bufferNum) +{ + return m_bCheckLTMSB[bufferNum]; +} + +Void TComReferencePictureSet::setCheckLTMSBPresent(Int bufferNum, Bool b) +{ + m_bCheckLTMSB[bufferNum] = b; +} + +/** set the reference idc value at uiBufferNum entry to the value of iRefIdc + * \param uiBufferNum + * \param iRefIdc + * \returns Void + */ +Void TComReferencePictureSet::setRefIdc(Int bufferNum, Int refIdc) +{ + m_refIdc[bufferNum] = refIdc; +} + +/** get the reference idc value at uiBufferNum + * \param uiBufferNum + * \returns Int + */ +Int TComReferencePictureSet::getRefIdc(Int bufferNum) +{ + return m_refIdc[bufferNum]; +} + +/** Sorts the deltaPOC and Used by current values in the RPS based on the deltaPOC values. + * deltaPOC values are sorted with -ve values before the +ve values. -ve values are in decreasing order. + * +ve values are in increasing order. + * \returns Void + */ +Void TComReferencePictureSet::sortDeltaPOC() +{ + // sort in increasing order (smallest first) + for(Int j=1; j < getNumberOfPictures(); j++) + { + Int deltaPOC = getDeltaPOC(j); + Bool used = getUsed(j); + for (Int k=j-1; k >= 0; k--) + { + Int temp = getDeltaPOC(k); + if (deltaPOC < temp) + { + setDeltaPOC(k+1, temp); + setUsed(k+1, getUsed(k)); + setDeltaPOC(k, deltaPOC); + setUsed(k, used); + } + } + } + // flip the negative values to largest first + Int numNegPics = getNumberOfNegativePictures(); + for(Int j=0, k=numNegPics-1; j < numNegPics>>1; j++, k--) + { + Int deltaPOC = getDeltaPOC(j); + Bool used = getUsed(j); + setDeltaPOC(j, getDeltaPOC(k)); + setUsed(j, getUsed(k)); + setDeltaPOC(k, deltaPOC); + setUsed(k, used); + } +} + +/** Prints the deltaPOC and RefIdc (if available) values in the RPS. + * A "*" is added to the deltaPOC value if it is Used bu current. + * \returns Void + */ +Void TComReferencePictureSet::printDeltaPOC() +{ + printf("DeltaPOC = { "); + for(Int j=0; j < getNumberOfPictures(); j++) + { + printf("%d%s ", getDeltaPOC(j), (getUsed(j)==1)?"*":""); + } + if (getInterRPSPrediction()) + { + printf("}, RefIdc = { "); + for(Int j=0; j < getNumRefIdc(); j++) + { + printf("%d ", getRefIdc(j)); + } + } + printf("}\n"); +} + +TComRPSList::TComRPSList() +:m_referencePictureSets (NULL) +{ +} + +TComRPSList::~TComRPSList() +{ +} + +Void TComRPSList::create( Int numberOfReferencePictureSets) +{ + m_numberOfReferencePictureSets = numberOfReferencePictureSets; + m_referencePictureSets = new TComReferencePictureSet[numberOfReferencePictureSets]; +} + +Void TComRPSList::destroy() +{ + if (m_referencePictureSets) + { + delete [] m_referencePictureSets; + } + m_numberOfReferencePictureSets = 0; + m_referencePictureSets = NULL; +} + + + +TComReferencePictureSet* TComRPSList::getReferencePictureSet(Int referencePictureSetNum) +{ + return &m_referencePictureSets[referencePictureSetNum]; +} + +Int TComRPSList::getNumberOfReferencePictureSets() +{ + return m_numberOfReferencePictureSets; +} + +Void TComRPSList::setNumberOfReferencePictureSets(Int numberOfReferencePictureSets) +{ + m_numberOfReferencePictureSets = numberOfReferencePictureSets; +} + +TComRefPicListModification::TComRefPicListModification() +: m_bRefPicListModificationFlagL0 (false) +, m_bRefPicListModificationFlagL1 (false) +{ + ::memset( m_RefPicSetIdxL0, 0, sizeof(m_RefPicSetIdxL0) ); + ::memset( m_RefPicSetIdxL1, 0, sizeof(m_RefPicSetIdxL1) ); +} + +TComRefPicListModification::~TComRefPicListModification() +{ +} + +TComScalingList::TComScalingList() +{ + init(); +} + +TComScalingList::~TComScalingList() +{ + destroy(); +} + +/** set default quantization matrix to array +*/ +Void TComSlice::setDefaultScalingList() +{ + for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) + { + for(UInt listId=0;listId<SCALING_LIST_NUM;listId++) + { + getScalingList()->processDefaultMatrix(sizeId, listId); + } + } +} +/** check if use default quantization matrix + * \returns true if use default quantization matrix in all size +*/ +Bool TComSlice::checkDefaultScalingList() +{ + UInt defaultCounter=0; + + for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) + { + for(UInt listId=0;listId<SCALING_LIST_NUM;listId++) + { + if( !memcmp(getScalingList()->getScalingListAddress(sizeId,listId), getScalingList()->getScalingListDefaultAddress(sizeId, listId),sizeof(Int)*min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId])) // check value of matrix + && ((sizeId < SCALING_LIST_16x16) || (getScalingList()->getScalingListDC(sizeId,listId) == 16))) // check DC value + { + defaultCounter++; + } + } + } + + return (defaultCounter == (SCALING_LIST_NUM * SCALING_LIST_SIZE_NUM )) ? false : true; +} + +/** get scaling matrix from RefMatrixID + * \param sizeId size index + * \param Index of input matrix + * \param Index of reference matrix + */ +Void TComScalingList::processRefMatrix( UInt sizeId, UInt listId , UInt refListId ) +{ + ::memcpy(getScalingListAddress(sizeId, listId),((listId == refListId)? getScalingListDefaultAddress(sizeId, refListId): getScalingListAddress(sizeId, refListId)),sizeof(Int)*min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId])); +} + +/** parse syntax infomation + * \param pchFile syntax infomation + * \returns false if successful + */ + +static Void outputScalingListHelp(std::ostream &os) +{ + os << "The scaling list file specifies all matrices and their DC values; none can be missing,\n" + "but their order is arbitrary.\n\n" + "The matrices are specified by:\n" + "<matrix name><unchecked data>\n" + " <value>,<value>,<value>,....\n\n" + " Line-feeds can be added arbitrarily between values, and the number of values needs to be\n" + " at least the number of entries for the matrix (superfluous entries are ignored).\n" + " The <unchecked data> is text on the same line as the matrix that is not checked\n" + " except to ensure that the matrix name token is unique. It is recommended that it is ' ='\n" + " The values in the matrices are the absolute values (0-255), not the delta values as\n" + " exchanged between the encoder and decoder\n\n" + "The DC values (for matrix sizes larger than 8x8) are specified by:\n" + "<matrix name>_DC<unchecked data>\n" + " <value>\n"; + + os << "The permitted matrix names are:\n"; + for(UInt sizeIdc = 0; sizeIdc < SCALING_LIST_SIZE_NUM; sizeIdc++) + { + for(UInt listIdc = 0; listIdc < SCALING_LIST_NUM; listIdc++) + { + if ((sizeIdc!=SCALING_LIST_32x32) || (listIdc%(SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) == 0)) + { + os << " " << MatrixType[sizeIdc][listIdc] << '\n'; + } + } + } +} + +Void TComScalingList::outputScalingLists(std::ostream &os) const +{ + for(UInt sizeIdc = 0; sizeIdc < SCALING_LIST_SIZE_NUM; sizeIdc++) + { + const UInt size = min(8,4<<(sizeIdc)); + for(UInt listIdc = 0; listIdc < SCALING_LIST_NUM; listIdc++) + { + if ((sizeIdc!=SCALING_LIST_32x32) || (listIdc%(SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) == 0)) + { + const Int *src = getScalingListAddress(sizeIdc, listIdc); + os << (MatrixType[sizeIdc][listIdc]) << " =\n "; + for(UInt y=0; y<size; y++) + { + for(UInt x=0; x<size; x++, src++) + { + os << std::setw(3) << (*src) << ", "; + } + os << (y+1<size?"\n ":"\n"); + } + if(sizeIdc > SCALING_LIST_8x8) + { + os << MatrixType_DC[sizeIdc][listIdc] << " = \n " << std::setw(3) << getScalingListDC(sizeIdc, listIdc) << "\n"; + } + os << "\n"; + } + } + } +} + +Bool TComScalingList::xParseScalingList(Char* pchFile) +{ + static const Int LINE_SIZE=1024; + FILE *fp = NULL; + Char line[LINE_SIZE]; + + if (pchFile == NULL) + { + fprintf(stderr, "Error: no scaling list file specified. Help on scaling lists being output\n"); + outputScalingListHelp(std::cout); + std::cout << "\n\nExample scaling list file using default values:\n\n"; + outputScalingLists(std::cout); + exit (1); + return true; + } + else if ((fp = fopen(pchFile,"r")) == (FILE*)NULL) + { + fprintf(stderr, "Error: cannot open scaling list file %s for reading\n",pchFile); + return true; + } + + for(UInt sizeIdc = 0; sizeIdc < SCALING_LIST_SIZE_NUM; sizeIdc++) + { + const UInt size = min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeIdc]); + + for(UInt listIdc = 0; listIdc < SCALING_LIST_NUM; listIdc++) + { + Int * const src = getScalingListAddress(sizeIdc, listIdc); + + if ((sizeIdc==SCALING_LIST_32x32) && (listIdc%(SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) != 0)) // derive chroma32x32 from chroma16x16 + { + const Int *srcNextSmallerSize = getScalingListAddress(sizeIdc-1, listIdc); + for(UInt i=0; i<size; i++) + { + src[i] = srcNextSmallerSize[i]; + } + setScalingListDC(sizeIdc,listIdc,(sizeIdc > SCALING_LIST_8x8) ? getScalingListDC(sizeIdc-1, listIdc) : src[0]); + } + else + { + { + fseek(fp, 0, SEEK_SET); + Bool bFound=false; + while ((!feof(fp)) && (!bFound)) + { + Char *ret = fgets(line, LINE_SIZE, fp); + Char *findNamePosition= ret==NULL ? NULL : strstr(line, MatrixType[sizeIdc][listIdc]); + // This could be a match against the DC string as well, so verify it isn't + if (findNamePosition!= NULL && (MatrixType_DC[sizeIdc][listIdc]==NULL || strstr(line, MatrixType_DC[sizeIdc][listIdc])==NULL)) + { + bFound=true; + } + } + if (!bFound) + { + fprintf(stderr, "Error: cannot find Matrix %s from scaling list file %s\n", MatrixType[sizeIdc][listIdc], pchFile); + return true; + } + } + for (UInt i=0; i<size; i++) + { + Int data; + if (fscanf(fp, "%d,", &data)!=1) + { + fprintf(stderr, "Error: cannot read value #%d for Matrix %s from scaling list file %s at file position %ld\n", i, MatrixType[sizeIdc][listIdc], pchFile, ftell(fp)); + return true; + } + if (data<0 || data>255) + { + fprintf(stderr, "Error: QMatrix entry #%d of value %d for Matrix %s from scaling list file %s at file position %ld is out of range (0 to 255)\n", i, data, MatrixType[sizeIdc][listIdc], pchFile, ftell(fp)); + return true; + } + src[i] = data; + } + + //set DC value for default matrix check + setScalingListDC(sizeIdc,listIdc,src[0]); + + if(sizeIdc > SCALING_LIST_8x8) + { + { + fseek(fp, 0, SEEK_SET); + Bool bFound=false; + while ((!feof(fp)) && (!bFound)) + { + Char *ret = fgets(line, LINE_SIZE, fp); + Char *findNamePosition= ret==NULL ? NULL : strstr(line, MatrixType_DC[sizeIdc][listIdc]); + if (findNamePosition!= NULL) + { + // This won't be a match against the non-DC string. + bFound=true; + } + } + if (!bFound) + { + fprintf(stderr, "Error: cannot find DC Matrix %s from scaling list file %s\n", MatrixType_DC[sizeIdc][listIdc], pchFile); + return true; + } + } + Int data; + if (fscanf(fp, "%d,", &data)!=1) + { + fprintf(stderr, "Error: cannot read DC %s from scaling list file %s at file position %ld\n", MatrixType_DC[sizeIdc][listIdc], pchFile, ftell(fp)); + return true; + } + if (data<0 || data>255) + { + fprintf(stderr, "Error: DC value %d for Matrix %s from scaling list file %s at file position %ld is out of range (0 to 255)\n", data, MatrixType[sizeIdc][listIdc], pchFile, ftell(fp)); + return true; + } + //overwrite DC value when size of matrix is larger than 16x16 + setScalingListDC(sizeIdc,listIdc,data); + } + } + } + } +// std::cout << "\n\nRead scaling lists of:\n\n"; +// outputScalingLists(std::cout); + + fclose(fp); + return false; +} + +/** initialization process of quantization matrix array + */ +Void TComScalingList::init() +{ + for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) + { + for(UInt listId = 0; listId < SCALING_LIST_NUM; listId++) + { + m_scalingListCoef[sizeId][listId] = new Int [min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId])]; + } + } +} + +/** destroy quantization matrix array + */ +Void TComScalingList::destroy() +{ + for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) + { + for(UInt listId = 0; listId < SCALING_LIST_NUM; listId++) + { + if(m_scalingListCoef[sizeId][listId]) delete [] m_scalingListCoef[sizeId][listId]; + } + } +} + +/** get default address of quantization matrix + * \param sizeId size index + * \param listId list index + * \returns pointer of quantization matrix + */ +Int* TComScalingList::getScalingListDefaultAddress(UInt sizeId, UInt listId) +{ + Int *src = 0; + switch(sizeId) + { + case SCALING_LIST_4x4: + src = g_quantTSDefault4x4; + break; + case SCALING_LIST_8x8: + case SCALING_LIST_16x16: + case SCALING_LIST_32x32: + src = (listId < (SCALING_LIST_NUM/NUMBER_OF_PREDICTION_MODES) ) ? g_quantIntraDefault8x8 : g_quantInterDefault8x8; + break; + default: + assert(0); + src = NULL; + break; + } + return src; +} + +/** process of default matrix + * \param sizeId size index + * \param Index of input matrix + */ +Void TComScalingList::processDefaultMatrix(UInt sizeId, UInt listId) +{ + ::memcpy(getScalingListAddress(sizeId, listId),getScalingListDefaultAddress(sizeId,listId),sizeof(Int)*min(MAX_MATRIX_COEF_NUM,(Int)g_scalingListSize[sizeId])); + setScalingListDC(sizeId,listId,SCALING_LIST_DC); +} + +/** check DC value of matrix for default matrix signaling + */ +Void TComScalingList::checkDcOfMatrix() +{ + for(UInt sizeId = 0; sizeId < SCALING_LIST_SIZE_NUM; sizeId++) + { + for(UInt listId = 0; listId < SCALING_LIST_NUM; listId++) + { + //check default matrix? + if(getScalingListDC(sizeId,listId) == 0) + { + processDefaultMatrix(sizeId, listId); + } + } + } +} + +ParameterSetManager::ParameterSetManager() +: m_vpsMap(MAX_NUM_VPS) +, m_spsMap(MAX_NUM_SPS) +, m_ppsMap(MAX_NUM_PPS) +, m_activeVPSId(-1) +, m_activeSPSId(-1) +, m_activePPSId(-1) +{ +} + + +ParameterSetManager::~ParameterSetManager() +{ +} + +//! activate a SPS from a active parameter sets SEI message +//! \returns true, if activation is successful +Bool ParameterSetManager::activateSPSWithSEI(Int spsId) +{ + TComSPS *sps = m_spsMap.getPS(spsId); + if (sps) + { + Int vpsId = sps->getVPSId(); + if (m_vpsMap.getPS(vpsId)) + { + m_activeVPSId = vpsId; + m_activeSPSId = spsId; + return true; + } + else + { + printf("Warning: tried to activate SPS using an Active parameter sets SEI message. Referenced VPS does not exist."); + } + } + else + { + printf("Warning: tried to activate non-existing SPS using an Active parameter sets SEI message."); + } + return false; +} + +//! activate a PPS and depending on isIDR parameter also SPS and VPS +//! \returns true, if activation is successful +Bool ParameterSetManager::activatePPS(Int ppsId, Bool isIRAP) +{ + TComPPS *pps = m_ppsMap.getPS(ppsId); + if (pps) + { + Int spsId = pps->getSPSId(); + if (!isIRAP && (spsId != m_activeSPSId)) + { + printf("Warning: tried to activate PPS referring to a inactive SPS at non-IDR."); + return false; + } + TComSPS *sps = m_spsMap.getPS(spsId); + if (sps) + { + Int vpsId = sps->getVPSId(); + if (!isIRAP && (vpsId != m_activeVPSId)) + { + printf("Warning: tried to activate PPS referring to a inactive VPS at non-IDR."); + return false; + } + if (m_vpsMap.getPS(vpsId)) + { + m_activePPSId = ppsId; + m_activeVPSId = vpsId; + m_activeSPSId = spsId; + return true; + } + else + { + printf("Warning: tried to activate PPS that refers to a non-existing VPS."); + } + } + else + { + printf("Warning: tried to activate a PPS that refers to a non-existing SPS."); + } + } + else + { + printf("Warning: tried to activate non-existing PPS."); + } + return false; +} + +ProfileTierLevel::ProfileTierLevel() + : m_profileSpace (0) + , m_tierFlag (Level::MAIN) + , m_profileIdc (Profile::NONE) + , m_levelIdc (Level::NONE) + , m_progressiveSourceFlag (false) + , m_interlacedSourceFlag (false) + , m_nonPackedConstraintFlag(false) + , m_frameOnlyConstraintFlag(false) +{ + ::memset(m_profileCompatibilityFlag, 0, sizeof(m_profileCompatibilityFlag)); +} + +TComPTL::TComPTL() +{ + ::memset(m_subLayerProfilePresentFlag, 0, sizeof(m_subLayerProfilePresentFlag)); + ::memset(m_subLayerLevelPresentFlag, 0, sizeof(m_subLayerLevelPresentFlag )); +} + + +//! \}