环境:
OS: ubuntu 12.04.3
android-ndk-r9d
ffmpeg: 2.6.3
第一步:解压ffmpeg
命令:tar jxvf ffmpeg-2.5.3.tar.bz2
第二步:在android-ndk-r9d/sources下新建ffmpeg-2/jni,复制解压后的ffmpeg-2.6.3至此文件夹。(放入sample文件夹下会报:./configure:no such file 错误)
文件目录结构为:~/android-ndk-r9d/sources/ffmpeg-2/jni
第三步:修改替换ffmpeg文件夹中的configure文件,将以下四行
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'
替换为
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
第四步:在ffmpeg目录下创建build_android.sh文件,内容如下:
(6.29号更新如下,原因是后面使用时发现配置不合适导致无法解码,无法播放视频)
NDK_ROOT=/home/liulq/android-ndk-r9d
PREBUILT=${NDK_ROOT}/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64
PLATFORM=${NDK_ROOT}/platforms/android-9/arch-arm
./configure --target-os=linux\
--arch=arm\
--enable-small\
--enable-static\
--disable-asm\
--enable-armv5te\
--enable-cross-compile\
--enable-muxers\
--enable-demuxers\
--enable-avfilter\
--enable-protocols\
--disable-debug\
--disable-doc\
--disable-stripping\
--disable-ffmpeg\
--disable-ffplay\
--disable-ffprobe\
--disable-ffserver\
--disable-encoders\
--disable-hwaccels\
--disable-bsfs\
--disable-avdevice\
--disable-shared\
--disable-postproc\
--cc=$PREBUILT/bin/arm-linux-androideabi-gcc\
--cross-prefix=$PREBUILT/bin/arm-linux-androideabi-\
--nm=$PREBUILT/bin/arm-linux-androideabi-nm\
--extra-cflags="-fPIC -DANDROID"\
--extra-ldflags='-L$PLATFORM/usr/lib -nostdlib'\
echo "#undef restrict" >> config.h
echo "#define restrict" >> config.h
echo "#undef HAVE_LRINT" >> config.h
echo "#define HAVE_LRINT 1" >> config.h
echo "#undef HAVE_LRINTF" >> config.h
echo "#define HAVE_LRINTF 1" >> config.h
echo "#undef HAVE_ROUND" >> config.h
echo "#define HAVE_ROUND 1" >> config.h
echo "#undef HAVE_ROUNDF" >> config.h
echo "#define HAVE_ROUNDF 1" >> config.h
echo "#undef HAVE_TRUNCF" >> config.h
echo "#define HAVE_TRUNCF 1" >> config.h
编辑好后依次执行命令:
chmod u+x build_android.sh
vi build_android.sh 删除每个“/”之前的空格
:setff=unix 修改文件格式
:wq 保存退出
./config_android.sh 执行sh文件
执行sh文件后生成了config.h文件,里面定义了很多解码类型。
第五步:编辑刚刚生成的config.h,找到这句
#define restrict restrict
Android的GCC不支持restrict关键字,于是修改成下面这样
#define restrict
并将
#define HAVE_GMTIME_R 0
改为
#define HAVE_GMTIME_R 1
将
#define HAVE_LOCALTIME_R 0
改为
#define HAVE_LOCALTIME_R 1
第六步:编辑libavutil/libm.h,把其中的static方法都删除。
可以用
#if 0
…
#endif 注释掉
第七步:分别修改libavcodec、libavfilter、libavformat、libavutil、libpostproc和libswscale,libswresample下的Makefile,把每个Makefile中的下面两句删除或注释掉
include $(SUBDIR)../config.mak
第八步:在ffmpeg下添加一个文件av.mk
# LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale
#include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
include $(LOCAL_PATH)/../config.mak
OBJS :=
OBJS-yes :=
MMX-OBJS-yes :=
include $(LOCAL_PATH)/Makefile
# 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
ffmpeg-2目录下
include $(all-subdir-makefiles)
jni目录下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_WHOLE_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale libswresample
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
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)
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)
libavutil下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES :=
LOCAL_C_INCLUDES += $(SYSROOT_INC)/usr/include
LOCAL_C_INCLUDES += \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
libavfilter、libpostproc和libswscale,libswresample下
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)
注:这些mk文件都要修改为unix文件格式
第十步:运行:~/android-ndk-r9d/ndk-build
运行后会在ffmpeg目录下生成libs和obj目录
在libs/armeabi目录下有libffmpeg.so,大小约为5000多kb
错误处理:
报错:
/home/liulq/android-ndk-r9d/build/core/build-binary.mk:120:*** target file `clean' has both : and :: entries. Stop.
解决:
修改libavfilter目录中的Makefile,它的末尾处多了 Clean 这个玩意儿 将其注释掉或者删掉就可以了
报错:
error: static declaration of 'localtime_r'follows non-static declaration
解决:找到这个文件,并不是未声明的错误,应该是configure的时候有错,所以修改config.h文件,如第五步所述。
在移植编译的过程中,遇到很多类似说未声明,少括号,没定义的错误,基本都不是真的,都是因为configure有错,一直改一直改一直试一直试就好了
报错:
生成的libffmpeg.so很小,只有5kb,肯定是不对的
解决:修改jni目录下的Android.mk,
LOCAL_STATIC_LIBRARIES 改为LOCAL_WHOLE_STATIC_LIBRARIES
最后可以测试一下生成的库是否可用,可以借鉴这篇博文
http://blog.sina.com.cn/s/blog_a000da9d01011lg8.html
整个流程参考了这篇博文,有一些改动,应该是由于平台和版本不同,谢谢博主!
http://www.cnblogs.com/uvsjoh/archive/2013/01/17/2864630.html
第一篇博文,也许也是唯一一篇,记录下,实在被这个东西折磨的够了!今天终于编出来了!吃好吃的去!