Beispiel #1
0
/*!
 * \brief	configure decoder parameters
 */
int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const SDecodingParam* kpParam) {
  if (NULL == pCtx || NULL == kpParam)
    return 1;

  pCtx->pParam	= (SDecodingParam*)WelsMallocz (sizeof (SDecodingParam), "SDecodingParam");

  if (NULL == pCtx->pParam)
    return 1;

  memcpy (pCtx->pParam, kpParam, sizeof (SDecodingParam));
  pCtx->eOutputColorFormat	= pCtx->pParam->eOutputColorFormat;
  if (!pCtx->bParseOnly) {
    int32_t iRet = DecoderSetCsp (pCtx, pCtx->pParam->eOutputColorFormat);
    if (iRet)
      return iRet;
  }
  pCtx->eErrorConMethod = pCtx->pParam->eEcActiveIdc;

  if (pCtx->bParseOnly) //parse only, disable EC method
    pCtx->eErrorConMethod = ERROR_CON_DISABLE;
  InitErrorCon (pCtx);

  if (VIDEO_BITSTREAM_SVC == pCtx->pParam->sVideoProperty.eVideoBsType ||
      VIDEO_BITSTREAM_AVC == pCtx->pParam->sVideoProperty.eVideoBsType) {
    pCtx->eVideoType = pCtx->pParam->sVideoProperty.eVideoBsType;
  } else {
    pCtx->eVideoType = VIDEO_BITSTREAM_DEFAULT;
  }

  WelsLog (& (pCtx->sLogCtx), WELS_LOG_INFO, "eVideoType: %d", pCtx->eVideoType);

  return 0;
}
// the return value of this function is not suitable, it need report failure info to upper layer.
int32_t CWelsDecoder::InitDecoder (const SDecodingParam* pParam) {

  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO,
           "CWelsDecoder::init_decoder(), openh264 codec version = %s, ParseOnly = %d",
           VERSION_NUMBER, (int32_t)pParam->bParseOnly);

  //reset decoder context
  if (m_pDecContext) //free
    UninitDecoder();
  m_pDecContext = (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
  if (NULL == m_pDecContext)
    return cmMallocMemeError;
  int32_t iCacheLineSize = 16;   // on chip cache line size in byte
  m_pDecContext->pMemAlign = new CMemoryAlign (iCacheLineSize);
  WELS_VERIFY_RETURN_PROC_IF (1, (NULL == m_pDecContext->pMemAlign), UninitDecoder())

  //fill in default value into context
  WelsDecoderDefaults (m_pDecContext, &m_pWelsTrace->m_sLogCtx);

  //check param and update decoder context
  m_pDecContext->pParam = (SDecodingParam*) m_pDecContext->pMemAlign->WelsMallocz (sizeof (SDecodingParam),
                          "SDecodingParam");
  WELS_VERIFY_RETURN_PROC_IF (cmMallocMemeError, (NULL == m_pDecContext->pParam), UninitDecoder());
  int32_t iRet = DecoderConfigParam (m_pDecContext, pParam);
  WELS_VERIFY_RETURN_IFNEQ (iRet, cmResultSuccess);

  //init decoder
  WELS_VERIFY_RETURN_PROC_IF (cmInitParaError, WelsInitDecoder (m_pDecContext, &m_pWelsTrace->m_sLogCtx), UninitDecoder())

  return cmResultSuccess;
}
Beispiel #3
0
static int32_t CreatePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiSize,
                              const int32_t kiPicWidth, const int32_t kiPicHeight) {
  PPicBuff pPicBuf = NULL;
  int32_t iPicIdx = 0;
  if (kiSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {
    return 1;
  }

  pPicBuf	= (PPicBuff)WelsMallocz (sizeof (SPicBuff), "PPicBuff");

  if (NULL == pPicBuf) {
    return 1;
  }

  pPicBuf->ppPic = (PPicture*)WelsMallocz (kiSize * sizeof (PPicture), "PPicture*");

  if (NULL == pPicBuf->ppPic) {
    pPicBuf->iCapacity = 0;
    DestroyPicBuff (&pPicBuf);
    return 1;
  }

  for (iPicIdx = 0; iPicIdx < kiSize; ++ iPicIdx) {
    PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);
    if (NULL == pPic) {
      // init capacity first for free memory
      pPicBuf->iCapacity = iPicIdx;
      DestroyPicBuff (&pPicBuf);
      return 1;
    }
    pPicBuf->ppPic[iPicIdx] = pPic;
  }

// initialize context in queue
  pPicBuf->iCapacity	 = kiSize;
  pPicBuf->iCurrentIdx = 0;
  * ppPicBuf			 = pPicBuf;

  return 0;
}
Beispiel #4
0
// the return value of this function is not suitable, it need report failure info to upper layer.
int32_t CWelsDecoder::InitDecoder (const bool bParseOnly) {

  WelsLog (&m_pWelsTrace->m_sLogCtx, WELS_LOG_INFO, "CWelsDecoder::init_decoder(), openh264 codec version = %s",
           VERSION_NUMBER);

  if (m_pDecContext) //free
    UninitDecoder();
  m_pDecContext	= (PWelsDecoderContext)WelsMallocz (sizeof (SWelsDecoderContext), "m_pDecContext");
  if (NULL == m_pDecContext)
    return cmMallocMemeError;

  return WelsInitDecoder (m_pDecContext, bParseOnly, &m_pWelsTrace->m_sLogCtx);
}
Beispiel #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

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

    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*) WelsMallocz (sizeof (SWelsCabacDecEngine), "pCtx->pCabacDecEngine");

  return ERR_NONE;
}
Beispiel #6
0
static int32_t DecreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,
                                const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {
  PPicBuff pPicOldBuf = *ppPicBuf;
  PPicBuff pPicNewBuf = NULL;
  int32_t iPicIdx = 0;
  if (kiOldSize <= 0 || kiNewSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {
    return 1;
  }

  pPicNewBuf	= (PPicBuff)WelsMallocz (sizeof (SPicBuff), "PPicBuff");

  if (NULL == pPicNewBuf) {
    return 1;
  }

  pPicNewBuf->ppPic = (PPicture*)WelsMallocz (kiNewSize * sizeof (PPicture), "PPicture*");

  if (NULL == pPicNewBuf->ppPic) {
    pPicNewBuf->iCapacity	 = 0;
    DestroyPicBuff (&pPicNewBuf);
    return 1;
  }

  int32_t iPrevPicIdx = -1;
  for (iPrevPicIdx = 0; iPrevPicIdx < kiOldSize; ++iPrevPicIdx) {
    if (pCtx->pPreviousDecodedPictureInDpb == pPicOldBuf->ppPic[iPrevPicIdx]) {
      break;
    }
  }
  int32_t iDelIdx;
  if (iPrevPicIdx < kiOldSize && iPrevPicIdx >= kiNewSize) {
    // found pPreviousDecodedPictureInDpb,
    pPicNewBuf->ppPic[0] = pPicOldBuf->ppPic[iPrevPicIdx];
    pPicNewBuf->iCurrentIdx = 0;
    memcpy (pPicNewBuf->ppPic + 1, pPicOldBuf->ppPic, (kiNewSize - 1) * sizeof (PPicture));
    iDelIdx = kiNewSize - 1;
  } else {
    memcpy (pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiNewSize * sizeof (PPicture));
    pPicNewBuf->iCurrentIdx = iPrevPicIdx < kiNewSize ? iPrevPicIdx : 0;
    iDelIdx = kiNewSize;
  }

  for (iPicIdx = iDelIdx; iPicIdx < kiOldSize; iPicIdx++) {
    if (iPrevPicIdx != iPicIdx) {
      if (pPicOldBuf->ppPic[iPicIdx] != NULL) {
        FreePicture (pPicOldBuf->ppPic[iPicIdx]);
        pPicOldBuf->ppPic[iPicIdx] = NULL;
      }
    }
  }

  // initialize context in queue
  pPicNewBuf->iCapacity	 = kiNewSize;
  *ppPicBuf			 = pPicNewBuf;

  for (int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {
    pPicNewBuf->ppPic[i]->bUsedAsRef = false;
    pPicNewBuf->ppPic[i]->bIsLongRef = false;
    pPicNewBuf->ppPic[i]->uiRefCount = 0;
    pPicNewBuf->ppPic[i]->bAvailableFlag = true;
    pPicNewBuf->ppPic[i]->bIsComplete = false;
  }
  // remove old PicBuf
  if (pPicOldBuf->ppPic != NULL) {
    WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");
    pPicOldBuf->ppPic	= NULL;
  }
  pPicOldBuf->iCapacity	= 0;
  pPicOldBuf->iCurrentIdx = 0;
  WelsFree (pPicOldBuf, "pPicOldBuf");
  pPicOldBuf = NULL;

  return 0;
}
Beispiel #7
0
static int32_t IncreasePicBuff (PWelsDecoderContext pCtx, PPicBuff* ppPicBuf, const int32_t kiOldSize,
                                const int32_t kiPicWidth, const int32_t kiPicHeight, const int32_t kiNewSize) {
  PPicBuff pPicOldBuf = *ppPicBuf;
  PPicBuff pPicNewBuf = NULL;
  int32_t iPicIdx = 0;
  if (kiOldSize <= 0 || kiNewSize <= 0 || kiPicWidth <= 0 || kiPicHeight <= 0) {
    return 1;
  }

  pPicNewBuf	= (PPicBuff)WelsMallocz (sizeof (SPicBuff), "PPicBuff");

  if (NULL == pPicNewBuf) {
    return 1;
  }

  pPicNewBuf->ppPic = (PPicture*)WelsMallocz (kiNewSize * sizeof (PPicture), "PPicture*");

  if (NULL == pPicNewBuf->ppPic) {
    pPicNewBuf->iCapacity = 0;
    DestroyPicBuff (&pPicNewBuf);
    return 1;
  }

  // increase new PicBuf
  for (iPicIdx = kiOldSize; iPicIdx < kiNewSize; ++ iPicIdx) {
    PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);
    if (NULL == pPic) {
      // Set maximum capacity as the new malloc memory at the tail
      pPicNewBuf->iCapacity = iPicIdx;
      DestroyPicBuff (&pPicNewBuf);
      return 1;
    }
    pPicNewBuf->ppPic[iPicIdx] = pPic;
  }

  // copy old PicBuf to new PicBuf
  memcpy (pPicNewBuf->ppPic, pPicOldBuf->ppPic, kiOldSize * sizeof (PPicture));

// initialize context in queue
  pPicNewBuf->iCapacity	 = kiNewSize;
  pPicNewBuf->iCurrentIdx = pPicOldBuf->iCurrentIdx;
  * ppPicBuf			 = pPicNewBuf;

  for (int32_t i = 0; i < pPicNewBuf->iCapacity; i++) {
    pPicNewBuf->ppPic[i]->bUsedAsRef = false;
    pPicNewBuf->ppPic[i]->bIsLongRef = false;
    pPicNewBuf->ppPic[i]->uiRefCount = 0;
    pPicNewBuf->ppPic[i]->bAvailableFlag = true;
    pPicNewBuf->ppPic[i]->bIsComplete = false;
  }
// remove old PicBuf
  if (pPicOldBuf->ppPic != NULL) {
    WelsFree (pPicOldBuf->ppPic, "pPicOldBuf->queue");
    pPicOldBuf->ppPic	= NULL;
  }
  pPicOldBuf->iCapacity	= 0;
  pPicOldBuf->iCurrentIdx = 0;
  WelsFree (pPicOldBuf, "pPicOldBuf");
  pPicOldBuf = NULL;
  return 0;
}