728 lines · 23.6 KB · C++
RawDownload
/*! * \copy *     Copyright (c)  2009-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. * * * \file	decoder.c * * \brief	Interfaces implementation introduced in decoder system architecture * * \date	03/10/2009 Created * ************************************************************************************* */#include "codec_def.h"#include "decoder.h"#include "cpu.h"#include "au_parser.h"#include "get_intra_predictor.h"#include "rec_mb.h"#include "mc.h"#include "decode_mb_aux.h"#include "manage_dec_ref.h"#include "decoder_core.h"#include "deblocking.h"#include "expand_pic.h"#include "decode_slice.h"#include "mem_align.h"#include "ls_defines.h" namespace WelsDec { extern PPicture AllocPicture (PWelsDecoderContext pCtx, const int32_t kiPicWidth, const int32_t kiPicHeight); extern void FreePicture (PPicture pPic); inline void GetValueOf4Bytes (uint8_t* pDstNal, int32_t iDdstIdx) {  ST32(pDstNal, iDdstIdx);} 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)WelsMalloc (sizeof (SPicBuff), "PPicBuff");   if (NULL == pPicBuf) {    return 1;  }   pPicBuf->ppPic = (PPicture*)WelsMalloc (kiSize * sizeof (PPicture), "PPicture*");   if (NULL == pPicBuf->ppPic) {    return 1;  }  for (iPicIdx = 0; iPicIdx < kiSize; ++ iPicIdx) {    PPicture pPic = AllocPicture (pCtx, kiPicWidth, kiPicHeight);    if (NULL == pPic) {      return 1;    }    pPicBuf->ppPic[iPicIdx] = pPic;  }   // initialize context in queue  pPicBuf->iCapacity	 = kiSize;  pPicBuf->iCurrentIdx = 0;  *ppPicBuf			 = pPicBuf;   return 0;} static void DestroyPicBuff (PPicBuff* ppPicBuf) {  PPicBuff pPicBuf = NULL;   if (NULL == ppPicBuf || NULL == *ppPicBuf)    return;   pPicBuf = *ppPicBuf;  while (pPicBuf->ppPic != NULL) {    int32_t iPicIdx = 0;    while (iPicIdx < pPicBuf->iCapacity) {      PPicture pPic = pPicBuf->ppPic[iPicIdx];      if (pPic != NULL) {        FreePicture (pPic);      }      pPic = NULL;      ++ iPicIdx;    }     WelsFree (pPicBuf->ppPic, "pPicBuf->queue");     pPicBuf->ppPic	= NULL;  }  pPicBuf->iCapacity	= 0;  pPicBuf->iCurrentIdx = 0;   WelsFree (pPicBuf, "pPicBuf");   pPicBuf = NULL;  *ppPicBuf = NULL;}/* * 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  #if defined(X86_ASM)  pCtx->uiCpuFlag = WelsCPUFeatureDetect (&iCpuCores);#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; } /* *	destory_mb_blocks */  /* *	get size of reference picture list in target layer incoming, = (iNumRefFrames x 2) */static inline int32_t GetTargetRefListSize (PWelsDecoderContext pCtx) {  bool*  pSubsetSpsAvail = &pCtx->bSubspsAvailFlags[0];  bool*  pSpsAvail		= &pCtx->bSpsAvailFlags[0];  int32_t iSubsetIdx		= -1;  int32_t iSpsIdx			= -1;  bool  bExistSubsetSps = false;  int32_t bExistSps		= false;  int32_t iPos			= MAX_SPS_COUNT - 1;  int32_t iNumRefFrames	= 0;   while (iPos >= 0) {    if (pSubsetSpsAvail[iPos]) {      bExistSubsetSps	= true;      iSubsetIdx		= iPos;      break;    }    -- iPos;  }   if (!bExistSubsetSps) {    iPos = MAX_SPS_COUNT - 1;    while (iPos >= 0) {      if (pSpsAvail[iPos]) {        bExistSps	= true;        iSpsIdx		= iPos;        break;      }      -- iPos;    }  }   if (! (bExistSubsetSps || bExistSps)) {    iNumRefFrames = MAX_REF_PIC_COUNT;  } else {    PSps pSps = bExistSubsetSps ? (&pCtx->sSubsetSpsBuffer[iSubsetIdx].sSps) : (&pCtx->sSpsBuffer[iSpsIdx]);     iNumRefFrames	= (pSps->iNumRefFrames) + 1;  }   if (0 == iNumRefFrames)    iNumRefFrames	= (MIN_REF_PIC_COUNT); #ifdef LONG_TERM_REF  //pic_queue size minimum set 2  if (iNumRefFrames < 2) {    iNumRefFrames = 2;  }#endif   return iNumRefFrames;} /* *	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);    }  }   // 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;} /* *	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->bHaveGotMemory	= false; } /*! * \brief	Open decoder */void WelsOpenDecoder (PWelsDecoderContext pCtx) {  // function pointers  //initial MC function pointer--  InitMcFunc (& (pCtx->sMcFunc), pCtx->uiCpuFlag);   InitExpandPictureFunc (& (pCtx->sExpandPicFunc), pCtx->uiCpuFlag);  AssignFuncPointerForRec (pCtx);   // vlc tables  InitVlcTable (&pCtx->sVlcTable);   // startup memory  if (ERR_NONE != WelsInitMemory (pCtx))    return; #ifdef LONG_TERM_REF  pCtx->bParamSetsLostFlag = true;#else  pCtx->bReferenceLostAtT0Flag	= true;	// should be true to waiting IDR at incoming AU bits following, 6/4/2010#endif //LONG_TERM_REF} /*! * \brief	Close decoder */void WelsCloseDecoder (PWelsDecoderContext pCtx) {  WelsFreeMem (pCtx);   WelsFreeMemory (pCtx);   UninitialDqLayersContext (pCtx); #ifdef LONG_TERM_REF  pCtx->bParamSetsLostFlag       = false;#else  pCtx->bReferenceLostAtT0Flag = false;#endif} /*! * \brief	configure decoder parameters */int32_t DecoderConfigParam (PWelsDecoderContext pCtx, const void* kpParam) {  if (NULL == pCtx || NULL == kpParam)    return 1;   pCtx->pParam	= (SDecodingParam*)WelsMalloc (sizeof (SDecodingParam), "SDecodingParam");   if (NULL == pCtx->pParam)    return 1;   memcpy (pCtx->pParam, kpParam, sizeof (SDecodingParam));  pCtx->iOutputColorFormat	= pCtx->pParam->iOutputColorFormat;  pCtx->bErrorResilienceFlag	= pCtx->pParam->uiEcActiveFlag ? true : false;   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, WELS_LOG_INFO, "eVideoType: %d\n", pCtx->eVideoType);   return 0;} /*! ************************************************************************************* * \brief	Initialize Wels decoder parameters and memory * * \param 	pCtx input context to be initialized at first stage * * \return	0 - successed * \return	1 - failed * * \note	N/A ************************************************************************************* */int32_t WelsInitDecoder (PWelsDecoderContext pCtx, void* pTraceHandle, PWelsLogCallbackFunc pLog) {  if (pCtx == NULL) {    return ERR_INFO_INVALID_PTR;  }   // default  WelsDecoderDefaults (pCtx);   pCtx->pTraceHandle = pTraceHandle;   g_pLog = pLog;   // open decoder  WelsOpenDecoder (pCtx);    return ERR_NONE;} /*! ************************************************************************************* * \brief	Uninitialize Wels decoder parameters and memory * * \param 	pCtx input context to be uninitialized at release stage * * \return	NONE * * \note	N/A ************************************************************************************* */void WelsEndDecoder (PWelsDecoderContext pCtx) {  // close decoder  WelsCloseDecoder (pCtx);} void GetVclNalTemporalId (PWelsDecoderContext pCtx) {  PAccessUnit pAccessUnit = pCtx->pAccessUnitList;  int32_t idx = pAccessUnit->uiStartPos;   pCtx->iFeedbackVclNalInAu = FEEDBACK_VCL_NAL;  pCtx->iFeedbackTidInAu    = pAccessUnit->pNalUnitsList[idx]->sNalHeaderExt.uiTemporalId;} /*! ************************************************************************************* * \brief	First entrance to decoding core interface. * * \param 	pCtx	        decoder context * \param	pBufBs	        bit streaming buffer * \param	kBsLen	        size in bytes length of bit streaming buffer input * \param	ppDst	        picture payload data to be output * \param	pDstBufInfo	    buf information of ouput data * * \return	0 - successed * \return	1 - failed * * \note	N/A ************************************************************************************* */int32_t WelsDecodeBs (PWelsDecoderContext pCtx, const uint8_t* kpBsBuf, const int32_t kiBsLen,                      uint8_t** ppDst, SBufferInfo* pDstBufInfo) {  if (!pCtx->bEndOfStreamFlag) {    SDataBuffer* pRawData   = &pCtx->sRawData;     int32_t iSrcIdx        = 0; //the index of source bit-stream till now after parsing one or more NALs    int32_t iSrcConsumed   = 0; // consumed bit count of source bs    int32_t iDstIdx        = 0; //the size of current NAL after 0x03 removal and 00 00 01 removal    int32_t iSrcLength     = 0;	//the total size of current AU or NAL     int32_t iConsumedBytes = 0;    int32_t iOffset        = 0;     uint8_t* pSrcNal       = NULL;    uint8_t* pDstNal       = NULL;    uint8_t* pNalPayload   = NULL;      if (NULL == DetectStartCodePrefix (kpBsBuf, &iOffset,                                       kiBsLen)) {  //CAN'T find the 00 00 01 start prefix from the source buffer      return dsBitstreamError;    }     pSrcNal    = const_cast<uint8_t*> (kpBsBuf) + iOffset;    iSrcLength = kiBsLen - iOffset;     if ((kiBsLen + 4) > (pRawData->pEnd - pRawData->pCurPos)) {      pRawData->pCurPos = pRawData->pHead;    }      //copy raw data from source buffer (application) to raw data buffer (codec inside)    //0x03 removal and extract all of NAL Unit from current raw data    pDstNal = pRawData->pCurPos + 4; //4-bytes used to write the length of current NAL rbsp     while (iSrcConsumed < iSrcLength) {      if ((2 + iSrcConsumed < iSrcLength) &&          (0 == LD16 (pSrcNal + iSrcIdx)) &&          ((pSrcNal[2 + iSrcIdx] == 0x03) || (pSrcNal[2 + iSrcIdx] == 0x01))) {        if (pSrcNal[2 + iSrcIdx] == 0x03) {          ST16 (pDstNal + iDstIdx, 0);          iDstIdx	+= 2;          iSrcIdx	+= 3;          iSrcConsumed += 3;        } else {          GetValueOf4Bytes (pDstNal - 4, iDstIdx);  //pDstNal-4 (non-aligned by 4) in Solaris10(SPARC). Given value by byte.           iConsumedBytes = 0;          pNalPayload	= ParseNalHeader (pCtx, &pCtx->sCurNalHead, pDstNal, iDstIdx, pSrcNal - 3, iSrcIdx + 3, &iConsumedBytes);           if (pCtx->bAuReadyFlag) {            ConstructAccessUnit (pCtx, ppDst, pDstBufInfo);

Lines 1–500 of 728.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t