/**
 * fills the pRefPic.pRefList.
 */
int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
  int32_t i, iCount = 0;

  if ((pCtx->sRefPic.uiShortRefCount[LIST_0] + pCtx->sRefPic.uiLongRefCount[LIST_0] <= 0) && (pCtx->eSliceType != I_SLICE
      && pCtx->eSliceType != SI_SLICE)) {
    if (pCtx->iErrorConMethod != ERROR_CON_DISABLE) { //IDR lost!, recover it for future decoding with data all set to 0
      PPicture pRef = PrefetchPic (pCtx->pPicBuff[0]);
      if (pRef != NULL) {
        memset (pRef->pData[0], 0, pRef->iLinesize[0] * pRef->iHeightInPixel);
        memset (pRef->pData[1], 0, pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
        memset (pRef->pData[2], 0, pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
        pRef->iFrameNum = 0;
        pRef->iFramePoc = 0;
        pRef->uiTemporalId = pRef->uiQualityId = 0;
        AddShortTermToList (&pCtx->sRefPic, pRef);
      } else {
        WelsLog (pCtx, WELS_LOG_ERROR, "WelsInitRefList()::PrefetchPic for EC errors.\n");
        pCtx->iErrorCode |= dsOutOfMemory;
        return ERR_INFO_REF_COUNT_OVERFLOW;
      }
    }
  }

  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) {
    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 WelsMarkAsRef (PWelsDecoderContext pCtx) {
  PRefPic pRefPic = &pCtx->sRefPic;
  PRefPicMarking pRefPicMarking = pCtx->pCurDqLayer->pRefPicMarking;
  PAccessUnit pCurAU = pCtx->pAccessUnitList;
  bool bIsIDRAU = false;
  uint32_t j;

  int32_t iRet = ERR_NONE;

  pCtx->pDec->uiQualityId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiQualityId;
  pCtx->pDec->uiTemporalId = pCtx->pCurDqLayer->sLayerInfo.sNalHeaderExt.uiTemporalId;
  pCtx->pDec->iSpsId = pCtx->pSps->iSpsId;
  pCtx->pDec->iPpsId = pCtx->pPps->iPpsId;

  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 (pRefPicMarking->bAdaptiveRefPicMarkingModeFlag) {
      iRet = MMCO (pCtx, pRefPicMarking);
      if (iRet != ERR_NONE) {
        if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
          iRet = RemainOneBufferInDpbForEC (pCtx);
          WELS_VERIFY_RETURN_IF (iRet, iRet);
        } else {
          return iRet;
        }
      }

      if (pCtx->bLastHasMmco5) {
        pCtx->pDec->iFrameNum = 0;
        pCtx->pDec->iFramePoc = 0;
      }

    } else {
      iRet = SlidingWindow (pCtx);
      if (iRet != ERR_NONE) {
        if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
          iRet = RemainOneBufferInDpbForEC (pCtx);
          WELS_VERIFY_RETURN_IF (iRet, iRet);
        } else {
          return iRet;
        }
      }
    }
  }

  if (!pCtx->pDec->bIsLongRef) {
    if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX (1, pCtx->pSps->iNumRefFrames)) {
      if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) {
        iRet = RemainOneBufferInDpbForEC (pCtx);
        WELS_VERIFY_RETURN_IF (iRet, iRet);
      } else {
        return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
      }
    }
    iRet = AddShortTermToList (pRefPic, pCtx->pDec);
  }

  return iRet;
}
/**
 * fills the pRefPic.pRefList.
 */
int32_t WelsInitRefList (PWelsDecoderContext pCtx, int32_t iPoc) {
  int32_t i, iCount = 0;

  if ((pCtx->sRefPic.uiShortRefCount[LIST_0] + pCtx->sRefPic.uiLongRefCount[LIST_0] <= 0) && (pCtx->eSliceType != I_SLICE
      && pCtx->eSliceType != SI_SLICE)) {
    if (pCtx->eErrorConMethod != ERROR_CON_DISABLE) { //IDR lost!, recover it for future decoding with data all set to 0
      PPicture pRef = PrefetchPic (pCtx->pPicBuff[0]);
      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;
        pCtx->iErrorCode |= dsDataErrorConcealed;
        bool bCopyPrevious = ((ERROR_CON_FRAME_COPY_CROSS_IDR == pCtx->eErrorConMethod)
                              || (ERROR_CON_SLICE_COPY_CROSS_IDR == pCtx->eErrorConMethod)
                              || (ERROR_CON_SLICE_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod)
                              || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR == pCtx->eErrorConMethod)
                              || (ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE == pCtx->eErrorConMethod))
                             && (NULL != pCtx->pPreviousDecodedPictureInDpb);
        bCopyPrevious = bCopyPrevious && (pRef->iWidthInPixel == pCtx->pPreviousDecodedPictureInDpb->iWidthInPixel)
                        && (pRef->iHeightInPixel == pCtx->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->pPreviousDecodedPictureInDpb) {
          WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "WelsInitRefList()::EC memcpy overlap.");
        } else {
          memcpy (pRef->pData[0], pCtx->pPreviousDecodedPictureInDpb->pData[0], pRef->iLinesize[0] * pRef->iHeightInPixel);
          memcpy (pRef->pData[1], pCtx->pPreviousDecodedPictureInDpb->pData[1], pRef->iLinesize[1] * pRef->iHeightInPixel / 2);
          memcpy (pRef->pData[2], pCtx->pPreviousDecodedPictureInDpb->pData[2], pRef->iLinesize[2] * pRef->iHeightInPixel / 2);
        }
        pRef->iFrameNum = 0;
        pRef->iFramePoc = 0;
        pRef->uiTemporalId = pRef->uiQualityId = 0;
        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;
      }
    }
  }

  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));
  //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 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;
}