Example #1
0
WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiCurDid) {
  CWelsBaseTask* pTask = NULL;
  int32_t kiTaskCount;
  uint32_t uiSliceMode = pEncCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceArgument.uiSliceMode;

  if (uiSliceMode != SM_SIZELIMITED_SLICE) {
    kiTaskCount = m_iTaskNum[kiCurDid] = pEncCtx->pSvcParam->sSpatialLayers[kiCurDid].sSliceArgument.uiSliceNum;
  } else {
    kiTaskCount = m_iTaskNum[kiCurDid] = pEncCtx->iActiveThreadsNum;
  }

  for (int idx = 0; idx < kiTaskCount; idx++) {
    pTask = WELS_NEW_OP (CWelsUpdateMbMapTask (this, pEncCtx, idx), CWelsUpdateMbMapTask);
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cPreEncodingTaskList[kiCurDid]->push_back (pTask);
  }

  for (int idx = 0; idx < kiTaskCount; idx++) {
    if (uiSliceMode==SM_SIZELIMITED_SLICE) {
      pTask = WELS_NEW_OP (CWelsConstrainedSizeSlicingEncodingTask (this, pEncCtx, idx), CWelsConstrainedSizeSlicingEncodingTask);
    } else {
    if (pEncCtx->pSvcParam->bUseLoadBalancing) {
      pTask = WELS_NEW_OP (CWelsLoadBalancingSlicingEncodingTask (this, pEncCtx, idx), CWelsLoadBalancingSlicingEncodingTask);
    } else {
      pTask = WELS_NEW_OP (CWelsSliceEncodingTask (this, pEncCtx, idx), CWelsSliceEncodingTask);
    }
    }
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cEncodingTaskList[kiCurDid]->push_back (pTask);
  }

  //printf ("CWelsTaskManageBase CreateTasks m_iThreadNum %d kiTaskCount=%d\n", m_iThreadNum, kiTaskCount);
  return ENC_RETURN_SUCCESS;
}
Example #2
0
/*
 *	request memory blocks for decoder avc part
 */
int32_t WelsRequestMem (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const int32_t kiMbHeight) {
  const int32_t kiPicWidth	= kiMbWidth << 4;
  const int32_t kiPicHeight	= kiMbHeight << 4;
  int32_t iErr = ERR_NONE;

  int32_t iListIdx			= 0;	//, mb_blocks	= 0;
  int32_t	iPicQueueSize		= 0;	// adaptive size of picture queue, = (pSps->iNumRefFrames x 2)
  bool  bNeedChangePicQueue	= true;

  WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pCtx || kiPicWidth <= 0 || kiPicHeight <= 0))

  // Fixed the issue about different gop size over last, 5/17/2010
  // get picture queue size currently
  iPicQueueSize	= GetTargetRefListSize (pCtx);	// adaptive size of picture queue, = (pSps->iNumRefFrames x 2)
  pCtx->iPicQueueNumber = iPicQueueSize;
  if (pCtx->pPicBuff[LIST_0] != NULL
      && pCtx->pPicBuff[LIST_0]->iCapacity ==
      iPicQueueSize)	// comparing current picture queue size requested and previous allocation picture queue
    bNeedChangePicQueue	= false;
  // HD based pic buffer need consider memory size consumed when switch from 720p to other lower size
  WELS_VERIFY_RETURN_IF (ERR_NONE, pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel
                         && kiPicHeight == pCtx->iImgHeightInPixel) && (!bNeedChangePicQueue))	// have same scaled buffer

  // sync update pRefList
  WelsResetRefPic (pCtx);	// added to sync update ref list due to pictures are free

  // for Recycled_Pic_Queue
  for (iListIdx = LIST_0; iListIdx < LIST_A; ++ iListIdx) {
    PPicBuff* ppPic = &pCtx->pPicBuff[iListIdx];
    if (NULL != ppPic && NULL != *ppPic) {
      DestroyPicBuff (ppPic);
    }
  }

  pCtx->pPreviousDecodedPictureInDpb = NULL;

  // currently only active for LIST_0 due to have no B frames
  iErr = CreatePicBuff (pCtx, &pCtx->pPicBuff[LIST_0], iPicQueueSize, kiPicWidth, kiPicHeight);
  if (iErr != ERR_NONE)
    return iErr;


  pCtx->iImgWidthInPixel	= kiPicWidth;	// target width of image to be reconstruted while decoding
  pCtx->iImgHeightInPixel	= kiPicHeight;	// target height of image to be reconstruted while decoding

  pCtx->bHaveGotMemory	= true;			// global memory for decoder context related is requested
  pCtx->pDec		        = NULL;			// need prefetch a new pic due to spatial size changed
  return ERR_NONE;
}
Example #3
0
int32_t CWelsPreProcess::AllocSpatialPictures (sWelsEncCtx* pCtx, SWelsSvcCodingParam* pParam) {
  CMemoryAlign* pMa						= pCtx->pMemAlign;
  const int32_t kiDlayerCount					= pParam->iSpatialLayerNum;
  int32_t iDlayerIndex							= 0;

  // spatial pictures
  iDlayerIndex = 0;
  do {
    const int32_t kiPicWidth = pParam->sDependencyLayers[iDlayerIndex].iFrameWidth;
    const int32_t kiPicHeight   = pParam->sDependencyLayers[iDlayerIndex].iFrameHeight;
    const uint8_t kuiLayerInTemporal = 2 + WELS_MAX (pParam->sDependencyLayers[iDlayerIndex].iHighestTemporalId, 1);
    const uint8_t kuiRefNumInTemporal = kuiLayerInTemporal + pParam->iLTRRefNum;
    uint8_t i = 0;

    do {
      SPicture* pPic = AllocPicture (pMa, kiPicWidth, kiPicHeight, false);
      WELS_VERIFY_RETURN_IF(1, (NULL == pPic))
      m_pSpatialPic[iDlayerIndex][i] = pPic;
      ++ i;
    } while (i < kuiRefNumInTemporal);

    m_uiSpatialLayersInTemporal[iDlayerIndex] = kuiLayerInTemporal;
    m_uiSpatialPicNum[iDlayerIndex] = kuiRefNumInTemporal;
    ++ iDlayerIndex;
  } while (iDlayerIndex < kiDlayerCount);

  return 0;
}
Example #4
0
/*
 * set colorspace format in decoder
 */
int32_t DecoderSetCsp (PWelsDecoderContext pCtx, const int32_t kiColorFormat) {
  WELS_VERIFY_RETURN_IF (1, (NULL == pCtx));

  pCtx->iOutputColorFormat	= kiColorFormat;
  if (pCtx->pParam != NULL) {
    pCtx->pParam->iOutputColorFormat	= kiColorFormat;
  }

  return 0;
}
WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiTaskCount) {
  CWelsBaseTask* pTask = NULL;

  for (int idx = 0; idx < kiTaskCount; idx++) {
    pTask = WELS_NEW_OP (CWelsSliceEncodingTask (pEncCtx, idx), CWelsSliceEncodingTask);
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cTaskList->push_back (pTask);
  }
  m_iTaskNum = kiTaskCount;

  //printf("CWelsTaskManageBase CreateTasks m_iThreadNum %d kiTaskCount=%d\n", m_iThreadNum, kiTaskCount);
  return ENC_RETURN_SUCCESS;
}
//TODO: at present there is no diff betweenCWelsTaskManageParallel and CWelsTaskManageBase, to finish later
WelsErrorType  CWelsTaskManageParallel::ExecuteTasks() {
  WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == m_pThreadPool)

  // need lock here?
  m_iWaitTaskNum = static_cast<int32_t> (m_cTaskList->size());

  while (NULL != m_cTaskList->begin()) {
    m_pThreadPool->QueueTask (m_cTaskList->begin());
    m_cTaskList->pop_front();
  }
  WelsEventWait (&m_hTaskEvent);

  return ENC_RETURN_SUCCESS;
}
WelsErrorType CWelsTaskManageBase::CreateTasks (sWelsEncCtx* pEncCtx, const int32_t kiTaskCount) {
  CWelsBaseTask* pTask = NULL;

  for (int idx = 0; idx < kiTaskCount; idx++) {
    pTask = WELS_NEW_OP (CWelsUpdateMbMapTask (pEncCtx, idx), CWelsUpdateMbMapTask);
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cPreEncodingTaskList->push_back (pTask);
  }

  for (int idx = 0; idx < kiTaskCount; idx++) {
    if (pEncCtx->pSvcParam->bUseLoadBalancing) {
      pTask = WELS_NEW_OP (CWelsLoadBalancingSlicingEncodingTask (pEncCtx, idx), CWelsLoadBalancingSlicingEncodingTask);
    } else {
      pTask = WELS_NEW_OP (CWelsSliceEncodingTask (pEncCtx, idx), CWelsSliceEncodingTask);
    }
    WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == pTask)
    m_cEncodingTaskList->push_back (pTask);
  }
  m_iTotalTaskNum = kiTaskCount;

  //printf ("CWelsTaskManageBase CreateTasks m_iThreadNum %d kiTaskCount=%d\n", m_iThreadNum, kiTaskCount);
  return ENC_RETURN_SUCCESS;
}
WelsErrorType CWelsTaskManageBase::Init (sWelsEncCtx* pEncCtx) {
  m_pEncCtx = pEncCtx;

  m_iThreadNum = m_pEncCtx->pSvcParam->iMultipleThreadIdc;
  m_pThreadPool = WELS_NEW_OP (WelsCommon::CWelsThreadPool (this, m_iThreadNum),
                               WelsCommon::CWelsThreadPool);
  WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == m_pThreadPool)

  m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_ENCODING] = m_cEncodingTaskList;
  m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_UPDATEMBMAP] = m_cPreEncodingTaskList;

  m_iCurrentTaskNum = pEncCtx->pSvcParam->sSpatialLayers[0].sSliceArgument.uiSliceNum;
  //printf ("CWelsTaskManageBase Init m_iThreadNum %d m_iCurrentTaskNum %d pEncCtx->iMaxSliceCount %d\n", m_iThreadNum, m_iCurrentTaskNum, pEncCtx->iMaxSliceCount);
  return CreateTasks (pEncCtx, pEncCtx->iMaxSliceCount);
}
Example #9
0
/*
 * set colorspace format in decoder
 */
int32_t DecoderSetCsp (PWelsDecoderContext pCtx, const int32_t kiColorFormat) {
  WELS_VERIFY_RETURN_IF (1, (NULL == pCtx));

  pCtx->eOutputColorFormat	= (EVideoFormatType) kiColorFormat;
  if (pCtx->pParam != NULL) {
    pCtx->pParam->eOutputColorFormat	= (EVideoFormatType) kiColorFormat;
  }

  //For now, support only videoFormatI420!
  if (kiColorFormat != (int32_t) videoFormatI420) {
    WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "Support I420 output only for now! Change to I420...\n");
    pCtx->pParam->eOutputColorFormat = pCtx->eOutputColorFormat = videoFormatI420;
  }

  return 0;
}
Example #10
0
WelsErrorType CWelsTaskManageBase::Init (sWelsEncCtx* pEncCtx) {
  m_pEncCtx = pEncCtx;

  m_iThreadNum = m_pEncCtx->pSvcParam->iMultipleThreadIdc;
  m_pThreadPool = WELS_NEW_OP (WelsCommon::CWelsThreadPool (this, m_iThreadNum),
                               WelsCommon::CWelsThreadPool);
  WELS_VERIFY_RETURN_IF (ENC_RETURN_MEMALLOCERR, NULL == m_pThreadPool)

  int32_t iReturn = 0;
  for (int32_t iDid = 0; iDid < MAX_DEPENDENCY_LAYER; iDid++) {
    m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_ENCODING][iDid] = m_cEncodingTaskList[iDid];
    m_pcAllTaskList[CWelsBaseTask::WELS_ENC_TASK_UPDATEMBMAP][iDid] = m_cPreEncodingTaskList[iDid];
    iReturn |= CreateTasks (pEncCtx, iDid);
  }

  //printf ("CWelsTaskManageBase Init m_iThreadNum %d m_iCurrentTaskNum %d pEncCtx->iMaxSliceCount %d\n", m_iThreadNum, m_iCurrentTaskNum, pEncCtx->iMaxSliceCount);
  return iReturn;
}
Example #11
0
/*!
 * \brief	Initialize slice segment (Single/multiple slices)
 *
 * \param	pSliceSeg			SSlice segment to be initialized
 * \param	uiSliceMode			SSlice mode
 * \param	multi_slice_argv	Multiple slices argument
 * \param	iMbWidth			MB width
 * \param	iMbHeight			MB height
 *
 * \return	0 - successful; none 0 - failed;
 */
int32_t InitSliceSegment (SSliceCtx* pSliceSeg,
                          CMemoryAlign* pMa,
                          SMulSliceOption* pMso,
                          const int32_t kiMbWidth,
                          const int32_t kiMbHeight) {
  const int32_t kiCountMbNum = kiMbWidth * kiMbHeight;
  SliceMode uiSliceMode = SM_SINGLE_SLICE;

  if (NULL == pSliceSeg || NULL == pMso || kiMbWidth == 0 || kiMbHeight == 0)
    return 1;

  uiSliceMode = pMso->uiSliceMode;
  if (pSliceSeg->iMbNumInFrame == kiCountMbNum && pSliceSeg->iMbWidth == kiMbWidth
      && pSliceSeg->iMbHeight == kiMbHeight && pSliceSeg->uiSliceMode == uiSliceMode && pSliceSeg->pOverallMbMap != NULL)
    return 0;
  else if (pSliceSeg->iMbNumInFrame != kiCountMbNum) {
    if (NULL != pSliceSeg->pOverallMbMap) {
      pMa->WelsFree (pSliceSeg->pOverallMbMap, "pSliceSeg->pOverallMbMap");

      pSliceSeg->pOverallMbMap = NULL;
    }
    if (NULL != pSliceSeg->pFirstMbInSlice) {
      pMa->WelsFree (pSliceSeg->pFirstMbInSlice, "pSliceSeg->pFirstMbInSlice");

      pSliceSeg->pFirstMbInSlice = NULL;
    }
    if (NULL != pSliceSeg->pCountMbNumInSlice) {
      pMa->WelsFree (pSliceSeg->pCountMbNumInSlice, "pSliceSeg->pCountMbNumInSlice");

      pSliceSeg->pCountMbNumInSlice	= NULL;
    }
    // just for safe
    pSliceSeg->iSliceNumInFrame	= 0;
    pSliceSeg->iMbNumInFrame		= 0;
    pSliceSeg->iMbWidth				= 0;
    pSliceSeg->iMbHeight			= 0;
    pSliceSeg->uiSliceMode			= SM_SINGLE_SLICE;	// sigle in default
  }

  if (SM_SINGLE_SLICE == uiSliceMode) {
    pSliceSeg->pOverallMbMap	= (uint8_t*)pMa->WelsMalloc (kiCountMbNum * sizeof (uint8_t), "pSliceSeg->pOverallMbMap");

    WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pOverallMbMap)
    pSliceSeg->iSliceNumInFrame	= 1;

    pSliceSeg->pFirstMbInSlice	= (int16_t*)pMa->WelsMalloc (pSliceSeg->iSliceNumInFrame * sizeof (int16_t),
                                  "pSliceSeg->pFirstMbInSlice");

    WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pFirstMbInSlice)

    pSliceSeg->pCountMbNumInSlice = (int32_t*)pMa->WelsMalloc (pSliceSeg->iSliceNumInFrame * sizeof (int32_t),
                                    "pSliceSeg->pCountMbNumInSlice");

    WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pCountMbNumInSlice)
    pSliceSeg->uiSliceMode			= uiSliceMode;
    pSliceSeg->iMbWidth				= kiMbWidth;
    pSliceSeg->iMbHeight			= kiMbHeight;
    pSliceSeg->iMbNumInFrame		= kiCountMbNum;
    pSliceSeg->pCountMbNumInSlice[0]	= kiCountMbNum;
    pSliceSeg->pFirstMbInSlice[0]		= 0;

    return AssignMbMapSingleSlice (pSliceSeg->pOverallMbMap, kiCountMbNum, sizeof (pSliceSeg->pOverallMbMap[0]));
  } else { //if ( SM_MULTIPLE_SLICE == uiSliceMode )
    if (uiSliceMode != SM_FIXEDSLCNUM_SLICE && uiSliceMode != SM_ROWMB_SLICE && uiSliceMode != SM_RASTER_SLICE
        && uiSliceMode != SM_DYN_SLICE)
      return 1;

    pSliceSeg->pOverallMbMap	= (uint8_t*)pMa->WelsMalloc (kiCountMbNum * sizeof (uint8_t), "pSliceSeg->pOverallMbMap");

    WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pOverallMbMap)

    //SM_DYN_SLICE: init, set pSliceSeg->iSliceNumInFrame	= 1;
    pSliceSeg->iSliceNumInFrame = GetInitialSliceNum (kiMbWidth, kiMbHeight, pMso);

    if (-1 == pSliceSeg->iSliceNumInFrame)
      return 1;

    pSliceSeg->pCountMbNumInSlice	= (int32_t*)pMa->WelsMalloc (pSliceSeg->iSliceNumInFrame * sizeof (int32_t),
                                    "pSliceSeg->pCountMbNumInSlice");

    WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pCountMbNumInSlice)

    pSliceSeg->pFirstMbInSlice		= (int16_t*)pMa->WelsMalloc (pSliceSeg->iSliceNumInFrame * sizeof (int16_t),
                                    "pSliceSeg->pFirstMbInSlice");

    WELS_VERIFY_RETURN_IF (1, NULL == pSliceSeg->pFirstMbInSlice)
    pSliceSeg->uiSliceMode			= pMso->uiSliceMode;
    pSliceSeg->iMbWidth				= kiMbWidth;
    pSliceSeg->iMbHeight			= kiMbHeight;
    pSliceSeg->iMbNumInFrame		= kiCountMbNum;
    if (SM_DYN_SLICE == pMso->uiSliceMode) {
      if (0 < pMso->sSliceArgument.uiSliceSizeConstraint) {
        pSliceSeg->uiSliceSizeConstraint = pMso->sSliceArgument.uiSliceSizeConstraint;
      } else {
        return 1;
      }
    } else {
      pSliceSeg->uiSliceSizeConstraint = DEFAULT_MAXPACKETSIZE_CONSTRAINT;
    }
    // about "iMaxSliceNumConstraint"
    //only used in SM_DYN_SLICE mode so far,
    //now follows NAL_UNIT_CONSTRAINT, (see definition)
    //will be adjusted under MT if there is limitation on iLayerNum
    pSliceSeg->iMaxSliceNumConstraint = MAX_SLICES_NUM;


    return AssignMbMapMultipleSlices (pSliceSeg, pMso);
  }
  return 0;
}
Example #12
0
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;
}
Example #13
0
/*
 *  request memory blocks for decoder avc part
 */
int32_t WelsRequestMem (PWelsDecoderContext pCtx, const int32_t kiMbWidth, const int32_t kiMbHeight,
                        bool& bReallocFlag) {
  const int32_t kiPicWidth      = kiMbWidth << 4;
  const int32_t kiPicHeight     = kiMbHeight << 4;
  int32_t iErr = ERR_NONE;

  int32_t iListIdx              = 0;    //, mb_blocks   = 0;
  int32_t iPicQueueSize         = 0;    // adaptive size of picture queue, = (pSps->iNumRefFrames x 2)
  bReallocFlag                  = false;
  bool  bNeedChangePicQueue     = true;
  CMemoryAlign* pMa = pCtx->pMemAlign;

  WELS_VERIFY_RETURN_IF (ERR_INFO_INVALID_PARAM, (NULL == pCtx || kiPicWidth <= 0 || kiPicHeight <= 0))

  // Fixed the issue about different gop size over last, 5/17/2010
  // get picture queue size currently
  iPicQueueSize = GetTargetRefListSize (pCtx);  // adaptive size of picture queue, = (pSps->iNumRefFrames x 2)
  pCtx->iPicQueueNumber = iPicQueueSize;
  if (pCtx->pPicBuff[LIST_0] != NULL
      && pCtx->pPicBuff[LIST_0]->iCapacity ==
      iPicQueueSize) // comparing current picture queue size requested and previous allocation picture queue
    bNeedChangePicQueue = false;
  // HD based pic buffer need consider memory size consumed when switch from 720p to other lower size
  WELS_VERIFY_RETURN_IF (ERR_NONE, pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel
                         && kiPicHeight == pCtx->iImgHeightInPixel) && (!bNeedChangePicQueue)) // have same scaled buffer

  // sync update pRefList
  WelsResetRefPic (pCtx); // added to sync update ref list due to pictures are free

  if (pCtx->bHaveGotMemory && (kiPicWidth == pCtx->iImgWidthInPixel && kiPicHeight == pCtx->iImgHeightInPixel)
      && pCtx->pPicBuff[LIST_0] != NULL && pCtx->pPicBuff[LIST_0]->iCapacity != iPicQueueSize) {
    // currently only active for LIST_0 due to have no B frames
    WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
             "WelsRequestMem(): memory re-alloc for no resolution change (size = %d * %d), ref list size change from %d to %d",
             kiPicWidth, kiPicHeight, pCtx->pPicBuff[LIST_0]->iCapacity, iPicQueueSize);
    if (pCtx->pPicBuff[LIST_0]->iCapacity < iPicQueueSize) {
      iErr = IncreasePicBuff (pCtx, &pCtx->pPicBuff[LIST_0], pCtx->pPicBuff[LIST_0]->iCapacity, kiPicWidth, kiPicHeight,
                              iPicQueueSize);
    } else {
      iErr = DecreasePicBuff (pCtx, &pCtx->pPicBuff[LIST_0], pCtx->pPicBuff[LIST_0]->iCapacity, kiPicWidth, kiPicHeight,
                              iPicQueueSize);
    }
  } else {
    if (pCtx->bHaveGotMemory)
      WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO,
               "WelsRequestMem(): memory re-alloc for resolution change, size change from %d * %d to %d * %d, ref list size change from %d to %d",
               pCtx->iImgWidthInPixel, pCtx->iImgHeightInPixel, kiPicWidth, kiPicHeight, pCtx->pPicBuff[LIST_0]->iCapacity,
               iPicQueueSize);
    else
      WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "WelsRequestMem(): memory alloc size = %d * %d, ref list size = %d",
               kiPicWidth, kiPicHeight, iPicQueueSize);
    // for Recycled_Pic_Queue
    for (iListIdx = LIST_0; iListIdx < LIST_A; ++ iListIdx) {
      PPicBuff* ppPic = &pCtx->pPicBuff[iListIdx];
      if (NULL != ppPic && NULL != *ppPic) {
        DestroyPicBuff (ppPic, pMa);
      }
    }

    pCtx->pPreviousDecodedPictureInDpb = NULL;

    // currently only active for LIST_0 due to have no B frames
    iErr = CreatePicBuff (pCtx, &pCtx->pPicBuff[LIST_0], iPicQueueSize, kiPicWidth, kiPicHeight);
  }

  if (iErr != ERR_NONE)
    return iErr;


  pCtx->iImgWidthInPixel    = kiPicWidth;   // target width of image to be reconstruted while decoding
  pCtx->iImgHeightInPixel   = kiPicHeight;  // target height of image to be reconstruted while decoding

  pCtx->bHaveGotMemory      = true;         // global memory for decoder context related is requested
  pCtx->pDec                = NULL;         // need prefetch a new pic due to spatial size changed

  if (pCtx->pCabacDecEngine == NULL)
    pCtx->pCabacDecEngine = (SWelsCabacDecEngine*) pMa->WelsMallocz (sizeof (SWelsCabacDecEngine), "pCtx->pCabacDecEngine");
  WELS_VERIFY_RETURN_IF (ERR_INFO_OUT_OF_MEMORY, (NULL == pCtx->pCabacDecEngine))

  bReallocFlag              = true;         // memory re-allocation successfully finished
  return ERR_NONE;
}