ffmpeg 移植到Android(1)

   今天主要介绍利用NDK 在应用程序中编译ffmpeg,生成一个动态库libffmpeg。
1.软硬件环境
操作系统:ubuntu 12.04 64bit
开发环境:
Eclipse:Eclipse Indigo Service Release 2
CDT:CDT 8.0.2
ADT:ADT 21.1.0
NDK:android-ndk-r8e-linux-x86_64
2.下载ffmpeg-0.11.3
ffmpeg.org
3.在Eclipse新建项目
<1>在Eclipse 中新建 应用程序 FFmpegPlayer,Android版本确定在Android4.0.对该项目添加 Native Support(右键单击FFmpegPlayer->Android Tools->Add Native Support),会自动生成jni文件夹。如果所使用的ADT没有集成NDK的设置。可以在项目的根目录中手动添加 名为jni的文件夹。
<2> 将ffmpeg-0.11.3,拷贝到jni目录下,重命名为libffmpeg.在jni下新建Android.mk文件,文件内容很简单就是 include $(all-subdir-makefiles)
<3>在libffmpeg 中新建 configure.sh 文件,文件内容如下
  #!/bin/bash
PREBUILT=/develop/program/sdk/androidndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64
PLATFORM=/develop/program/sdk/androidndk/platforms/android-14/arch-arm
./configure --target-os=linux \
--arch=arm \
--enable-cross-compile \
--cc=$PREBUILT/bin/arm-linux-androideabi-gcc-4.4.3 \
--cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
--nm=$PREBUILT/bin/arm-linux-androideabi-nm \
--extra-cflags="-fPIC -DANDROID" \
--enable-static \
--enable-shared \
--disable-asm \
--disable-yasm \
--extra-libs=-lgcc \
--extra-ldflags="-Wl,-T,/develop/program/sdk/androidndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x -Wl,-rpath-link=/develop/program/sdk/androidndk/platforms/android-14/arch-arm/usr/lib -L/develop/program/sdk/androidndk/platforms/android-14/arch-arm/usr/lib -nostdlib /develop/program/sdk/androidndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.4.3/crtbegin.o /develop/program/sdk/androidndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.4.3/crtend.o -lc -lm -ldl"
<4> 因为在 ndkr8e 这个版本中,platform 最大只到了android-14,所以我们的应用的Android 版本我也确定在了 Android4.0,对于toolchanis ,我选择的是4.4.3,ndkr8e默认的是4.6,但是用4.6编译的时候总是有问题,所以暂时选择4.4.3。
<5> 确保configure.sh 中不要包含多余的空格,多余的空格会导致 执行configure.sh 时报错。
<6>在libffmpeg 中 chmod +x configure.sh chmod +x version.sh chmod +x configure 
<7>执行 ./configure.sh.
<8>修改 生成的config.h 文件
#define restrict restrict  改成 #define restrict
#define HAVE_LRINT 0 改成 define HAVE_LRINT 1
#define HAVE_LRINTF 0 改成 define HAVE_LRINTF 1
#define HAVE_ROUND 0  改成 #define HAVE_ROUND 1  
#define HAVE_ROUNDF 0 改成 #define HAVE_ROUNDF 1
#define HAVE_TRUNC 0 改成 #define HAVE_TRUNC 1 
#define HAVE_TRUNCF 0 改成#define HAVE_TRUNCF 1
<9>修改 libffmpeg/libavutil/libm.h
将里面的static 函数全部修改成非static 函数。
<10>在libffmpeg 中添加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
ifdef ADDITION_INC
include $(ADDITION_INC)
endif


# 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))


<11>更改Makefile文件
在libffmpeg,liblibavcodec,libavdevice ,libavfilter,libavformat,libavresample,libavutil,libpostproc,libswresample,libswscale的Makefile 删除如下这行。
include $(SUBDIR)../config.mak
<12> 添加Android.mk 文件
libffmpeg/Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_WHOLE_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale libavresample libswresample libavdevice libavfilter
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))


libffmpeg/libavformat/Android.mk
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)




libffmpeg/libavcodec/Android.mk
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)


libffmpeg/libavutil/Android.mk
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)


libffmpeg/libpostproc/Android.mk
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)


libffmpeg/libswscale/Android.mk
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)


libffmpeg/libavresample/Android.mk
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)




libffmpeg/libswresample/Android.mk
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)




libffmpeg/libavdevice/Android.mk
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)


libffmpeg/libavfilter/Android.mk
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)




这些 Android.mk 的内容基本一样,只是要注意各个库的依赖关系。
<10>在 libffmpeg 下执行如下命令
cat libavcodec/avcodec.h | libavcodec/codec_names.sh config.h libavcodec/codec_names.h
<11> 进入 项目的根目录 执行 
NDK_TOOLCHAIN=arm-linux-androideabi-4.4.3 ndk-build
因为 configures.sh 力使用的4.4.3,所以我选择4.4.3,ndkr8e 默认是4.6,在Eclipse 中执行Build 的时候,默认会使用4.6
<12> 执行完成后,会输出
StaticLibrary  : libavutil.a
STATICLibrary  : libffmpeg.so
Install        : libffmpeg.so => libs/armeabi/libffmpeg.so
4.编译中可能出现的问题
1.执行configure.sh
/develop/program/sdk/androidndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc-4.4.3 is unable to create an executable file.
C compiler test failed.
添加  --extra-libs=-lgcc \
2.执行configure.sh
Unknown option "".
See ./configure --help for available options.
./configure.sh: line 16: --extra-ldflags=-Wl,-T,/develop/program/sdk/androidndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x -Wl,-rpath-link=/develop/program/sdk/androidndk/platforms/android-14/arch-arm/usr/lib -L/develop/program/sdk/androidndk/platforms/android-14/arch-arm/usr/lib -nostdlib /develop/program/sdk/androidndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.4.3/crtbegin.o /develop/program/sdk/androidndk/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.4.3/crtend.o -lc -lm -ldl: No such file or directory
检查一下 configure.sh 中是否存在不必要的空格。
3.提示: multiple definition of `ff_inverse'
解决方案:
  修改 libavcodec 中的Makefile文件,将如下这行删除
   OBJS-$(!CONFIG_SMALL)                  += inverse.o










    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值