操作系統:Ubuntu 10.04
ffmpeg源碼版本:ffmpeg-0.6.1
android ndk版本:android-ndk-r5b-linux-x86
目的:
用來了解ffmpeg源碼的編譯場景和編譯過程
準備工作:
將android-ndk-r5b解壓後放在/home/mfcai目錄下
在/home/mfcai/android-ndk-r5b/samples/目錄下創建一個FFMPEG文件夾,在FFMPEG目錄下再新建一個jni文件夾,然後把ffmpeg-0.6源碼放在jni裏面,所以最後ffmpeg源碼的路徑是:
/home/mfcai/android-ndk-r5b/samples/FFMPEG/jni/ffmpeg-0.6
一、設置NDK環境變量
配置NDK環境,增加/home/ndk目錄到PATH環境變量:
$sudo gedit ~/.bashrc
文件底部添加以下兩行:
NDK_ROOT=/home/mfcai/android-ndk-r5b
export NDK_ROOT
二、配置編譯參數
在ffmpeg-0.6源文件夾下創建一個config.sh
config.sh是一個腳本,執行這個腳本的時候又調用了另外一個腳本configure,
configure主要是根據編譯選項,生成相應的編譯配置,即自己定製編譯選項的內容。
1)新建一個config.sh
#!/bin/bash
PREBUILT=${NDK_ROOT}/toolchains/arm-eabi-4.4.0/prebuilt/linux-x86
PLATFORM=${NDK_ROOT}/platforms/android-8/arch-arm
./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-mpegaudio-hp \
--disable-avdevice \
--enable-cross-compile \
--cc=$PREBUILT/bin/arm-eabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-eabi- \
--nm=$PREBUILT/bin/arm-eabi-nm \
--extra-cflags="-fPIC -DANDROID" \
--disable-asm \
--enable-neon \
--enable-armv5te \
--extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
2)執行config.sh腳本文件
$ chmod +x config.sh
$ ./config.sh
如果配置正確的話顯示出來的最後兩行是這樣的:
License: nonfree and unredistributable
Creating config.mak and config.h...
3)編輯config.h文件
編輯 /root/ffmpeg/jni/ffmpeg-0.6.1 目錄中的 config.h 文件,
將#define restrict restrict修改爲#define restrict
將
#define HAVE_LLRINT 0
#define HAVE_LLRINTF 0
#define HAVE_LRINT 0
#define HAVE_LRINTF 0
#define HAVE_ROUND 0
#define HAVE_ROUNDF 0
#define HAVE_TRUNCF 0
修改爲:
#define HAVE_LLRINT 1
#define HAVE_LLRINTF 1
#define HAVE_LRINT 1
#define HAVE_LRINTF 1
#define HAVE_ROUND 1
#define HAVE_ROUNDF 1
#define HAVE_TRUNCF 1
三、準備編譯ffmpeg1、編輯ffmpegffmpeg-0.6.1下各個模塊的Makefile文件
分別把libavutil、libavcodec、libavformat、libavfilter、libpostproct和libswscale下的Makefile文件中下面兩行刪除掉:
include $(SUBDIR)../subdir.mak
include $(SUBDIR)../config.mak
2、在ffmpegffmpeg-0.6.1根目錄下新建一個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))
3、新建Android.mk文件
在jni目錄建立Android.mk文件.
在ffmpegffmpeg-0.6.1下新建Android.mk文件
在libavformat,libavcodec,libavfilter、libavutil、libpostproc和libswscale目錄建立同樣的文件
1)在jni文件夾新建Android.mk文件
include $(all-subdir-makefiles)
2)在ffmpeg下新建Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_WHOLE_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale libavfilter
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
3)在ffmpeg/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_SHARED_LIBRARIES := libavutil libavcodec
LOCAL_MODULE := $(FFNAME)
include $(BUILD_SHARED_LIBRARY)
4)在ffmpeg/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_SHARED_LIBRARIES := libavutil
LOCAL_MODULE := $(FFNAME)
include $(BUILD_SHARED_LIBRARY)
5)在ffmpeg/libavfilter下新建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_SHARED_LIBRARIES := libavutil libswscale libavcodec
LOCAL_MODULE := $(FFNAME)
include $(BUILD_SHARED_LIBRARY)
6)在ffmpeg/libavutil下新建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_MODULE := $(FFNAME)
include $(BUILD_SHARED_LIBRARY)
7)在ffmpeg/libpostproc下新建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_SHARED_LIBRARIES :=libavutil
LOCAL_MODULE := $(FFNAME)
include $(BUILD_SHARED_LIBRARY)
8)在ffmpeg/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_SHARED_LIBRARIES := libavutil
LOCAL_MODULE := $(FFNAME)
include $(BUILD_SHARED_LIBRARY)
四、編譯
在jni目錄下運行ndk-build
如果編譯成功,產生出libavcodec.so、libavfilter.so、libavformat.so、libavutil.so、 libffmpeg.so,libpostproc.so和libswscale.so。
五、問題
1、同樣的配置,在cygwin下編譯了兩天通不過。所以建議還是在linux環境下編譯
2、libffmpeg.so大小隻有1k。
網上的做法修改ffmpeg下的android.mk
發現出來的libffmpeg.so只有十幾KB,按照網上搜索的資料,
方法一:修改ffmpeg下的android.mk:
LOCAL_STATIC_LIBRARIES := libavcodec libavformat libavutil libavfilter libpostproc libswscale
改後爲:
LOCAL_WHOLE_STATIC_LIBRARIES := libavcodec libavformat libavutil libavfilter libpostproc libswscale
方法二:指定使用 arm-eabi-4.4.0 來編譯:
由於android-ndk-r5 默認是使用 arm-linux-androideabi-4.4.3 編譯,而不是 arm-eabi-4.4.0。
但 android-ndk-r5/toolchains/arm-linux-androideabi-4.4.3 目錄中的 setup.mk 文件裏定義的cmd-build-shared-library 函數
並沒有將靜態庫文件鏈接在一起生成動態庫文件。所以解決的辦法就是在執行 ndk-build 時加上 NDK_TOOLCHAIN 參數,指定使用 arm-eabi-4.4.0 來編譯。
完整命令如下
ndk-build NDK_TOOLCHAIN=arm-eabi-4.4.0 NDK_PLATFORM=android-8
同樣不行。
希望高手能給指條道了
需要編譯通過的ffmpeg-0.61文件的,文件太大上傳不了,請到
http://download.csdn.net/detail/mfcai_blog/5968953,下載
本文歡迎轉載,轉載請註明出處與作者
出處:http://blog.sina.com.cn/staratsky
作者:流星