Void TComSlice::decodingRefMarkingForLD( TComList<TComPic*>& rcListPic, Int iMaxNumRefFrames, Int iCurrentPOC ) { assert( iMaxNumRefFrames >= 1 ); while( getActualRefNumber( rcListPic ) > iMaxNumRefFrames ) { sortPicList( rcListPic ); TComList<TComPic*>::iterator it = rcListPic.begin(); while( it != rcListPic.end() ) { if ( (*it)->getSlice(0)->isReferenced() && (*it)->getSlice(0)->getPOC() != iCurrentPOC && (*it)->getSlice(0)->getPOC() % 4 != 0 ) { (*it)->getSlice(0)->setReferenced( false ); // mark POC%4!=0 as unused for reference break; } it++; } if ( it == rcListPic.end() ) // all the reference frames POC%4== 0, mark the first reference frame as unused for reference { it = rcListPic.begin(); while( it != rcListPic.end() ) { if ( (*it)->getSlice(0)->isReferenced() ) { (*it)->getSlice(0)->setReferenced( false ); break; } it++; } } } }
Int TComSlice::getActualRefNumber( TComList<TComPic*>& rcListPic ) { Int iActualNumOfReference = 0; TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end() ) { TComPic* rpcPic = *(iterPic); if ( rpcPic->getSlice( 0 )->isReferenced() && rpcPic->getReconMark() ) { iActualNumOfReference++; } iterPic++; } return iActualNumOfReference; }
/** Function for marking reference pictures with higher temporal layer IDs as not used if the current picture is a temporal layer switching point. * \param rcListPic List of picture buffers * Both the encoder and decoder call this function to mark reference pictures with temporal layer ID higher than current picture's temporal layer ID as not used. */ Void TComSlice::decodingTLayerSwitchingMarking( TComList<TComPic*>& rcListPic ) { TComPic* rpcPic; if ( m_bTLayerSwitchingFlag ) { // mark all pictures of temporal layer > m_uiTLyr as not used for reference TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end() ) { rpcPic = *(iterPic); if ( rpcPic->getTLayer() > m_uiTLayer ) { rpcPic->getSlice( 0 )->setReferenced( false ); } iterPic++; } } }
/** Function for mimicking decoder's reference picture buffer management. * \param rcListPic List of picture buffers * \param iGOPSIze Current GOP size * \param iMaxRefPicNum Maximum number of reference pictures allowed * The encoder calls this function to mimic the picture buffer management of the decoder in the function xGetNewPicBuffer. * This will ensure in the encoder that the pictures that does not exist in the decoder will not be used as reference. * TODO: This assumes that the new pics are added at the end of the list. * This needs to be changed for the general case including for the long-term ref pics. * In the future, we should create a single common function for both the encoder and decoder. */ Void TComSlice::decodingMarking( TComList<TComPic*>& rcListPic, Int iGOPSIze, Int& iMaxRefPicNum ) { Int iActualNumOfReference = 0; TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end() ) { TComPic* rpcPic = *(iterPic); if ( rpcPic->getSlice( 0 )->isReferenced() ) { if ( rpcPic != getPic() ) { iActualNumOfReference++; } } iterPic++; } // TODO: This assumes that the new pics are added at the end of the list // This needs to be changed for the general case including for the long-term ref pics iMaxRefPicNum = max(iMaxRefPicNum, max(max(2, getNumRefIdx(REF_PIC_LIST_0)+1), iGOPSIze/2 + 2 + getNumRefIdx(REF_PIC_LIST_0))); if ( iActualNumOfReference >= iMaxRefPicNum ) { Int iNumToBeReset = iActualNumOfReference - iMaxRefPicNum + 1; iterPic = rcListPic.begin(); while ( iterPic != rcListPic.end() && iNumToBeReset > 0 ) { TComPic* rpcPic = *(iterPic); if ( rpcPic->getSlice( 0 )->isReferenced() ) { rpcPic->getSlice( 0 )->setReferenced( false ); iNumToBeReset--; } iterPic++; } } }
/** Function for marking the reference pictures when an IDR and CDR is encountered. * \param uiPOCCDR POC of the CDR 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 all pictures in the reference picture list * is marked as "unused for reference" * Otherwise do for the CDR case (non CDR case has no effect since both if conditions below will not be true) * 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 CDR picture (uiPOCCDR), * mark all reference pictures except the latest CDR picture as "unused for reference" and set * the bRefreshPending flag to false. * If the nal_unit_type is CDR, set the bRefreshPending flag to true and iPOCCDR 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(UInt& uiPOCCDR, Bool& bRefreshPending, TComList<TComPic*>& rcListPic) { TComPic* rpcPic; UInt uiPOCCurr = getPOC(); if (getNalUnitType() == NAL_UNIT_CODED_SLICE_IDR) // IDR { // 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() != uiPOCCurr) rpcPic->getSlice(0)->setReferenced(false); iterPic++; } } else // CDR or No DR { if (bRefreshPending==true && uiPOCCurr > uiPOCCDR) // CDR reference marking pending { TComList<TComPic*>::iterator iterPic = rcListPic.begin(); while (iterPic != rcListPic.end()) { rpcPic = *(iterPic); if (rpcPic->getPOC() != uiPOCCurr && rpcPic->getPOC() != uiPOCCDR) rpcPic->getSlice(0)->setReferenced(false); iterPic++; } bRefreshPending = false; } if (getNalUnitType() == NAL_UNIT_CODED_SLICE_CDR) // CDR picture found { bRefreshPending = true; uiPOCCDR = uiPOCCurr; } } }
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* TAppDecTop::xGetPicFromView( Int viewId, Int poc, Bool isDepth ) { assert( ( viewId >= 0 ) ); #if FLEX_CODING_ORDER_M23723 if (getTDecTop(viewId,isDepth)) { TComList<TComPic*>* apcListPic = getTDecTop( viewId, isDepth )->getListPic(); TComPic* pcPic = NULL; for( TComList<TComPic*>::iterator it=apcListPic->begin(); it!=apcListPic->end(); it++ ) { if( (*it)->getPOC() == poc ) { pcPic = *it; break; } } return pcPic; } else return NULL; #else TComList<TComPic*>* apcListPic = getTDecTop( viewId, isDepth )->getListPic(); TComPic* pcPic = NULL; for( TComList<TComPic*>::iterator it=apcListPic->begin(); it!=apcListPic->end(); it++ ) { if( (*it)->getPOC() == poc ) { pcPic = *it; break; } } return pcPic; #endif }
Void TComSlice::setRefPicList ( TComList<TComPic*>& rcListPic ) { if (m_eSliceType == I_SLICE) { ::memset( m_apcRefPicList, 0, sizeof (m_apcRefPicList)); ::memset( m_aiNumRefIdx, 0, sizeof ( m_aiNumRefIdx )); return; } m_aiNumRefIdx[0] = min ( m_aiNumRefIdx[0], (Int)(rcListPic.size())-1 ); m_aiNumRefIdx[1] = min ( m_aiNumRefIdx[1], (Int)(rcListPic.size())-1 ); sortPicList(rcListPic); TComPic* pcRefPic; for (Int n = 0; n < 2; n++) { RefPicList eRefPicList = (RefPicList)n; UInt uiOrderDRB = 1; UInt uiOrderERB = 1; Int iRefIdx = 0; UInt uiActualListSize = 0; if ( m_eSliceType == P_SLICE && eRefPicList == REF_PIC_LIST_1 ) { m_aiNumRefIdx[eRefPicList] = 0; ::memset( m_apcRefPicList[eRefPicList], 0, sizeof(m_apcRefPicList[eRefPicList])); break; } // First DRB pcRefPic = xGetRefPic(rcListPic, true, ERB_NONE, m_iPOC, eRefPicList, uiOrderDRB, m_uiTLayer); if (pcRefPic != NULL) { m_apcRefPicList[eRefPicList][iRefIdx] = pcRefPic; pcRefPic->getPicYuvRec()->extendPicBorder(); iRefIdx++; uiOrderDRB++; uiActualListSize++; } if ( (Int)uiActualListSize >= m_aiNumRefIdx[eRefPicList] ) { m_aiNumRefIdx[eRefPicList] = uiActualListSize; continue; } // Long term reference // Should be enabled to support long term refernce //* // First ERB pcRefPic = xGetRefPic(rcListPic, false, ERB_LTR, m_iPOC, eRefPicList, uiOrderERB, m_uiTLayer); if (pcRefPic != NULL) { Bool bChangeDrbErb = false; if (iRefIdx > 0 && eRefPicList == REF_PIC_LIST_0 && pcRefPic->getPOC() > m_apcRefPicList[eRefPicList][iRefIdx-1]->getPOC()) { bChangeDrbErb = true; } else if (iRefIdx > 0 && eRefPicList == REF_PIC_LIST_1 && pcRefPic->getPOC() < m_apcRefPicList[eRefPicList][iRefIdx-1]->getPOC()) { bChangeDrbErb = true; } if ( bChangeDrbErb) { m_apcRefPicList[eRefPicList][iRefIdx] = m_apcRefPicList[eRefPicList][iRefIdx-1]; m_apcRefPicList[eRefPicList][iRefIdx-1] = pcRefPic; } else { m_apcRefPicList[eRefPicList][iRefIdx] = pcRefPic; } pcRefPic->getPicYuvRec()->extendPicBorder(); iRefIdx++; uiOrderERB++; uiActualListSize++; } //*/ // Short term reference // Residue DRB UInt uiBreakCount = 17 - iRefIdx; while (1) { uiBreakCount--; if ( (Int)uiActualListSize >= m_aiNumRefIdx[eRefPicList] || uiBreakCount == 0 ) { break; } pcRefPic = xGetRefPic(rcListPic, true, ERB_NONE, m_iPOC, eRefPicList, uiOrderDRB, m_uiTLayer); if (pcRefPic != NULL) { uiOrderDRB++; } if (pcRefPic != NULL) { m_apcRefPicList[eRefPicList][iRefIdx] = pcRefPic; pcRefPic->getPicYuvRec()->extendPicBorder(); iRefIdx++; uiActualListSize++; } } m_aiNumRefIdx[eRefPicList] = uiActualListSize; } }
Void TEncTop::encode(Bool flush, TComPicYuv* pcPicYuvOrg, TComPicYuv* pcPicYuvTrueOrg, const InputColourSpaceConversion snrCSC, TComList<TComPicYuv*>& rcListPicYuvRecOut, std::list<AccessUnit>& accessUnitsOut, Int& iNumEncoded, Bool isTff) { iNumEncoded = 0; for (Int fieldNum=0; fieldNum<2; fieldNum++) { if (pcPicYuvOrg) { /* -- field initialization -- */ const Bool isTopField=isTff==(fieldNum==0); TComPic *pcField; xGetNewPicBuffer( pcField ); pcField->setReconMark (false); // where is this normally? if (fieldNum==1) // where is this normally? { TComPicYuv* rpcPicYuvRec; // org. buffer if ( rcListPicYuvRecOut.size() >= (UInt)m_iGOPSize+1 ) // need to maintain field 0 in list of RecOuts while processing field 1. Hence +1 on m_iGOPSize. { rpcPicYuvRec = rcListPicYuvRecOut.popFront(); } else { rpcPicYuvRec = new TComPicYuv; rpcPicYuvRec->create( m_iSourceWidth, m_iSourceHeight, m_chromaFormatIDC, m_maxCUWidth, m_maxCUHeight, m_maxTotalCUDepth, true); } rcListPicYuvRecOut.pushBack( rpcPicYuvRec ); } pcField->getSlice(0)->setPOC( m_iPOCLast ); // superfluous? pcField->getPicYuvRec()->setBorderExtension(false);// where is this normally? pcField->setTopField(isTopField); // interlaced requirement for (UInt componentIndex = 0; componentIndex < pcPicYuvOrg->getNumberValidComponents(); componentIndex++) { const ComponentID component = ComponentID(componentIndex); const UInt stride = pcPicYuvOrg->getStride(component); separateFields((pcPicYuvOrg->getBuf(component) + pcPicYuvOrg->getMarginX(component) + (pcPicYuvOrg->getMarginY(component) * stride)), pcField->getPicYuvOrg()->getAddr(component), pcPicYuvOrg->getStride(component), pcPicYuvOrg->getWidth(component), pcPicYuvOrg->getHeight(component), isTopField); separateFields((pcPicYuvTrueOrg->getBuf(component) + pcPicYuvTrueOrg->getMarginX(component) + (pcPicYuvTrueOrg->getMarginY(component) * stride)), pcField->getPicYuvTrueOrg()->getAddr(component), pcPicYuvTrueOrg->getStride(component), pcPicYuvTrueOrg->getWidth(component), pcPicYuvTrueOrg->getHeight(component), isTopField); } // compute image characteristics if ( getUseAdaptiveQP() ) { m_cPreanalyzer.xPreanalyze( dynamic_cast<TEncPic*>( pcField ) ); } } if ( m_iNumPicRcvd && ((flush&&fieldNum==1) || (m_iPOCLast/2)==0 || m_iNumPicRcvd==m_iGOPSize ) ) { // compress GOP m_cGOPEncoder.compressGOP(m_iPOCLast, m_iNumPicRcvd, m_cListPic, rcListPicYuvRecOut, accessUnitsOut, true, isTff, snrCSC, m_printFrameMSE,&m_cSearch); iNumEncoded += m_iNumPicRcvd; m_uiNumAllPicCoded += m_iNumPicRcvd; m_iNumPicRcvd = 0; } } }