diff options
Diffstat (limited to 'test/libskiahw/SkLibTiJpeg_Test.cpp')
-rw-r--r-- | test/libskiahw/SkLibTiJpeg_Test.cpp | 1402 |
1 files changed, 1402 insertions, 0 deletions
diff --git a/test/libskiahw/SkLibTiJpeg_Test.cpp b/test/libskiahw/SkLibTiJpeg_Test.cpp new file mode 100644 index 0000000..be78eae --- /dev/null +++ b/test/libskiahw/SkLibTiJpeg_Test.cpp @@ -0,0 +1,1402 @@ +/* + * Copyright (C) Texas Instruments - http://www.ti.com/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ +/* ============================================================================== +* Texas Instruments OMAP (TM) Platform Software +* (c) Copyright Texas Instruments, Incorporated. All Rights Reserved. +* +* Use of this software is controlled by the terms and conditions found +* in the license agreement under which this software has been supplied. +* ============================================================================ */ +/** +* @file SkLibTiJpeg_Test.cpp +* +* This test program will be used to test the JPEG decoder and encoder +* from libskia level. +* +*/ + +#include <unistd.h> +#include "SkLibTiJpeg_Test.h" +#include "SkTime.h" + +#ifdef ANDROID +#include <cutils/properties.h> +#endif + +extern "C" { +#include "md5.h" +}; + +#define LIBSKIAHWTEST "[SkLibTiJpeg_Test_Script]" +#define PASS 0 +#define FAIL 1 +#define ERROR -1 + +#define PRINT printf + +//enable this for additional debug prints. +//#define DEBUG 1 + +//#define TIME_MEASUREMENT 1 +#ifdef DEBUG +#define DBGPRINT printf +#else +#define DBGPRINT +#endif + +#define BUFSIZE (1024 * 8) +#define MD5_SUM_LENGTH 16 +#define JPGD_MD5SUM_LIST 0 +#define JPGE_MD5SUM_LIST 1 + +#define PASSCOUNT_ARM 0 +#define PASSCOUNT_TIDSP 1 +#define PASSCOUNT_SIMCOP 2 +#define FAILCOUNT 3 +#define COUNT_MANUALVERIFY 4 +#define COUNT_MAX_INDEX 5 + +#define CODECTYPE_SW 0 +#define CODECTYPE_DSP 1 +#define CODECTYPE_SIMCOP 2 + +//test case count +unsigned int nTestCount[5]; //[0]-ARM; [1]-TI; + //[2]-SIMCOP; [3]-Fail count; + //[4]-manual verification needed +int flagDumpMd5Sum; +int flagCodecType; //0- SW codec ( ARM) + //1- TI DSP codec + //2- SIMCOP codec + +FILE* pFileDump; //for dumping the md5sum strings +char testID[40]; + +//------------------------------------------------------------------------------------ +#ifdef TIME_MEASUREMENT +class AutoTimeMillis { +public: + AutoTimeMillis(const char label[]) : fLabel(label) { + if (!fLabel) { + fLabel = ""; + } + fNow = SkTime::GetMSecs(); + } + + ~AutoTimeMillis() { + PRINT("---- Input file Resolution :%dx%d",width,height); + PRINT("---- JPEG Time (ms): %s %d\n", fLabel, SkTime::GetMSecs() - fNow); + } + + void setResolution(int width, int height){ + this->width=width; + this->height=height; + } + +private: + const char* fLabel; + SkMSec fNow; + int width; + int height; +}; +#endif + +//----------------------------------------------------------------------------- +void printDecoderTestUsage() { + + PRINT("\nDecoder Test parameters:\n"); + PRINT("SkLibTiJpeg_Test <D> <Input_File_Name> <Output_File_Name> <nOutformat> <SF %s> <nSections> <nXOrigin> <nYOrigin> <nXLength> <nYLength> <SF value/UserW> <UserH>\n\n","%"); + PRINT("<D> = D-Decoder test\n"); + PRINT("<Input_File_Name> = .jpg file name\n"); + PRINT("<Output_File_Name>= .raw file name\n"); + PRINT("<nOutformat> = Output color format: 4-16bit_RBG565, 6-32bit_ARGB8888\n"); + PRINT("<SF %s> = Scalefactor: 100, 50, 25, 12 percent\n","%"); + PRINT("<nSections> = SliceOutput Mode: Number of rows per slice\n"); + PRINT("<nXOrigin> = Sub Region Decode: X-origin\n"); + PRINT("<nYOrigin> = Sub Region Decode: Y-origin\n"); + PRINT("<nXLength> = Sub Region Decode: X-Length\n"); + PRINT("<nYLength> = Sub Region Decode: Y-Length\n"); + PRINT("<SFvalue | nUserW>= Scale Factor number(OMAP4->1-256; OMAP3->1,2,4,8) OR User's desired output Width\n"); + PRINT("<nUserH > = User's desired output Height.\n"); + + PRINT("\nNOTE: nUserW * nUserH : if nUserW alone given it will be taken as scaleFactor value.\n"); + PRINT(" if both values are given then the scale factor is calculated based on valid values of them\n"); + PRINT(" if both value are valid then the scale factor will be calculated using nUserW\n"); + PRINT(" if nUserW = 0 and nUserH > 0 then the scale factor will be calculated using nUserH\n"); + +} //End of printDecoderTestUsage() + +//----------------------------------------------------------------------------- +void printEncoderTestUsage() { + + PRINT("\nEncoder Test parameters:\n"); + PRINT("SkLibTiJpeg_Test <E> <Input_File_Name> <Output_File_Name> <nInformat> <nQFactor 1-100>\n\n"); + PRINT("<E> = E-Encoder test\n"); + PRINT("<Input_File_Name> = .raw file name\n"); + PRINT("<Output_File_Name>= .jpg file name\n"); + PRINT("<nInformat> = Input color format: 4-16bit_RBG565, 6-32bit_ARGB8888\n"); + PRINT("<nQFactor> = Quality factor: 1-100\n"); +} //End of printEncoderTestUsage() + +//----------------------------------------------------------------------------- +void printInputScriptFormat() { + + PRINT("\nUsing Script/Folder:\n"); + PRINT("SkLibTiJpeg_Test <<S|F>[M][C]> <script file name | Folder Path> [Repeat Count]\n"); + PRINT("\n[S|F] - S-> scriptfile; F-> Folder path; **NOTE: 'F'is only for Decoder Test\n"); + PRINT("[M] - Do Memory leak test\n"); + PRINT("[C] - Dump the md5sum values in to a file <md5sum_dump.txt>.\n"); + PRINT("[Repeat Count] - Repeat the script/folder contents this many times.\n"); + PRINT("\nThe script file should contain <%s> as the first line.\n",LIBSKIAHWTEST); + PRINT("Example format of the script file is:\n"); + + PRINT("\n|------------------------------------------------------------------------------|\n"); + PRINT("[SkLibTiJpeg_Test_Script]\n"); + PRINT("#Commented line or commented testcase starts with '#' character.\n"); + PRINT("#TestcaseID SkLibTiJpeg_Test <E | D> <Input File> <Output File> <other params......> \n"); + PRINT("DECTestID-1: SkLibTiJpeg_Test D I_000265_12MP_4000x3000.jpg output/12MP-1.raw 4 100 \n"); + PRINT("#TestID-2: SkLibTiJpeg_Test D akiy4big07.jpg output/akiy4big07-2.raw 4 100 \n"); + PRINT("ENCTestID-1: SkLibTiJpeg_Test E akiy4big07-2.raw enctest-1.jpg 1200 1600 4 100 \n"); + PRINT("\n|------------------------------------------------------------------------------|\n"); +} + +//----------------------------------------------------------------------------- +void printUsage() { + + PRINT("\n\nUSAGE: \n\n"); + PRINT("Encoder Test: ./SkLibTiJpeg_Test <E> < parameters..... > \n"); + PRINT("Decoder Test: ./SkLibTiJpeg_Test <D> < parameters..... > \n"); + PRINT("Using Script: ./SkLibTiJpeg_Test <S[M][C]> <script file name> [Repeat Count]\n"); + PRINT("Folder Decode: ./SkLibTiJpeg_Test <F[M][C]> <Folder Path> [Repeat Count]\n"); + + PRINT("\n|------------------------------------------------------------------------------|\n"); + printEncoderTestUsage(); + PRINT("\n|------------------------------------------------------------------------------|\n"); + printDecoderTestUsage(); + PRINT("\n|------------------------------------------------------------------------------|\n"); + printInputScriptFormat(); + PRINT("\n|------------------------------------------------------------------------------|\n"); + +} //End of printUsage() + +//----------------------------------------------------------------------------- +//Currently this function will parse the header and give only image width and Height. +//can be added to parse for other information also. +U32 jpegHeaderParser(SkStream* stream, JPEG_IMAGE_INFO* JpegImageInfo) { + + U8 cByte; + U8 flagDone = 0; + U32 marker; + size_t segLength; + S32 lSize = 0; + lSize = stream->getLength(); + stream->rewind(); + JpegImageInfo->nWidth = 0; + JpegImageInfo->nHeight = 0; + + //check for the JPEG marker + cByte = stream->readU8(); + if ( cByte != 0xff || stream->readU8() != M_SOI ) { + return 0; + } + + while(1) { + for(;;) { + cByte = stream->readU8(); + //PRINT("%02x-",cByte); + if( cByte == 0xff ) break; + } //end of for (;;) + + marker = stream->readU8(); + + switch ( marker) { + + case M_SOS: + case M_EOI: + return 0; + break; + + case M_SOF2: + //PRINTF("nProgressive IMAGE!\n"); + //JpegImageInfo->nProgressive=1; + case M_SOF0: + case M_SOF1: + case M_SOF3: + case M_SOF5: + case M_SOF6: + case M_SOF7: + case M_SOF9: + case M_SOF10: + case M_SOF11: + case M_SOF13: + case M_SOF14: + case M_SOF15: + //skip 2bytes length and one byte bits/sample. + stream->skip(3); + //read Height and width + JpegImageInfo->nHeight = (int)( (stream->readU8() << 8) | (stream->readU8()) ); + JpegImageInfo->nWidth = (int)( (stream->readU8() << 8) | (stream->readU8()) ); + flagDone = 1; + break; + + default: + //read the length of the marker segment and skip that segment data + segLength = (int)( (stream->readU8() << 8) || (stream->readU8()) ); + segLength = stream->skip(segLength-2); //segLength include these 2 bytes for length value. + if (segLength == 0){ + return 0; + } + break; + } //end of Switch + + if(flagDone) + return lSize; + + } //end of while(1) +} //End of jpegHeaderParser() + +//----------------------------------------------------------------------------- +U32 getMeminfo(FILE* pFile, const char* pStr) { + + U32 value = 0; + int i; + char strLine[80]; + + //search the line which contains the required mem info. + while(!feof(pFile) ) { + if( NULL == fgets(strLine, sizeof(strLine), pFile)) { + break; + } + if ( NULL == strstr(strLine, pStr) ) { + continue; + } + else { + sscanf(strLine+strlen(pStr), "%ld", &value); + break; + } + } + rewind(pFile); + return value; +} +//----------------------------------------------------------------------------- +void analyzeMemoryInfo(const char* firstFile, const char* secondFile) { + U32 freeMemBeforeTest = 0; + U32 freeMemAfterTest = 0; + U32 cachedMemBeforeTest = 0; + U32 cachedMemAfterTest = 0; + FILE* pFile1 = NULL; + + PRINT("\n\n>>>>>>>>>>>>>>>>>>>>>>>>>>> ANALYZING MEMORY LEAK <<<<<<<<<<<<<<<<<<<<<<<<<<< \n\n"); + pFile1 = fopen(firstFile, "r"); + if (pFile1 == NULL) { + PRINT("%s():%d::!!!! Could not open file %s\n",__FUNCTION__,__LINE__,firstFile); + goto EXIT; + } + + //get the memory info before test. + freeMemBeforeTest = getMeminfo(pFile1, "MemFree:"); + cachedMemBeforeTest = getMeminfo(pFile1, "Cached:"); + fclose(pFile1); + + pFile1 = fopen(secondFile, "r"); + if (pFile1 == NULL) { + PRINT("%s():%d::!!!! Could not open file %s\n",__FUNCTION__,__LINE__,secondFile); + goto EXIT; + } + + //get the memory info after test + freeMemAfterTest = getMeminfo(pFile1, "MemFree:"); + cachedMemAfterTest = getMeminfo(pFile1, "Cached:"); + fclose(pFile1); + + PRINT("MemFree: Before::After => %ld KB :: %ld KB\n",freeMemBeforeTest, freeMemAfterTest); + PRINT("Cached: Before::After => %ld KB :: %ld KB\n\n",cachedMemBeforeTest, cachedMemAfterTest); + + if( ((freeMemBeforeTest+cachedMemBeforeTest) - (freeMemAfterTest-cachedMemAfterTest)) > (5*1024*1024)) { + PRINT("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + PRINT("!!!!!! Looks like there is a MEMORY LEAK during the Test Execution!!!!!!\n"); + PRINT("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + } + else { + PRINT("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + PRINT("!!!!!!!!!!!!!!!!!!!!!!!! MEMORY TEST OK !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + PRINT("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + } + return; + +EXIT: + PRINT("!!!!!!!!!!!!!!!!!!!!! MEMORY TEST not Successful!!!!!!!!!!!!!!!!!!!!!!!!!!\n"); + return; +} //End of analyzeMemoryInfo() + +//----------------------------------------------------------------------------- +void extractFileName(char* InFileName, char* imgFileName) { + + char ch = '/'; + char* pTmpName = NULL; + + pTmpName = strrchr( InFileName, (int)ch ); + if (pTmpName == NULL) { + strcpy ( imgFileName, (const char*)InFileName ); + } + else { + strcpy ( imgFileName, (const char*)pTmpName+1 ); + } +} //End of extractFileName() + +//----------------------------------------------------------------------------- +void md5SumFile(unsigned char *md, char* pFileName) { + + MD5_CTX md5_c; + int fd; + int i; + static unsigned char buf[BUFSIZE]; + FILE* pFile = NULL; + + pFile = fopen(pFileName, "r"); + if ( pFile == NULL ) { + PRINT("\nERROR!!!! Not able to open the file: %s\n", pFileName); + return; + } + + MD5_Init(&md5_c); + for (;;) { + i = fread( (void*)buf, 1, BUFSIZE, pFile ); + if (i <= 0) break; + MD5_Update( &md5_c, buf, (unsigned long)i ); + } + MD5_Final( md, &md5_c ); + + fclose(pFile); + + DBGPRINT("%s:%d::MD5SUM = ",__FUNCTION__,__LINE__); + for (i = 0; i < MD5_SUM_LENGTH; i++) + DBGPRINT("%02x",md[i]); + DBGPRINT("\n"); + +} //End of md5SumFile() + +//----------------------------------------------------------------------------- +void md5SumBuf(unsigned char* md, void* pBuf, unsigned long nBufSize) { + + MD5_CTX md5_c; + int i; + + MD5_Init(&md5_c); + MD5_Update(&md5_c, pBuf, nBufSize); + MD5_Final( md, &md5_c ); + + DBGPRINT("%s:%d::MD5SUM = ",__FUNCTION__,__LINE__); + for (i = 0; i < MD5_SUM_LENGTH; i++) + DBGPRINT("%02x",md[i]); + DBGPRINT("\n"); + +} //End of md5SumBuf() + +//----------------------------------------------------------------------------- +void updateTestCount(int id) { + + android::countMutex.lock(); + if ( id < COUNT_MAX_INDEX ) { + nTestCount[id] += 1; + } + android::countMutex.unlock(); + +} + +//----------------------------------------------------------------------------- +void dumpMd5Sum(char* imgFileName, char* mdString, void* pList) { + const struct JPGD_TEST_OUTPUT_FILE_LIST *pDBList = (const struct JPGD_TEST_OUTPUT_FILE_LIST *)pList; + + //dump the file name and its md5sum string in to a file + fprintf(pFileDump, "{ // %s\n",testID); + fprintf(pFileDump, "\"%s\",\n",imgFileName); + + switch(flagCodecType) { + + case CODECTYPE_SW: + if(pDBList){ + fprintf(pFileDump, "\"%s\",\n",mdString); + fprintf(pFileDump, "\"%s\",\n",pDBList->md5CheckSumTi); + fprintf(pFileDump, "\"%s\"\n",pDBList->md5CheckSumSimcop); + } + else { + fprintf(pFileDump, "\"%s\",\n",mdString); + fprintf(pFileDump, "\"0\",\n"); + fprintf(pFileDump, "\"0\"\n"); + } + break; + + case CODECTYPE_DSP: + if(pDBList){ + fprintf(pFileDump, "\"%s\",\n",pDBList->md5CheckSumArm); + fprintf(pFileDump, "\"%s\",\n",mdString); + fprintf(pFileDump, "\"%s\"\n",pDBList->md5CheckSumSimcop); + } + else { + fprintf(pFileDump, "\"0\",\n"); + fprintf(pFileDump, "\"%s\",\n",mdString); + fprintf(pFileDump, "\"0\"\n"); + } + break; + + case CODECTYPE_SIMCOP: + if(pDBList){ + fprintf(pFileDump, "\"%s\",\n",pDBList->md5CheckSumArm); + fprintf(pFileDump, "\"%s\",\n",pDBList->md5CheckSumTi); + fprintf(pFileDump, "\"%s\"\n",mdString); + } + else { + fprintf(pFileDump, "\"0\",\n"); + fprintf(pFileDump, "\"0\",\n"); + fprintf(pFileDump, "\"%s\"\n",mdString); + } + break; + + default: + break; + } + fprintf(pFileDump, "},\n"); + +} //End of dumpMd5Sum() + +//----------------------------------------------------------------------------- +int verifyMd5Sum( char* InFileName, void *pBuf, unsigned long nBufSize, int flag ) { + + unsigned char md[MD5_SUM_LENGTH]; //16bytes (128bits) + char mdString[(MD5_SUM_LENGTH * 2) + 1]; //32bytes + null char + char imgFileName[128]; + const struct JPGD_TEST_OUTPUT_FILE_LIST *pMd5SumDBList = NULL; + int i; + int result = ERROR; + + /*Generate the md5sum for the current output from file */ + if ( pBuf == NULL) { + md5SumFile( md, InFileName ); + } + else { + /*Generate the md5sum for the current output from buffer */ + md5SumBuf( md, pBuf, nBufSize ); + } + + /* Convert the md5 sum to a string */ + for (i = 0; i < MD5_SUM_LENGTH; i++){ + sprintf( (char*)&mdString[i*2],"%02x",md[i]); + } + + /* Extract the file name alone from the full path */ + extractFileName(InFileName, imgFileName); + PRINT("md5sum String = %s\n",mdString); + + /*comapre the md5sum with the data base */ + if ( flag == JPGD_MD5SUM_LIST ) { + pMd5SumDBList = &st_jpgd_file_list[0]; + } + else { + pMd5SumDBList = &st_jpge_file_list[0]; + } + + for(i = 0; strlen(pMd5SumDBList[i].fileName) != 0; i++) { + + if ( strcmp ( pMd5SumDBList[i].fileName, imgFileName ) == 0 ) { + /* File name found. Now check the md5sum */ + if ( strcmp( pMd5SumDBList[i].md5CheckSumArm , (const char*)mdString ) == 0 ) { + PRINT("Md5Sum matches with ARM Codec output.\n"); + updateTestCount(PASSCOUNT_ARM); + result = PASS; + break; + } + else if ( strcmp( pMd5SumDBList[i].md5CheckSumTi , (const char*)mdString ) == 0 ) { + PRINT("Md5Sum matches with TI Codec output.\n"); + updateTestCount(PASSCOUNT_TIDSP); + result = PASS; + break; + } + else if ( strcmp( pMd5SumDBList[i].md5CheckSumSimcop , (const char*)mdString ) == 0 ) { + PRINT("Md5Sum matches with SIMCOP Codec output.\n"); + updateTestCount(PASSCOUNT_SIMCOP); + result = PASS; + break; + } + else { + PRINT("%s():%d:: ERROR!!! Md5Sum Mismatch !!!.\n",__FUNCTION__,__LINE__); + result = FAIL; + break; + } + } + } + + if ( result == ERROR ) { + PRINT("\n%s():%d:: !!!!!New test output file. Manual verification required.!!!!!.\n",__FUNCTION__,__LINE__); + updateTestCount(COUNT_MANUALVERIFY); + if(flagDumpMd5Sum) { + dumpMd5Sum(imgFileName, mdString, NULL); + } + return PASS; + } + else { + if(flagDumpMd5Sum) { + dumpMd5Sum(imgFileName, mdString,(void*) &pMd5SumDBList[i]); + } + return result; + } + +} //End of verifyMd5Sum() + +//----------------------------------------------------------------------------- +int calcScaleFactor(int userW, int userH, SkStream* iStream) { + int nOrgW = 0; + int nOrgH = 0; + int scaleFactor = 1; + S32 inputFileSize = 0; + JPEG_IMAGE_INFO JpegImageInfo; + char outFileName[256]; + + /* Parse the input file and get the image Width and Height */ + inputFileSize = jpegHeaderParser(iStream, &JpegImageInfo); + iStream->rewind(); + PRINT("Input Image W x H = %d x %d :: fileSize = %ld\n",JpegImageInfo.nWidth, JpegImageInfo.nHeight,inputFileSize); + if ( inputFileSize == 0) { + scaleFactor = 1; + } + else { + nOrgW = JpegImageInfo.nWidth; + nOrgH = JpegImageInfo.nHeight; + + if ( userW >= nOrgW || userH >= nOrgH ){ + scaleFactor = 1; + } + else if ( userW > 0 ) { + scaleFactor = nOrgW / userW; + } + else if ( userH > 0 ) { + scaleFactor = nOrgH / userH; + } + } + PRINT("%s():%d:: Calculated ScaleFactor = %d\n",__FUNCTION__,__LINE__,scaleFactor); + return scaleFactor; + +} //End of calcScaleFactor() + +//----------------------------------------------------------------------------- +int findJPGDType(SkStream *stream) { + char prop[2] = {'0','\0'}; + char sizeTh[] = "0000000000"; + unsigned int imageSizeTh =0; + unsigned int fileSize = 0; + +#ifdef TARGET_OMAP4 + //TDB -SIMCOP: HW deocder selection logic has to be done here. + // return CODECTYPE_SIMCOP; + + //currently return SW JPGD by default + +#else //OMAP3 DSP jpeg decoder + property_get("jpeg.libskiahw.decoder.enable", prop, "0"); + if(prop[0] == '1'){ //uses DSP JPGD + //check for the file size threshold + property_get("jpeg.libskiahw.decoder.thresh", sizeTh, "0"); + imageSizeTh = atoi(sizeTh); + fileSize = stream->getLength(); + if(fileSize > imageSizeTh) { + return CODECTYPE_DSP; + } + } +#endif + return CODECTYPE_SW; //uses SW JPGD + +} //End of findJPGDType() +//----------------------------------------------------------------------------- +int runJPEGDecoderTest(int argc, char** argv) { + + SkImageDecoder* skJpegDec = NULL; + SkBitmap skBM; + SkIRect subRegion; + SkBitmap::Config prefConfig = SkBitmap::kRGB_565_Config; + int reSize = 1; + int nReqWidth = 0; + int nReqHeight = 0; + int result = PASS; + char* cmd = NULL; + JpegDecoderParams jpegDecParams; + bool bSubRegDecFlag = false; + + memset((void*)&jpegDecParams, 0, sizeof(JpegDecoderParams) ); + flagCodecType = CODECTYPE_SW; + + /*check the parameter counts*/ + if (argc < 4) { + PRINT("%s:%d::!!!!!Wrong number of arguments....\n",__FUNCTION__,__LINE__); + printDecoderTestUsage(); + return ERROR; + } + + /* check if the output file already exists and delete it*/ + { + char rmCmd[300]; + FILE* fp = fopen(argv[3],"r"); + if (fp) { + DBGPRINT("%s():%d:: Output file already exists. Deleting it.\n",__FUNCTION__,__LINE__); + fclose(fp); + sprintf(rmCmd,"rm %s",argv[3]); + system(rmCmd); + } + } + + SkFILEStream inStream(argv[2]); + PRINT("InputFile = %s\n",argv[2]); + PRINT("OutputFile = %s\n",argv[3]); + + if (inStream.isValid() == false) { + PRINT("%s:%d::!!!!!!!!!!Input File is not found....\n",__FUNCTION__,__LINE__); + return ERROR; + } + + /*output color format*/ + if (argc >= 5) { + prefConfig = (SkBitmap::Config)atoi(argv[4]); + if(prefConfig == SkBitmap::kARGB_8888_Config) { + DBGPRINT("%s():%d:: Output Color Format : ARGB_8888 32bit.\n",__FUNCTION__,__LINE__); + } + else if (prefConfig == SkBitmap::kRGB_565_Config) { + DBGPRINT("%s():%d:: Output Color Format : RGB_565 16bit.\n",__FUNCTION__,__LINE__); + } + else{ + /*Eventhough the android supports some more RGB color format, TI DSP SN supports the + above two color format among the android color formats. + TI DSP SN supports more formats in YUV too, but android does not support YUV o/p formats.*/ + PRINT("%s():%d::!!!!Invalid output color format option..\n",__FUNCTION__,__LINE__); + + /* Allow the wrong color format to test the error handling */ + //prefConfig = SkBitmap::kRGB_565_Config; + } + } + + /*resize mode*/ + if (argc >= 6) { + reSize = atoi(argv[5]); + + switch ( reSize){ + case (12): + reSize = 8; + break; + + case (25): + reSize = 4; + break; + + case (50): + reSize = 2; + break; + + case (100): + reSize = 1; + break; + + default: + reSize = 1; + DBGPRINT("%s():%d:: Scalefactor set to default 1 (noResize) .\n",__FUNCTION__,__LINE__); + break; + } + + PRINT("%s():%d:: Scale factor=%d. (1-100,2-50,4-25,8-12 percent resize)\n",__FUNCTION__,__LINE__,reSize); + } + + /*Section Decode - Slice output mode*/ + if (argc >= 7) { + } + else{ + } + + /*Sub Region Decode*/ + if (argc == 11) { + jpegDecParams.nXOrg = atoi(argv[7]); + jpegDecParams.nYOrg = atoi(argv[8]); + jpegDecParams.nXLength = atoi(argv[9]); + jpegDecParams.nYLength = atoi(argv[10]); + + if ( jpegDecParams.nXOrg || jpegDecParams.nYOrg || + jpegDecParams.nXLength || jpegDecParams.nYLength ) { + bSubRegDecFlag = true; + + PRINT("%s():%d:: !!!! subregion decode.\n",__FUNCTION__,__LINE__); + subRegion.fLeft = jpegDecParams.nXOrg; + subRegion.fRight = jpegDecParams.nXOrg + jpegDecParams.nXLength; + subRegion.fTop = jpegDecParams.nYOrg; + subRegion.fBottom = jpegDecParams.nYOrg + jpegDecParams.nYLength; + } + /* OMAP3: Check for the co-ordinates multiples + TI DSP Socket Node has contraint on the multiples of the co-ordinates */ + // Allow the users input. Libskiahw should take care in case of errors. + DBGPRINT("%s():%d:: NOTE: Refer the Codec guide for the constraints on X & Y origin values.\n",__FUNCTION__,__LINE__); + + } + else{ + } + + /* Check for the scale factor number : omap3= 1,2,4,8 ; OMAP4= 1 to 1256 */ + if (argc == 12) { + reSize = atoi(argv[11]); + } + /* Check for the desired output resolution and modify the scale factor accordingly. */ + else if (argc == 13) { + nReqWidth = atoi(argv[11]); + nReqHeight = atoi(argv[12]); + reSize = calcScaleFactor(nReqWidth, nReqHeight, &inStream ); + } + + /* Get the Decoder handle */ + skJpegDec = SkImageDecoder::Factory(&inStream); + if( skJpegDec == NULL ) { + PRINT("%s():%d:: !!!! NULL Decoder Handle received..\n",__FUNCTION__,__LINE__); + return FAIL; + } + + /*set the scale factor */ + skJpegDec->setSampleSize(reSize); + skJpegDec->SetDeviceConfig(prefConfig); + + /*check which decoder handle is chosen by the Factory()*/ + flagCodecType = findJPGDType(&inStream); + + +#ifdef TIME_MEASUREMENT + { + AutoTimeMicros atm("Decode Time Measurement:"); +#endif + + //SW(ARM) subregion decode supported + if( CODECTYPE_SW == flagCodecType && bSubRegDecFlag ){ + int ht = 0, wd = 0; + + if( skJpegDec->buildTileIndex(&inStream, &wd, &ht) == false ) { + PRINT("%s():%d:: !!!! skJpegDec->buildTileIndex() returned false..\n",__FUNCTION__,__LINE__); + PRINT("%s():%d:: !!!! Test Failed..\n",__FUNCTION__,__LINE__); + delete skJpegDec; + return FAIL; + } + if( skJpegDec->decodeRegion(&skBM, subRegion, prefConfig) == false) { + PRINT("%s():%d:: !!!! skJpegDec->decodeRegion() returned false..\n",__FUNCTION__,__LINE__); + PRINT("%s():%d:: !!!! Test Failed..\n",__FUNCTION__,__LINE__); + delete skJpegDec; + return FAIL; + } + } + else { //if !(CODECTYPE_SW == flagCodecType && bSubRegDecFlag ) + + /*call decode*/ + if (skJpegDec->decode(&inStream, &skBM, prefConfig, SkImageDecoder::kDecodePixels_Mode) == false) { + PRINT("%s():%d:: !!!! skJpegDec->decode returned false..\n",__FUNCTION__,__LINE__); + PRINT("%s():%d:: !!!! Test Failed..\n",__FUNCTION__,__LINE__); + delete skJpegDec; + return FAIL; + } + } + +#ifdef TIME_MEASUREMENT + atm.setResolution(skBM.width() , skBM.height()); + atm.setScaleFactor(reSize); + } +#endif + + { //scope to close the output file/stream handle + SkFILEWStream outStream(argv[3]); + outStream.write(skBM.getPixels(), skBM.getSize()); + DBGPRINT("%s():%d:: Wrote %d bytes to output file<%s>.\n",__FUNCTION__,__LINE__,skBM.getSize(),argv[3]); + delete skJpegDec; + + result = verifyMd5Sum(argv[3], skBM.getPixels(), skBM.getSize(), JPGD_MD5SUM_LIST ); + } + + //Now change the output filename with W & H if the scalefactor modified the output resolution + if (reSize != 1) { + char temp[256]; + PRINT("%s:%d:: Modified output WxH = %d x %d\n",__FUNCTION__,__LINE__,skBM.width(),skBM.height()); + strcpy(temp, argv[3]); + cmd = strrchr(temp, '.'); + cmd[0] = '\0'; + cmd =(char*) malloc(600); + if ( cmd !=NULL) { + sprintf(cmd, "mv %s %s___%dx%d.raw",argv[3],temp,skBM.width(),skBM.height() ); + system(cmd); + free(cmd); + } + } + return result; + +} //End of runJPEGDecoderTest() + +//----------------------------------------------------------------------------- +int runJPEGEncoderTest(int argc, char** argv) { + + SkImageEncoder* skJpegEnc = NULL; + SkBitmap skBM; + SkBitmap::Config inConfig = SkBitmap::kRGB_565_Config; + void *tempInBuff = NULL; + int nWidth = 0; + int nHeight = 0; + int nQFactor = 100; + + /*check the parameter counts*/ + if (argc < 6) { + PRINT("%s:%d::!!!!!Wrong number of arguments....\n",__FUNCTION__,__LINE__); + printEncoderTestUsage(); + return ERROR; + } + + /* check if the output file already exists and delete it*/ + { + char rmCmd[300]; + FILE* fp = fopen(argv[3],"r"); + if (fp) { + DBGPRINT("%s():%d:: Output file already exists. Deleting it.\n",__FUNCTION__,__LINE__); + fclose(fp); + sprintf(rmCmd,"rm %s",argv[3]); + system(rmCmd); + } + } + + SkFILEStream inStream(argv[2]); + SkFILEWStream outStream(argv[3]); + + PRINT("InputFile = %s\n",argv[2]); + PRINT("OutputFile = %s\n",argv[3]); + + if (inStream.isValid() == false) { + PRINT("%s:%d::!!!!!!!!!!!Input File is not found....\n",__FUNCTION__,__LINE__); + return ERROR; + } + + /* width and height */ + nWidth = atoi(argv[4]); + nHeight = atoi(argv[5]); + + /*Input color format*/ + if (argc >= 7) { + inConfig = (SkBitmap::Config)atoi(argv[6]); + if(inConfig == SkBitmap::kARGB_8888_Config) { + DBGPRINT("%s():%d:: Input Color Format : ARGB_8888 32bit.\n",__FUNCTION__,__LINE__); + } + else if (inConfig == SkBitmap::kRGB_565_Config) { + DBGPRINT("%s():%d:: Input Color Format : RGB_565 16bit.\n",__FUNCTION__,__LINE__); + } + else{ + /*Eventhough the android supports some more RGB color format, TI DSP SN supports the + above two color format among the android color formats. + TI DSP SN supports more formats in YUV too, but android does not support YUV i/p formats.*/ + PRINT("%s():%d::!!!!Invalid input color format option..\n",__FUNCTION__,__LINE__); + + /* still allows to execute to validate the error handling libskiiahw code */ + } + } + + /* QFactor */ + if (argc >= 8) { + nQFactor = atoi(argv[7]); + DBGPRINT("%s():%d:: Quality Factor : %d.\n",__FUNCTION__,__LINE__,nQFactor); + } + + /* create the input temp buffer for the input file */ + tempInBuff = (void*)malloc(inStream.getLength()); + if ( tempInBuff == NULL) { + PRINT("%s():%d::!!!!malloc failed...\n",__FUNCTION__,__LINE__); + return ERROR; + } + inStream.read(tempInBuff, inStream.getLength()); + + /*configure the SkBitmap */ + skBM.setConfig(inConfig, nWidth, nHeight); + skBM.setPixels(tempInBuff); + + /* get the JPEG Encoder Handle */ + skJpegEnc = SkImageEncoder::Create(SkImageEncoder::kJPEG_Type); + + /* call onEncode */ + if (skJpegEnc->encodeStream( &outStream, skBM, nQFactor) == false) { + PRINT("%s():%d::!!!onEncode failed....\n",__FUNCTION__,__LINE__); + free(tempInBuff); + delete skJpegEnc; + return FAIL; + } + + DBGPRINT("%s():%d:: Encoded image written in to output file<%s>.\n",__FUNCTION__,__LINE__,argv[3]); + free(tempInBuff); + delete skJpegEnc; + + return PASS; +}//End of runJPEGEncoderTest() + + +//----------------------------------------------------------------------------- +int runFromCmdArgs(int argc, char** argv) { + + if(strcmp(argv[1],"D") == 0) { + /*call decoder test function*/ + return runJPEGDecoderTest(argc, argv); + } + else if (strcmp(argv[1],"E") == 0) { + /*call Encoder test function*/ + if( runJPEGEncoderTest(argc, argv) == PASS) { + return ( verifyMd5Sum (argv[3], NULL, 0, JPGE_MD5SUM_LIST) ); + } + else { + return FAIL; + } + } + else { + PRINT("%s():%d:: !!! Invalid test option. only D/E is valid (Decoder/Encoder).\n",__FUNCTION__,__LINE__); + printUsage(); + } + return ERROR; + +}//end of runFromCmdArgs() + +//----------------------------------------------------------------------------- +void RunFromScript(char* scriptFileName) { + + FILE* fp = NULL; + char *pArgs[12]; + char strLine[500]; + char *pstrLine = strLine; + int argsCount=0, i=0; + int result = 0; + + DBGPRINT("%s():%d::Automated Test Started....\n",__FUNCTION__,__LINE__); + fp = fopen( scriptFileName, "r"); + if ( NULL == fp ) { + PRINT("\n !!Error while opening the script file-%s.\n",scriptFileName); + return; + } + + for(i = 0; i < 12; i++) { + pArgs[i] = (char *)malloc(200); + } + + /* Check the script file is valid one or not */ + memset( (void*)pstrLine, 0, 500); + fgets (pstrLine, sizeof(strLine), fp); + if (strncmp(LIBSKIAHWTEST, pstrLine, strlen(LIBSKIAHWTEST) ) != 0) { + PRINT("\n%s():%d:: !!!!Not a valid script file-(%s).\n",__FUNCTION__,__LINE__,scriptFileName); + printInputScriptFormat(); + fclose(fp); + return; + } + + while( !feof(fp) ) { + + /*Read one line from the script and parse*/ + memset( (void*)pstrLine, 0, 500); + if( NULL == fgets (pstrLine, sizeof(strLine), fp) ) { + /*file end*/ + break; + } + + if ( strlen(pstrLine) < strlen(LIBSKIAHWTEST) ) { + continue; + } + + /*Check for comment line in the script and skip*/ + if (pstrLine[0] == '#' || pstrLine[0] == '\n') { + pstrLine[0] = '\0'; + continue; + } + DBGPRINT("===============================================================================\n"); + DBGPRINT("TestCase read from script file: \n%s ",pstrLine); + + argsCount = sscanf(pstrLine,"%s %s %s %s %s %s %s %s %s %s %s %s %s", &testID[0], + pArgs[0],pArgs[1],pArgs[2],pArgs[3],pArgs[4],pArgs[5], + pArgs[6],pArgs[7],pArgs[8],pArgs[9],pArgs[10],pArgs[11]); + + if ( argsCount == 0 ) { + /*Empty Line with whitespaces. Skip this and continue */ + continue; + } + + DBGPRINT("TestCase: ./"); + for (i = 0; i < argsCount-1; i++) { + DBGPRINT("%s ",pArgs[i]); + } + DBGPRINT("\n"); + + PRINT("===============================================================================\n"); + PRINT("Executing %s.....\n",testID); + result = runFromCmdArgs(argsCount-1,(char**)&pArgs); + + /* Print the result */ + if (result == FAIL){ + updateTestCount(FAILCOUNT); + PRINT("\n%15s: <%s>.....FAIL !!!\n",testID,pArgs[2]); + } + else if(result == ERROR) { + PRINT("\n%15s.....ERROR occured during the test !!!.\n",testID); + } + else { + PRINT("\n%15s.....PASS\n",testID); + } + + } //End of while loop + + + for(i = 0; i < 12; i++) { + free(pArgs[i]); + } + + fclose(fp); + PRINT("\n <--------------------------End of script: %s------------------------>\n",scriptFileName); + +} //End of RunFromScript() + +//----------------------------------------------------------------------------- +void parseFolderOptions(int argc, char** argv) { + + char* pStr = argv[1]; + char* pArgs[12]; + int argCnt = 0; + int count = 1; + int flagMemoryTest = 0; + int result = PASS; + int i; + DIR* pDir = NULL; + DIRENTRY* pDirEnt = NULL; + + flagDumpMd5Sum = 0; //reset flag + + for(i = 0; i < 12; i++) { + pArgs[i] = (char *)malloc(200); + } + + //options: + // M-memory test. + // C-dump MD5-checksum strings into a file. + for (i=0; pStr[i] != '\0'; i++) { + switch (pStr[i]) { + case 'M': + flagMemoryTest = 1; + break; + + case 'C': + pFileDump = fopen("md5sum_dump.txt", "w"); + if (pFileDump == NULL) { + PRINT("%s():%d::!!!!! Counld not create <md5sum_dump.txt> file!!! \n",__FUNCTION__,__LINE__); + flagDumpMd5Sum = 0; + } + else { + flagDumpMd5Sum = 1; + } + break; + + default: + break; + } + } + + if (flagMemoryTest) { + //get the memory info + system("cat /proc/meminfo > MemInfoBeforeTest.txt"); + system("cat MemInfoBeforeTest.txt"); + } + + if (argc == 3) { + //run the script content one time + count = 1; + } + else if (argc == 4 ){ + count = atoi(argv[3]); + if (count == 0) { + count =1; + } + } + + //Navigate through the directory for .jpg files. + pDir = opendir(argv[2]); + if (pDir == NULL) { + PRINT("%s():%d:: !!!!! unable to open the Directory (%s)!!!!\n",__FUNCTION__,__LINE__,argv[2]); + return; + } + + //Create the parameters for decoder test + strcpy(pArgs[0], argv[0]); + argCnt++; + + //Decoder flag + strcpy(pArgs[1], "D"); + argCnt++; + + //output color format + if (argc > 4 ) { + strcpy(pArgs[4], argv[4]); + } + else { + strcpy(pArgs[4], "4"); //default RGB16 + } + argCnt++; + + //scale factor percentage + if (argc > 5 ) { + strcpy(pArgs[5], argv[5]); + } + else { + strcpy(pArgs[5], "100"); //default scale factor 100% + } + argCnt++; + + //Output Slice mode + if (argc > 6 ) { + strcpy(pArgs[6], argv[6]); + argCnt++; + } + + //Subregion Decode xOrg, yOrg, xLength, yLength + if (argc > 10 ) { + strcpy(pArgs[7], argv[7]); + strcpy(pArgs[8], argv[8]); + strcpy(pArgs[9], argv[9]); + strcpy(pArgs[10], argv[10]); + argCnt += 4; + } + + //Scale Factor value or the desired output Width + if (argc > 11 ) { + strcpy(pArgs[11], argv[11]); + argCnt++; + } + + //desired output Height + if (argc > 11 ) { + strcpy(pArgs[11], argv[11]); + argCnt++; + } + + argCnt +=2; //for input file and output file parameters + for (i = 0; i < count; i++) { //to repeat the folder + do { //for the files inside the specified folder + pDirEnt = readdir(pDir); + if (pDirEnt != NULL) { + if (strstr(pDirEnt->d_name, ".jpg") == NULL && + strstr(pDirEnt->d_name, ".JPG") == NULL ) { + continue; + } + + PRINT("\n-------------------------------------------------------------------------------\n"); + //input file + strcpy(pArgs[2], argv[2]); //path + pStr = argv[2]; + if ( pStr[strlen(pStr)-1] != '/') { + strcat(pArgs[2], "/"); + } + strcat(pArgs[2], pDirEnt->d_name); //append the file name + + //output File + strcpy(pArgs[3], pArgs[2]); + ((char*)pArgs[3])[strlen(pArgs[2])-3] = '\0'; + strcat(pArgs[3], "raw"); + + result = runFromCmdArgs(argCnt, (char**)&pArgs); + + /* Print the result */ + if (result){ + PRINT("\n<%s>.....FAIL !!!\n",pArgs[2]); + } + else { + PRINT("\n.....PASS\n\n"); + } + } //end of if(pDir != NULL) + } while (pDirEnt != NULL); + PRINT("\n\nRepeating the folder... (%d) more times..\n\n",((count-1)-i) ); + rewinddir(pDir); + PRINT("\n===================================================================================\n"); + } //end of for loop + + closedir(pDir); + + if (flagDumpMd5Sum == 1 && pFileDump != NULL) { + fclose(pFileDump); + } + + if (flagMemoryTest) { + //wait for 2 seconds + sleep(2); + + //get the memory info + system("cat /proc/meminfo > MemInfoAfterTest.txt"); + system("cat MemInfoAfterTest.txt"); + + //Analyze the memory info + analyzeMemoryInfo("MemInfoBeforeTest.txt", "MemInfoAfterTest.txt"); + + //delete the meminfo files + system("rm MemInfoBeforeTest.txt"); + system("rm MemInfoAfterTest.txt"); + } + +} //End of parseFolderOptions() + +//----------------------------------------------------------------------------- +void parseScriptOptions(int argc, char** argv) { + + char* pStr = argv[1]; + int flagMemoryTest = 0; + int i, count = 1; + + flagDumpMd5Sum = 0; //reset flag + + //options: + // M-memory test. + // C-dump MD5-checksum strings into a file. + for (i=0; pStr[i] != '\0'; i++) { + switch (pStr[i]) { + case 'M': + flagMemoryTest = 1; + break; + + case 'C': + pFileDump = fopen("md5sum_dump.txt", "w"); + if (pFileDump == NULL) { + PRINT("%s():%d::!!!!! Counld not create <md5sum_dump.txt> file!!! \n",__FUNCTION__,__LINE__); + flagDumpMd5Sum = 0; + } + else { + flagDumpMd5Sum = 1; + } + break; + + default: + break; + } + } + + if (flagMemoryTest) { + //get the memory info + system("cat /proc/meminfo"); + system("cat /proc/meminfo > MemInfoBeforeTest.txt"); + } + + if (argc == 3) { + //run the script content one time + count = 1; + } + else if (argc == 4) { + count = atoi(argv[3]); + if (count == 0) { + count =1; + } + } + + for(i = 0; i < count; i++) { + /* Test using script file*/ + RunFromScript(argv[2]); + PRINT("\n\nRepeating the Script... (%d) more times..\n\n",((count-1)-i) ); + } + + if (flagDumpMd5Sum == 1 && pFileDump != NULL) { + fclose(pFileDump); + } + + if (flagMemoryTest) { + //get the memory info + sleep(2); + system("cat /proc/meminfo"); + system("cat /proc/meminfo > MemInfoAfterTest.txt"); + + //Analyze the memory info + analyzeMemoryInfo("MemInfoBeforeTest.txt", "MemInfoAfterTest.txt"); + + //delete the meminfo files + system("rm MemInfoBeforeTest.txt"); + system("rm MemInfoAfterTest.txt"); + } + + +} //End of parseScriptOptions() + +//----------------------------------------------------------------------------- +int main(int argc, char** argv) { + + int result = PASS; + int count = 0; + int i = 0; + unsigned int nTotalTests = 0; + char* pStr = NULL; + + nTestCount[0] = 0; + nTestCount[1] = 0; + nTestCount[2] = 0; + nTestCount[3] = 0; + nTestCount[4] = 0; + + PRINT("\n|------------------------------------------------------------------------------|\n"); + PRINT ("|-Skia JPEG Decoder/Encoder Test App built on:"__DATE__":"__TIME__"\n"); + PRINT ("|------------------------------------------------------------------------------|\n"); + + if (argc < 2) { + printUsage(); + return 0; + } + pStr = (char*)argv[1]; + switch (pStr[0]) { + + case 'D': + case 'E': + /* test using command line parameters*/ + result = runFromCmdArgs(argc, argv); + + if (result == PASS){ + PRINT("\nTest.....PASS\n"); + } + else { + PRINT("\nTest.....FAIL !!!\n"); + } + + break; + + case 'F': + //Folder for Decoder test only. Decodes all the jpg files in the folder specified. + parseFolderOptions(argc, argv); + break; + + case 'S': + parseScriptOptions(argc, argv); + break; + + default: + PRINT("%s():%d::!!!! Invalid options..\n",__FUNCTION__,__LINE__); + printUsage(); + break; + } + + //print the PASS FAIL report + nTotalTests = ( nTestCount[0] + nTestCount[1] + nTestCount[2] + nTestCount[3] + nTestCount[4]); + if ( nTotalTests ) { + PRINT("\n|------------------------------------------------------------------------------|\n"); + PRINT ("| Total Test cases run = %d\n|\n",nTotalTests ); + PRINT ("| Test cases run on ARM = %d\t (%d %c)\n",nTestCount[0], ((100*nTestCount[0])/nTotalTests),'%' ); + PRINT ("| Test cases run on TI-DSP = %d\t (%d %c)\n",nTestCount[1], ((100*nTestCount[1])/nTotalTests),'%' ); + PRINT ("| Test cases run on SIMCOP = %d\t (%d %c)\n",nTestCount[2], ((100*nTestCount[2])/nTotalTests),'%' ); + PRINT ("| Test cases FAILED = %d\t (%d %c)\n",nTestCount[3], ((100*nTestCount[3])/nTotalTests),'%' ); + PRINT ("| Test cases needs manual check = %d\t (%d %c)\n",nTestCount[4], ((100*nTestCount[4])/nTotalTests),'%' ); + PRINT("|\n|------------------------------------------------------------------------------|\n"); + } + + return 0; +} //end of main + + + + |