项目中需要对jpeg解码, 最终选择libjpeg开源库, 并做用mjpegtools做jpeg2yuv的转换, 在此做个记录。
运行平台是Android, 在native层实现。
libjpeg-turdo支持NEON, 在arm平台上较快,因此选用这个版本。
libjpeg的源代码在http://www.libjpeg-turbo.org/DeveloperInfo/SVNAccess
可在Android平台上编译的版本:git://git.linaro.org/people/tomgall/libjpeg-turbo/libjpeg-turbo.git, 但此版本较老,其中有一个较明显的bug,
当解码mjpeg的时候,部分jpeg的解码异常,参见bug:http://sourceforge.net/p/libjpeg-turbo/bugs/15/, 这个bug在最新的libjpeg上已经fix,
但要使最新的版本在Android上编译运行成功较费劲,直接将此bug的patch合入到Android版本上, 修改如下:
在jdhuff.c 的decode_mcu_fast (j_decompress_ptr cinfo, JBLOCKROW *MCU_data)
if (cinfo->unread_marker != 0) {
cinfo->unread_marker = 0;
return FALSE;
}
==>
if (cinfo->unread_marker != 0 && !cinfo->entropy->insufficient_data) {
WARNMS(cinfo, JWRN_HIT_MARKER);
//cinfo->unread_marker = 0;
//return FALSE;
cinfo->entropy->insufficient_data = TRUE;
}
修改Android.mk, 编译出静态链接库:
# Makefile for libmyjpeg-turbo
ifneq ($(TARGET_SIMULATOR),true)
##################################################
### simd ###
##################################################
LOCAL_PATH := $(my-dir)
include $(CLEAR_VARS)
ifeq ($(ARCH_ARM_HAVE_NEON),true)
LOCAL_CFLAGS += -D__ARM_HAVE_NEON
endif
# From autoconf-generated Makefile
EXTRA_DIST = simd/nasm_lt.sh simd/jcclrmmx.asm simd/jcclrss2.asm simd/jdclrmmx.asm simd/jdclrss2.asm \
simd/jdmrgmmx.asm simd/jdmrgss2.asm simd/jcclrss2-64.asm simd/jdclrss2-64.asm \
simd/jdmrgss2-64.asm simd/CMakeLists.txt
libsimd_SOURCES_DIST = simd/jsimd_arm_neon.S \
simd/jsimd_arm.c
LOCAL_SRC_FILES := $(libsimd_SOURCES_DIST)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/simd \
$(LOCAL_PATH)/android
AM_CFLAGS := -march=armv7-a -mfpu=neon
AM_CCASFLAGS := -march=armv7-a -mfpu=neon
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := libsimd
include $(BUILD_STATIC_LIBRARY)
######################################################
### libmyjpeg.so ##
######################################################
include $(CLEAR_VARS)
# From autoconf-generated Makefile
libjpeg_SOURCES_DIST = jcapimin.c jcapistd.c jccoefct.c jccolor.c \
jcdctmgr.c jchuff.c jcinit.c jcmainct.c jcmarker.c jcmaster.c \
jcomapi.c jcparam.c jcphuff.c jcprepct.c jcsample.c jctrans.c \
jdapimin.c jdapistd.c jdatadst.c jdatasrc.c jdcoefct.c jdcolor.c \
jddctmgr.c jdhuff.c jdinput.c jdmainct.c jdmarker.c jdmaster.c \
jdmerge.c jdphuff.c jdpostct.c jdsample.c jdtrans.c jerror.c \
jfdctflt.c jfdctfst.c jfdctint.c jidctflt.c jidctfst.c jidctint.c \
jidctred.c jquant1.c jquant2.c jutils.c jmemmgr.c jmemnobs.c \
jaricom.c jcarith.c jdarith.c \
turbojpeg.c transupp.c jdatadst-tj.c jdatasrc-tj.c \
turbojpeg-mapfile
LOCAL_SRC_FILES:= $(libjpeg_SOURCES_DIST)
LOCAL_SHARED_LIBRARIES := libcutils
LOCAL_STATIC_LIBRARIES := libsimd
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS := -DAVOID_TABLES -O3 -fstrict-aliasing -fprefetch-loop-arrays -DANDROID \
-DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_STATIC_LIBRARY)
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := libmyjpeg
ifeq ($(notdir $(MAKECMDGOALS)),libmyjpeg.a)
LOCAL_SRC_FILES += $(libsimd_SOURCES_DIST)
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := dummy
endif
include $(BUILD_SHARED_LIBRARY)
######################################################
### cjpeg ###
######################################################
include $(CLEAR_VARS)
# From autoconf-generated Makefile
cjpeg_SOURCES = cdjpeg.c cjpeg.c rdbmp.c rdgif.c \
rdppm.c rdswitch.c rdtarga.c
LOCAL_SRC_FILES:= $(cjpeg_SOURCES)
LOCAL_SHARED_LIBRARIES := libmyjpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/android
LOCAL_CFLAGS := -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED \
-DANDROID -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLE)
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := cjpeg
include $(BUILD_EXECUTABLE)
######################################################
### djpeg ###
######################################################
include $(CLEAR_VARS)
# From autoconf-generated Makefile
djpeg_SOURCES = cdjpeg.c djpeg.c rdcolmap.c rdswitch.c \
wrbmp.c wrgif.c wrppm.c wrtarga.c
LOCAL_SRC_FILES:= $(djpeg_SOURCES)
LOCAL_SHARED_LIBRARIES := libmyjpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/android
LOCAL_CFLAGS := -DBMP_SUPPORTED -DGIF_SUPPORTED -DPPM_SUPPORTED -DTARGA_SUPPORTED \
-DANDROID -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLE)
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := djpeg
include $(BUILD_EXECUTABLE)
######################################################
### jpegtran ###
######################################################
include $(CLEAR_VARS)
# From autoconf-generated Makefile
jpegtran_SOURCES = jpegtran.c rdswitch.c cdjpeg.c transupp.c
LOCAL_SRC_FILES:= $(jpegtran_SOURCES)
LOCAL_SHARED_LIBRARIES := libmyjpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH) \
$(LOCAL_PATH)/android
LOCAL_CFLAGS := -DANDROID -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLE)
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := jpegtran
include $(BUILD_EXECUTABLE)
######################################################
### tjunittest ###
######################################################
include $(CLEAR_VARS)
# From autoconf-generated Makefile
tjunittest_SOURCES = tjunittest.c tjutil.c
LOCAL_SRC_FILES:= $(tjunittest_SOURCES)
LOCAL_SHARED_LIBRARIES := libmyjpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS := -DANDROID -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLE)
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := tjunittest
include $(BUILD_EXECUTABLE)
######################################################
### tjbench ###
######################################################
include $(CLEAR_VARS)
# From autoconf-generated Makefile
tjbench_SOURCES = tjbench.c bmp.c tjutil.c rdbmp.c rdppm.c \
wrbmp.c wrppm.c
LOCAL_SRC_FILES:= $(tjbench_SOURCES)
LOCAL_SHARED_LIBRARIES := libmyjpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS := -DBMP_SUPPORTED -DPPM_SUPPORTED \
-DANDROID -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLE)
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := tjbench
include $(BUILD_EXECUTABLE)
######################################################
### rdjpgcom ###
######################################################
include $(CLEAR_VARS)
# From autoconf-generated Makefile
rdjpgcom_SOURCES = rdjpgcom.c
LOCAL_SRC_FILES:= $(rdjpgcom_SOURCES)
LOCAL_SHARED_LIBRARIES := libmyjpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS := -DANDROID -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLE)
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := rdjpgcom
include $(BUILD_EXECUTABLE)
######################################################
### wrjpgcom ###
######################################################
include $(CLEAR_VARS)
# From autoconf-generated Makefile
wrjpgcom_SOURCES = wrjpgcom.c
LOCAL_SRC_FILES:= $(wrjpgcom_SOURCES)
LOCAL_SHARED_LIBRARIES := libmyjpeg
LOCAL_C_INCLUDES := $(LOCAL_PATH)
LOCAL_CFLAGS := -DANDROID -DANDROID_TILE_BASED_DECODE -DENABLE_ANDROID_NULL_CONVERT
LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLE)
LOCAL_MODULE_TAGS := debug
LOCAL_MODULE := wrjpgcom
include $(BUILD_EXECUTABLE)
endif # TARGET_SIMULATOR != true
编译出libmyjpeg.a
接下来加入mjpegtools中jpeg2yuv的功能, 由于只需要这一部分功能,所以单独抽出decode部分就好了,
最后编译出libjpeg2yuv.so, 就可以使用decode_jpeg_raw接口了(见jpegutils.c)
源代码:https://github.com/icefreedom/jpeg2yuv