这段时间在学习android的多媒体处理,个人理解,如果有误,望指教。
android下的多媒体处理框架,应该是基于硬件设备的快速处理,关于软件处理图像视频的内容,貌似要使用第三方的支持,根据javacv的理解,大部分使用的是ffmpeg和opencv,本文只涉及ffmpeg,看网上ffmpeg在android的使用的资料很多,一种是关于linux下直接裁剪ffmpeg,然后再使用ndk编译的,生成so的文件,该文件可以直接移植到android使用。一种是直接使用ndk编译ffmpeg,在jni目录生成多个.a文件和一个工程相关的so文件。本文讲解如何在window下使用ndk编译ffmpeg,后续文章将讲解如何使用。
先列出pc机上需要配置的环境变量
CLASSPATH
.;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar;%JAVA_HOME%\bin;
JAVA_HOME
C:\Program Files\Java\jdk1.7.0_25
NDK
/cygdrive/d/android-ndk-r8e
PATH
D:\android-ndk-r8e;%JAVA_HOME%\bin;D:\adt-bundle-windows-x86-20130522\sdk\platforms;D:\adt-bundle-windows-x86-20130522\sdk\platform-tools;
workspace
/cygdrive/d/android/workspace
以下内容网上大同小异,根据自己的不同去配置。新建一个android工程,建立jni目录,把下载的ffmpeg源码(在cygwin中使用tar -xf 解压),文件的编译使用UE修改直接上configure的bash.sh文件:
#!/bin/bash
export TMPDIR="e:/temp"
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows
PLATFORM=$NDK/platforms/android-8/arch-arm
./configure --target-os=linux --prefix=./android/armv7-a --enable-cross-compile --extra-libs=" -lgcc " --arch=arm --cc=$PREBUILT/bin/arm-linux-androideabi-gcc --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- --nm=$PREBUILT/bin/arm-linux-androideabi-nm --sysroot=$PLATFORM --extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 -Dipv6mr_interface=ipv6mr_ifindex -fasm -Wno-psabi -fno-short-enums -fno-strict-aliasing -finline-limit=300 -mfloat-abi=softfp -mfpu=neon -marm -march=armv7-a " --disable-shared --enable-static --extra-ldflags=" -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib " --disable-everything --enable-muxer=mp4 --disable-ffplay --enable-avformat --enable-avcodec --enable-encoder=mpeg4 --disable-network --enable-zlib --disable-avfilter --disable-avdevice
进入cygwin,给予bash执行权限,使用./bash.sh 执行configure,得到如下信息
install prefix ./android/armv7-a
source path .
C compiler /cygdrive/d/android-ndk-r8e/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/arm-linux-androideabi-gcc
ARCH arm (armv7-a)
big-endian no
runtime cpu detection yes
ARMv5TE enabled yes
ARMv6 enabled yes
ARMv6T2 enabled yes
VFP enabled yes
NEON enabled yes
THUMB enabled no
debug symbols yes
strip symbols yes
optimize for size no
optimizations yes
static yes
shared no
postprocessing support no
new filter support no
network support no
threading support no
safe bitstream reader yes
SDL support no
texi2html enabled no
perl enabled yes
pod2man enabled yes
makeinfo enabled yes
External libraries:
Enabled decoders:
Enabled encoders:
h263 mpeg4
Enabled hwaccels:
Enabled parsers:
Enabled demuxers:
Enabled muxers:
mov mp4
Enabled protocols:
Enabled filters:
Enabled bsfs:
Enabled indevs:
Enabled outdevs:
License: LGPL version 2.1 or later
Creating config.mak and config.h...
libavutil/avconfig.h is unchanged
WARNING: /cygdrive/d/android-ndk-r8e/toolchains/arm-linux-androideabi-4.4.3/preb uilt/windows/bin/arm-linux-androideabi-pkg-config not found, library detection m ay fail.
WARNING: Compiler does not indicate floating-point ABI, guessing vfp.
目前没有明白,我只是使用mpeg4的编码,怎么会有个h263的?
修改config.h文件 ,我的编译后在gcc4.4.3后面多了一个问号,删除就可以了
#define CC_IDENT "gcc 4.4.3(GCC)"
#define av_restrict //restrict
我使用的是ffmpeg1.2.1 在后面编译执行到Compile thumb : avutil <= parseutils.c报struct tm 引起的错误,我是在修改了该目录下的makefile文件删除了parseutils相关的编译内容。ndk-build过程中遇到的错误,可以直接到指定文件修改。
在jni目录下建立Android.mk 和 Application.mk文件,内容分别如下
Android.mk
include $(all-subdir-makefiles)
Application.mk
# The ARMv7 is significanly faster due to the use of the hardware FPU
APP_ABI := armeabi-v7a
#APP_ABI := armeabi
APP_PLATFORM := android-8
在ffmpeg的目录下新建av.mk 和 Android.mk 文件
av.mk
# collect objects
OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)
OBJS += $(OBJS-yes)
FFNAME := lib$(NAME)
FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))
FFCFLAGS = -DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch -Wno-pointer-sign
FFCFLAGS += -DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\"
ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)/*.S)
ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))
ifneq ($(ALL_S_FILES),)
ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))
C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))
S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))
else
C_OBJS := $(OBJS)
S_OBJS :=
endif
C_FILES := $(patsubst %.o,%.c,$(C_OBJS))
S_FILES := $(patsubst %.o,%.S,$(S_OBJS))
FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
以下几个Android.mk文件分别位于各自lib的目录
libavcodec:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
libavfilter、libavutil 、 libpostproc 、 libswscale:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
libavformat:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
修改各自lib**目录下的makefile文件 注释掉 #include $(SUBDIR)../config.mak
修改libavutil目录下libm.h文件,注释掉所有的static 函数
然后执行ndk-build,
SharedLibrary : libffmpeg.so
Install : libffmpeg.so => libs/armeabi-v7a/libffmpeg.so
完成之后在android的项目工程obj\local\armeabi-v7a下生成多个.a文件,估计现在可以使用ndk编写jni的应用了,但是libs/armeabi-v7a/libffmpeg.so文件只有5k大小,在android打包的apk中,应该会包含.a文件,直觉告诉我,需要在ffmpeg的configure之后,使用 make && make install 生成裁剪后的ffmpeg,然后再在jni环境下写应用。