用Android NDK编译FFmpeg
Android内置的编解码器实在太少,于是我们需要FFmpeg。Android提供了NDK,为我们使用FFmpeg这种C语言代码提供了方便。
不过为了用NDK编译FFmpeg,还真的花费了不少时间,也得到了很多人的帮助,最应该谢谢havlenapetr。我觉得我现在这些方法算是比较简洁的了--
下面就尽量詳細的说一下我是怎么在项目中使用FFmpeg的,但是基于我混乱的表达能力,有不明白的就问我。
你得了解JNI和AndroidNDK的基本用法,若觉得我的文章还不错,可以看之前写的JNI简单入门和AndroidNDK入门
首先创建一个标准的Android项目vPlayer
androidcreateproject-nvPlayer-t8-pvPlayer-kme.abitno.vplayer-aPlayerView
然后在vPlayer目录里
mkdirjni&&cdjni
wgethttp://ffmpeg.org/releases/ffmpeg-0.6.tar.bz2
tarxfffmpeg-0.6.tar.bz2&&mvffmpeg-0.6ffmpeg&&cdffmpeg
在ffmpeg下新建一个config.sh,内容如下,注意把PREBUILT和PLATFORM设置正确。另外里面有些参数你也可以自行调整,我主要是为了配置一个播放器而这样设置的。
#!/bin/bash
PREBUILT=/home/abitno/Android/android-ndk-r4/build/prebuilt/linux-x86/arm-eabi-4.4.0
PLATFORM=/home/abitno/Android/android-ndk-r4/build/platforms/android-8/arch-arm
./configure--target-os=linux\
--arch=arm\
--enable-version3\
--enable-gpl\
--enable-nonfree\
--disable-stripping\
--disable-ffmpeg\
--disable-ffplay\
--disable-ffserver\
--disable-ffprobe\
--disable-encoders\
--disable-muxers\
--disable-devices\
--disable-protocols\
--enable-protocol=file\
--enable-avfilter\
--disable-network\
--disable-mpegaudio-hp\
--disable-avdevice\
--enable-cross-compile\
--cc=$PREBUILT/bin/arm-eabi-gcc\
--cross-prefix=$PREBUILT/bin/arm-eabi-\
--nm=$PREBUILT/bin/arm-eabi-nm\
--extra-cflags="-fPIC-DANDROID"\
--disable-asm\
--enable-neon\
--enable-armv5te\
--extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x-Wl,-rpath-link=$PLATFORM/usr/lib-L$PLATFORM/usr/lib-nostdlib$PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o$PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o-lc-lm-ldl"
运行config.sh开始configure
chmod+xconfig.sh
./config.sh
configure完成后,编辑刚刚生成的config.h,找到这句
#definerestrictrestrict
Android的GCC不支持restrict关键字,于是修改成下面这样
#definerestrict
编辑libavutil/libm.h,把其中的static方法都删除。
分别修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale下的Makefile,把下面两句删除
include$(SUBDIR)../subdir.mak
include$(SUBDIR)../config.mak
在ffmpeg下添加一个文件av.mk,内容如下
#LOCAL_PATHisoneoflibavutil,libavcodec,libavformat,orlibswscale
#include$(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
include$(LOCAL_PATH)/../config.mak
OBJS:=
OBJS-yes:=
MMX-OBJS-yes:=
include$(LOCAL_PATH)/Makefile
#collectobjects
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,在jni根目录下的内容如下
include$(all-subdir-makefiles)
在ffmpeg目录下,Android.mk
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES:=libavformatlibavcodeclibavutillibpostproclibswscale
LOCAL_MODULE:=ffmpeg
include$(BUILD_SHARED_LIBRARY)
include$(callall-makefiles-under,$(LOCAL_PATH))
libavformat/Android.mk
LOCAL_PATH:=$(callmy-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)
libavcodec/Android.mk
LOCAL_PATH:=$(callmy-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下的Android.mk内容如下
LOCAL_PATH:=$(callmy-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)
最外层的jni/Android.mk和jni/ffmpeg/Android.mk我只是随便这样写的,你应该根据自己的需求改写。
最后运行ndk-build,经过漫长的等待就编译完成了。至于具体怎么应用可能以后会写,我变得太懒了。。。
我已经尽最大努力写明白了,希望大家努力啊,一个全功能的解码器或者只是播放器还是很有必要的。