From 855e4cc61c0eb01e9a49e35ec689ed0b9b527edf Mon Sep 17 00:00:00 2001 From: seven332 Date: Wed, 17 Sep 2014 14:51:24 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=AD=A3=20armv7=20=E8=80=8C=E6=97=A0?= =?UTF-8?q?=20neon=20=E8=80=8C=E5=AF=BC=E8=87=B4=E7=9A=84=E8=A7=A3?= =?UTF-8?q?=E7=A0=81=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- jni/Android.mk | 8 +- jni/jpeg.c | 5 +- jni/libjpeg-turbo/jdcolor.c | 10 +- jni/libpng/arm/arm_init.c | 2 +- jni/libpng/contrib/arm-neon/linux.c | 159 ++++++++++++++++++++++++++++ jni/libpng/pnglibconf.h | 2 +- 6 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 jni/libpng/contrib/arm-neon/linux.c diff --git a/jni/Android.mk b/jni/Android.mk index 983e9812b..23c270fe4 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -47,7 +47,11 @@ libjpeg-turbo/turbojpeg.c LOCAL_CFLAGS := -O3 ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) - LOCAL_CFLAGS += -mfpu=neon + # Don't add -mfpu=neon + # Some arm v7 cpu do not support neon, + # libjpeg-turbo can check neon in init_simd() + # through parse_proc_cpuinfo() + #LOCAL_CFLAGS += -mfpu=neon endif ifeq ($(TARGET_ARCH),arm) @@ -143,6 +147,8 @@ libpng/pngtrans.c LOCAL_CFLAGS := -O3 ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) + # Add -mfpu=neon + # libpng only check neon when add -mfpu=neon LOCAL_CFLAGS += -mfpu=neon LOCAL_SRC_FILES += \ libpng/arm/arm_init.c \ diff --git a/jni/jpeg.c b/jni/jpeg.c index b5502a974..f2256c235 100644 --- a/jni/jpeg.c +++ b/jni/jpeg.c @@ -11,9 +11,11 @@ struct my_error_mgr { typedef struct my_error_mgr * my_error_ptr; +char emsg[JMSG_LENGTH_MAX]; + static void my_error_exit(j_common_ptr cinfo) { my_error_ptr myerr = (my_error_ptr) cinfo->err; - (*cinfo->err->output_message)(cinfo); + (*cinfo->err->format_message)(cinfo, emsg); longjmp(myerr->setjmp_buffer, 1); } @@ -43,6 +45,7 @@ jobject JPEG_DecodeFileHandler(JNIEnv* env, FILE* fp, jint format) { cinfo.err = jpeg_std_error(&jerr.pub); jerr.pub.error_exit = my_error_exit; if (setjmp(jerr.setjmp_buffer)) { + LOGE("%s", emsg); free(jpeg); jpeg_destroy_decompress(&cinfo); return NULL; diff --git a/jni/libjpeg-turbo/jdcolor.c b/jni/libjpeg-turbo/jdcolor.c index ffedabd55..b2d34a3f8 100644 --- a/jni/libjpeg-turbo/jdcolor.c +++ b/jni/libjpeg-turbo/jdcolor.c @@ -633,9 +633,9 @@ jinit_color_deconverter (j_decompress_ptr cinfo) case JCS_EXT_ARGB: cinfo->out_color_components = rgb_pixelsize[cinfo->out_color_space]; if (cinfo->jpeg_color_space == JCS_YCbCr) { - if (jsimd_can_ycc_rgb()) + if (jsimd_can_ycc_rgb()) { cconvert->pub.color_convert = jsimd_ycc_rgb_convert; - else { + } else { cconvert->pub.color_convert = ycc_rgb_convert; build_ycc_rgb_table(cinfo); } @@ -649,8 +649,12 @@ jinit_color_deconverter (j_decompress_ptr cinfo) cconvert->pub.color_convert = null_convert; else cconvert->pub.color_convert = rgb_rgb_convert; - } else + } else if (cinfo->jpeg_color_space == JCS_CMYK) { + // TODO ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } else { + ERREXIT(cinfo, JERR_CONVERSION_NOTIMPL); + } break; case JCS_RGB565: diff --git a/jni/libpng/arm/arm_init.c b/jni/libpng/arm/arm_init.c index b0e929bc1..4d33c4b05 100644 --- a/jni/libpng/arm/arm_init.c +++ b/jni/libpng/arm/arm_init.c @@ -33,7 +33,7 @@ */ #ifndef PNG_ARM_NEON_FILE # ifdef __linux__ -# define PNG_ARM_NEON_FILE "contrib/arm-neon/linux.c" +# define PNG_ARM_NEON_FILE "../contrib/arm-neon/linux.c" # endif #endif diff --git a/jni/libpng/contrib/arm-neon/linux.c b/jni/libpng/contrib/arm-neon/linux.c new file mode 100644 index 000000000..182f37605 --- /dev/null +++ b/jni/libpng/contrib/arm-neon/linux.c @@ -0,0 +1,159 @@ +/* contrib/arm-neon/linux.c + * + * Copyright (c) 2014 Glenn Randers-Pehrson + * Written by John Bowler, 2014. + * Last changed in libpng 1.6.10 [March 6, 2014] + * + * This code is released under the libpng license. + * For conditions of distribution and use, see the disclaimer + * and license in png.h + * + * SEE contrib/arm-neon/README before reporting bugs + * + * STATUS: SUPPORTED + * BUG REPORTS: png-mng-implement@sourceforge.net + * + * png_have_neon implemented for Linux by reading the widely available + * pseudo-file /proc/cpuinfo. + * + * This code is strict ANSI-C and is probably moderately portable, it does + * however use and assumes that /proc/cpuinfo is never localized. + */ +#include + +static int +png_have_neon(png_structp png_ptr) +{ + FILE *f = fopen("/proc/cpuinfo", "rb"); + + if (f != NULL) + { + /* This is a simple state machine which reads the input byte-by-byte until + * it gets a match on the 'neon' feature or reaches the end of the stream. + */ + static const char ch_feature[] = { 70, 69, 65, 84, 85, 82, 69, 83 }; + static const char ch_neon[] = { 78, 69, 79, 78 }; + + enum + { + StartLine, Feature, Colon, StartTag, Neon, HaveNeon, SkipTag, SkipLine + } state; + int counter; + + for (state=StartLine, counter=0;;) + { + int ch = fgetc(f); + + if (ch == EOF) + { + /* EOF means error or end-of-file, return false; neon at EOF is + * assumed to be a mistake. + */ + fclose(f); + return 0; + } + + switch (state) + { + case StartLine: + /* Match spaces at the start of line */ + if (ch <= 32) /* skip control characters and space */ + break; + + counter=0; + state = Feature; + /* FALL THROUGH */ + + case Feature: + /* Match 'FEATURE', ASCII case insensitive. */ + if ((ch & ~0x20) == ch_feature[counter]) + { + if (++counter == (sizeof ch_feature)) + state = Colon; + break; + } + + /* did not match 'feature' */ + state = SkipLine; + /* FALL THROUGH */ + + case SkipLine: + skipLine: + /* Skip everything until we see linefeed or carriage return */ + if (ch != 10 && ch != 13) + break; + + state = StartLine; + break; + + case Colon: + /* Match any number of space or tab followed by ':' */ + if (ch == 32 || ch == 9) + break; + + if (ch == 58) /* i.e. ':' */ + { + state = StartTag; + break; + } + + /* Either a bad line format or a 'feature' prefix followed by + * other characters. + */ + state = SkipLine; + goto skipLine; + + case StartTag: + /* Skip space characters before a tag */ + if (ch == 32 || ch == 9) + break; + + state = Neon; + counter = 0; + /* FALL THROUGH */ + + case Neon: + /* Look for 'neon' tag */ + if ((ch & ~0x20) == ch_neon[counter]) + { + if (++counter == (sizeof ch_neon)) + state = HaveNeon; + break; + } + + state = SkipTag; + /* FALL THROUGH */ + + case SkipTag: + /* Skip non-space characters */ + if (ch == 10 || ch == 13) + state = StartLine; + + else if (ch == 32 || ch == 9) + state = StartTag; + break; + + case HaveNeon: + /* Have seen a 'neon' prefix, but there must be a space or new + * line character to terminate it. + */ + if (ch == 10 || ch == 13 || ch == 32 || ch == 9) + { + fclose(f); + return 1; + } + + state = SkipTag; + break; + + default: + png_error(png_ptr, "png_have_neon: internal error (bug)"); + } + } + } + + else + png_warning(png_ptr, "/proc/cpuinfo open failed"); + + return 0; +} diff --git a/jni/libpng/pnglibconf.h b/jni/libpng/pnglibconf.h index 1ffa74e35..fb28b6c54 100644 --- a/jni/libpng/pnglibconf.h +++ b/jni/libpng/pnglibconf.h @@ -17,7 +17,7 @@ #define PNG_16BIT_SUPPORTED #define PNG_ALIGNED_MEMORY_SUPPORTED #define PNG_ARM_NEON_API_SUPPORTED -/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/ +#define PNG_ARM_NEON_CHECK_SUPPORTED #define PNG_BENIGN_ERRORS_SUPPORTED #define PNG_BENIGN_READ_ERRORS_SUPPORTED /*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/