blob: e756a1fce4dbcece8d2c9bde4b4df14eb20b0f90 [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.
*/
#include "H264SwDecApi.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void WriteOutput(FILE *fid, u8 *data, u32 picSize);
/*------------------------------------------------------------------------------
Function name: main
Purpose:
main function. Assuming that executable is named 'decoder' the usage
is as follows
decoder inputFileName
, where inputFileName shall be name of file containing h264 stream
data.
------------------------------------------------------------------------------*/
int main(int argc, char **argv)
{
u8 *byteStrmStart;
u8 *byteStrm;
u32 strmLen;
u32 picSize;
H264SwDecInst decInst;
H264SwDecRet ret;
H264SwDecInput decInput;
H264SwDecOutput decOutput;
H264SwDecPicture decPicture;
H264SwDecInfo decInfo;
u32 picNumber;
FILE *finput;
FILE *foutput;
/* Check that enough command line arguments given, if not -> print usage
* information out */
if (argc < 2)
{
printf( "Usage: %s file.h264\n", argv[0]);
return -1;
}
/* open output file for writing, output file named out.yuv. If file open
* fails -> exit */
foutput = fopen("out.yuv", "wb");
if (foutput == NULL)
{
printf("UNABLE TO OPEN OUTPUT FILE\n");
return -1;
}
/* open input file for reading, file name given by user. If file open
* fails -> exit */
finput = fopen(argv[argc-1], "rb");
if (finput == NULL)
{
printf("UNABLE TO OPEN INPUT FILE\n");
return -1;
}
/* check size of the input file -> length of the stream in bytes */
fseek(finput, 0L, SEEK_END);
strmLen = (u32)ftell(finput);
rewind(finput);
/* allocate memory for stream buffer, exit if unsuccessful */
byteStrm = byteStrmStart = (u8 *)H264SwDecMalloc(sizeof(u8), strmLen);
if (byteStrm == NULL)
{
printf("UNABLE TO ALLOCATE MEMORY\n");
return -1;
}
/* read input stream from file to buffer and close input file */
fread(byteStrm, sizeof(u8), strmLen, finput);
fclose(finput);
/* initialize decoder. If unsuccessful -> exit */
ret = H264SwDecInit(&decInst, 0);
if (ret != H264SWDEC_OK)
{
printf("DECODER INITIALIZATION FAILED\n");
return -1;
}
/* initialize H264SwDecDecode() input structure */
decInput.pStream = byteStrmStart;
decInput.dataLen = strmLen;
decInput.intraConcealmentMethod = 0;
picNumber = 0;
/* For performance measurements, read the start time (in seconds) here.
* The decoding time should be measured over several frames and after
* that average fps (frames/second) can be calculated.
*
* startTime = GetTime();
*
* To prevent calculating file I/O latensies as a decoding time,
* comment out WriteOutput function call. Also prints to stdout might
* consume considerable amount of cycles during measurement */
/* main decoding loop */
do
{
/* call API function to perform decoding */
ret = H264SwDecDecode(decInst, &decInput, &decOutput);
switch(ret)
{
case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
/* picture dimensions are available for query now */
ret = H264SwDecGetInfo(decInst, &decInfo);
if (ret != H264SWDEC_OK)
return -1;
/* picture size in pixels */
picSize = decInfo.picWidth * decInfo.picHeight;
/* memory needed for YCbCr 4:2:0 picture in bytes */
picSize = (3 * picSize)/2;
/* memory needed for 16-bit RGB picture in bytes
* picSize = (decInfo.picWidth * decInfo.picHeight) * 2; */
printf("Width %d Height %d\n",
decInfo.picWidth, decInfo.picHeight);
/* update H264SwDecDecode() input structure, number of bytes
* "consumed" is computed as difference between the new stream
* pointer and old stream pointer */
decInput.dataLen -=
(u32)(decOutput.pStrmCurrPos - decInput.pStream);
decInput.pStream = decOutput.pStrmCurrPos;
break;
case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
case H264SWDEC_PIC_RDY:
/* update H264SwDecDecode() input structure, number of bytes
* "consumed" is computed as difference between the new stream
* pointer and old stream pointer */
decInput.dataLen -=
(u32)(decOutput.pStrmCurrPos - decInput.pStream);
decInput.pStream = decOutput.pStrmCurrPos;
/* use function H264SwDecNextPicture() to obtain next picture
* in display order. Function is called until no more images
* are ready for display */
while (H264SwDecNextPicture(decInst, &decPicture, 0) ==
H264SWDEC_PIC_RDY) { picNumber++;
printf("PIC %d, type %s, concealed %d\n", picNumber,
decPicture.isIdrPicture ? "IDR" : "NON-IDR",
decPicture.nbrOfErrMBs);
fflush(stdout);
/* Do color conversion if needed to get display image
* in RGB-format
*
* YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */
/* write next display image to output file */
WriteOutput(foutput, (u8*)decPicture.pOutputPicture,
picSize);
}
break;
case H264SWDEC_EVALUATION_LIMIT_EXCEEDED:
/* evaluation version of the decoder has limited decoding
* capabilities */
printf("EVALUATION LIMIT REACHED\n");
goto end;
default:
printf("UNRECOVERABLE ERROR\n");
return -1;
}
/* keep decoding until all data from input stream buffer consumed */
} while (decInput.dataLen > 0);
end:
/* if output in display order is preferred, the decoder shall be forced
* to output pictures remaining in decoded picture buffer. Use function
* H264SwDecNextPicture() to obtain next picture in display order. Function
* is called until no more images are ready for display. Second parameter
* for the function is set to '1' to indicate that this is end of the
* stream and all pictures shall be output */
while (H264SwDecNextPicture(decInst, &decPicture, 1) ==
H264SWDEC_PIC_RDY) {
picNumber++;
printf("PIC %d, type %s, concealed %d\n", picNumber,
decPicture.isIdrPicture ? "IDR" : "NON-IDR",
decPicture.nbrOfErrMBs);
fflush(stdout);
/* Do color conversion if needed to get display image
* in RGB-format
*
* YuvToRgb( decPicture.pOutputPicture, pRgbPicture ); */
/* write next display image to output file */
WriteOutput(foutput, (u8*)decPicture.pOutputPicture, picSize);
}
/* For performance measurements, read the end time (in seconds) here.
*
* endTime = GetTime();
*
* Now the performance can be calculated as frames per second:
* fps = picNumber / (endTime - startTime); */
/* release decoder instance */
H264SwDecRelease(decInst);
/* close output file */
fclose(foutput);
/* free byte stream buffer */
free(byteStrmStart);
return 0;
}
/*------------------------------------------------------------------------------
Function name: WriteOutput
Purpose:
Write picture pointed by data to file pointed by fid. Size of the
picture in pixels is indicated by picSize.
------------------------------------------------------------------------------*/
void WriteOutput(FILE *fid, u8 *data, u32 picSize)
{
fwrite(data, 1, picSize, fid);
}
/*------------------------------------------------------------------------------
Function name: H264SwDecTrace
Purpose:
Example implementation of H264SwDecTrace function. Prototype of this
function is given in H264SwDecApi.h. This implementation appends
trace messages to file named 'dec_api.trc'.
------------------------------------------------------------------------------*/
void H264SwDecTrace(char *string)
{
FILE *fp;
fp = fopen("dec_api.trc", "at");
if (!fp)
return;
fwrite(string, 1, strlen(string), fp);
fwrite("\n", 1,1, fp);
fclose(fp);
}
/*------------------------------------------------------------------------------
Function name: H264SwDecmalloc
Purpose:
Example implementation of H264SwDecMalloc function. Prototype of this
function is given in H264SwDecApi.h. This implementation uses
library function malloc for allocation of memory.
------------------------------------------------------------------------------*/
void* H264SwDecMalloc(u32 size, u32 num)
{
if (size > UINT32_MAX / num) {
return NULL;
}
return malloc(size * num);
}
/*------------------------------------------------------------------------------
Function name: H264SwDecFree
Purpose:
Example implementation of H264SwDecFree function. Prototype of this
function is given in H264SwDecApi.h. This implementation uses
library function free for freeing of memory.
------------------------------------------------------------------------------*/
void H264SwDecFree(void *ptr)
{
free(ptr);
}
/*------------------------------------------------------------------------------
Function name: H264SwDecMemcpy
Purpose:
Example implementation of H264SwDecMemcpy function. Prototype of this
function is given in H264SwDecApi.h. This implementation uses
library function memcpy to copy src to dest.
------------------------------------------------------------------------------*/
void H264SwDecMemcpy(void *dest, void *src, u32 count)
{
memcpy(dest, src, count);
}
/*------------------------------------------------------------------------------
Function name: H264SwDecMemset
Purpose:
Example implementation of H264SwDecMemset function. Prototype of this
function is given in H264SwDecApi.h. This implementation uses
library function memset to set content of memory area pointed by ptr.
------------------------------------------------------------------------------*/
void H264SwDecMemset(void *ptr, i32 value, u32 count)
{
memset(ptr, value, count);
}