blob: f820dfd576cfa15ef6dde551433ee24ea2dd0719 [file] [log] [blame]
/*
* Copyright (C) 2009 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*------------------------------------------------------------------------------
Table of contents
1. Include headers
2. External compiler flags
3. Module defines
4. Local function prototypes
5. Functions
H264SwDecInit
H264SwDecGetInfo
H264SwDecRelease
H264SwDecDecode
H264SwDecGetAPIVersion
H264SwDecNextPicture
------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------
1. Include headers
------------------------------------------------------------------------------*/
#include <log/log.h>
#include <stdlib.h>
#include <string.h>
#include "basetype.h"
#include "h264bsd_container.h"
#include "H264SwDecApi.h"
#include "h264bsd_decoder.h"
#include "h264bsd_util.h"
#define UNUSED(x) (void)(x)
/*------------------------------------------------------------------------------
Version Information
------------------------------------------------------------------------------*/
#define H264SWDEC_MAJOR_VERSION 2
#define H264SWDEC_MINOR_VERSION 3
/*------------------------------------------------------------------------------
2. External compiler flags
--------------------------------------------------------------------------------
H264DEC_TRACE Trace H264 Decoder API function calls.
H264DEC_EVALUATION Compile evaluation version, restricts number of frames
that can be decoded
--------------------------------------------------------------------------------
3. Module defines
------------------------------------------------------------------------------*/
#ifdef H264DEC_TRACE
#include <stdio.h>
#define DEC_API_TRC(str) H264SwDecTrace(str)
#else
#define DEC_API_TRC(str)
#endif
#ifdef H264DEC_EVALUATION
#define H264DEC_EVALUATION_LIMIT 500
#endif
void H264SwDecTrace(char *string) {
UNUSED(string);
}
void* H264SwDecMalloc(u32 size, u32 num) {
if (size > UINT32_MAX / num) {
ALOGE("can't allocate %u * %u bytes", size, num);
android_errorWriteLog(0x534e4554, "27855419");
return NULL;
}
return malloc(size * num);
}
void H264SwDecFree(void *ptr) {
free(ptr);
}
void H264SwDecMemcpy(void *dest, void *src, u32 count) {
memcpy(dest, src, count);
}
void H264SwDecMemset(void *ptr, i32 value, u32 count) {
memset(ptr, value, count);
}
/*------------------------------------------------------------------------------
Function: H264SwDecInit()
Functional description:
Initialize decoder software. Function reserves memory for the
decoder instance and calls h264bsdInit to initialize the
instance data.
Inputs:
noOutputReordering flag to indicate decoder that it doesn't have
to try to provide output pictures in display
order, saves memory
Outputs:
decInst pointer to initialized instance is stored here
Returns:
H264SWDEC_OK successfully initialized the instance
H264SWDEC_INITFAIL initialization failed
H264SWDEC_PARAM_ERR invalid parameters
H264SWDEC_MEM_FAIL memory allocation failed
------------------------------------------------------------------------------*/
H264SwDecRet H264SwDecInit(H264SwDecInst *decInst, u32 noOutputReordering)
{
u32 rv = 0;
decContainer_t *pDecCont;
DEC_API_TRC("H264SwDecInit#");
/* check that right shift on negative numbers is performed signed */
/*lint -save -e* following check causes multiple lint messages */
if ( ((-1)>>1) != (-1) )
{
DEC_API_TRC("H264SwDecInit# ERROR: Right shift is not signed");
return(H264SWDEC_INITFAIL);
}
/*lint -restore */
if (decInst == NULL)
{
DEC_API_TRC("H264SwDecInit# ERROR: decInst == NULL");
return(H264SWDEC_PARAM_ERR);
}
pDecCont = (decContainer_t *)H264SwDecMalloc(sizeof(decContainer_t), 1);
if (pDecCont == NULL)
{
DEC_API_TRC("H264SwDecInit# ERROR: Memory allocation failed");
return(H264SWDEC_MEMFAIL);
}
#ifdef H264DEC_TRACE
sprintf(pDecCont->str, "H264SwDecInit# decInst %p noOutputReordering %d",
(void*)decInst, noOutputReordering);
DEC_API_TRC(pDecCont->str);
#endif
rv = h264bsdInit(&pDecCont->storage, noOutputReordering);
if (rv != HANTRO_OK)
{
H264SwDecRelease(pDecCont);
return(H264SWDEC_MEMFAIL);
}
pDecCont->decStat = INITIALIZED;
pDecCont->picNumber = 0;
#ifdef H264DEC_TRACE
sprintf(pDecCont->str, "H264SwDecInit# OK: return %p", (void*)pDecCont);
DEC_API_TRC(pDecCont->str);
#endif
*decInst = (decContainer_t *)pDecCont;
return(H264SWDEC_OK);
}
/*------------------------------------------------------------------------------
Function: H264SwDecGetInfo()
Functional description:
This function provides read access to decoder information. This
function should not be called before H264SwDecDecode function has
indicated that headers are ready.
Inputs:
decInst decoder instance
Outputs:
pDecInfo pointer to info struct where data is written
Returns:
H264SWDEC_OK success
H264SWDEC_PARAM_ERR invalid parameters
H264SWDEC_HDRS_NOT_RDY information not available yet
------------------------------------------------------------------------------*/
H264SwDecRet H264SwDecGetInfo(H264SwDecInst decInst, H264SwDecInfo *pDecInfo)
{
storage_t *pStorage;
DEC_API_TRC("H264SwDecGetInfo#");
if (decInst == NULL || pDecInfo == NULL)
{
DEC_API_TRC("H264SwDecGetInfo# ERROR: decInst or pDecInfo is NULL");
return(H264SWDEC_PARAM_ERR);
}
pStorage = &(((decContainer_t *)decInst)->storage);
if (pStorage->activeSps == NULL || pStorage->activePps == NULL)
{
DEC_API_TRC("H264SwDecGetInfo# ERROR: Headers not decoded yet");
return(H264SWDEC_HDRS_NOT_RDY);
}
#ifdef H264DEC_TRACE
sprintf(((decContainer_t*)decInst)->str,
"H264SwDecGetInfo# decInst %p pDecInfo %p", decInst, (void*)pDecInfo);
DEC_API_TRC(((decContainer_t*)decInst)->str);
#endif
/* h264bsdPicWidth and -Height return dimensions in macroblock units,
* picWidth and -Height in pixels */
pDecInfo->picWidth = h264bsdPicWidth(pStorage) << 4;
pDecInfo->picHeight = h264bsdPicHeight(pStorage) << 4;
pDecInfo->videoRange = h264bsdVideoRange(pStorage);
pDecInfo->matrixCoefficients = h264bsdMatrixCoefficients(pStorage);
h264bsdCroppingParams(pStorage,
&pDecInfo->croppingFlag,
&pDecInfo->cropParams.cropLeftOffset,
&pDecInfo->cropParams.cropOutWidth,
&pDecInfo->cropParams.cropTopOffset,
&pDecInfo->cropParams.cropOutHeight);
/* sample aspect ratio */
h264bsdSampleAspectRatio(pStorage,
&pDecInfo->parWidth,
&pDecInfo->parHeight);
/* profile */
pDecInfo->profile = h264bsdProfile(pStorage);
DEC_API_TRC("H264SwDecGetInfo# OK");
return(H264SWDEC_OK);
}
/*------------------------------------------------------------------------------
Function: H264SwDecRelease()
Functional description:
Release the decoder instance. Function calls h264bsdShutDown to
release instance data and frees the memory allocated for the
instance.
Inputs:
decInst Decoder instance
Outputs:
none
Returns:
none
------------------------------------------------------------------------------*/
void H264SwDecRelease(H264SwDecInst decInst)
{
decContainer_t *pDecCont;
DEC_API_TRC("H264SwDecRelease#");
if (decInst == NULL)
{
DEC_API_TRC("H264SwDecRelease# ERROR: decInst == NULL");
return;
}
pDecCont = (decContainer_t*)decInst;
#ifdef H264DEC_TRACE
sprintf(pDecCont->str, "H264SwDecRelease# decInst %p",decInst);
DEC_API_TRC(pDecCont->str);
#endif
h264bsdShutdown(&pDecCont->storage);
H264SwDecFree(pDecCont);
}
/*------------------------------------------------------------------------------
Function: H264SwDecDecode
Functional description:
Decode stream data. Calls h264bsdDecode to do the actual decoding.
Input:
decInst decoder instance
pInput pointer to input struct
Outputs:
pOutput pointer to output struct
Returns:
H264SWDEC_NOT_INITIALIZED decoder instance not initialized yet
H264SWDEC_PARAM_ERR invalid parameters
H264SWDEC_STRM_PROCESSED stream buffer decoded
H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY headers decoded,
stream buffer not finished
H264SWDEC_PIC_RDY decoding of a picture finished
H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY decoding of a picture finished,
stream buffer not finished
H264SWDEC_STRM_ERR serious error in decoding, no
valid parameter sets available
to decode picture data
H264SWDEC_EVALUATION_LIMIT_EXCEEDED this can only occur when
evaluation version is used,
max number of frames reached
------------------------------------------------------------------------------*/
H264SwDecRet H264SwDecDecode(H264SwDecInst decInst, H264SwDecInput *pInput,
H264SwDecOutput *pOutput)
{
decContainer_t *pDecCont;
u32 strmLen;
u32 numReadBytes;
u8 *tmpStream;
u32 decResult = 0;
H264SwDecRet returnValue = H264SWDEC_STRM_PROCESSED;
DEC_API_TRC("H264SwDecDecode#");
/* Check that function input parameters are valid */
if (pInput == NULL || pOutput == NULL)
{
DEC_API_TRC("H264SwDecDecode# ERROR: pInput or pOutput is NULL");
return(H264SWDEC_PARAM_ERR);
}
if ((pInput->pStream == NULL) || (pInput->dataLen == 0))
{
DEC_API_TRC("H264SwDecDecode# ERROR: Invalid input parameters");
return(H264SWDEC_PARAM_ERR);
}
pDecCont = (decContainer_t *)decInst;
/* Check if decoder is in an incorrect mode */
if (decInst == NULL || pDecCont->decStat == UNINITIALIZED)
{
DEC_API_TRC("H264SwDecDecode# ERROR: Decoder not initialized");
return(H264SWDEC_NOT_INITIALIZED);
}
#ifdef H264DEC_EVALUATION
if (pDecCont->picNumber >= H264DEC_EVALUATION_LIMIT)
return(H264SWDEC_EVALUATION_LIMIT_EXCEEDED);
#endif
#ifdef H264DEC_TRACE
sprintf(pDecCont->str, "H264SwDecDecode# decInst %p pInput %p pOutput %p",
decInst, (void*)pInput, (void*)pOutput);
DEC_API_TRC(pDecCont->str);
#endif
pOutput->pStrmCurrPos = NULL;
numReadBytes = 0;
strmLen = pInput->dataLen;
tmpStream = pInput->pStream;
pDecCont->storage.intraConcealmentFlag = pInput->intraConcealmentMethod;
do
{
/* Return HDRS_RDY after DPB flush caused by new SPS */
if (pDecCont->decStat == NEW_HEADERS)
{
decResult = H264BSD_HDRS_RDY;
pDecCont->decStat = INITIALIZED;
}
else /* Continue decoding normally */
{
decResult = h264bsdDecode(&pDecCont->storage, tmpStream, strmLen,
pInput->picId, &numReadBytes);
}
tmpStream += numReadBytes;
/* check if too many bytes are read from stream */
if ( (i32)(strmLen - numReadBytes) >= 0 )
strmLen -= numReadBytes;
else
strmLen = 0;
pOutput->pStrmCurrPos = tmpStream;
switch (decResult)
{
case H264BSD_HDRS_RDY:
if(pDecCont->storage.dpb->flushed &&
pDecCont->storage.dpb->numOut !=
pDecCont->storage.dpb->outIndex)
{
/* output first all DPB stored pictures
* DPB flush caused by new SPS */
pDecCont->storage.dpb->flushed = 0;
pDecCont->decStat = NEW_HEADERS;
returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY;
strmLen = 0;
}
else
{
returnValue = H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY;
strmLen = 0;
}
break;
case H264BSD_PIC_RDY:
pDecCont->picNumber++;
if (strmLen == 0)
returnValue = H264SWDEC_PIC_RDY;
else
returnValue = H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY;
strmLen = 0;
break;
case H264BSD_PARAM_SET_ERROR:
if ( !h264bsdCheckValidParamSets(&pDecCont->storage) &&
strmLen == 0 )
{
returnValue = H264SWDEC_STRM_ERR;
}
break;
case H264BSD_MEMALLOC_ERROR:
{
returnValue = H264SWDEC_MEMFAIL;
strmLen = 0;
}
break;
default:
break;
}
} while (strmLen);
#ifdef H264DEC_TRACE
sprintf(pDecCont->str, "H264SwDecDecode# OK: DecResult %d",
returnValue);
DEC_API_TRC(pDecCont->str);
#endif
return(returnValue);
}
/*------------------------------------------------------------------------------
Function: H264SwDecGetAPIVersion
Functional description:
Return version information of the API
Inputs:
none
Outputs:
none
Returns:
API version
------------------------------------------------------------------------------*/
H264SwDecApiVersion H264SwDecGetAPIVersion()
{
H264SwDecApiVersion ver;
ver.major = H264SWDEC_MAJOR_VERSION;
ver.minor = H264SWDEC_MINOR_VERSION;
return(ver);
}
/*------------------------------------------------------------------------------
Function: H264SwDecNextPicture
Functional description:
Get next picture in display order if any available.
Input:
decInst decoder instance.
flushBuffer force output of all buffered pictures
Output:
pOutput pointer to output structure
Returns:
H264SWDEC_OK no pictures available for display
H264SWDEC_PIC_RDY picture available for display
H264SWDEC_PARAM_ERR invalid parameters
------------------------------------------------------------------------------*/
H264SwDecRet H264SwDecNextPicture(H264SwDecInst decInst,
H264SwDecPicture *pOutput, u32 flushBuffer)
{
decContainer_t *pDecCont;
u32 numErrMbs, isIdrPic, picId;
u32 *pOutPic;
DEC_API_TRC("H264SwDecNextPicture#");
if (decInst == NULL || pOutput == NULL)
{
DEC_API_TRC("H264SwDecNextPicture# ERROR: decInst or pOutput is NULL");
return(H264SWDEC_PARAM_ERR);
}
pDecCont = (decContainer_t*)decInst;
#ifdef H264DEC_TRACE
sprintf(pDecCont->str, "H264SwDecNextPicture# decInst %p pOutput %p %s %d",
decInst, (void*)pOutput, "flushBuffer", flushBuffer);
DEC_API_TRC(pDecCont->str);
#endif
if (flushBuffer)
h264bsdFlushBuffer(&pDecCont->storage);
pOutPic = (u32*)h264bsdNextOutputPicture(&pDecCont->storage, &picId,
&isIdrPic, &numErrMbs);
if (pOutPic == NULL)
{
DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_OK");
return(H264SWDEC_OK);
}
else
{
pOutput->pOutputPicture = pOutPic;
pOutput->picId = picId;
pOutput->isIdrPicture = isIdrPic;
pOutput->nbrOfErrMBs = numErrMbs;
DEC_API_TRC("H264SwDecNextPicture# OK: return H264SWDEC_PIC_RDY");
return(H264SWDEC_PIC_RDY);
}
}