摘要:本文主要介紹將FFmpeg音視頻編解碼庫移植到Android平台上的編譯和基本測試過程。
環境准備:
Ubuntu12.04 TLS
android-ndk-r9d-linux-x86_64.tar.bz2
ffmpeg2.2
---------------------------------------------------------
第一步:下載
1.配置ubuntu12.04 TLS 系統環境。
2.下載ndk版本為 r9d。
3.下載ffmpeg2.2版本。
第二步:在ubuntu下編譯環境設置
1. 安裝好ubuntu12.04 TLS 64位linux系統之后,可以選擇安裝一下內容:
在在參考一些其他有關linux下NDK環境搭建資料上看到64位ubuntu 安裝之后需要再下載 bison
64位ubuntu下還需要下載 gcc-multilib 和g++-multilib:
終端命令:" sudo apt-get install bison gcc-multilib g++-multilib "
2.下載ndk之后解壓后目錄:/home/admin/develop/android-ndk-r9d
配置NDK環境變量:
(2.) 配置NDK的環境變量:
終端內執行:“ gedit ~/.bashrc ”
在打開的文件末尾添加如下內容:
NDK=/home/admin/develop/android-ndk-r9d
export NDK
(3.)在當前bash環境下讀取並執行 ~/.bashrc 中的命令:
終端執行:" source ~/.bashrc "
(4.)查看是否生效:
終端執行: " echo $NDK "
結果:/home/test/develop/android-ndk-r9d
(5.)測試NDK編譯JNI工程:
到android-ndk-r9d 的sample目錄的hello-jni 目錄里
終端執行:“ $NDK/ndk-build ”
如果環境配置成功會生成so庫的。
3.解壓ffmpeg-2.2源碼
將ffmpeg-2.2.tar.gz解壓后拷貝到任意目錄,本例是拷貝到.../android-ndk-r9d/sample/ffmpeg2.2 目錄內。
拷貝之后添加" build_android.sh "文件:
#!/bin/bash SYSROOT=$NDK/platforms/android-9/arch-arm/ TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64 function build_one { ./configure \ --prefix=$PREFIX \ --enable-shared \ --disable-static \ --disable-doc \ --disable-ffserver \ --enable-cross-compile \ --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \ --target-os=linux \ --arch=arm \ --sysroot=$SYSROOT \ --extra-cflags="-Os -fpic $ADDI_CFLAGS" \ --extra-ldflags="$ADDI_LDFLAGS" \ $ADDITIONAL_CONFIGURE_FLAG } CPU=arm PREFIX=$(pwd)/android/$CPU ADDI_CFLAGS="-marm" build_one
有的資料上面 build_android.sh 的前幾行是這樣寫的:
#!/bin/bash NDK=/home/admin/develop/android-ndk-r9d SYSROOT=$NDK/platforms/android-9/arch-arm/ TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64 ..... .....
因為之前已經在linux下設置NDK的環境路徑,所以就不需要在build_android.sh里指定NDK的路徑了。
在編譯ffmpeg的時候推薦先設置NDK的環境路徑到系統環境中,因為如果不設置的話,使用" NDK=/home/admin/... " 個人感覺是非常惡心的,尤其是在windows下使用cygwin編譯的時候經常出現NDK路徑找不到的問題,所以windows下編譯最好也配置好NDK環境路徑。
修改configure文件:
很多ffmpeg編譯資料上面說要修改configure文件 ,說的原因是 如果不修改的話,在android上 System.loadLibrary("xxx"); 的時候個別so庫無法加載的問題。
打開 ffmpeg源碼內 configure 文件進行如下修改:
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)' LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)' SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)' 替換為: SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)' LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"' SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' SLIB_INSTALL_LINKS='$(SLIBNAME)'
第三步:在ubuntu 64位下進行編譯ffmpeg源碼以得到android平台 arm下能使用的那幾個so庫
1.給build_android.sh 和 configure 增加可執行權限:
終端執行:
“ $chmod+x ./build_android.sh ”
“ $chmod+x ./configure ”
2.給build_android.sh 和 configure 轉換格式:
終端執行:(需要先安裝 dos2unix)
“ $dos2unix ./build_android.sh ”
“ $dos2unix ./configure ”
3.最后編譯:
終端執行:
“ $ ./build_android.sh ”
“ $ make ”
“$ make install ”
----------------------
編譯成功會在ffmpeg源碼目錄下生成一個“android”目錄里面有編譯好的 so庫和 需要的頭文件等等。
其中so庫應該是一下幾個:
libavutil-52.so libavcodec-55.so libswresample-0.so libavformat-55.so libswscale-2.so libpostproc-52.so libavfilter-4.so libavdevice-55.so
第四步:android下使用這幾個庫:
----------------------------------------------------
1.使用NDK里sample目錄下的hello-jni 工程進行使用這幾個庫:
(a.)在hello-jni 源碼的JNI目錄下新建ffmpeglib目錄,把那幾個庫全部拷貝到 /hello-jni/jni/ffmpeglib/ 目錄下。
(b.)然后把編譯好的ffmpeg的頭文件全部拷貝到 /hello-jni/jni/ 目錄下。
(c.)在 hello-jni.c 文件內進行使用ffmpeg:
#include <string.h> #include <jni.h> #include <libavcodec/avcodec.h> jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ) { char str[25]; sprintf(str, "%d", avcodec_version()); return (*env)->NewStringUTF(env, str); }
(d.)在 HelloJni.java 文件加載so庫進行調用JNI內的測試函數:
static { System.loadLibrary("avutil-52"); System.loadLibrary("avcodec-55"); System.loadLibrary("swresample-0"); System.loadLibrary("avformat-55"); System.loadLibrary("swscale-2"); System.loadLibrary("postproc-52"); System.loadLibrary("avfilter-4"); System.loadLibrary("avdevice-55"); System.loadLibrary("hello-jni"); } public native String stringFromJNI();
(e.)修改 hello-jni 源碼中jni目錄下的 Android.mk 文件:
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := avcodec-55-ffmpeglib LOCAL_SRC_FILES := ffmpeglib/libavcodec-55.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avdevice-55-ffmpeglib LOCAL_SRC_FILES := ffmpeglib/libavdevice-55.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avfilter-4-ffmpeglib LOCAL_SRC_FILES := ffmpeglib/libavfilter-4.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avformat-55-ffmpeglib LOCAL_SRC_FILES := ffmpeglib/libavformat-55.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avutil-52-ffmpeglib LOCAL_SRC_FILES := ffmpeglib/libavutil-52.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avswresample-0-ffmpeglib LOCAL_SRC_FILES := ffmpeglib/libswresample-0.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := swscale-2-ffmpeglib LOCAL_SRC_FILES := ffmpeglib/libswscale-2.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := postproc-52-ffmpeglib LOCAL_SRC_FILES := ffmpeglib/libpostproc-52.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := hello-jni LOCAL_SRC_FILES := hello-jni.c LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid LOCAL_SHARED_LIBRARIES := avcodec-55-prebuilt avdevice-55-prebuilt avfilter-4-prebuilt avformat-55-prebuilt avutil-52-prebuilt swscale-2-prebuilt postproc-52-prebuilt avswresample-0-prebuilt include $(BUILD_SHARED_LIBRARY)
(f.)windows下使用cygwin編譯hello-jni工程:
" $NDK/ndk-build "
生成 libhello-jni.so 完成。
----------------------------------------
附上ubuntu下編譯好的所有so庫和頭文件:
http://download.csdn.net/detail/wain163/7494547
!!!==========================================
針對之前有的小伙伴說使用hello-jni測試 NDK-r9編譯好的最新的FFmpeg2.2的所有so庫和頭文件 的時候。
在使用cygwin編譯jni的時候會報錯:”undefined reference to 'avcodec_version'“ 的問題,所以現在把本人在hello-jni的程序弄上來,供大家參考。
hello-jni工程地址:
http://download.csdn.net/detail/wain163/8859195
備注:
此demo需要在 HelloJni.java 中加上:
static { System.loadLibrary("avutil-52"); System.loadLibrary("avcodec-55"); System.loadLibrary("swresample-0"); System.loadLibrary("avformat-55"); System.loadLibrary("swscale-2"); System.loadLibrary("postproc-52"); System.loadLibrary("avfilter-4"); System.loadLibrary("avdevice-55"); System.loadLibrary("hello-jni"); }
並且需要cygwin 對jni進行編譯 出so才能運行。
==========================================
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
參考資料:
http://blog.csdn.net/gobitan/article/details/22750719