您的位置:首页 > 移动开发 > Android开发

ffmpeg移植Android方法以及常见问题汇总

2014-08-02 17:49 344 查看
ffmpeg移植Android方法以及常见问题汇总:

1.在ffmpeg官网下载源码包,比如ffmpeg-2.3。在ffmpeg目录下增加Android.mk 和av.mk config.sh三个文件。

2.config.sh用于配置ffmpeg环境脚本,可键入

#!/bin/sh

PREBUILT=...android-ndk-r7b/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86

PLATFORM=...android-ndk-r7b/platforms/android-14/arch-arm

exportTMPDIR=.../ tmp

./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\

--disable-shared\

--disable-asm\

--disable-yasm\

--extra-ldflags="-Wl,-T,$PREBUILT/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib$PREBUILT/lib/gcc/arm-linux-androideabi/4.4.3/crtbegin.o$PREBUILT/lib/gcc/arm-linux-androideabi/4.4.3/crtend.o
-lc -lm -ldl"

PREBUILT、PLATFORM、TMPDIR是需要修改的,配置自己的ndk路径,通常这一步出错概率极高。TMPDIR路径一定要存在且可以访问。

常见错误:

arm-linux-androideabi-gccis unable to create an executable file,一般是tmp文件没有设置。

UnknownC compiler/toolchains/arm-linux-androideabi-4.4.3/prebuilt/windows/bin/ arm-linux-androideabi-gcc,一般是NDK配置错误。

./config.sh:line 8: --arch: command not found,./configure每一个参数后的转行符号\,注意后面不要有空格符,另外也有可能是字符格式错误,要转为unix,在vim里 :set ff=unix保存退出。

--cc、--cross-prefix、--nm、--extra-ldflags注意配置路径要正确,否则脚本执行失败。

./configure是配置ffmpeg选项的,可以按个人需求添加删减,不赘述。

执行该脚本,如果正确,大约数分钟后执行结束,会自动生成config.h和config.mak。如果执行出错,一般是配置问题。

3.av.mk文件键入

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

即可。

4.在需要编译的目录(不同版本ffmpeg有区别),比如在libavcodec、ibavdevice、libavfilter、libavformat、libavutil、libpostproc、libswscale、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)

即可,这几个目录下的Android.mk是一样的。也可以自己配置LOCAL_MODULE和LOCAL_STATIC_LIBRARIES,不过上述脚本配置简单。

然后删除libavcodec、ibavdevice、libavfilter、libavformat、libavutil、libpostproc、libswscale、libswresample目录下的Makefile中的

include$(SUBDIR)../config.mak和include$(SUBDIR)../subdir.mak,后者在2.3版本中并不存在,确保自己的Makefile里没有这2句就可以了。

5.编写Android.mk,放置ffmpeg根目录,即av.mk、config.sh同级目录

这里有2个,一个是用于编译libffmpeg.so的脚本,如下:

LOCAL_PATH:= $(call my-dir)

include$(CLEAR_VARS)

LOCAL_STATIC_LIBRARIES:= libavformat libavcodec libavutil libpostproc libswscale libavfilterlibavdevice

LOCAL_MODULE_TAGS:= optional

LOCAL_MODULE:= libffmpeg

include$(BUILD_SHARED_LIBRARY)

include$(call all-makefiles-under,$(LOCAL_PATH))

也可以写一个生产ffmpeg的执行文件的mk脚本:

LOCAL_PATH:= $(call my-dir)

include$(CLEAR_VARS)

LOCAL_MODULE_TAGS:= optional

LOCAL_PRELINK_MODULE:= false

LOCAL_SRC_FILES:=\

cmdutils.c \

ffmpeg.c \

ffmpeg_opt.c \

ffmpeg_filter.c

LOCAL_SHARED_LIBRARIES:= \

libffmpeg

LOCAL_MODULE:= ffmpeg

#include$(BUILD_SHARED_LIBRARY)

include$(BUILD_EXECUTABLE)

include$(call all-makefiles-under,$(LOCAL_PATH))

其中,LOCAL_SRC_FILES具体文件视版本而定,至少包含cmdutils.c和ffmpeg.c,编译后根据错误依次添加对应的c文件即可。

6.常用的移植修改和编译报错

因为是移植,所以有些文件必须修改才能编译通过,对config.h修改:

老的ffmpeg是将#define restrict restrict改为#define restrict

新版本是#defineav_restrict av_restrict改为#define av_restrict

将ffmpeg/libavutil/libm.h中所有static的函数删除。然后编译,如果

报错/works/workspace/android-console/jni/ffmpeg.c:3636:19:error: storage size of 'rusage' isn't known

/works/workspace/android-console/jni/ffmpeg.c:3638:15:error: 'RUSAGE_SELF' undeclared (first use in this function)

将config.h 中

#define HAVE_GETRUSAGE 1修改为#define HAVE_GETRUSAGE 0

报错/works/workspace/android-console/jni/cmdutils.c:270:19:error: storage size of 'rl' isn't known

/works/workspace/android-console/jni/cmdutils.c:271:19:error: 'RLIMIT_CPU' undeclared (first use in this function)

将config.h 中

#define HAVE_SETRLIMIT 1修改为 #define HAVE_SETRLIMIT0

报错/works/workspace/android-console/jni/cmdutils.c:41:21:fatal error: version.h: No such file ordirectory

在ffmpeg根目录下运行./version.sh . version.h

报错android-ndk-r8d/build/core/build-binary.mk:41:*** target file

`clean' has both : and :: entries. Stop.

把libavfilter目录中的Makefile末尾的clean命令注释掉

报错.../platforms/android-18/arch-arm/usr/include/stdlib.h:54:14:error: expected identifier or '(' before 'void'

.../platforms/android-18/arch-arm/usr/include/stdlib.h:54:14:error: expected ')' before numeric constant

将config.h里面的#define getenv(x) NULL注释掉。注意:这个修改是查询很多方法无效后自己修改的,发现问题是getenv和stblib里面的函数冲突了,grep看了一下没有用到这个宏,基本都是用的stblib的getenv方法,所以把这个宏注释掉。

诸如for(int i;i<x;i++)不支持这种写法的编译器,把参数提出来声明即可。

以上包含我遇到的也是常见的错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: