windows下用ndk r9編譯ffmpeg
網上大部分資料都是用ndk r4在linux下編譯ffmpeg,本文介紹在windows下用r9的ndk編譯ffmpeg2.2.4的歷程。
前面的配置借鑑了網上的資料,但還是詳細闡述下吧(ps:以下涉及到新建檔案的地方都必須是UNIX格式檔案):
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
ffserver.c
libavcodec/fft-test.c
libavcodec/dct-test.c
libavcodec/motion-test.c
libavformat/rtspenc.c
libavformat/utils.c
libavformat/hls.c
libavformat/sapenc.c
libavformat/rtspdec.c
libavformat/network.c
libavformat/rtpdec.c
libavformat/rtsp.c
libavformat/mux.c:37
libavformat/hlsproto.c
libavformat/ftp.c
libavformat/udp.c
libavformat/rtmphttp.c
libavformat/tcp.c
libavformat/avio.c
libavutil/avtime.c
libavutil/des.c 編譯的時候入到找不到libavutil/time.h,改成libavutil/avtime.h即可
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
如果遇到其他編譯問題可以百度查一下,但是建議自己看看錯誤原因進行分析。
我是折騰了一陣子,祝你好運~_~