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

更新时间:2024-03-19 02:18:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

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 export TMPDIR=.../ 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=\--enable-static \\ --disable-shared \\ --disable-asm \\ --disable-yasm \\

--extra-ldflags=\nux_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-gcc is unable to create an executable file,一般是tmp文件没有设置。

Unknown C 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=\\\

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 libavfilter libavdevice 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 新版本是#define av_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_SETRLIMIT 0

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

在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

以上包含我遇到的也是常见的错误。

本文来源:https://www.bwwdw.com/article/tvv8.html

Top