Window 平臺 FFmpeg Android .so檔案編譯
需要的工具
360網盤
環境搭建:
測試cygwin搭建好了沒有,輸入make
解壓ndk壓縮包
配置環境變數,在C:\cygwin64\home\linyehui.bash_profile最後新增兩行
export ANDROID_NDK_HOME=/cygdrive/c/android-ndk-r9c
export PATH=$ANDROID_NDK_HOME:$PATH
測試ndk-build bash下直接測試下ndk-build命令,提示正常的話就是安裝成功了
解壓ffmpeg2.2
修改ffmpeg-2.2/configure檔案
如果直接按照未修改的配置進行編譯,結果編譯出來的so檔案類似libavcodec.so.55.39.101,版本號位於so之後,Android上似乎無法載入。因此需要按如下修改:
將該檔案中的如下四行:
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)'
編寫build_android.sh指令碼檔案
FFmpeg可以說是一個包絡音視訊編解碼及格式的超級霸。因此在編譯前通常都需要進行配置,設定相應的環境變數等。
所有的配置選項都在ffmpeg-2.2/configure這個指令碼檔案中,可以通過執行如下命令來檢視所有的配置選項:
$ ./configure –help
配置選項很多,也較為複雜,這裡先把我需要的搞出來,然後有時間再慢慢看。
我們將需要的配置項和環境變數設定寫成一個sh指令碼檔案來執行以便編譯出Android平臺需要的so檔案出來。
我的是D:\wodekf\android-ndk-r10b
build_android.sh的內容如下:
#!/bin/bash
NDK=/cygdrive/d/wodekf/android-ndk-r10b
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
這個指令碼檔案有幾個地方需要注意:
(1) NDK,SYSROOT和TOOLCHAIN這三個環境變數一定要換成你自己機器裡的。
(2) 確保cross-prefix變數所指向的路徑是存在的。
執行build_android.sh
$./build_android.sh
配置該指令碼完成對ffmpeg的配置,會生成config.h等配置檔案,後面的編譯會用到。如果未經過配置直接進行編譯會提示無法找到config.h檔案等錯誤。
執行make,命令
執行make install
-rwxr-xr-x 1 dennisdennis 55208 Mar 29 16:26libavdevice-55.so
-rwxr-xr-x 1 dennisdennis 632476 Mar 29 16:26 libavfilter-4.so
-rwxr-xr-x 1 dennisdennis 1442948 Mar 29 16:26 libavformat-55.so
-rwxr-xr-x 1 dennisdennis 7985396 Mar 29 16:26 libavcodec-55.so
-rwxr-xr-x 1 dennisdennis 83356 Mar 29 16:26libswresample-0.so
-rwxr-xr-x 1 dennisdennis 308636 Mar 29 16:26 libswscale-2.so
-rwxr-xr-x 1 dennisdennis 300580 Mar 29 16:26libavutil-52.so
建立一個Android 工程
我這裡是Android Studio“
com_example_administrator_myapplication_CameraAc.h裡的內容需要手動生成
javah -d jni -classpath C:\Users\Administrator\AppData\Local\Android\Sdk\platforms\android-21\android.jar;.\app\build\intermediates\classes\debug com.exam
javah -d (jni新建檔名) -classpath (sdk路徑);(class 路徑) (class檔名,包括包名)
CameraAc.java裡的內容
public class CameraAc extends Activity {
private Button bt_up;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bt_up = (Button)findViewById(R.id.bt_up);
int codecID = 28;
int res = avcodeDecoder(codecID);
if (res == 1) {
bt_up.setText("Success!");
} else {
bt_up.setText("Failed!");
}
}
static {
System.loadLibrary("avutil-52");
System.loadLibrary("avcodec-55");
System.loadLibrary("swresample-0");
System.loadLibrary("avformat-55");
System.loadLibrary("swscale-2");
System.loadLibrary("avfilter-4");
System.loadLibrary("avdevice-55");
System.loadLibrary("ffmpeg_codec");
}
public native int avcodeDecoder(int codecID);
}
Android.mk裡的內容
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec-55-prebuilt
LOCAL_SRC_FILES := prebuilt/libavcodec-55.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avdevice-55-prebuilt
LOCAL_SRC_FILES := prebuilt/libavdevice-55.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avfilter-4-prebuilt
LOCAL_SRC_FILES := prebuilt/libavfilter-4.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avformat-55-prebuilt
LOCAL_SRC_FILES := prebuilt/libavformat-55.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avutil-52-prebuilt
LOCAL_SRC_FILES := prebuilt/libavutil-52.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avswresample-0-prebuilt
LOCAL_SRC_FILES := prebuilt/libswresample-0.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swscale-2-prebuilt
LOCAL_SRC_FILES := prebuilt/libswscale-2.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg_codec
LOCAL_SRC_FILES := com_example_administrator_myapplication_CameraAc.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
include $(BUILD_SHARED_LIBRARY)
Application.mk裡的內容
#APP_ABI := armeabi
#APP_ABI := armeabi-v7a
APP_ABI := all
APP_PLATFORM := android-10
com_example_administrator_myapplication_CameraAc.c裡的內容
#include <stddef.h>
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "com_example_administrator_myapplication_CameraAc.h"
JNIEXPORT jint JNICALL Java_com_example_administrator_myapplication_CameraAc_avcodeDecoder
(JNIEnv *env, jobject obj, jint codecID)
{
AVCodec *codec = NULL;
av_register_all();
codec= avcodec_find_decoder(codecID);
if(codec != NULL)
{
return 1;
}
else
{
return-1;
}
}
妹的一直報錯,記得把FUCKjni改成jni
果斷用別的方法
編譯好之後jni外面的資料夾下就會有lib目錄
把jni資料夾弄出去,然後執行
**