网上大部分资料都是用ndk r4在linux下编译ffmpeg,本文介绍在windows下用r9的ndk编译ffmpeg2.2.4的历程。
最终目标:libffmpeg.so
前面的配置借鉴了网上的资料,但还是详细阐述下吧(ps:以下涉及到新建文件的地方都必须是UNIX格式文件):
1.下载源码解压ffmpeg release v2.2.4
2.用eclipse新建一个android工程,新建jni目录把源码目录ffmpeg2.2.4拷贝到此目录下
3.安装cygwin(之前就有安装的的,所以不知道依赖哪些包,用的时候缺哪里就下载什么吧)
4.下载并解压ndk,adt也可以,新建系统环境变量ANDROID_NDK_HOME,设置好自己的ndk目录
5.在工程目录下新建编译脚本build_ffmpeg.h(UNIX格式),内容如下:
APPNAME="FFmpegRecorder"
# options
echo "Build C/C++ code for $APPNAME using Android NDK"
# paths
NDK_ROOT="${ANDROID_NDK_HOME}"
if [ -z "${NDK_ROOT+aaa}" ];then
echo "please define NDK_ROOT"
exit 1
fi
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# ... use paths from sytem path
APP_ROOT="$DIR/.."
APP_ANDROID_ROOT="$DIR"
echo "NDK_ROOT = $NDK_ROOT"
echo "APP_ROOT = $APP_ROOT"
echo "APP_ANDROID_ROOT = $APP_ANDROID_ROOT"
"$NDK_ROOT"/ndk-build -C "$APP_ANDROID_ROOT" $* "NDK_MODULE_PATH="
6.在jni目录下新建Android.mk文件,内容如下:
include $(all-subdir-makefiles)
#LOCAL_PATH := $(call my-dir)
7.在ffmpeg2.2.4目录下新建配置脚本config.sh,内容如下:
#!/bin/bash
#
# paths
export NDK_ROOT="${ANDROID_NDK_HOME}"
PREBUILT=$NDK_ROOT/toolchains/arm-linux-androideabi-4.6/prebuilt/windows-x86_64
PLATFORM=$NDK_ROOT/platforms/android-19/arch-arm
ARMELF_PATH=$PREBUILT/arm-linux-androideabi/lib/ldscripts/armelf_linux_eabi.x
CRT_DIR=$PREBUILT/lib/gcc/arm-linux-androideabi/4.6
echo "PREBUILT = $PREBUILT"
echo "PLATFORM = $PLATFORM"
echo "ARMELF_PATH = $ARMELF_PATH"
echo "CRT_DIR = $CRT_DIR"
./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-avdevice \
--enable-cross-compile \
--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" \
--disable-asm \
--enable-neon \
--enable-armv5te \
--extra-cflags="-I ${PLATFORM}/usr/include -fPIC -DANDROID -std=c99" \
--extra-ldflags="-Wl,-T,$ARMELF_PATH -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $CRT_DIR/crtbegin.o $CRT_DIR/crtend.o -lc -lm -ldl"
8.添加各个模块文件
ffmpeg2.2.4目录下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))
ffmpeg2.2.4目录下Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_WHOLE_STATIC_LIBRARIES := \
libavutil \
libavcodec \
libavfilter \
libavformat \
libpostproc \
libswscale \
libswresample
LOCAL_LDLIBS := -lz
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
ffmpeg2.2.4\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)
ffmpeg-0.6.6\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)
ffmpeg2.2.4/libavfilter、libavutil、libpostproc、
libswresample
和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)
9.源代码修改:
将libavutil/time.h改名libavutil/avtime.h
libavutil/time.c改名libavutil/avtime.c
10.启动cygwin切换到ffmpeg2.2.4目录下,执行:sh config.sh,执行的比较慢,等待完成吧,
如果有错,一般是config.sh里面的路径配置错了,或者自己看看config.log解决问题
11.上一步执行成功,则会生成config.h,对此文件的部分内容做如下修改:
在#define av_restrict restrict这一行之前添加
#define restrict
修改如下定义为下面的值:
#define HAVE_CBRT 1
#define HAVE_ISINF 1
#define HAVE_ISNAN 1
#define HAVE_LOG2F 0
#define HAVE_LRINT 1
#define HAVE_LRINTF 1
#define HAVE_RINT 1
#define HAVE_ROUND 1
#define HAVE_TRUNC 1
12.cygnwin切换到工程目录下执行:sh build_ffmpeg.sh
如果成功,最后会输出以下语句:
[armeabi] SharedLibrary : libffmpeg.so
[armeabi] Install : libffmpeg.so => libs/armeabi/libffmpeg.so
libffmpeg.so即为最终结果动态库,大概5.3M大小:libffmpeg.so
如果遇到其他编译问题可以百度查一下,但是建议自己看看错误原因进行分析。
我是折腾了一阵子,祝你好运~_~