Esempio n. 1
0
/*
 * fill data fields in default for decoder context
 */
void WelsDecoderDefaults (PWelsDecoderContext pCtx) {
  int32_t iCpuCores               = 1;
  memset (pCtx, 0, sizeof (SWelsDecoderContext));	// fill zero first

  pCtx->pArgDec                   = NULL;

  pCtx->iOutputColorFormat		= videoFormatI420;	// yuv in default
  pCtx->bHaveGotMemory			= false;	// not ever request memory blocks for decoder context related
  pCtx->uiCpuFlag					= 0;

  pCtx->bAuReadyFlag				= 0; // au data is not ready


  pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);

  pCtx->iImgWidthInPixel		= 0;
  pCtx->iImgHeightInPixel		= 0;		// alloc picture data when picture size is available

  pCtx->iFrameNum				= -1;
  pCtx->iPrevFrameNum			= -1;
  pCtx->iErrorCode			= ERR_NONE;

  pCtx->pDec					= NULL;

  WelsResetRefPic (pCtx);

  pCtx->iActiveFmoNum			= 0;

  pCtx->pPicBuff[LIST_0]		= NULL;
  pCtx->pPicBuff[LIST_1]		= NULL;

  pCtx->bAvcBasedFlag			= true;
  pCtx->iErrorConMethod = ERROR_CON_DISABLE;

}
Esempio n. 2
0
/*
 *	free memory blocks in avc
 */
void WelsFreeMem (PWelsDecoderContext pCtx) {
  int32_t iListIdx = 0;

  /* TODO: free memory blocks introduced in avc */
  ResetFmoList (pCtx);

  WelsResetRefPic (pCtx);

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

  // added for safe memory
  pCtx->iImgWidthInPixel	= 0;
  pCtx->iImgHeightInPixel = 0;
  pCtx->iLastImgWidthInPixel	= 0;
  pCtx->iLastImgHeightInPixel = 0;
  pCtx->bFreezeOutput = true;
  pCtx->bHaveGotMemory	= false;
  WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
}
Esempio n. 3
0
/*
 *  free memory dynamically allocated during decoder
 */
void WelsFreeDynamicMemory (PWelsDecoderContext pCtx) {
  int32_t iListIdx = 0;
  CMemoryAlign* pMa = pCtx->pMemAlign;

  //free dq layer memory
  UninitialDqLayersContext (pCtx);

  //free FMO memory
  ResetFmoList (pCtx);

  //free ref-pic list & picture memory
  WelsResetRefPic (pCtx);
  for (iListIdx = LIST_0; iListIdx < LIST_A; ++ iListIdx) {
    PPicBuff* pPicBuff = &pCtx->pPicBuff[iListIdx];
    if (NULL != pPicBuff && NULL != *pPicBuff) {
      DestroyPicBuff (pPicBuff, pMa);
    }
  }

  // added for safe memory
  pCtx->iImgWidthInPixel  = 0;
  pCtx->iImgHeightInPixel = 0;
  pCtx->iLastImgWidthInPixel  = 0;
  pCtx->iLastImgHeightInPixel = 0;
  pCtx->bFreezeOutput = true;
  pCtx->bHaveGotMemory = false;

  //free CABAC memory
  pMa->WelsFree (pCtx->pCabacDecEngine, "pCtx->pCabacDecEngine");
}
Esempio n. 4
0
/*
 * fill data fields in default for decoder context
 */
void WelsDecoderDefaults (PWelsDecoderContext pCtx, SLogContext* pLogCtx) {
  int32_t iCpuCores               = 1;
  pCtx->sLogCtx = *pLogCtx;

  pCtx->pArgDec                   = NULL;

  pCtx->eOutputColorFormat        = videoFormatI420;    // yuv in default
  pCtx->bHaveGotMemory            = false;              // not ever request memory blocks for decoder context related
  pCtx->uiCpuFlag                 = 0;

  pCtx->bAuReadyFlag              = 0;                  // au data is not ready
  pCtx->bCabacInited = false;

  pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);

  pCtx->iImgWidthInPixel          = 0;
  pCtx->iImgHeightInPixel         = 0;                  // alloc picture data when picture size is available
  pCtx->iLastImgWidthInPixel      = 0;
  pCtx->iLastImgHeightInPixel     = 0;
  pCtx->bFreezeOutput = true;

  pCtx->iFrameNum                 = -1;
  pCtx->iPrevFrameNum             = -1;
  pCtx->iErrorCode                = ERR_NONE;

  pCtx->pDec                      = NULL;

  WelsResetRefPic (pCtx);

  pCtx->iActiveFmoNum             = 0;

  pCtx->pPicBuff[LIST_0]          = NULL;
  pCtx->pPicBuff[LIST_1]          = NULL;

  pCtx->bAvcBasedFlag             = true;
  pCtx->eErrorConMethod = ERROR_CON_SLICE_MV_COPY_CROSS_IDR_FREEZE_RES_CHANGE;
  pCtx->pPreviousDecodedPictureInDpb = NULL;
  pCtx->sDecoderStatistics.iAvgLumaQp = -1;
  pCtx->bSpsLatePps = false;
  pCtx->bUseScalingList = false;
  pCtx->iSpsErrorIgnored = 0;
  pCtx->iSubSpsErrorIgnored = 0;
  pCtx->iPpsErrorIgnored = 0;
  pCtx->iPPSInvalidNum = 0;
  pCtx->iPPSLastInvalidId = -1;
  pCtx->iSPSInvalidNum = 0;
  pCtx->iSPSLastInvalidId = -1;
  pCtx->iSubSPSInvalidNum = 0;
  pCtx->iSubSPSLastInvalidId = -1;
}
Esempio n. 5
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;
}
Esempio n. 6
0
/*
 * fill data fields in default for decoder context
 */
void_t WelsDecoderDefaults (PWelsDecoderContext pCtx) {
  int32_t iCpuCores               = 1;
  memset (pCtx, 0, sizeof (SWelsDecoderContext));	// fill zero first

  pCtx->pArgDec                   = NULL;

  pCtx->iOutputColorFormat		= videoFormatI420;	// yuv in default
  pCtx->bHaveGotMemory			= false;	// not ever request memory blocks for decoder context related
  pCtx->uiCpuFlag					= 0;

  pCtx->bAuReadyFlag				= 0; // au data is not ready


  g_uiCacheLineSize				= 16;
#if defined(X86_ASM)
  pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);
#ifdef HAVE_CACHE_LINE_ALIGN
  if (pCtx->uiCpuFlag & WELS_CPU_CACHELINE_64) {
    g_uiCacheLineSize	= 64;
  } else if (pCtx->uiCpuFlag & WELS_CPU_CACHELINE_32) {
    g_uiCacheLineSize	= 32;
  }
#endif//HAVE_CACHE_LINE_ALIGN
#endif//X86_ASM	

  pCtx->iImgWidthInPixel		= 0;
  pCtx->iImgHeightInPixel		= 0;		// alloc picture data when picture size is available

  pCtx->iFrameNum				= -1;
  pCtx->iPrevFrameNum			= -1;
  pCtx->iErrorCode			= ERR_NONE;

  pCtx->pDec					= NULL;

  WelsResetRefPic (pCtx);

  pCtx->iActiveFmoNum			= 0;

  pCtx->pPicBuff[LIST_0]		= NULL;
  pCtx->pPicBuff[LIST_1]		= NULL;

  pCtx->bAvcBasedFlag			= true;

}
Esempio n. 7
0
static int32_t MMCOProcess (PWelsDecoderContext pCtx, uint32_t uiMmcoType,
                            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);
    if (pPic == NULL) {
      WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_SHORT2UNUSED: delete a empty entry from short term list");
    }
    break;
  case MMCO_LONG2UNUSED:
    pPic = WelsDelLongFromListSetUnref (pRefPic, uiLongTermPicNum);
    if (pPic == NULL) {
      WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_LONG2UNUSED: delete a empty entry from long term list");
    }
    break;
  case MMCO_SHORT2LONG:
    if (iLongTermFrameIdx > pRefPic->iMaxLongTermFrameIdx) {
      return ERR_INFO_INVALID_MMCO_LONG_TERM_IDX_EXCEED_MAX;
    }
    pPic = WelsDelShortFromList (pRefPic, iShortFrameNum);
    if (pPic == NULL) {
      WelsLog (& (pCtx->sLogCtx), WELS_LOG_WARNING, "MMCO_LONG2LONG: delete a empty entry from short term list");
      break;
    }
    WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
#ifdef LONG_TERM_REF
    pCtx->bCurAuContainLtrMarkSeFlag = true;
    pCtx->iFrameNumOfAuMarkedLtr      = iShortFrameNum;
    WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "ex_mark_avc():::MMCO_SHORT2LONG:::LTR marking....iFrameNum: %d",
             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);
      }
    }
    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;
    }
    WelsDelLongFromListSetUnref (pRefPic, iLongTermFrameIdx);
    if (pRefPic->uiLongRefCount[LIST_0] + pRefPic->uiShortRefCount[LIST_0] >= WELS_MAX (1, pCtx->pSps->iNumRefFrames)) {
      return ERR_INFO_INVALID_MMCO_REF_NUM_OVERFLOW;
    }
#ifdef LONG_TERM_REF
    pCtx->bCurAuContainLtrMarkSeFlag = true;
    pCtx->iFrameNumOfAuMarkedLtr      = pCtx->iFrameNum;
    WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "ex_mark_avc():::MMCO_LONG:::LTR marking....iFrameNum: %d",
             pCtx->iFrameNum);
#endif
    iRet = AddLongTermToList (pRefPic, pCtx->pDec, iLongTermFrameIdx);
    break;
  default :
    break;
  }

  return iRet;
}
Esempio n. 8
0
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;
}
Esempio n. 9
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;
}