Ethan HuggInitial Commit70e5e6212 years agoHistory
850 lines · 24.5 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 <string.h>#include "macros.h"#include "codec_def.h"#include "decoder.h"#include "error_code.h"#include "cpu.h"#include "cpu_core.h"#include "au_parser.h"#include "utils.h"#include "nal_prefix.h"#include "dec_frame.h"#include "pic_queue.h"#include "vlc_decoder.h"#include "get_intra_predictor.h"#include "rec_mb.h"#include "mc.h"#include "decode_mb_aux.h"#include "manage_dec_ref.h"#include "codec_app_def.h"#include "decoder_core.h"#include "deblocking.h"#include "expand_pic.h"#include "decode_slice.h"#include "crt_util_safe_x.h"	// Safe CRT routines like utils for cross platforms#include "mem_align.h" namespace WelsDec { extern PPicture AllocPicture( PWelsDecoderContext pCtx,const int32_t kiPicWidth, const int32_t kiPicHeight ); extern void_t FreePicture( PPicture pPic ); #ifdef WORDS_BIGENDIANinline void_t GetValueOf4Bytes( uint8_t* pDstNal, int32_t iDdstIdx ){	pDstNal[0] = (iDdstIdx & 0xff000000) >> 24;	pDstNal[1] = (iDdstIdx & 0xff0000) >> 16;	pDstNal[2] = (iDdstIdx & 0xff00) >> 8;	pDstNal[3] = (iDdstIdx & 0xff);}#else //WORDS_BIGENDIANinline void_t GetValueOf4Bytes( uint8_t* pDstNal, int32_t iDdstIdx ){	pDstNal[0] = (iDdstIdx & 0xff);	pDstNal[1] = (iDdstIdx & 0xff00) >> 8;	pDstNal[2] = (iDdstIdx & 0xff0000) >> 16;	pDstNal[3] = (iDdstIdx & 0xff000000) >> 24;}#endif //WORDS_BIGENDIAN 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_t 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_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; } /* *	destory_mb_blocks */  /* *	get size of reference picture list in target layer incoming, = (iNumRefFrames x 2) */static inline int32_t GetTargetRefListSize( PWelsDecoderContext pCtx ){		bool_t  *pSubsetSpsAvail= &pCtx->bSubspsAvailFlags[0];	bool_t  *pSpsAvail		= &pCtx->bSpsAvailFlags[0];	int32_t iSubsetIdx		= -1;	int32_t iSpsIdx			= -1;	bool_t  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_t  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_t 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_t 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;	 	pCtx->iMaxWidthInSps	= 0;	pCtx->iMaxHeightInSps	= 0;#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_t 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_t* 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_t * pTraceHandle, PWelsLogCallbackFunc pLog ){	if ( pCtx == NULL ){		return ERR_INFO_INVALID_PTR;	} 	// default	WelsDecoderDefaults( pCtx );	 	pCtx->pTraceHandle = pTraceHandle; 	g_pLog = pLog; 	// open decoder	WelsOpenDecoder( pCtx );		// decode mode setting 	pCtx->iDecoderMode = SW_MODE;	pCtx->iSetMode = AUTO_MODE;	pCtx->iDecoderOutputProperty = BUFFER_HOST;	pCtx->iModeSwitchType = 0; // 0: do not do mode switch  	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_t WelsEndDecoder( PWelsDecoderContext pCtx ){	// close decoder	WelsCloseDecoder( pCtx );	} void_t GetVclNalTemporalId( PWelsDecoderContext pCtx ){

Lines 1–500 of 850.

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