ref: edba95536681d8c589ed6dccc1b88a8499a98d3b
dir: /codec/decoder/core/src/manage_dec_ref.cpp/
/*! * \copy * Copyright (c) 2008-2013, Cisco Systems * 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. * * 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. * * * manage_ref_pic.cpp * * Abstract * Implementation for managing reference picture * * History * 07/21/2008 Created * *****************************************************************************/ #include <string.h> #include "manage_dec_ref.h" #include "error_code.h" #include "utils.h" #include "as264_common.h" // for LTR macro can be delete later namespace WelsDec { static void_t SetUnRef(PPicture pRef) { if( NULL != pRef) { pRef->bUsedAsRef = false; pRef->bIsLongRef = false; pRef->iFrameNum = -1; pRef->iFramePoc = 0; pRef->iLongTermFrameIdx = -1; pRef->bRefBaseFlag = 0; pRef->uiQualityId = -1; pRef->uiTemporalId = -1; pRef->uiSpatialId = -1; pRef->iSpsId = -1; } } //reset pRefList when // 1.sps arrived that is new sequence starting // 2.IDR NAL i.e. 1st layer in IDR AU void_t WelsResetRefPic(PWelsDecoderContext pCtx) { int32_t i = 0; PRefPic pRefPic = &pCtx->sRefPic; pCtx->sRefPic.uiLongRefCount[0] = pCtx->sRefPic.uiShortRefCount[0] = 0; pRefPic->uiRefCount[LIST_0] = 0; for(i=0; i < MAX_SHORT_REF_COUNT; i++) { if ( pRefPic->pShortRefList[LIST_0][i] != NULL){ SetUnRef(pRefPic->pShortRefList[LIST_0][i]); pRefPic->pShortRefList[LIST_0][i] = NULL; } } pRefPic->uiShortRefCount[LIST_0] = 0; for(i=0; i < MAX_LONG_REF_COUNT; i++){ if (pRefPic->pLongRefList[LIST_0][i] != NULL) { SetUnRef(pRefPic->pLongRefList[LIST_0][i]); pRefPic->pLongRefList[LIST_0][i] = NULL; } } pRefPic->uiLongRefCount[LIST_0] = 0; } /** * fills the pRefPic.pRefList. */ int32_t WelsInitRefList(PWelsDecoderContext pCtx, int32_t iPoc) { int32_t i,j, iCount=0; const bool_t kbUseRefBasePicFlag = pCtx->pCurDqLayer->bUseRefBasePicFlag; PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0]; memset(pCtx->sRefPic.pRefList[LIST_0],0,MAX_REF_PIC_COUNT*sizeof(PPicture)); //short for(i=0; i<pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i){ if( kbUseRefBasePicFlag == ppShoreRefList[i]->bRefBaseFlag ) { pCtx->sRefPic.pRefList[LIST_0][iCount++ ]= ppShoreRefList[i]; }else{ for ( j = 0;j<pCtx->sRefPic.uiShortRefCount[LIST_0];++j) { if (ppShoreRefList[j]->iFrameNum == ppShoreRefList[i]->iFrameNum && ppShoreRefList[j]->bRefBaseFlag == kbUseRefBasePicFlag) { break; } } if (j == pCtx->sRefPic.uiShortRefCount[LIST_0]) { pCtx->sRefPic.pRefList[LIST_0][iCount++] = ppShoreRefList[i]; } } } //long j = 0; for(i=0; i< pCtx->sRefPic.uiLongRefCount[LIST_0] ; ++i){ if(kbUseRefBasePicFlag == ppLongRefList[i]->bRefBaseFlag){ pCtx->sRefPic.pRefList[LIST_0][iCount++ ]= ppLongRefList[i]; }else{ for ( j = 0;j<pCtx->sRefPic.uiLongRefCount[LIST_0];++j) { if (ppLongRefList[j]->iLongTermFrameIdx == ppLongRefList[i]->iLongTermFrameIdx && ppLongRefList[j]->bRefBaseFlag == kbUseRefBasePicFlag) { break; } } if (j == pCtx->sRefPic.uiLongRefCount[LIST_0]) { pCtx->sRefPic.pRefList[LIST_0][iCount++] = ppLongRefList[i]; } } } pCtx->sRefPic.uiRefCount[LIST_0] = iCount; return ERR_NONE; } int32_t WelsReorderRefList(PWelsDecoderContext pCtx) { PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering; PNalUnitHeaderExt pNalHeaderExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt; PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader; PPicture pPic = NULL; PPicture* ppRefList = pCtx->sRefPic.pRefList[LIST_0]; int32_t iRefCount = pCtx->sRefPic.uiRefCount[LIST_0]; int32_t iPredFrameNum = pSliceHeader->iFrameNum; int32_t iMaxPicNum = 1<<pSliceHeader->pSps->uiLog2MaxFrameNum; int32_t iAbsDiffPicNum = -1; int32_t iReorderingIndex = 0; int32_t i = 0; if(pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) { return ERR_NONE; } if ( iRefCount <= 0 ) { pCtx->iErrorCode = dsNoParamSets; //No any reference for decoding, SHOULD request IDR return ERR_INFO_REFERENCE_PIC_LOST; } if (pRefPicListReorderSyn->bRefPicListReorderingFlag[LIST_0]){ while (pRefPicListReorderSyn->sReorderingSyn[LIST_0][iReorderingIndex].uiReorderingOfPicNumsIdc != 3) { uint16_t uiReorderingOfPicNumsIdc = pRefPicListReorderSyn->sReorderingSyn[LIST_0][iReorderingIndex].uiReorderingOfPicNumsIdc; if (uiReorderingOfPicNumsIdc <2){ iAbsDiffPicNum = pRefPicListReorderSyn->sReorderingSyn[LIST_0][iReorderingIndex].uiAbsDiffPicNumMinus1 + 1; if (uiReorderingOfPicNumsIdc == 0){ iPredFrameNum -= iAbsDiffPicNum; }else{ iPredFrameNum += iAbsDiffPicNum; } iPredFrameNum &= iMaxPicNum-1; for( i= iRefCount-1; i>=iReorderingIndex; i--){ if (ppRefList[i]->iFrameNum == iPredFrameNum && !ppRefList[i]->bIsLongRef) { if( ( pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId ) && ( pSliceHeader->iSpsId != ppRefList[i]->iSpsId ) )//check; { WelsLog( pCtx, WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d\n",pSliceHeader->iSpsId, ppRefList[i]->iSpsId ); pCtx->iErrorCode = dsNoParamSets; //cross-IDR reference frame selection, SHOULD request IDR.-- return ERR_INFO_REFERENCE_PIC_LOST; }else{ break; } } } }else if (uiReorderingOfPicNumsIdc == 2){ for( i = iRefCount -1; i>=iReorderingIndex; i--){ if( ppRefList[i]->bIsLongRef && ppRefList[i]->iLongTermFrameIdx == pRefPicListReorderSyn->sReorderingSyn[LIST_0][iReorderingIndex].uiLongTermPicNum ) { if ( ( pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId ) && ( pSliceHeader->iSpsId != ppRefList[i]->iSpsId ) )//check; { WelsLog( pCtx, WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d\n",pSliceHeader->iSpsId, ppRefList[i]->iSpsId ); pCtx->iErrorCode = dsNoParamSets; //cross-IDR reference frame selection, SHOULD request IDR.-- return ERR_INFO_REFERENCE_PIC_LOST; }else{ break; } } } } if (i < 0) { return ERR_INFO_REFERENCE_PIC_LOST; } pPic = ppRefList[i]; memmove(&ppRefList[1+iReorderingIndex], &ppRefList[iReorderingIndex], (i-iReorderingIndex)*sizeof(PPicture));//confirmed_safe_unsafe_usage ppRefList[iReorderingIndex]= pPic; iReorderingIndex++; } } return ERR_NONE; } int32_t WelsMarkAsRef(PWelsDecoderContext pCtx, const bool_t kbRefBaseMarkingFlag) { PRefPic pRefPic = &pCtx->sRefPic; PRefPicMarking pRefPicMarking = pCtx->pCurDqLayer->pRefPicMarking; PRefBasePicMarking pRefPicBaseMarking =pCtx->pCurDqLayer->pRefPicBaseMarking; PAccessUnit pCurAU = pCtx->pAccessUnitList; bool_t bIsIDRAU = FALSE; uint32_t j; int32_t iRet = ERR_NONE; if(pCtx->pCurDqLayer->bStoreRefBasePicFlag && (pCtx->pSps->iNumRefFrames<2)){ return ERR_INFO_INVALID_MMCO_REF_NUM_NOT_ENOUGH; } pCtx->pDec->bUsedAsRef = TRUE; pCtx->pDec->uiQualityId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiQualityId; pCtx->pDec->uiTemporalId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiTemporalId; pCtx->pDec->bRefBaseFlag = kbRefBaseMarkingFlag; for( j = pCurAU->uiStartPos; j <= pCurAU->uiEndPos; j++ ) { if (pCurAU->pNalUnitsList[j]->sNalHeaderExt.sNalUnitHeader.eNalUnitType== NAL_UNIT_CODED_SLICE_IDR|| pCurAU->pNalUnitsList[j]->sNalHeaderExt.bIdrFlag) { bIsIDRAU = TRUE; break; } } if(bIsIDRAU){ if (pRefPicMarking->bLongTermRefFlag){ pCtx->sRefPic.iMaxLongTermFrameIdx = 0; AddLongTermToList(pRefPic,pCtx->pDec,0); }else{ pCtx->sRefPic.iMaxLongTermFrameIdx = -1; } }else{ if (pRefPicBaseMarking->bAdaptiveRefBasePicMarkingModeFlag){ iRet = MMCOBase(pCtx,pRefPicBaseMarking); } if (iRet != ERR_NONE){ return iRet; } if (pRefPicMarking->bAdaptiveRefPicMarkingModeFlag){ iRet = MMCO(pCtx,pRefPicMarking); if( pCtx->bLastHasMmco5 ) { pCtx->pDec->iFrameNum = 0; pCtx->pDec->iFramePoc = 0; } if (pRefPic->uiLongRefCount[LIST_0]+pRefPic->uiShortRefCount[LIST_0] > pCtx->pSps->iNumRefFrames){ return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW; } }else{ iRet = SlidingWindow(pCtx); } } if (!pCtx->pDec->bIsLongRef){ AddShortTermToList(pRefPic,pCtx->pDec); } return iRet; } static int32_t MMCOBase(PWelsDecoderContext pCtx,PRefBasePicMarking pRefPicBaseMarking) { PSps pSps = pCtx->pCurDqLayer->sLayerInfo.pSps; int32_t i = 0; int32_t iRet = ERR_NONE; for ( i = 0 ; pRefPicBaseMarking->mmco_base[i].uiMmcoType != MMCO_END; i++){ uint32_t uiMmcoType = pRefPicBaseMarking->mmco_base[i].uiMmcoType; int32_t iShortFrameNum = (pCtx->iFrameNum - pRefPicBaseMarking->mmco_base[i].uiDiffOfPicNums) &((1<<pSps->uiLog2MaxFrameNum)-1); uint32_t uiLongTermPicNum = pRefPicBaseMarking->mmco_base[i].uiLongTermPicNum; if ( uiMmcoType > MMCO_LONG2UNUSED) { return ERR_INFO_INVALID_MMCO_OPCODE_BASE; } iRet = MMCOProcess(pCtx,uiMmcoType,TRUE,iShortFrameNum,uiLongTermPicNum,0,0); if (iRet != ERR_NONE){ return iRet; } } return ERR_NONE; } static int32_t MMCO(PWelsDecoderContext pCtx,PRefPicMarking pRefPicMarking) { PSps pSps = pCtx->pCurDqLayer->sLayerInfo.pSps; int32_t i = 0; int32_t iRet = ERR_NONE; for ( i = 0; pRefPicMarking->sMmcoRef[i].uiMmcoType != MMCO_END; i++){ uint32_t uiMmcoType = pRefPicMarking->sMmcoRef[i].uiMmcoType; int32_t iShortFrameNum = (pCtx->iFrameNum - pRefPicMarking->sMmcoRef[i].iDiffOfPicNum) & ((1<<pSps->uiLog2MaxFrameNum)-1); uint32_t uiLongTermPicNum = pRefPicMarking->sMmcoRef[i].uiLongTermPicNum; int32_t iLongTermFrameIdx = pRefPicMarking->sMmcoRef[i].iLongTermFrameIdx; int32_t iMaxLongTermFrameIdx = pRefPicMarking->sMmcoRef[i].iMaxLongTermFrameIdx; if ( uiMmcoType > MMCO_LONG) { return ERR_INFO_INVALID_MMCO_OPCODE_BASE; } iRet = MMCOProcess(pCtx,uiMmcoType,FALSE,iShortFrameNum,uiLongTermPicNum,iLongTermFrameIdx,iMaxLongTermFrameIdx); if (iRet != ERR_NONE){ return iRet; } } return ERR_NONE; } static int32_t MMCOProcess( PWelsDecoderContext pCtx,uint32_t uiMmcoType,bool_t bRefBasePic, int32_t iShortFrameNum,uint32_t uiLongTermPicNum ,int32_t iLongTermFrameIdx,int32_t iMaxLongTermFrameIdx ) { PRefPic pRefPic = &pCtx->sRefPic; PPicture pPic = NULL; int32_t i = 0; int32_t iRet = ERR_NONE; switch (uiMmcoType) { case MMCO_SHORT2UNUSED: pPic = WelsDelShortFromListSetUnref(pRefPic,iShortFrameNum,(ERemoveFlag) bRefBasePic); break; case MMCO_LONG2UNUSED: pPic = WelsDelLongFromListSetUnref(pRefPic,uiLongTermPicNum,(ERemoveFlag) bRefBasePic); break; case MMCO_SHORT2LONG: if(iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx){ return ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX; } pPic = WelsDelShortFromList(pRefPic,iShortFrameNum,REMOVE_TARGET); WelsDelLongFromListSetUnref(pRefPic,iLongTermFrameIdx,REMOVE_TARGET); WelsDelShortFromList(pRefPic,iShortFrameNum,REMOVE_BASE); WelsDelLongFromListSetUnref(pRefPic,iLongTermFrameIdx,REMOVE_BASE); #ifdef LONG_TERM_REF pCtx->bCurAuContainLtrMarkSeFlag = true; pCtx->iFrameNumOfAuMarkedLtr = iShortFrameNum; WelsLog( pCtx, WELS_LOG_INFO, "ex_mark_avc():::MMCO_SHORT2LONG:::LTR marking....iFrameNum: %d\n", pCtx->iFrameNumOfAuMarkedLtr ); #endif MarkAsLongTerm(pRefPic,iShortFrameNum,iLongTermFrameIdx); break; case MMCO_SET_MAX_LONG: pRefPic->iMaxLongTermFrameIdx = iMaxLongTermFrameIdx; for (i = 0 ;i <pRefPic->uiLongRefCount[LIST_0];i++) { if (pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx) { WelsDelLongFromListSetUnref(pRefPic,pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx,REMOVE_BASE_FIRST); } } break; case MMCO_RESET: WelsResetRefPic(pCtx); pCtx->bLastHasMmco5 = true; break; case MMCO_LONG: if(iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx){ return ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX; } #ifdef LONG_TERM_REF pCtx->bCurAuContainLtrMarkSeFlag = true; pCtx->iFrameNumOfAuMarkedLtr = pCtx->iFrameNum; WelsLog( pCtx, WELS_LOG_INFO, "ex_mark_avc():::MMCO_LONG:::LTR marking....iFrameNum: %d\n", pCtx->iFrameNum ); #endif WelsDelLongFromListSetUnref(pRefPic,iLongTermFrameIdx,REMOVE_TARGET); WelsDelLongFromListSetUnref(pRefPic,iLongTermFrameIdx,REMOVE_BASE); iRet = AddLongTermToList(pRefPic,pCtx->pDec,iLongTermFrameIdx); break; default : break; } return iRet; } static int32_t SlidingWindow( PWelsDecoderContext pCtx ) { PRefPic pRefPic = &pCtx->sRefPic; PPicture pPic = NULL; int32_t i = 0; if (pCtx->sRefPic.uiShortRefCount[LIST_0] +pCtx->sRefPic.uiLongRefCount[LIST_0] >= pCtx->pSps->iNumRefFrames){ for ( i = pRefPic->uiShortRefCount[LIST_0] -1;i>=0;i--){ pPic = WelsDelShortFromList(pRefPic,pRefPic->pShortRefList[LIST_0][i]->iFrameNum,REMOVE_BASE_FIRST); if (pPic){ SetUnRef(pPic); break; }else{ return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW; } } } return ERR_NONE; } static PPicture WelsDelShortFromList(PRefPic pRefPic, int32_t iFrameNum, ERemoveFlag eRemoveFlag) { int32_t i = 0; int32_t iMoveSize = 0; PPicture pPic = NULL; for(i=0; i<pRefPic->uiShortRefCount[LIST_0]; i++){ if( pRefPic->pShortRefList[LIST_0][i]->iFrameNum == iFrameNum) { if( ( eRemoveFlag == REMOVE_TARGET && !pRefPic->pShortRefList[LIST_0][i]->bRefBaseFlag ) ||( eRemoveFlag == REMOVE_BASE && pRefPic->pShortRefList[LIST_0][i]->bRefBaseFlag) ||(eRemoveFlag == REMOVE_BASE_FIRST ) ) { iMoveSize = pRefPic->uiShortRefCount[LIST_0] - i - 1; pRefPic->pShortRefList[LIST_0][i]->bUsedAsRef = false; pPic = pRefPic->pShortRefList[LIST_0][i]; pRefPic->pShortRefList[LIST_0][i]= NULL; if (iMoveSize > 0){ memmove(&pRefPic->pShortRefList[LIST_0][i], &pRefPic->pShortRefList[LIST_0][i+1], iMoveSize * sizeof(PPicture));//confirmed_safe_unsafe_usage } pRefPic->uiShortRefCount[LIST_0]--; pRefPic->pShortRefList[LIST_0][pRefPic->uiShortRefCount[0]] = NULL; break; } } } return pPic; } static PPicture WelsDelShortFromListSetUnref(PRefPic pRefPic, int32_t iFrameNum, ERemoveFlag eRemoveFlag) { PPicture pPic = WelsDelShortFromList(pRefPic,iFrameNum,eRemoveFlag); if (pPic){ SetUnRef(pPic); } return pPic; } static PPicture WelsDelLongFromList(PRefPic pRefPic, uint32_t uiLongTermFrameIdx, ERemoveFlag eRemoveFlag) { PPicture pPic = NULL; int32_t i = 0; for ( i = 0;i<pRefPic->uiLongRefCount[LIST_0];i++) { pPic = pRefPic->pLongRefList[LIST_0][i]; if ( pPic->iLongTermFrameIdx == (int32_t)uiLongTermFrameIdx) { if( ((eRemoveFlag == REMOVE_TARGET) && !(pPic->bRefBaseFlag)) || ((eRemoveFlag == REMOVE_BASE) && pPic->bRefBaseFlag) ) { int32_t iMoveSize = pRefPic->uiLongRefCount[LIST_0] - i - 1; pPic->bUsedAsRef = FALSE; pPic->bIsLongRef = FALSE; if (iMoveSize > 0){ memmove(&pRefPic->pLongRefList[LIST_0][i], &pRefPic->pLongRefList[LIST_0][i+1], iMoveSize * sizeof(PPicture));//confirmed_safe_unsafe_usage } pRefPic->uiLongRefCount[LIST_0]--; pRefPic->pLongRefList[LIST_0][pRefPic->uiLongRefCount[LIST_0]] = NULL; return pPic; } } } return NULL; } static PPicture WelsDelLongFromListSetUnref(PRefPic pRefPic, uint32_t uiLongTermFrameIdx, ERemoveFlag eRemoveFlag) { PPicture pPic = WelsDelLongFromList(pRefPic,uiLongTermFrameIdx,eRemoveFlag); if (pPic){ SetUnRef(pPic); } return pPic; } static int32_t AddShortTermToList(PRefPic pRefPic,PPicture pPic) { pPic->bUsedAsRef = TRUE; pPic->bIsLongRef = FALSE; pPic->iLongTermFrameIdx = -1; if (pRefPic->uiShortRefCount[LIST_0]>0) { memmove(&pRefPic->pShortRefList[LIST_0][1],&pRefPic->pShortRefList[LIST_0][0],pRefPic->uiShortRefCount[LIST_0]*sizeof(PPicture));//confirmed_safe_unsafe_usage } pRefPic->pShortRefList[LIST_0][0] = pPic; pRefPic->uiShortRefCount[LIST_0]++; return ERR_NONE; } static int32_t AddLongTermToList(PRefPic pRefPic,PPicture pPic, int32_t iLongTermFrameIdx) { int32_t i = 0; pPic->bUsedAsRef = TRUE; pPic->bIsLongRef = TRUE; pPic->iLongTermFrameIdx = iLongTermFrameIdx; if (pRefPic->uiLongRefCount[LIST_0] == 0){ pRefPic->pLongRefList[LIST_0][pRefPic->uiLongRefCount[LIST_0]] = pPic; }else if (pRefPic->uiLongRefCount[LIST_0] >0){ for ( i = 0; i<pRefPic->uiLongRefCount[LIST_0];i++){ if (pRefPic->pLongRefList[LIST_0][i]->iLongTermFrameIdx > pPic->iLongTermFrameIdx) { break; } } memmove(&pRefPic->pLongRefList[LIST_0][i+1],&pRefPic->pLongRefList[LIST_0][i],(pRefPic->uiLongRefCount[LIST_0]-i)*sizeof(PPicture));//confirmed_safe_unsafe_usage pRefPic->pLongRefList[LIST_0][i] = pPic; }else{ return ERR_INFO_REF_COUNT_OVERFLOW; } pRefPic->uiLongRefCount[LIST_0]++; return ERR_NONE; } static int32_t AssignLongTermIdx(PRefPic pRefPic,int32_t iFrameNum,int32_t iLongTermFrameIdx ) { PPicture pPic = NULL; int32_t iRet = ERR_NONE; WelsDelLongFromListSetUnref(pRefPic,iLongTermFrameIdx,REMOVE_TARGET); WelsDelLongFromListSetUnref(pRefPic,iLongTermFrameIdx,REMOVE_BASE); pPic = WelsDelShortFromList(pRefPic,iFrameNum,REMOVE_TARGET); if (pPic){ iRet = AddLongTermToList(pRefPic,pPic,iLongTermFrameIdx); }else{ return ERR_INFO_INVALID_REF_MARKING; } pPic = NULL; pPic = WelsDelShortFromList(pRefPic,iFrameNum,REMOVE_BASE); if (pPic){ iRet = AddLongTermToList(pRefPic,pPic,iLongTermFrameIdx); } return iRet; } static int32_t MarkAsLongTerm( PRefPic pRefPic,int32_t iFrameNum, int32_t iLongTermFrameIdx ) { PPicture pPic = NULL; int32_t i = 0; int32_t iRet = ERR_NONE; WelsDelLongFromListSetUnref(pRefPic,iLongTermFrameIdx,REMOVE_TARGET); WelsDelLongFromListSetUnref(pRefPic,iLongTermFrameIdx,REMOVE_BASE); for (i = 0; i<pRefPic->uiRefCount[LIST_0];i++) { pPic = pRefPic->pRefList[LIST_0][i]; if ( pPic->iFrameNum == iFrameNum && !pPic->bIsLongRef){ iRet = AddLongTermToList(pRefPic,pPic,iLongTermFrameIdx); } } return iRet; } } // namespace WelsDec