/*! * \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_dec_ref.cpp * * Abstract * Implementation for managing reference picture * * History * 07/21/2008 Created * *****************************************************************************/ #include "manage_dec_ref.h"#include "error_concealment.h"#include "error_code.h"#include "decoder.h" static PPicture WelsDelShortFromList (PRefPic pRefPic, int32_t iFrameNum);static PPicture WelsDelLongFromList (PRefPic pRefPic, uint32_t uiLongTermFrameIdx);static PPicture WelsDelShortFromListSetUnref (PRefPic pRefPic, int32_t iFrameNum);static PPicture WelsDelLongFromListSetUnref (PRefPic pRefPic, uint32_t uiLongTermFrameIdx); static int32_t MMCO (PWelsDecoderContext pCtx, PRefPic pRefPic, PRefPicMarking pRefPicMarking);static int32_t MMCOProcess (PWelsDecoderContext pCtx, PRefPic pRefPic, uint32_t uiMmcoType, int32_t iShortFrameNum, uint32_t uiLongTermPicNum, int32_t iLongTermFrameIdx, int32_t iMaxLongTermFrameIdx);static int32_t SlidingWindow (PWelsDecoderContext pCtx, PRefPic pRefPic); static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic);static int32_t AddLongTermToList (PRefPic pRefPic, PPicture pPic, int32_t iLongTermFrameIdx, uint32_t uiLongTermPicNum);static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLongTermFrameIdx, uint32_t uiLongTermPicNum);static int32_t WelsCheckAndRecoverForFutureDecoding (PWelsDecoderContext pCtx);#ifdef LONG_TERM_REFint32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum);#endifstatic int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx, PRefPic pRefPic); static void SetUnRef (PPicture pRef) { if (NULL != pRef) { pRef->bUsedAsRef = false; pRef->bIsLongRef = false; pRef->iFrameNum = -1; pRef->iFrameWrapNum = -1; //pRef->iFramePoc = 0; pRef->iLongTermFrameIdx = -1; pRef->uiLongTermPicNum = 0; pRef->uiQualityId = -1; pRef->uiTemporalId = -1; pRef->uiSpatialId = -1; pRef->iSpsId = -1; pRef->bIsComplete = false; pRef->iRefCount = 0; if (pRef->eSliceType == I_SLICE) { return; } int32_t lists = pRef->eSliceType == P_SLICE ? 1 : 2; for (int32_t i = 0; i < MAX_DPB_COUNT; ++i) { for (int32_t list = 0; list < lists; ++list) { if (pRef->pRefPic[list][i] != NULL) { pRef->pRefPic[list][i]->iRefCount = 0; pRef->pRefPic[list][i] = NULL; } } } }} //reset pRefList when// 1.sps arrived that is new sequence starting// 2.IDR NAL i.e. 1st layer in IDR AU void WelsResetRefPic (PWelsDecoderContext pCtx) { int32_t i; PRefPic pRefPic = &pCtx->sRefPic; pCtx->sRefPic.uiLongRefCount[LIST_0] = pCtx->sRefPic.uiShortRefCount[LIST_0] = 0; pRefPic->uiRefCount[LIST_0] = 0; pRefPic->uiRefCount[LIST_1] = 0; for (i = 0; i < MAX_DPB_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_DPB_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;} void WelsResetRefPicWithoutUnRef (PWelsDecoderContext pCtx) { int32_t i; PRefPic pRefPic = &pCtx->sRefPic; pCtx->sRefPic.uiLongRefCount[LIST_0] = pCtx->sRefPic.uiShortRefCount[LIST_0] = 0; pRefPic->uiRefCount[LIST_0] = 0; pRefPic->uiRefCount[LIST_1] = 0; for (i = 0; i < MAX_DPB_COUNT; i++) { pRefPic->pShortRefList[LIST_0][i] = NULL; } pRefPic->uiShortRefCount[LIST_0] = 0; for (i = 0; i < MAX_DPB_COUNT; i++) { pRefPic->pLongRefList[LIST_0][i] = NULL; } pRefPic->uiLongRefCount[LIST_0] = 0;} static int32_t WelsCheckAndRecoverForFutureDecoding (PWelsDecoderContext pCtx) { if ((pCtx->sRefPic.uiShortRefCount[LIST_0] + pCtx->sRefPic.uiLongRefCount[LIST_0] <= 0) && (pCtx->eSliceType != I_SLICE && pCtx->eSliceType != SI_SLICE)) { if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) { //IDR lost!, recover it for future decoding with data all set to 0 PPicture pRef = PrefetchPic (pCtx->pPicBuff); if (pRef != NULL) { // IDR lost, set new pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture pRef->iSpsId = pCtx->pSps->iSpsId; pRef->iPpsId = pCtx->pPps->iPpsId; if (pCtx->eSliceType == B_SLICE) { //reset reference's references when IDR is lost for (int32_t list = LIST_0; list < LIST_A; ++list) { for (int32_t i = 0; i < MAX_DPB_COUNT; ++i) { pRef->pRefPic[list][i] = NULL; } } } pCtx->iErrorCode |= dsDataErrorConcealed; bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc) || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc) || (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc) || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc) || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc)) && (NULL != pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb); bCopyPrevious = bCopyPrevious && (pRef->iWidthInPixel == pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iWidthInPixel) && (pRef->iHeightInPixel == pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iHeightInPixel); if (!bCopyPrevious) { memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel); memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2); memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2); } else if (pRef == pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsInitRefList()::EC memcpy overlap."); } else { memcpy (pRef->pData[0], pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->pData[0], pRef->iLinesize[0] * pRef->iHeightInPixel); memcpy (pRef->pData[1], pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->pData[1], pRef->iLinesize[1] * pRef->iHeightInPixel / 2); memcpy (pRef->pData[2], pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->pData[2], pRef->iLinesize[2] * pRef->iHeightInPixel / 2); } pRef->iFrameNum = 0; pRef->iFramePoc = 0; pRef->uiTemporalId = pRef->uiQualityId = 0; pRef->eSliceType = pCtx->eSliceType; ExpandReferencingPicture (pRef->pData, pRef->iWidthInPixel, pRef->iHeightInPixel, pRef->iLinesize, pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture); AddShortTermToList (&pCtx->sRefPic, pRef); } else { WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "WelsInitRefList()::PrefetchPic for EC errors."); pCtx->iErrorCode |= dsOutOfMemory; return ERR_INFO_REF_COUNT_OVERFLOW; } } } return ERR_NONE;} static void WrapShortRefPicNum (PWelsDecoderContext pCtx) { int32_t i; PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader; int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum; PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; int32_t iShortRefCount = pCtx->sRefPic.uiShortRefCount[LIST_0]; //wrap pic num for (i = 0; i < iShortRefCount; i++) { if (ppShoreRefList[i]) { if (ppShoreRefList[i]->iFrameNum > pSliceHeader->iFrameNum) ppShoreRefList[i]->iFrameWrapNum = ppShoreRefList[i]->iFrameNum - iMaxPicNum; else ppShoreRefList[i]->iFrameWrapNum = ppShoreRefList[i]->iFrameNum; } }} /*** fills the pRefPic.pRefList LIST_0 and LIST_0 for B-Slice.*/int32_t WelsInitBSliceRefList (PWelsDecoderContext pCtx, int32_t iPoc) { int32_t err = WelsCheckAndRecoverForFutureDecoding (pCtx); if (err != ERR_NONE) return err; WrapShortRefPicNum (pCtx); PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0]; memset (pCtx->sRefPic.pRefList[LIST_0], 0, MAX_DPB_COUNT * sizeof (PPicture)); memset (pCtx->sRefPic.pRefList[LIST_1], 0, MAX_DPB_COUNT * sizeof (PPicture)); int32_t iLSCurrPocCount = 0; int32_t iLTCurrPocCount = 0; PPicture pLSCurrPocList0[MAX_DPB_COUNT]; PPicture pLTCurrPocList0[MAX_DPB_COUNT]; for (int32_t i = 0; i < pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i) { if (ppShoreRefList[i]->iFramePoc < iPoc) { pLSCurrPocList0[iLSCurrPocCount++] = ppShoreRefList[i]; } } for (int32_t i = pCtx->sRefPic.uiShortRefCount[LIST_0] - 1; i >= 0; --i) { if (ppShoreRefList[i]->iFramePoc > iPoc) { pLTCurrPocList0[iLTCurrPocCount++] = ppShoreRefList[i]; } } if (pCtx->sRefPic.uiLongRefCount[LIST_0] > 1) { //long sorts in increasing order PPicture pTemp; for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) { for (int32_t j = i + 1; j < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++j) { if (ppLongRefList[j]->iFramePoc < ppLongRefList[i]->iFramePoc) { pTemp = ppLongRefList[i]; ppLongRefList[i] = ppLongRefList[j]; ppLongRefList[j] = pTemp; } } } } int32_t iCurrPocCount = iLSCurrPocCount + iLTCurrPocCount; int32_t iCount = 0; //LIST_0 //short //It may need to sort LIST_0 and LIST_1 so that they will have the right default orders. for (int32_t i = 0; i < iLSCurrPocCount; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++] = pLSCurrPocList0[i]; } if (iLSCurrPocCount > 1) { //LIST_0 short sorts in decreasing order PPicture pTemp; for (int32_t i = 0; i < iLSCurrPocCount; ++i) { for (int32_t j = i + 1; j < iLSCurrPocCount; ++j) { if (pCtx->sRefPic.pRefList[LIST_0][j]->iFramePoc > pCtx->sRefPic.pRefList[LIST_0][i]->iFramePoc) { pTemp = pCtx->sRefPic.pRefList[LIST_0][i]; pCtx->sRefPic.pRefList[LIST_0][i] = pCtx->sRefPic.pRefList[LIST_0][j]; pCtx->sRefPic.pRefList[LIST_0][j] = pTemp; } } } } for (int32_t i = 0; i < iLTCurrPocCount; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++] = pLTCurrPocList0[i]; } if (iLTCurrPocCount > 1) { //LIST_0 short sorts in increasing order PPicture pTemp; for (int32_t i = iLSCurrPocCount; i < iCurrPocCount; ++i) { for (int32_t j = i + 1; j < iCurrPocCount; ++j) { if (pCtx->sRefPic.pRefList[LIST_0][j]->iFramePoc < pCtx->sRefPic.pRefList[LIST_0][i]->iFramePoc) { pTemp = pCtx->sRefPic.pRefList[LIST_0][i]; pCtx->sRefPic.pRefList[LIST_0][i] = pCtx->sRefPic.pRefList[LIST_0][j]; pCtx->sRefPic.pRefList[LIST_0][j] = pTemp; } } } } //long for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++] = ppLongRefList[i]; } pCtx->sRefPic.uiRefCount[LIST_0] = iCount; iCount = 0; //LIST_1 //short for (int32_t i = 0; i < iLTCurrPocCount; ++i) { pCtx->sRefPic.pRefList[LIST_1][iCount++] = pLTCurrPocList0[i]; } if (iLTCurrPocCount > 1) { //LIST_1 short sorts in increasing order PPicture pTemp; for (int32_t i = 0; i < iLTCurrPocCount; ++i) { for (int32_t j = i + 1; j < iLTCurrPocCount; ++j) { if (pCtx->sRefPic.pRefList[LIST_1][j]->iFramePoc < pCtx->sRefPic.pRefList[LIST_1][i]->iFramePoc) { pTemp = pCtx->sRefPic.pRefList[LIST_1][i]; pCtx->sRefPic.pRefList[LIST_1][i] = pCtx->sRefPic.pRefList[LIST_1][j]; pCtx->sRefPic.pRefList[LIST_1][j] = pTemp; } } } } for (int32_t i = 0; i < iLSCurrPocCount; ++i) { pCtx->sRefPic.pRefList[LIST_1][iCount++] = pLSCurrPocList0[i]; } if (iLSCurrPocCount > 1) { //LIST_1 short sorts in decreasing order PPicture pTemp; for (int32_t i = iLTCurrPocCount; i < iCurrPocCount; ++i) { for (int32_t j = i + 1; j < iCurrPocCount; ++j) { if (pCtx->sRefPic.pRefList[LIST_1][j]->iFramePoc > pCtx->sRefPic.pRefList[LIST_1][i]->iFramePoc) { pTemp = pCtx->sRefPic.pRefList[LIST_1][i]; pCtx->sRefPic.pRefList[LIST_1][i] = pCtx->sRefPic.pRefList[LIST_1][j]; pCtx->sRefPic.pRefList[LIST_1][j] = pTemp; } } } } //long for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) { pCtx->sRefPic.pRefList[LIST_1][iCount++] = ppLongRefList[i]; } pCtx->sRefPic.uiRefCount[LIST_1] = iCount; return ERR_NONE;} /** * fills the pRefPic.pRefList. */int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) { USED(iPoc); int32_t err = WelsCheckAndRecoverForFutureDecoding (pCtx); if (err != ERR_NONE) return err; WrapShortRefPicNum (pCtx); PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0]; memset (pCtx->sRefPic.pRefList[LIST_0], 0, MAX_DPB_COUNT * sizeof (PPicture)); int32_t i, iCount = 0; //short for (i = 0; i < pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++ ] = ppShoreRefList[i]; } //long for (i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0] ; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++ ] = ppLongRefList[i]; } pCtx->sRefPic.uiRefCount[LIST_0] = iCount; return ERR_NONE;} int32_t WelsReorderRefList (PWelsDecoderContext pCtx) { if (pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) { return ERR_NONE; } PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering; PNalUnitHeaderExt pNalHeaderExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt; PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader; int32_t ListCount = 1; if (pCtx->eSliceType == B_SLICE) ListCount = 2; for (int32_t listIdx = 0; listIdx < ListCount; ++listIdx) { PPicture pPic; PPicture* ppRefList = pCtx->sRefPic.pRefList[listIdx]; int32_t iMaxRefIdx = pCtx->iPicQueueNumber; if (iMaxRefIdx >= MAX_REF_PIC_COUNT) { iMaxRefIdx = MAX_REF_PIC_COUNT - 1; } int32_t iRefCount = pSliceHeader->uiRefCount[listIdx]; int32_t iPredFrameNum = pSliceHeader->iFrameNum; int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum; int32_t iAbsDiffPicNum; int32_t iReorderingIndex = 0; int32_t i = 0; if (iRefCount <= 0) { pCtx->iErrorCode = dsNoParamSets; //No any reference for decoding, SHOULD request IDR return ERR_INFO_REFERENCE_PIC_LOST; } if (pRefPicListReorderSyn->bRefPicListReorderingFlag[listIdx]) { while ((iReorderingIndex < iMaxRefIdx) && (pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiReorderingOfPicNumsIdc != 3)) { uint16_t uiReorderingOfPicNumsIdc = pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiReorderingOfPicNumsIdc; if (uiReorderingOfPicNumsIdc < 2) { iAbsDiffPicNum = pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiAbsDiffPicNumMinus1 + 1; if (uiReorderingOfPicNumsIdc == 0) { iPredFrameNum -= iAbsDiffPicNum; } else { iPredFrameNum += iAbsDiffPicNum; } iPredFrameNum &= iMaxPicNum - 1; for (i = iMaxRefIdx - 1; i >= 0; i--) { if (ppRefList[i] != NULL && ppRefList[i]->iFrameNum == iPredFrameNum && !ppRefList[i]->bIsLongRef) { if ((pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId) && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check; WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d", 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 = iMaxRefIdx - 1; i >= 0; i--) { if (ppRefList[i] != NULL && ppRefList[i]->bIsLongRef && ppRefList[i]->iLongTermFrameIdx == pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiLongTermPicNum) { if ((pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId) && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check; WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d", 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]; if (i > iReorderingIndex) { memmove (&ppRefList[1 + iReorderingIndex], &ppRefList[iReorderingIndex], (i - iReorderingIndex) * sizeof (PPicture)); //confirmed_safe_unsafe_usage } else if (i < iReorderingIndex) { memmove (&ppRefList[1 + iReorderingIndex], &ppRefList[iReorderingIndex], (iMaxRefIdx - iReorderingIndex) * sizeof (PPicture)); } ppRefList[iReorderingIndex] = pPic; iReorderingIndex++; } } } return ERR_NONE;} //WelsReorderRefList2 is the test codeint32_t WelsReorderRefList2 (PWelsDecoderContext pCtx) { if (pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) { return ERR_NONE; } PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering; PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader; PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; int32_t iShortRefCount = pCtx->sRefPic.uiShortRefCount[LIST_0]; PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0]; int32_t iLongRefCount = pCtx->sRefPic.uiLongRefCount[LIST_0]; int32_t i; int32_t j; int32_t k; int32_t iMaxRefIdx = pCtx->pSps->iNumRefFrames; const int32_t iCurFrameNum = pSliceHeader->iFrameNum; const int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum; int32_t iListCount = 1; if (pCtx->eSliceType == B_SLICE) iListCount = 2; for (int32_t listIdx = 0; listIdx < iListCount; ++listIdx) { PPicture* ppRefList = pCtx->sRefPic.pRefList[listIdx]; int32_t iCount = 0;Lines 1–500 of 950. Load more
/*! * \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_dec_ref.cpp * * Abstract * Implementation for managing reference picture * * History * 07/21/2008 Created * *****************************************************************************/ #include "manage_dec_ref.h" #include "error_concealment.h" #include "error_code.h" #include "decoder.h" static PPicture WelsDelShortFromList (PRefPic pRefPic, int32_t iFrameNum); static PPicture WelsDelLongFromList (PRefPic pRefPic, uint32_t uiLongTermFrameIdx); static PPicture WelsDelShortFromListSetUnref (PRefPic pRefPic, int32_t iFrameNum); static PPicture WelsDelLongFromListSetUnref (PRefPic pRefPic, uint32_t uiLongTermFrameIdx); static int32_t MMCO (PWelsDecoderContext pCtx, PRefPic pRefPic, PRefPicMarking pRefPicMarking); static int32_t MMCOProcess (PWelsDecoderContext pCtx, PRefPic pRefPic, uint32_t uiMmcoType, int32_t iShortFrameNum, uint32_t uiLongTermPicNum, int32_t iLongTermFrameIdx, int32_t iMaxLongTermFrameIdx); static int32_t SlidingWindow (PWelsDecoderContext pCtx, PRefPic pRefPic); static int32_t AddShortTermToList (PRefPic pRefPic, PPicture pPic); static int32_t AddLongTermToList (PRefPic pRefPic, PPicture pPic, int32_t iLongTermFrameIdx, uint32_t uiLongTermPicNum); static int32_t MarkAsLongTerm (PRefPic pRefPic, int32_t iFrameNum, int32_t iLongTermFrameIdx, uint32_t uiLongTermPicNum); static int32_t WelsCheckAndRecoverForFutureDecoding (PWelsDecoderContext pCtx); #ifdef LONG_TERM_REF int32_t GetLTRFrameIndex (PRefPic pRefPic, int32_t iAncLTRFrameNum); #endif static int32_t RemainOneBufferInDpbForEC (PWelsDecoderContext pCtx, PRefPic pRefPic); static void SetUnRef (PPicture pRef) { if (NULL != pRef) { pRef->bUsedAsRef = false; pRef->bIsLongRef = false; pRef->iFrameNum = -1; pRef->iFrameWrapNum = -1; //pRef->iFramePoc = 0; pRef->iLongTermFrameIdx = -1; pRef->uiLongTermPicNum = 0; pRef->uiQualityId = -1; pRef->uiTemporalId = -1; pRef->uiSpatialId = -1; pRef->iSpsId = -1; pRef->bIsComplete = false; pRef->iRefCount = 0; if (pRef->eSliceType == I_SLICE) { return; } int32_t lists = pRef->eSliceType == P_SLICE ? 1 : 2; for (int32_t i = 0; i < MAX_DPB_COUNT; ++i) { for (int32_t list = 0; list < lists; ++list) { if (pRef->pRefPic[list][i] != NULL) { pRef->pRefPic[list][i]->iRefCount = 0; pRef->pRefPic[list][i] = NULL; } } } } } //reset pRefList when // 1.sps arrived that is new sequence starting // 2.IDR NAL i.e. 1st layer in IDR AU void WelsResetRefPic (PWelsDecoderContext pCtx) { int32_t i; PRefPic pRefPic = &pCtx->sRefPic; pCtx->sRefPic.uiLongRefCount[LIST_0] = pCtx->sRefPic.uiShortRefCount[LIST_0] = 0; pRefPic->uiRefCount[LIST_0] = 0; pRefPic->uiRefCount[LIST_1] = 0; for (i = 0; i < MAX_DPB_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_DPB_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; } void WelsResetRefPicWithoutUnRef (PWelsDecoderContext pCtx) { int32_t i; PRefPic pRefPic = &pCtx->sRefPic; pCtx->sRefPic.uiLongRefCount[LIST_0] = pCtx->sRefPic.uiShortRefCount[LIST_0] = 0; pRefPic->uiRefCount[LIST_0] = 0; pRefPic->uiRefCount[LIST_1] = 0; for (i = 0; i < MAX_DPB_COUNT; i++) { pRefPic->pShortRefList[LIST_0][i] = NULL; } pRefPic->uiShortRefCount[LIST_0] = 0; for (i = 0; i < MAX_DPB_COUNT; i++) { pRefPic->pLongRefList[LIST_0][i] = NULL; } pRefPic->uiLongRefCount[LIST_0] = 0; } static int32_t WelsCheckAndRecoverForFutureDecoding (PWelsDecoderContext pCtx) { if ((pCtx->sRefPic.uiShortRefCount[LIST_0] + pCtx->sRefPic.uiLongRefCount[LIST_0] <= 0) && (pCtx->eSliceType != I_SLICE && pCtx->eSliceType != SI_SLICE)) { if (pCtx->pParam->eEcActiveIdc != ERROR_CON_DISABLE) { //IDR lost!, recover it for future decoding with data all set to 0 PPicture pRef = PrefetchPic (pCtx->pPicBuff); if (pRef != NULL) { // IDR lost, set new pRef->bIsComplete = false; // Set complete flag to false for lost IDR ref picture pRef->iSpsId = pCtx->pSps->iSpsId; pRef->iPpsId = pCtx->pPps->iPpsId; if (pCtx->eSliceType == B_SLICE) { //reset reference's references when IDR is lost for (int32_t list = LIST_0; list < LIST_A; ++list) { for (int32_t i = 0; i < MAX_DPB_COUNT; ++i) { pRef->pRefPic[list][i] = NULL; } } } pCtx->iErrorCode |= dsDataErrorConcealed; bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc) || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc) || (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc) || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->pParam->eEcActiveIdc) || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->pParam->eEcActiveIdc)) && (NULL != pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb); bCopyPrevious = bCopyPrevious && (pRef->iWidthInPixel == pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iWidthInPixel) && (pRef->iHeightInPixel == pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->iHeightInPixel); if (!bCopyPrevious) { memset (pRef->pData[0], 128, pRef->iLinesize[0] * pRef->iHeightInPixel); memset (pRef->pData[1], 128, pRef->iLinesize[1] * pRef->iHeightInPixel / 2); memset (pRef->pData[2], 128, pRef->iLinesize[2] * pRef->iHeightInPixel / 2); } else if (pRef == pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb) { WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsInitRefList()::EC memcpy overlap."); } else { memcpy (pRef->pData[0], pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->pData[0], pRef->iLinesize[0] * pRef->iHeightInPixel); memcpy (pRef->pData[1], pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->pData[1], pRef->iLinesize[1] * pRef->iHeightInPixel / 2); memcpy (pRef->pData[2], pCtx->pLastDecPicInfo->pPreviousDecodedPictureInDpb->pData[2], pRef->iLinesize[2] * pRef->iHeightInPixel / 2); } pRef->iFrameNum = 0; pRef->iFramePoc = 0; pRef->uiTemporalId = pRef->uiQualityId = 0; pRef->eSliceType = pCtx->eSliceType; ExpandReferencingPicture (pRef->pData, pRef->iWidthInPixel, pRef->iHeightInPixel, pRef->iLinesize, pCtx->sExpandPicFunc.pfExpandLumaPicture, pCtx->sExpandPicFunc.pfExpandChromaPicture); AddShortTermToList (&pCtx->sRefPic, pRef); } else { WelsLog (& (pCtx->sLogCtx), WELS_LOG_ERROR, "WelsInitRefList()::PrefetchPic for EC errors."); pCtx->iErrorCode |= dsOutOfMemory; return ERR_INFO_REF_COUNT_OVERFLOW; } } } return ERR_NONE; } static void WrapShortRefPicNum (PWelsDecoderContext pCtx) { int32_t i; PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader; int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum; PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; int32_t iShortRefCount = pCtx->sRefPic.uiShortRefCount[LIST_0]; //wrap pic num for (i = 0; i < iShortRefCount; i++) { if (ppShoreRefList[i]) { if (ppShoreRefList[i]->iFrameNum > pSliceHeader->iFrameNum) ppShoreRefList[i]->iFrameWrapNum = ppShoreRefList[i]->iFrameNum - iMaxPicNum; else ppShoreRefList[i]->iFrameWrapNum = ppShoreRefList[i]->iFrameNum; } } } /** * fills the pRefPic.pRefList LIST_0 and LIST_0 for B-Slice. */ int32_t WelsInitBSliceRefList (PWelsDecoderContext pCtx, int32_t iPoc) { int32_t err = WelsCheckAndRecoverForFutureDecoding (pCtx); if (err != ERR_NONE) return err; WrapShortRefPicNum (pCtx); PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0]; memset (pCtx->sRefPic.pRefList[LIST_0], 0, MAX_DPB_COUNT * sizeof (PPicture)); memset (pCtx->sRefPic.pRefList[LIST_1], 0, MAX_DPB_COUNT * sizeof (PPicture)); int32_t iLSCurrPocCount = 0; int32_t iLTCurrPocCount = 0; PPicture pLSCurrPocList0[MAX_DPB_COUNT]; PPicture pLTCurrPocList0[MAX_DPB_COUNT]; for (int32_t i = 0; i < pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i) { if (ppShoreRefList[i]->iFramePoc < iPoc) { pLSCurrPocList0[iLSCurrPocCount++] = ppShoreRefList[i]; } } for (int32_t i = pCtx->sRefPic.uiShortRefCount[LIST_0] - 1; i >= 0; --i) { if (ppShoreRefList[i]->iFramePoc > iPoc) { pLTCurrPocList0[iLTCurrPocCount++] = ppShoreRefList[i]; } } if (pCtx->sRefPic.uiLongRefCount[LIST_0] > 1) { //long sorts in increasing order PPicture pTemp; for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) { for (int32_t j = i + 1; j < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++j) { if (ppLongRefList[j]->iFramePoc < ppLongRefList[i]->iFramePoc) { pTemp = ppLongRefList[i]; ppLongRefList[i] = ppLongRefList[j]; ppLongRefList[j] = pTemp; } } } } int32_t iCurrPocCount = iLSCurrPocCount + iLTCurrPocCount; int32_t iCount = 0; //LIST_0 //short //It may need to sort LIST_0 and LIST_1 so that they will have the right default orders. for (int32_t i = 0; i < iLSCurrPocCount; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++] = pLSCurrPocList0[i]; } if (iLSCurrPocCount > 1) { //LIST_0 short sorts in decreasing order PPicture pTemp; for (int32_t i = 0; i < iLSCurrPocCount; ++i) { for (int32_t j = i + 1; j < iLSCurrPocCount; ++j) { if (pCtx->sRefPic.pRefList[LIST_0][j]->iFramePoc > pCtx->sRefPic.pRefList[LIST_0][i]->iFramePoc) { pTemp = pCtx->sRefPic.pRefList[LIST_0][i]; pCtx->sRefPic.pRefList[LIST_0][i] = pCtx->sRefPic.pRefList[LIST_0][j]; pCtx->sRefPic.pRefList[LIST_0][j] = pTemp; } } } } for (int32_t i = 0; i < iLTCurrPocCount; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++] = pLTCurrPocList0[i]; } if (iLTCurrPocCount > 1) { //LIST_0 short sorts in increasing order PPicture pTemp; for (int32_t i = iLSCurrPocCount; i < iCurrPocCount; ++i) { for (int32_t j = i + 1; j < iCurrPocCount; ++j) { if (pCtx->sRefPic.pRefList[LIST_0][j]->iFramePoc < pCtx->sRefPic.pRefList[LIST_0][i]->iFramePoc) { pTemp = pCtx->sRefPic.pRefList[LIST_0][i]; pCtx->sRefPic.pRefList[LIST_0][i] = pCtx->sRefPic.pRefList[LIST_0][j]; pCtx->sRefPic.pRefList[LIST_0][j] = pTemp; } } } } //long for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++] = ppLongRefList[i]; } pCtx->sRefPic.uiRefCount[LIST_0] = iCount; iCount = 0; //LIST_1 //short for (int32_t i = 0; i < iLTCurrPocCount; ++i) { pCtx->sRefPic.pRefList[LIST_1][iCount++] = pLTCurrPocList0[i]; } if (iLTCurrPocCount > 1) { //LIST_1 short sorts in increasing order PPicture pTemp; for (int32_t i = 0; i < iLTCurrPocCount; ++i) { for (int32_t j = i + 1; j < iLTCurrPocCount; ++j) { if (pCtx->sRefPic.pRefList[LIST_1][j]->iFramePoc < pCtx->sRefPic.pRefList[LIST_1][i]->iFramePoc) { pTemp = pCtx->sRefPic.pRefList[LIST_1][i]; pCtx->sRefPic.pRefList[LIST_1][i] = pCtx->sRefPic.pRefList[LIST_1][j]; pCtx->sRefPic.pRefList[LIST_1][j] = pTemp; } } } } for (int32_t i = 0; i < iLSCurrPocCount; ++i) { pCtx->sRefPic.pRefList[LIST_1][iCount++] = pLSCurrPocList0[i]; } if (iLSCurrPocCount > 1) { //LIST_1 short sorts in decreasing order PPicture pTemp; for (int32_t i = iLTCurrPocCount; i < iCurrPocCount; ++i) { for (int32_t j = i + 1; j < iCurrPocCount; ++j) { if (pCtx->sRefPic.pRefList[LIST_1][j]->iFramePoc > pCtx->sRefPic.pRefList[LIST_1][i]->iFramePoc) { pTemp = pCtx->sRefPic.pRefList[LIST_1][i]; pCtx->sRefPic.pRefList[LIST_1][i] = pCtx->sRefPic.pRefList[LIST_1][j]; pCtx->sRefPic.pRefList[LIST_1][j] = pTemp; } } } } //long for (int32_t i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0]; ++i) { pCtx->sRefPic.pRefList[LIST_1][iCount++] = ppLongRefList[i]; } pCtx->sRefPic.uiRefCount[LIST_1] = iCount; return ERR_NONE; } /** * fills the pRefPic.pRefList. */ int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) { USED(iPoc); int32_t err = WelsCheckAndRecoverForFutureDecoding (pCtx); if (err != ERR_NONE) return err; WrapShortRefPicNum (pCtx); PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0]; memset (pCtx->sRefPic.pRefList[LIST_0], 0, MAX_DPB_COUNT * sizeof (PPicture)); int32_t i, iCount = 0; //short for (i = 0; i < pCtx->sRefPic.uiShortRefCount[LIST_0]; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++ ] = ppShoreRefList[i]; } //long for (i = 0; i < pCtx->sRefPic.uiLongRefCount[LIST_0] ; ++i) { pCtx->sRefPic.pRefList[LIST_0][iCount++ ] = ppLongRefList[i]; } pCtx->sRefPic.uiRefCount[LIST_0] = iCount; return ERR_NONE; } int32_t WelsReorderRefList (PWelsDecoderContext pCtx) { if (pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) { return ERR_NONE; } PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering; PNalUnitHeaderExt pNalHeaderExt = &pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt; PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader; int32_t ListCount = 1; if (pCtx->eSliceType == B_SLICE) ListCount = 2; for (int32_t listIdx = 0; listIdx < ListCount; ++listIdx) { PPicture pPic; PPicture* ppRefList = pCtx->sRefPic.pRefList[listIdx]; int32_t iMaxRefIdx = pCtx->iPicQueueNumber; if (iMaxRefIdx >= MAX_REF_PIC_COUNT) { iMaxRefIdx = MAX_REF_PIC_COUNT - 1; } int32_t iRefCount = pSliceHeader->uiRefCount[listIdx]; int32_t iPredFrameNum = pSliceHeader->iFrameNum; int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum; int32_t iAbsDiffPicNum; int32_t iReorderingIndex = 0; int32_t i = 0; if (iRefCount <= 0) { pCtx->iErrorCode = dsNoParamSets; //No any reference for decoding, SHOULD request IDR return ERR_INFO_REFERENCE_PIC_LOST; } if (pRefPicListReorderSyn->bRefPicListReorderingFlag[listIdx]) { while ((iReorderingIndex < iMaxRefIdx) && (pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiReorderingOfPicNumsIdc != 3)) { uint16_t uiReorderingOfPicNumsIdc = pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiReorderingOfPicNumsIdc; if (uiReorderingOfPicNumsIdc < 2) { iAbsDiffPicNum = pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiAbsDiffPicNumMinus1 + 1; if (uiReorderingOfPicNumsIdc == 0) { iPredFrameNum -= iAbsDiffPicNum; } else { iPredFrameNum += iAbsDiffPicNum; } iPredFrameNum &= iMaxPicNum - 1; for (i = iMaxRefIdx - 1; i >= 0; i--) { if (ppRefList[i] != NULL && ppRefList[i]->iFrameNum == iPredFrameNum && !ppRefList[i]->bIsLongRef) { if ((pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId) && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check; WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d", 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 = iMaxRefIdx - 1; i >= 0; i--) { if (ppRefList[i] != NULL && ppRefList[i]->bIsLongRef && ppRefList[i]->iLongTermFrameIdx == pRefPicListReorderSyn->sReorderingSyn[listIdx][iReorderingIndex].uiLongTermPicNum) { if ((pNalHeaderExt->uiQualityId == ppRefList[i]->uiQualityId) && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check; WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsReorderRefList()::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d", 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]; if (i > iReorderingIndex) { memmove (&ppRefList[1 + iReorderingIndex], &ppRefList[iReorderingIndex], (i - iReorderingIndex) * sizeof (PPicture)); //confirmed_safe_unsafe_usage } else if (i < iReorderingIndex) { memmove (&ppRefList[1 + iReorderingIndex], &ppRefList[iReorderingIndex], (iMaxRefIdx - iReorderingIndex) * sizeof (PPicture)); } ppRefList[iReorderingIndex] = pPic; iReorderingIndex++; } } } return ERR_NONE; } //WelsReorderRefList2 is the test code int32_t WelsReorderRefList2 (PWelsDecoderContext pCtx) { if (pCtx->eSliceType == I_SLICE || pCtx->eSliceType == SI_SLICE) { return ERR_NONE; } PRefPicListReorderSyn pRefPicListReorderSyn = pCtx->pCurDqLayer->pRefPicListReordering; PSliceHeader pSliceHeader = &pCtx->pCurDqLayer->sLayerInfo.sSliceInLayer.sSliceHeaderExt.sSliceHeader; PPicture* ppShoreRefList = pCtx->sRefPic.pShortRefList[LIST_0]; int32_t iShortRefCount = pCtx->sRefPic.uiShortRefCount[LIST_0]; PPicture* ppLongRefList = pCtx->sRefPic.pLongRefList[LIST_0]; int32_t iLongRefCount = pCtx->sRefPic.uiLongRefCount[LIST_0]; int32_t i; int32_t j; int32_t k; int32_t iMaxRefIdx = pCtx->pSps->iNumRefFrames; const int32_t iCurFrameNum = pSliceHeader->iFrameNum; const int32_t iMaxPicNum = 1 << pSliceHeader->pSps->uiLog2MaxFrameNum; int32_t iListCount = 1; if (pCtx->eSliceType == B_SLICE) iListCount = 2; for (int32_t listIdx = 0; listIdx < iListCount; ++listIdx) { PPicture* ppRefList = pCtx->sRefPic.pRefList[listIdx]; int32_t iCount = 0;