用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,经过漫长的等待就编译完成了。至于具体怎么应用可能以后会写,我变得太懒了。。。

我已经尽最大努力写明白了,希望大家努力啊,一个全功能的解码器或者只是播放器还是很有必要的。

相关推荐