深入了解android平台的jni---编译ffmpeg源码
操作系统:Ubuntu10.04
ffmpeg源码版本:ffmpeg-0.6.1
androidndk版本:android-ndk-r5b-linux-x86
目的:
用来了解ffmpeg源码的编译场景和编译过程
准备工作:
将android-ndk-r5b解压后放在/home/mfcai目录下
在/home/mfcai/android-ndk-r5b/samples/目录下创建一个FFMPEG文件夹,在FFMPEG目录下再新建一个jni文件夹,然后把ffmpeg-0.6源码放在jni里面,所以最后ffmpeg源码的路径是:
/home/mfcai/android-ndk-r5b/samples/FFMPEG/jni/ffmpeg-0.6
一、设置NDK环境变量
配置NDK环境,增加/home/ndk目录到PATH环境变量:
$sudogedit~/.bashrc
文件底部添加以下两行:
NDK_ROOT=/home/mfcai/android-ndk-r5b
exportNDK_ROOT
二、配置编译参数
在ffmpeg-0.6源文件夹下创建一个config.sh
config.sh是一个脚本,执行这个脚本的时候又调用了另外一个脚本configure,
configure主要是根据编译选项,生成相应的编译配置,即自己定制编译选项的内容。
1)新建一个config.sh
#!/bin/bash
PREBUILT=${NDK_ROOT}/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86
PLATFORM=${NDK_ROOT}/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"
2)执行config.sh脚本文件
$chmod+xconfig.sh
$./config.sh
如果配置正确的话显示出来的最后两行是这样的:
License:nonfreeandunredistributable
Creatingconfig.makandconfig.h...
3)编辑config.h文件
编辑/root/ffmpeg/jni/ffmpeg-0.6.1目录中的config.h文件,
将#definerestrictrestrict修改为#definerestrict
将
#defineHAVE_LLRINT0
#defineHAVE_LLRINTF0
#defineHAVE_LRINT0
#defineHAVE_LRINTF0
#defineHAVE_ROUND0
#defineHAVE_ROUNDF0
#defineHAVE_TRUNCF0
修改为:
#defineHAVE_LLRINT1
#defineHAVE_LLRINTF1
#defineHAVE_LRINT1
#defineHAVE_LRINTF1
#defineHAVE_ROUND1
#defineHAVE_ROUNDF1
#defineHAVE_TRUNCF1
三、准备编译ffmpeg1、编辑ffmpegffmpeg-0.6.1下各个模块的Makefile文件
分别把libavutil、libavcodec、libavformat、libavfilter、libpostproct和libswscale下的Makefile文件中下面两行删除掉:
include$(SUBDIR)../subdir.mak
include$(SUBDIR)../config.mak
2、在ffmpegffmpeg-0.6.1根目录下新建一个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))
3、新建Android.mk文件
在jni目录建立Android.mk文件.
在ffmpegffmpeg-0.6.1下新建Android.mk文件
在libavformat,libavcodec,libavfilter、libavutil、libpostproc和libswscale目录建立同样的文件
1)在jni文件夹新建Android.mk文件
include$(all-subdir-makefiles)
2)在ffmpeg下新建Android.mk文件
LOCAL_PATH:=$(callmy-dir)
include$(CLEAR_VARS)
LOCAL_WHOLE_STATIC_LIBRARIES:=libavformatlibavcodeclibavutillibpostproclibswscalelibavfilter
LOCAL_MODULE:=ffmpeg
include$(BUILD_SHARED_LIBRARY)
include$(callall-makefiles-under,$(LOCAL_PATH))
3)在ffmpeg/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_SHARED_LIBRARIES:=libavutillibavcodec
LOCAL_MODULE:=$(FFNAME)
include$(BUILD_SHARED_LIBRARY)
4)在ffmpeg/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_SHARED_LIBRARIES:=libavutil
LOCAL_MODULE:=$(FFNAME)
include$(BUILD_SHARED_LIBRARY)
5)在ffmpeg/libavfilter下新建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_SHARED_LIBRARIES:=libavutillibswscalelibavcodec
LOCAL_MODULE:=$(FFNAME)
include$(BUILD_SHARED_LIBRARY)
6)在ffmpeg/libavutil下新建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_MODULE:=$(FFNAME)
include$(BUILD_SHARED_LIBRARY)
7)在ffmpeg/libpostproc下新建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_SHARED_LIBRARIES:=libavutil
LOCAL_MODULE:=$(FFNAME)
include$(BUILD_SHARED_LIBRARY)
8)在ffmpeg/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_SHARED_LIBRARIES:=libavutil
LOCAL_MODULE:=$(FFNAME)
include$(BUILD_SHARED_LIBRARY)
四、编译
在jni目录下运行ndk-build
如果编译成功,产生出libavcodec.so、libavfilter.so、libavformat.so、libavutil.so、libffmpeg.so,libpostproc.so和libswscale.so。
五、问题
1、同样的配置,在cygwin下编译了两天通不过。所以建议还是在linux环境下编译
2、libffmpeg.so大小只有1k。
网上的做法修改ffmpeg下的android.mk
发现出来的libffmpeg.so只有十几KB,按照网上搜索的资料,
方法一:修改ffmpeg下的android.mk:
LOCAL_STATIC_LIBRARIES:=libavcodeclibavformatlibavutillibavfilterlibpostproclibswscale
改后为:
LOCAL_WHOLE_STATIC_LIBRARIES:=libavcodeclibavformatlibavutillibavfilterlibpostproclibswscale
方法二:指定使用arm-eabi-4.4.0来编译:
由于android-ndk-r5默认是使用arm-linux-androideabi-4.4.3编译,而不是arm-eabi-4.4.0。
但android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3目录中的setup.mk文件里定义的cmd-build-shared-library函数
并没有将静态库文件链接在一起生成动态库文件。所以解决的办法就是在执行ndk-build时加上NDK_TOOLCHAIN参数,指定使用arm-eabi-4.4.0来编译。
完整命令如下
ndk-buildNDK_TOOLCHAIN=arm-eabi-4.4.0NDK_PLATFORM=android-8
同样不行。
希望高手能给指条道了
需要编译通过的ffmpeg-0.61文件的,文件太大上传不了,请到
http://download.csdn.net/detail/mfcai_blog/5968953,下载
本文欢迎转载,转载请注明出处与作者
出处:http://blog.sina.com.cn/staratsky
作者:流星
更多相关文章
- 在Eclipse中用javadoc给android工程库文件生成API说明文档
- android实现上传本地图片到网络功能
- 【Android(安卓)开发教程】保存到外部存储设备(SD卡)
- 用kotlin写了一些android常用的一些工具类
- Ubuntu 12.04 64位编译cm-10.2 总结
- AIDL接口描述语言的使用
- Ubuntu10.10下编译Android2.2内核
- Android(安卓)Studio 3.0+添加ButterKnife依赖报错的解决办法
- ionic app 目录结构说明