深刻了解android平臺的jni---編譯ffmpeg源碼

環境:
操做系統: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
1、設置NDK環境變量 linux

配置NDK環境,增長/home/ndk目錄到PATH環境變量:
$sudo gedit ~/.bashrc
文件底部添加如下兩行:
NDK_ROOT=/home/mfcai/android-ndk-r5b
export NDK_ROOT
2、配置編譯參數 android

在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
3、準備編譯ffmpeg一、編輯ffmpegffmpeg-0.6.1下各個模塊的Makefile文件 redis

分別把libavutil、libavcodec、libavformat、libavfilter、libpostproct和libswscale下的Makefile文件中下面兩行刪除掉:
include $(SUBDIR)../subdir.mak
include $(SUBDIR)../config.mak
二、在ffmpegffmpeg-0.6.1根目錄下新建一個av.mk文件 bash

# 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))
三、新建Android.mk文件 ide

在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)
4、編譯 函數

在jni目錄下運行ndk-build
若是編譯成功,產生出libavcodec.so、libavfilter.so、libavformat.so、libavutil.so、 libffmpeg.so,libpostproc.so和libswscale.so。 post


5、問題 ui

一、一樣的配置,在cygwin下編譯了兩天通不過。因此建議仍是在linux環境下編譯
二、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文件的,請到 idea

http://download.csdn.net/detail/mfcai_blog/5968953,下載 
本文歡迎轉載,轉載請註明出處與做者
出處:http://blog.sina.com.cn/staratsky
做者:流星 操作系統

相關文章
相關標籤/搜索