diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:08:09 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2008-12-17 18:08:09 -0800 |
commit | ab8beedeb70c6941e0ff68014d8db64cee4ef15d (patch) | |
tree | 605fac439e98d54240d6cbe0cc9090ed6d97cab5 /tests/bionic/libc/other/test_jpeg.c | |
parent | 7341494707810f709855ea85ce03a8ec3ac8dbaf (diff) | |
download | extras-ab8beedeb70c6941e0ff68014d8db64cee4ef15d.tar.gz |
Code drop from //branches/cupcake/...@124589
Diffstat (limited to 'tests/bionic/libc/other/test_jpeg.c')
-rw-r--r-- | tests/bionic/libc/other/test_jpeg.c | 362 |
1 files changed, 362 insertions, 0 deletions
diff --git a/tests/bionic/libc/other/test_jpeg.c b/tests/bionic/libc/other/test_jpeg.c new file mode 100644 index 00000000..8d7ef1a7 --- /dev/null +++ b/tests/bionic/libc/other/test_jpeg.c @@ -0,0 +1,362 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* this small program is used to measure the performance of libjpeg decompression + * algorithm... + */ + +#include <time.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> +#include <sys/time.h> +#include "jpeglib.h" +#include <setjmp.h> +#ifdef HAVE_ANDROID_OS +#include <hardware/qemu_tracing.h> +#endif + +#define USE_STDIO + +#define CHUNK 32768 + +typedef struct { + struct jpeg_source_mgr jpeg_mgr; + char* base; + char* cursor; + char* end; +} SourceMgrRec, *SourceMgr; + +static void +_source_init_source(j_decompress_ptr cinfo) +{ + SourceMgr src = (SourceMgr) cinfo->src; + + src->jpeg_mgr.next_input_byte = (unsigned char*)src->base, + src->jpeg_mgr.bytes_in_buffer = src->end - src->base; +} + +static int +_source_fill_input_buffer(j_decompress_ptr cinfo) +{ + SourceMgr src = (SourceMgr) cinfo->src; + + cinfo->err->error_exit((j_common_ptr)cinfo); + return FALSE; +} + +static void +_source_skip_input_data(j_decompress_ptr cinfo, long num_bytes) +{ + SourceMgr src = (SourceMgr) cinfo->src; + + if (src->jpeg_mgr.next_input_byte + num_bytes > (unsigned char*)src->end ) { + cinfo->err->error_exit((j_common_ptr)cinfo); + } + + src->jpeg_mgr.next_input_byte += num_bytes; + src->jpeg_mgr.bytes_in_buffer -= num_bytes; +} + +static int +_source_resync_to_restart( j_decompress_ptr cinfo, int desired) +{ + SourceMgr src = (SourceMgr) cinfo->src; + + src->jpeg_mgr.next_input_byte = (unsigned char*)src->base; + src->jpeg_mgr.bytes_in_buffer = src->end - src->base; + return TRUE; +} + +static void +_source_term_source(j_decompress_ptr cinfo) +{ + // nothing to do +} + +static void +_source_init( SourceMgr src, char* base, long size ) +{ + src->base = base; + src->cursor = base; + src->end = base + size; + + src->jpeg_mgr.init_source = _source_init_source; + src->jpeg_mgr.fill_input_buffer = _source_fill_input_buffer; + src->jpeg_mgr.skip_input_data = _source_skip_input_data; + src->jpeg_mgr.resync_to_restart = _source_resync_to_restart; + src->jpeg_mgr.term_source = _source_term_source; +} + + +typedef struct { + struct jpeg_error_mgr jpeg_mgr; + jmp_buf jumper; + int volatile error; + +} ErrorMgrRec, *ErrorMgr; + +static void _error_exit(j_common_ptr cinfo) +{ + ErrorMgr error = (ErrorMgr) cinfo->err; + + (*error->jpeg_mgr.output_message) (cinfo); + + /* Let the memory manager delete any temp files before we die */ + longjmp(error->jumper, -1); +} + +#ifdef USE_STDIO +int decompress(FILE* input_file, int dct_method, int disable_rgb) +#else +int decompress(char* data, long fsize) +#endif +{ + ErrorMgrRec errmgr; + SourceMgrRec sourcemgr; + struct jpeg_decompress_struct cinfo; + int volatile error = 0; + jmp_buf jumper; + int isRGB; + char* pixels; + JSAMPLE* temprow; + + memset( &cinfo, 0, sizeof(cinfo) ); + memset( &errmgr, 0, sizeof(errmgr) ); + jpeg_create_decompress(&cinfo); + cinfo.err = jpeg_std_error(&errmgr.jpeg_mgr); +#if 0 + errmgr.jpeg_mgr.error_exit = _error_exit; + errmgr.error = 0; +#endif + + if (setjmp(errmgr.jumper) != 0) { + fprintf(stderr, "returning error from jpeglib ---\n" ); + goto Exit; + } + +#ifdef USE_STDIO + /* Specify data source for decompression */ + jpeg_stdio_src(&cinfo, input_file); +#else + _source_init( &sourcemgr, data, fsize ); + cinfo.src = &sourcemgr.jpeg_mgr; +#endif + + jpeg_read_header(&cinfo, 1); + + if (3 == cinfo.num_components && JCS_RGB == cinfo.out_color_space) + isRGB = 1; + else if (1 == cinfo.num_components && JCS_GRAYSCALE == cinfo.out_color_space) + isRGB = 0; // could use Index8 config if we want... + else { + fprintf( stderr, "unsupported jpeg colorspace %d with %d components\n", + cinfo.jpeg_color_space, cinfo.num_components ); + goto Exit; + } + + cinfo.dct_method = dct_method; + if (disable_rgb) + cinfo.out_color_space = JCS_YCbCr; + + jpeg_start_decompress(&cinfo); + + temprow = calloc( cinfo.num_components * cinfo.output_width, sizeof(JSAMPLE) ); + + { + unsigned y; + for (y = 0; y < cinfo.output_height; y++) { + JSAMPLE* rowptr = temprow; + (void)jpeg_read_scanlines(&cinfo, &rowptr, 1); + } + } + jpeg_finish_decompress(&cinfo); + + free( temprow ); +Exit: + jpeg_destroy_decompress(&cinfo); + return error; +} + + +#define DEFAULT_REPEAT 10 + +static void usage(void) +{ + fprintf(stderr, "usage: test_jpeg [options] filename.jpg [filename2.jpg ...]\n" ); + fprintf(stderr, "options: -r NN repeat count (default %d)\n", DEFAULT_REPEAT ); + fprintf(stderr, " -d N idct method (0=default, 1=fastest, 2=slow, 3=float)\n" ); + fprintf(stderr, " -C no RGB color conversion (YCbCr instead)\n" ); + exit(1); +} + +static double +get_time_usec( void ) +{ +#ifdef HAVE_ANDROID_OS + struct timespec ts; + + if ( clock_gettime( CLOCK_MONOTONIC, &ts ) < 0 ) + fprintf(stderr, "clock_gettime: %s\n", strerror(errno) ); + + return ts.tv_sec*1e6 + ts.tv_nsec*1e-3; +#else + struct timeval tv; + if (gettimeofday( &tv, NULL ) < 0) + fprintf(stderr, "gettimeofday: %s\n", strerror(errno) ); + + return tv.tv_sec*1000000. + tv.tv_usec*1.0; +#endif +} + + +int main( int argc, char** argv ) +{ + FILE* f; + int repeat_count = DEFAULT_REPEAT; + int dct_method = JDCT_DEFAULT; + int disable_rgb = 0; + double usec0, usec1; + + if (argc < 2) + usage(); + + for ( ; argc > 1 && argv[1][0] == '-'; argc--, argv++) { + const char* arg = &argv[1][1]; + switch (arg[0]) { + case 'r': + if (arg[1] == 0) { + if (argc < 3) + usage(); + arg = argv[2]; + argc--; + argv++; + } else + arg += 1; + + repeat_count = strtol(arg, NULL, 10); + + if (repeat_count <= 0) + repeat_count = 1; + break; + + case 'C': + disable_rgb = 1; + break; + + case 'd': + if (arg[1] == 0) { + if (argc < 3) + usage(); + arg = argv[2]; + argc--; + argv++; + } else + arg += 1; + + dct_method = strtol(arg, NULL, 10); + switch (dct_method) { + case 0: + dct_method = JDCT_DEFAULT; + break; + case 1: + dct_method = JDCT_IFAST; + break; + case 2: + dct_method = JDCT_ISLOW; + break; + case 3: + dct_method = JDCT_FLOAT; + break; + default: + usage(); + } + break; + + default: + usage(); + } + } + + for ( ; argc > 1; argc--, argv++ ) + { + long fsize; + char* data; + FILE* f = fopen( argv[1], "rb" ); + int rr; + + if (f == NULL) { + fprintf(stderr, "could not open '%s': %s\n", argv[1], strerror(errno) ); + continue; + } + + fseek( f, 0, SEEK_END ); + fsize = ftell(f); + fseek( f, 0, SEEK_SET ); + + usec0 = get_time_usec(); +#ifdef HAVE_ANDROID_OS + qemu_start_tracing(); +#endif +#ifdef USE_STDIO + for ( rr = repeat_count; rr > 0; rr-- ) { + fseek( f, 0, SEEK_SET ); + decompress(f, dct_method, disable_rgb); + } + fclose( f ); +#else + + data = malloc( fsize ); + if (data == NULL) { + if (fsize > 0) + fprintf(stderr, "could not allocate %ld bytes to load '%s'\n", fsize, argv[1] ); + fclose(f); + continue; + } + fread( data, 1, fsize, f ); + fclose(f); + + usec1 = get_time_usec() - usec0; + printf( "compressed load: %10.2f ms (%ld bytes)\n", usec1*1e-3, fsize ); + + usec0 = get_time_usec(); + for ( rr = repeat_count; rr > 0; rr -- ) + { + decompress( data, fsize ); + } + free( data ); +#endif +#ifdef HAVE_ANDROID_OS + qemu_stop_tracing(); +#endif + usec1 = get_time_usec() - usec0; + printf( "decompression took: %10.3f ms (%.2f KB/s, %d passes)\n", usec1/1e3, fsize*(1e6/1024)*repeat_count/usec1, repeat_count ); + } + return 0; +} |