📄 mp4swdecapi.c
字号:
/*------------------------------------------------------------------------------
-- --
-- This software is confidential and proprietary and may be used --
-- only as expressly authorized by a licensing agreement from --
-- --
-- Hantro Products Oy. --
-- --
-- In the event of publication, the following notice is applicable: --
-- --
-- (C) COPYRIGHT 2004 HANTRO PRODUCTS OY --
-- ALL RIGHTS RESERVED --
-- --
-- The entire notice above must be reproduced on all copies. --
-- --
--------------------------------------------------------------------------------
--
-- Abstract : The API module C-functions of the MPEG4 Decoder
--
-------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
Table of contents
1. Include headers
2. External identifiers
3. Module defines
4. Module identifiers
5. Functions
- MP4SwDecDecode()
- MP4SwDecInit()
- MP4SwDecGetInfo()
- MP4SwDecGetUserData()
- MP4SwDecRelease()
- MP4SwDecGetAPIVersion()
- MP4SwDecGetQPs()
- MP4SwDecGetDeblockingInfo()
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include "MP4SwDecApi.h"
#include "SwDec_Container.h"
#include "SwDec.h"
#include "SwDec_Utils.h"
#ifndef MP4DEC_H263_ONLY
#include "SwDec_Headers.h"
#endif
#ifdef MP4DEC_TRACE
#include <stdio.h>
#endif
/*------------------------------------------------------------------------------
Version Information
------------------------------------------------------------------------------*/
#define MP4SWDEC_MAJOR_VERSION 3
#define MP4SWDEC_MINOR_VERSION 2
/*------------------------------------------------------------------------------
2. External compiler flags
--------------------------------------------------------------------------------
MP4DEC_H263_ONLY When this flag is defined the decoder supports
only H.263 decoding (MPEG-4 is disabled).
MP4DEC_TRACE Trace MP4 Decoder API function calls.
MP4DEC_EVALUATION if defined, decoder decodes only limited
number of frames.
MP4DEC_ARM11 Enables ARM11 optimizations.
MP4DEC_UNALIGNED Uses unaligned memory access support.
--------------------------------------------------------------------------------
3. Module defines
------------------------------------------------------------------------------*/
#define MP4DEC_EVALUATION_LIMIT 400
#ifndef NULL
#define NULL 0
#endif
#ifdef MP4DEC_TRACE
#define DEC_API_TRC(str) MP4SwDecTrace(str)
#else
#define DEC_API_TRC(str)
#endif
/*lint -e826 -e702 -e774 */
/*------------------------------------------------------------------------------
4. Module indentifiers
------------------------------------------------------------------------------*/
static void SwDec_ClearDataStructures(decContainer_t *pDecCont);
/*------------------------------------------------------------------------------
Function name: MP4SwDecDecode
Purpose: Decodes a block of MPEG4 stream
Input: pDecInst decoder instance
*pInput pointer to input structure
*pOutput pointer to output structure
Output: MP4SwDecRet (enum)
------------------------------------------------------------------------------*/
MP4SwDecRet MP4SwDecDecode(MP4SwDecInst pDecInst,
MP4SwDecInput *pInput,
MP4SwDecOutput *pOutput)
{
#define API_STOR pDecCont->ApiStorage
#define DEC_ERRS pDecCont->ErrInfo
decContainer_t *pDecCont;
u32 pcf = 0;
u32 DecResult = 0;
MP4SwDecRet returnValue = MP4SWDEC_OK;
if ((pInput == NULL) || (pOutput == NULL))
{
DEC_API_TRC("MP4SwDecDecode# ERROR: pInput == NULL or pOutput == NULL");
return(MP4SWDEC_PARAM_ERR);
}
/* Initialize function variables */
pOutput->nbrOfErrMBs = 0;
/* Check if decoder instance is NULL */
if(pDecInst == NULL)
{
DEC_API_TRC("MP4SwDecDecode# ERROR: Decoder instance is NULL");
return(MP4SWDEC_NOT_INITIALIZED);
}
pDecCont = (decContainer_t*)pDecInst;
/* Check if decoder is in an incorrect mode */
if(API_STOR.DecStat == UNINIT)
{
DEC_API_TRC("MP4SwDecDecode# ERROR: Decoder not initialized");
return(MP4SWDEC_NOT_INITIALIZED);
}
#ifdef MP4DEC_TRACE
sprintf(pDecCont->str, "MP4SwDecDecode# pDecInst %p pInput %p pOutput %p",
(MP4SwDecInst *)pDecInst, pInput, pOutput);
DEC_API_TRC(pDecCont->str);
#endif
/* Check that function input parameters are valid */
if((pInput->pStream == NULL) || (pInput->dataLen == 0))
{
DEC_API_TRC("MP4SwDecDecode# ERROR: Not valid Input parameters");
return(MP4SWDEC_PARAM_ERR);
}
if(API_STOR.DecStat == HEADERSDECODED)
{
/* allocate decoder internal memories if not user allocated */
if (pInput->pExtOutputPic != NULL)
pDecCont->StrmStorage.extPicBufAlloc = 1;
if (SwDec_MemAlloc(pDecCont))
{
API_STOR.BufStat = NEWBUF;
return (MP4SWDEC_MEMFAIL);
}
/* change state */
API_STOR.DecStat = STREAMDECODING;
}
if (API_STOR.BufStat == NEWBUF)
{
/* Assign pointers into structures */
pDecCont->StrmDesc.pStrmBuffStart = pInput->pStream;
pDecCont->StrmDesc.pStrmCurrPos = pInput->pStream;
pDecCont->StrmDesc.bitPosInWord = 0;
pDecCont->StrmDesc.strmBuffSize = pInput->dataLen;
pDecCont->StrmDesc.strmBuffReadBits = 0;
/* Set zeros to user data field.
* User data fields are valid only for the latest stream buffer */
pDecCont->StrmDesc.userDataVOSLen = 0;
pDecCont->StrmDesc.pUserDataVOS = 0;
pDecCont->StrmDesc.userDataVOSMaxLen = 0;
pDecCont->StrmDesc.userDataVOLen = 0;
pDecCont->StrmDesc.pUserDataVO = 0;
pDecCont->StrmDesc.userDataVOMaxLen = 0;
pDecCont->StrmDesc.userDataVOLLen = 0;
pDecCont->StrmDesc.pUserDataVOL = 0;
pDecCont->StrmDesc.userDataVOLMaxLen = 0;
pDecCont->StrmDesc.userDataGOVLen = 0;
pDecCont->StrmDesc.pUserDataGOV = 0;
pDecCont->StrmDesc.userDataGOVMaxLen = 0;
}
/* Check that output pointer is valid if external memory allocation */
if ( (pInput->pExtOutputPic == NULL) &&
(pDecCont->StrmStorage.extPicBufAlloc) )
{
DEC_API_TRC("MP4SwDecDecode# ERROR: Ext output pic pointer not valid");
return(MP4SWDEC_PARAM_ERR);
}
#ifndef _MP4API_UTEST
/*Check that reference picture pointer is valid if external memory alloc */
if ((pDecCont->pRef == NULL) &&
(pDecCont->VopDesc.vopNumber > 0) &&
(pDecCont->StrmStorage.extPicBufAlloc))
{
DEC_API_TRC("MP4API_Decode#ERROR: Reference picture pointer not valid");
return(MP4SWDEC_PARAM_ERR);
}
#endif
if (pDecCont->StrmStorage.extPicBufAlloc)
pDecCont->pOut = (u8*)pInput->pExtOutputPic;
#ifdef MP4DEC_EVALUATION
if (pDecCont->VopDesc.vopNumber > MP4DEC_EVALUATION_LIMIT)
return (MP4SWDEC_EVALUATION_LIMIT_EXCEEDED);
#endif
DecResult = SwDec_Decode(pDecCont);
switch(DecResult)
{
case DEC_ERROR:
/* Nothing finished, decoder not ready, cannot continue decoding
* before some headers received */
returnValue = MP4SWDEC_STRM_ERR;
API_STOR.BufStat = NEWBUF;
break;
case DEC_ERROR_BUF_NOT_EMPTY:
/* same as above but stream buffer not empty */
returnValue = MP4SWDEC_STRM_ERR_BUFF_NOT_EMPTY;
API_STOR.BufStat = OLDBUF;
break;
case DEC_END_OF_STREAM:
/* nothing finished, no data left in stream */
case DEC_RDY:
/* everything ok but no VOP finished */
returnValue = MP4SWDEC_STRM_PROCESSED;
API_STOR.BufStat = NEWBUF;
break;
case DEC_VOP_RDY:
case DEC_VOP_RDY_BUF_NOT_EMPTY:
/* vop finished */
pOutput->pOutputPicture = (u32*)pDecCont->pOut;
if (pDecCont->StrmStorage.extPicBufAlloc)
{
/* set reference picture pointer for the next VOP */
pDecCont->pRef = pDecCont->pOut;
}
pOutput->nbrOfErrMBs = DEC_ERRS.numErrMb;
#ifdef MP4DEC_H263_ONLY
/* picture frequency */
pcf = ((pDecCont->SvDesc.tics *
pDecCont->SvDesc.clockDivisor *
pDecCont->SvDesc.clockConversionCode) /
pDecCont->Hdrs.vopTimeIncrementResolution);
pOutput->timeCode.hours = (pcf / 3600);
pOutput->timeCode.minutes = (pcf / 60) % 60;
pOutput->timeCode.seconds = (pcf) % 60;
pOutput->timeCode.timeIncr =
(pDecCont->SvDesc.tics * pDecCont->SvDesc.clockDivisor *
pDecCont->SvDesc.clockConversionCode) %
pDecCont->Hdrs.vopTimeIncrementResolution;
pOutput->timeCode.timeRes =
pDecCont->Hdrs.vopTimeIncrementResolution;
#else
if (pDecCont->StrmStorage.shortVideo)
{
/* picture frequency */
pcf = ((pDecCont->SvDesc.tics *
pDecCont->SvDesc.clockDivisor *
pDecCont->SvDesc.clockConversionCode) /
pDecCont->Hdrs.vopTimeIncrementResolution);
pOutput->timeCode.hours = (pcf / 3600);
pOutput->timeCode.minutes = (pcf / 60) % 60;
pOutput->timeCode.seconds = (pcf) % 60;
pOutput->timeCode.timeIncr =
(pDecCont->SvDesc.tics * pDecCont->SvDesc.clockDivisor *
pDecCont->SvDesc.clockConversionCode) %
pDecCont->Hdrs.vopTimeIncrementResolution;
pOutput->timeCode.timeRes =
pDecCont->Hdrs.vopTimeIncrementResolution;
}
else
{
pOutput->timeCode.hours = pDecCont->VopDesc.timeCodeHours;
pOutput->timeCode.minutes = pDecCont->VopDesc.timeCodeMinutes;
pOutput->timeCode.seconds = pDecCont->VopDesc.timeCodeSeconds;
pOutput->timeCode.timeIncr = pDecCont->VopDesc.vopTimeIncrement;
pOutput->timeCode.timeRes =
pDecCont->Hdrs.vopTimeIncrementResolution;
}
#endif
if (DecResult == DEC_VOP_RDY)
{
API_STOR.BufStat = NEWBUF;
returnValue = MP4SWDEC_VOP_RDY;
}
else
{
API_STOR.BufStat = OLDBUF;
returnValue = MP4SWDEC_VOP_RDY_BUFF_NOT_EMPTY;
}
break;
case DEC_HDRS_RDY:
case DEC_HDRS_RDY_BUF_NOT_EMPTY:
/* either vol header decoded or short video source format
* determined */
API_STOR.DecStat = HEADERSDECODED;
/* set headers lock */
pDecCont->Hdrs.lock = 1;
if (DecResult == DEC_HDRS_RDY)
{
returnValue = MP4SWDEC_HDRS_RDY;
API_STOR.BufStat = NEWBUF;
}
else
{
returnValue = MP4SWDEC_HDRS_RDY_BUFF_NOT_EMPTY;
API_STOR.BufStat = OLDBUF;
}
break;
case DEC_VOS_END:
/* vos end code encountered, stopping */
returnValue = MP4SWDEC_VOS_END;
API_STOR.BufStat = NEWBUF;
break;
default:
returnValue = MP4SWDEC_STRM_ERR;
API_STOR.BufStat = NEWBUF;
}
#ifdef MP4DEC_TRACE
sprintf(pDecCont->str, "MP4SwDecDecode# OK: DecResult %d",
returnValue);
DEC_API_TRC(pDecCont->str);
#endif
return (returnValue);
#undef API_STOR
#undef DEC_ERRS
}
/*------------------------------------------------------------------------------
Function name: MP4SwDecInit()
Purpose: Initialize decoder
Input: MP4SwDecInst *pDecInst
Output: MP4SwDecRet
------------------------------------------------------------------------------*/
MP4SwDecRet MP4SwDecInit(MP4SwDecInst *pDecInst)
{
decContainer_t *pDecCont;
#ifdef MP4DEC_TRACE
DEC_API_TRC("MP4SwDecInit#");
#endif
/* check that right shift on negative numbers is performed signed */
/*lint --e(572) --e(649) --e(506) */
if ( ((-1)>>1) != (-1) )
{
DEC_API_TRC("MP4SwDecInit# ERROR: Right shift is not signed");
return(MP4SWDEC_PARAM_ERR);
}
pDecCont = (decContainer_t *)MP4SwDecMalloc(sizeof(decContainer_t));
if (pDecCont == NULL)
{
DEC_API_TRC("MP4SwDecInit# ERROR: pDecCont == NULL");
return(MP4SWDEC_MEMFAIL);
}
SwDec_ClearDataStructures(pDecCont);
SwDec_Init(pDecCont);
pDecCont->ApiStorage.DecStat = INITIALIZED;
pDecCont->ApiStorage.BufStat = NEWBUF;
#ifdef MP4DEC_TRACE
sprintf(pDecCont->str, "MP4SwDecInit# OK: return %p",(void*)pDecCont);
DEC_API_TRC(pDecCont->str);
#endif
/*lint --e(740) */
*pDecInst = (MP4SwDecInst *)pDecCont;
return (MP4SWDEC_OK);
}
/*------------------------------------------------------------------------------
Function name: MP4SwDecGetInfo()
Purpose: This function is used to get stream information.
Input: MP4SwDecInst pDecInst (decoder instance)
MP4SwDecInfo *pDecInfo (pointer to config structure)
Output: MP4SwDecRet
------------------------------------------------------------------------------*/
MP4SwDecRet MP4SwDecGetInfo(MP4SwDecInst pDecInst, MP4SwDecInfo *pDecInfo)
{
decContainer_t *pDecCont;
if ((pDecInst == NULL) || (pDecInfo == NULL))
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -