/*! * \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. Load more
/*! * \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_BIGENDIAN inline 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_BIGENDIAN inline 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 ) {