summaryrefslogtreecommitdiffstats
path: root/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
diff options
context:
space:
mode:
authorJames Dong <jdong@google.com>2011-05-31 18:53:46 -0700
committerJames Dong <jdong@google.com>2011-06-02 12:32:46 -0700
commit0c1bc742181ded4930842b46e9507372f0b1b963 (patch)
treec952bfcb03ff7cce5e0f91ad7d25c67a2fdd39cb /media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
parent92a746c3b18d035189f596ce32847bf26247aaca (diff)
downloadframeworks_av-0c1bc742181ded4930842b46e9507372f0b1b963.zip
frameworks_av-0c1bc742181ded4930842b46e9507372f0b1b963.tar.gz
frameworks_av-0c1bc742181ded4930842b46e9507372f0b1b963.tar.bz2
Initial-checkin for ON2 Software AVC/H264 decoder
o when neon is present, the performance gain of On2 AVC software decoder over PV software decoder is more than 30%. o In addition, it fixes some known PV software decoder issues like missing output frames o allow both pv and on2 software avc to be available for easy comparision o change output frames from 8 to 16 Change-Id: I567ad1842025ead7092f0c47e3513d6d9ca232dd
Diffstat (limited to 'media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c')
-rwxr-xr-xmedia/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c531
1 files changed, 531 insertions, 0 deletions
diff --git a/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
new file mode 100755
index 0000000..42170d3
--- /dev/null
+++ b/media/libstagefright/codecs/on2/h264dec/source/TestBenchMultipleInstance.c
@@ -0,0 +1,531 @@
+/*
+ * 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.
+ */
+
+/* CVS tag name for identification */
+const char tagName[256] = "$Name: FIRST_ANDROID_COPYRIGHT $";
+
+#include "H264SwDecApi.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define DEBUG(argv) printf argv
+
+/* _NO_OUT disables output file writing */
+#ifdef __arm
+#define _NO_OUT
+#endif
+
+/*------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------*/
+void WriteOutput(FILE *fid, u8 *data, u32 picSize);
+
+u32 CropPicture(u8 *pOutImage, u8 *pInImage,
+ u32 picWidth, u32 picHeight, CropParams *pCropParams);
+
+void CropWriteOutput(FILE *fid, u8 *imageData, u32 cropDisplay,
+ H264SwDecInfo *decInfo);
+
+typedef struct
+{
+ H264SwDecInst decInst;
+ H264SwDecInput decInput;
+ H264SwDecOutput decOutput;
+ H264SwDecPicture decPicture;
+ H264SwDecInfo decInfo;
+ FILE *foutput;
+ char outFileName[256];
+ u8 *byteStrmStart;
+ u32 picNumber;
+} Decoder;
+
+
+/*------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------*/
+int main(int argc, char **argv)
+{
+
+ i32 instCount, instRunning;
+ i32 i;
+ u32 maxNumPics;
+ u32 strmLen;
+ H264SwDecRet ret;
+ u32 numErrors = 0;
+ u32 cropDisplay = 0;
+ u32 disableOutputReordering = 0;
+ FILE *finput;
+ Decoder **decoder;
+ char outFileName[256] = "out.yuv";
+
+
+ if ( argc > 1 && strcmp(argv[1], "-T") == 0 )
+ {
+ fprintf(stderr, "%s\n", tagName);
+ return 0;
+ }
+
+ if (argc < 2)
+ {
+ DEBUG((
+ "Usage: %s [-Nn] [-Ooutfile] [-P] [-U] [-C] [-R] [-T] file1.264 [file2.264] .. [fileN.264]\n",
+ argv[0]));
+ DEBUG(("\t-Nn forces decoding to stop after n pictures\n"));
+#if defined(_NO_OUT)
+ DEBUG(("\t-Ooutfile output writing disabled at compile time\n"));
+#else
+ DEBUG(("\t-Ooutfile write output to \"outfile\" (default out.yuv)\n"));
+ DEBUG(("\t-Onone does not write output\n"));
+#endif
+ DEBUG(("\t-C display cropped image (default decoded image)\n"));
+ DEBUG(("\t-R disable DPB output reordering\n"));
+ DEBUG(("\t-T to print tag name and exit\n"));
+ exit(100);
+ }
+
+ instCount = argc - 1;
+
+ /* read command line arguments */
+ maxNumPics = 0;
+ for (i = 1; i < (argc-1); i++)
+ {
+ if ( strncmp(argv[i], "-N", 2) == 0 )
+ {
+ maxNumPics = (u32)atoi(argv[i]+2);
+ instCount--;
+ }
+ else if ( strncmp(argv[i], "-O", 2) == 0 )
+ {
+ strcpy(outFileName, argv[i]+2);
+ instCount--;
+ }
+ else if ( strcmp(argv[i], "-C") == 0 )
+ {
+ cropDisplay = 1;
+ instCount--;
+ }
+ else if ( strcmp(argv[i], "-R") == 0 )
+ {
+ disableOutputReordering = 1;
+ instCount--;
+ }
+ }
+
+ if (instCount < 1)
+ {
+ DEBUG(("No input files\n"));
+ exit(100);
+ }
+
+ /* allocate memory for multiple decoder instances
+ * one instance for every stream file */
+ decoder = (Decoder **)malloc(sizeof(Decoder*)*(u32)instCount);
+ if (decoder == NULL)
+ {
+ DEBUG(("Unable to allocate memory\n"));
+ exit(100);
+ }
+
+ /* prepare each decoder instance */
+ for (i = 0; i < instCount; i++)
+ {
+ decoder[i] = (Decoder *)calloc(1, sizeof(Decoder));
+
+ /* open input file */
+ finput = fopen(argv[argc-instCount+i],"rb");
+ if (finput == NULL)
+ {
+ DEBUG(("Unable to open input file <%s>\n", argv[argc-instCount+i]));
+ exit(100);
+ }
+
+ DEBUG(("Reading input file[%d] %s\n", i, argv[argc-instCount+i]));
+
+ /* read input stream to buffer */
+ fseek(finput,0L,SEEK_END);
+ strmLen = (u32)ftell(finput);
+ rewind(finput);
+ decoder[i]->byteStrmStart = (u8 *)malloc(sizeof(u8)*strmLen);
+ if (decoder[i]->byteStrmStart == NULL)
+ {
+ DEBUG(("Unable to allocate memory\n"));
+ exit(100);
+ }
+ fread(decoder[i]->byteStrmStart, sizeof(u8), strmLen, finput);
+ fclose(finput);
+
+ /* open output file */
+ if (strcmp(outFileName, "none") != 0)
+ {
+#if defined(_NO_OUT)
+ decoder[i]->foutput = NULL;
+#else
+ sprintf(decoder[i]->outFileName, "%s%i", outFileName, i);
+ decoder[i]->foutput = fopen(decoder[i]->outFileName, "wb");
+ if (decoder[i]->foutput == NULL)
+ {
+ DEBUG(("Unable to open output file\n"));
+ exit(100);
+ }
+#endif
+ }
+
+ ret = H264SwDecInit(&(decoder[i]->decInst), disableOutputReordering);
+
+ if (ret != H264SWDEC_OK)
+ {
+ DEBUG(("Init failed %d\n", ret));
+ exit(100);
+ }
+
+ decoder[i]->decInput.pStream = decoder[i]->byteStrmStart;
+ decoder[i]->decInput.dataLen = strmLen;
+ decoder[i]->decInput.intraConcealmentMethod = 0;
+
+ }
+
+ /* main decoding loop */
+ do
+ {
+ /* decode once using each instance */
+ for (i = 0; i < instCount; i++)
+ {
+ ret = H264SwDecDecode(decoder[i]->decInst,
+ &(decoder[i]->decInput),
+ &(decoder[i]->decOutput));
+
+ switch(ret)
+ {
+
+ case H264SWDEC_HDRS_RDY_BUFF_NOT_EMPTY:
+
+ ret = H264SwDecGetInfo(decoder[i]->decInst,
+ &(decoder[i]->decInfo));
+ if (ret != H264SWDEC_OK)
+ exit(1);
+
+ if (cropDisplay && decoder[i]->decInfo.croppingFlag)
+ {
+ DEBUG(("Decoder[%d] Cropping params: (%d, %d) %dx%d\n",
+ i,
+ decoder[i]->decInfo.cropParams.cropLeftOffset,
+ decoder[i]->decInfo.cropParams.cropTopOffset,
+ decoder[i]->decInfo.cropParams.cropOutWidth,
+ decoder[i]->decInfo.cropParams.cropOutHeight));
+ }
+
+ DEBUG(("Decoder[%d] Width %d Height %d\n", i,
+ decoder[i]->decInfo.picWidth,
+ decoder[i]->decInfo.picHeight));
+
+ DEBUG(("Decoder[%d] videoRange %d, matricCoefficients %d\n",
+ i, decoder[i]->decInfo.videoRange,
+ decoder[i]->decInfo.matrixCoefficients));
+ decoder[i]->decInput.dataLen -=
+ (u32)(decoder[i]->decOutput.pStrmCurrPos -
+ decoder[i]->decInput.pStream);
+ decoder[i]->decInput.pStream =
+ decoder[i]->decOutput.pStrmCurrPos;
+ break;
+
+ case H264SWDEC_PIC_RDY_BUFF_NOT_EMPTY:
+ decoder[i]->decInput.dataLen -=
+ (u32)(decoder[i]->decOutput.pStrmCurrPos -
+ decoder[i]->decInput.pStream);
+ decoder[i]->decInput.pStream =
+ decoder[i]->decOutput.pStrmCurrPos;
+ /* fall through */
+ case H264SWDEC_PIC_RDY:
+ if (ret == H264SWDEC_PIC_RDY)
+ decoder[i]->decInput.dataLen = 0;
+
+ ret = H264SwDecGetInfo(decoder[i]->decInst,
+ &(decoder[i]->decInfo));
+ if (ret != H264SWDEC_OK)
+ exit(1);
+
+ while (H264SwDecNextPicture(decoder[i]->decInst,
+ &(decoder[i]->decPicture), 0) == H264SWDEC_PIC_RDY)
+ {
+ decoder[i]->picNumber++;
+
+ numErrors += decoder[i]->decPicture.nbrOfErrMBs;
+
+ DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n",
+ i, decoder[i]->picNumber,
+ decoder[i]->decPicture.isIdrPicture
+ ? "IDR" : "NON-IDR",
+ decoder[i]->decPicture.nbrOfErrMBs));
+ fflush(stdout);
+
+ CropWriteOutput(decoder[i]->foutput,
+ (u8*)decoder[i]->decPicture.pOutputPicture,
+ cropDisplay, &(decoder[i]->decInfo));
+ }
+
+ if (maxNumPics && decoder[i]->picNumber == maxNumPics)
+ decoder[i]->decInput.dataLen = 0;
+ break;
+
+ case H264SWDEC_STRM_PROCESSED:
+ case H264SWDEC_STRM_ERR:
+ case H264SWDEC_PARAM_ERR:
+ decoder[i]->decInput.dataLen = 0;
+ break;
+
+ default:
+ DEBUG(("Decoder[%d] FATAL ERROR\n", i));
+ exit(10);
+ break;
+
+ }
+ }
+
+ /* check if any of the instances is still running (=has more data) */
+ instRunning = instCount;
+ for (i = 0; i < instCount; i++)
+ {
+ if (decoder[i]->decInput.dataLen == 0)
+ instRunning--;
+ }
+
+ } while (instRunning);
+
+
+ /* get last frames and close each instance */
+ for (i = 0; i < instCount; i++)
+ {
+ while (H264SwDecNextPicture(decoder[i]->decInst,
+ &(decoder[i]->decPicture), 1) == H264SWDEC_PIC_RDY)
+ {
+ decoder[i]->picNumber++;
+
+ DEBUG(("Decoder[%d] PIC %d, type %s, concealed %d\n",
+ i, decoder[i]->picNumber,
+ decoder[i]->decPicture.isIdrPicture
+ ? "IDR" : "NON-IDR",
+ decoder[i]->decPicture.nbrOfErrMBs));
+ fflush(stdout);
+
+ CropWriteOutput(decoder[i]->foutput,
+ (u8*)decoder[i]->decPicture.pOutputPicture,
+ cropDisplay, &(decoder[i]->decInfo));
+ }
+
+ H264SwDecRelease(decoder[i]->decInst);
+
+ if (decoder[i]->foutput)
+ fclose(decoder[i]->foutput);
+
+ free(decoder[i]->byteStrmStart);
+
+ free(decoder[i]);
+ }
+
+ free(decoder);
+
+ if (numErrors)
+ return 1;
+ else
+ return 0;
+
+}
+
+/*------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------*/
+void CropWriteOutput(FILE *foutput, u8 *imageData, u32 cropDisplay,
+ H264SwDecInfo *decInfo)
+{
+ u8 *tmpImage = NULL;
+ u32 tmp, picSize;
+
+ if (cropDisplay && decInfo->croppingFlag)
+ {
+ picSize = decInfo->cropParams.cropOutWidth *
+ decInfo->cropParams.cropOutHeight;
+ picSize = (3 * picSize)/2;
+ tmpImage = malloc(picSize);
+ if (tmpImage == NULL)
+ exit(1);
+ tmp = CropPicture(tmpImage, imageData,
+ decInfo->picWidth, decInfo->picHeight,
+ &(decInfo->cropParams));
+ if (tmp)
+ exit(1);
+ WriteOutput(foutput, tmpImage, picSize);
+ free(tmpImage);
+ }
+ else
+ {
+ picSize = decInfo->picWidth * decInfo->picHeight;
+ picSize = (3 * picSize)/2;
+ WriteOutput(foutput, imageData, picSize);
+ }
+
+}
+
+/*------------------------------------------------------------------------------
+
+------------------------------------------------------------------------------*/
+void WriteOutput(FILE *fid, u8 *data, u32 picSize)
+{
+ if (fid)
+ fwrite(data, 1, picSize, fid);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecTrace
+
+------------------------------------------------------------------------------*/
+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
+
+------------------------------------------------------------------------------*/
+void* H264SwDecMalloc(u32 size)
+{
+ return malloc(size);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecFree
+
+------------------------------------------------------------------------------*/
+void H264SwDecFree(void *ptr)
+{
+ free(ptr);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMemcpy
+
+------------------------------------------------------------------------------*/
+void H264SwDecMemcpy(void *dest, void *src, u32 count)
+{
+ memcpy(dest, src, count);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: H264SwDecMemset
+
+------------------------------------------------------------------------------*/
+void H264SwDecMemset(void *ptr, i32 value, u32 count)
+{
+ memset(ptr, value, count);
+}
+
+/*------------------------------------------------------------------------------
+
+ Function name: CropPicture
+
+------------------------------------------------------------------------------*/
+u32 CropPicture(u8 *pOutImage, u8 *pInImage,
+ u32 picWidth, u32 picHeight, CropParams *pCropParams)
+{
+
+ u32 i, j;
+ u32 outWidth, outHeight;
+ u8 *pOut, *pIn;
+
+ if (pOutImage == NULL || pInImage == NULL || pCropParams == NULL ||
+ !picWidth || !picHeight)
+ {
+ /* due to lint warning */
+ free(pOutImage);
+ return(1);
+ }
+
+ if ( ((pCropParams->cropLeftOffset + pCropParams->cropOutWidth) >
+ picWidth ) ||
+ ((pCropParams->cropTopOffset + pCropParams->cropOutHeight) >
+ picHeight ) )
+ {
+ /* due to lint warning */
+ free(pOutImage);
+ return(1);
+ }
+
+ outWidth = pCropParams->cropOutWidth;
+ outHeight = pCropParams->cropOutHeight;
+
+ pIn = pInImage + pCropParams->cropTopOffset*picWidth +
+ pCropParams->cropLeftOffset;
+ pOut = pOutImage;
+
+ /* luma */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth - outWidth;
+ }
+
+ outWidth >>= 1;
+ outHeight >>= 1;
+
+ pIn = pInImage + picWidth*picHeight +
+ pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
+
+ /* cb */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth/2 - outWidth;
+ }
+
+ pIn = pInImage + 5*picWidth*picHeight/4 +
+ pCropParams->cropTopOffset*picWidth/4 + pCropParams->cropLeftOffset/2;
+
+ /* cr */
+ for (i = outHeight; i; i--)
+ {
+ for (j = outWidth; j; j--)
+ {
+ *pOut++ = *pIn++;
+ }
+ pIn += picWidth/2 - outWidth;
+ }
+
+ return (0);
+
+}
+