1. 程式人生 > >windows下用ndk r9編譯ffmpeg

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 

將以下檔案中的"libavutil/time.h"作相應修改  ffmpeg.c  ffplay.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

如果遇到其他編譯問題可以百度查一下,但是建議自己看看錯誤原因進行分析。

我是折騰了一陣子,祝你好運~_~