1. 程式人生 > >Mac環境下Android Studio移植FFmpeg

Mac環境下Android Studio移植FFmpeg

準備:

1. Android Studio 2. FFmpeg-2.8.4   3. android-ndk-r10e

一、ndk編譯ffmpeg

1.下載ffmpeg和ndk

ffmpeg下載地址:http://ffmpeg.org/download.html  我下載的是2.8.4版本 ndk 官網下載,這個我就不說了,自備梯子翻越長城。。我下載的是 android-ndk-r10e 

2.解壓ffmpeg和ndk

將解壓的ffmpeg資料夾複製到 android-ndk-r10e ->sources 目錄中
修改資料夾ffmpeg-2.8.4中configure指令碼,由於編譯出來的動態庫檔名的版本號在.so之後(例如“libavcodec.so.5.100.1”),而android平臺不能識別這樣檔名,所以需要修改這種檔名。在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)'

3.配置編譯指令碼

在資料夾ffmpeg-2.8.4中新建指令碼 build_android.sh 
#!/bin/bash
export NDK=/Users/huxing/Downloads/android-ndk-r10e
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt
export PLATFORM=$NDK/platforms/android-21/arch-arm
export PREFIX=../simplefflib
build_one(){
  ./configure --target-os=linux --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--arch=arm \
--cc=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi- \
--disable-stripping \
--nm=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-nm \
--sysroot=$PLATFORM \
--enable-gpl --enable-shared --disable-static --enable-small \
--disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-ffserver --disable-debug \
--extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" 
}

build_one

make
make install
注意的是前面三個路徑替換成自己的路徑,還有一些不同版本ndk路徑的取名不同比如darwin-x86_64有的是linux-x86_64,自己注意一下路徑名稱

4.編譯ffmpeg

使用命令cd到指令碼目錄下,首先 chmod a+x build_android.sh 授權,然後 ./build_android.sh 執行指令碼。 編譯需要花一些時間,編譯完成之後就會在android-ndk-r10e -> source 目錄下多出一個 simplefflib 目錄 (還有8個.so檔案被我刪除了)

二、Android Studio 部分

1.新建 Android Studio工程

新建AS工程,在main目錄下新建一個jni目錄,在gradle.properties配置中新增 android.useDeprecatedNdk = true,在Project Structure中配置ndk location,指向你下載ndk的路徑
再將編譯的FFmpeg檔案複製到jni目錄中。

2.配置build.gradle

取消自動編譯,新增 :
 sourceSets.main.jni.srcDirs = []
新增ndk配置:
ndk {
            moduleName "helloffmpeg"
            abiFilter "armeabi"
            ldLibs "log", "z", "m", "jnigraphics", "android"
        }
全部配置為如下:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 23
    buildToolsVersion "23.0.0"

    sourceSets.main.jni.srcDirs = []
    defaultConfig {
        applicationId "hxing.com.myffmpeg"
        minSdkVersion 19
        targetSdkVersion 23
        versionCode 1
        versionName "1.0"

        ndk {
            moduleName "helloffmpeg"
            abiFilter "armeabi"
            ldLibs "log", "z", "m", "jnigraphics", "android"
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
}

3.生成標頭檔案

在MainActivity.class中新增Native方法和呼叫庫檔案,如下:
public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("helloffmpeg");
        System.loadLibrary("avutil-54");
        System.loadLibrary("avcodec-56");
        System.loadLibrary("avformat-56");
        System.loadLibrary("avdevice-56");
        System.loadLibrary("swresample-1");
        System.loadLibrary("swscale-3");
        System.loadLibrary("postproc-53");
        System.loadLibrary("avfilter-5");
    }

    public native String getffmpegFromJNI();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView textView = (TextView) findViewById(R.id.text);
        textView.setText(getffmpegFromJNI());

    }
}


開啟as的Terminal視窗,預設路徑是當前專案根路徑,輸入以下命令:
cd app/src/main/java
javah -d ../jni hxing.com.myffmpeg.MainActivity

進入java目錄下 使用javah命令在jni目錄下生成標頭檔案,然後再在jni目錄下建立對應的c檔案,c檔案程式碼如下:
//
// Created by 胡醒 on 15/12/31.
//
#include <jni.h>
#include "libavcodec/avcodec.h"

JNIEXPORT jstring JNICALL Java_hxing_com_myffmpeg_MainActivity_getffmpegFromJNI
        (JNIEnv * env, jobject thiz){
    char info[10000] = { 0 };
    sprintf(info, "%s\n", avcodec_configuration());
    return (*env)->NewStringUTF(env, info);
}



4.在jni目錄下建立Android.mk檔案

LOCAL_PATH := $(call my-dir)

# FFmpeg library
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := lib/libavcodec-56.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := avdevice
LOCAL_SRC_FILES := lib/libavdevice-56.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := avfilter
LOCAL_SRC_FILES := lib/libavfilter-5.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := avformat
LOCAL_SRC_FILES := lib/libavformat-56.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := avutil
LOCAL_SRC_FILES := lib/libavutil-54.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := postproc
LOCAL_SRC_FILES := lib/libpostproc-53.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := swresample
LOCAL_SRC_FILES := lib/libswresample-1.so
include $(PREBUILT_SHARED_LIBRARY)

include $(CLEAR_VARS)
LOCAL_MODULE := swscale
LOCAL_SRC_FILES := lib/libswscale-3.so
include $(PREBUILT_SHARED_LIBRARY)

# Program
include $(CLEAR_VARS)
LOCAL_MODULE := helloffmpeg
LOCAL_SRC_FILES := hxing_com_myffmpeg_MainActivity.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale
include $(BUILD_SHARED_LIBRARY)

還可以在當前目錄下建立Application.mk,這個檔案用來指定編譯的平臺,我這裡只指定armeabi
APP_ABI := armeabi


5.編譯ffmpeg.so檔案

進入Terminal視窗,輸入命令 “ cd ../jni” 返回到jni目錄中,在輸入命令:
/Users/huxing/Downloads/android-ndk-r10e/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/huxing/Documents/myFFmpeg2/app/src/main/jni/Android.mk APP_PLATFORM=android-21 NDK_OUT=/Users/huxing/Documents/myFFmpeg2/app/build/intermediates/ndk/debug/obj NDK_LIBS_OUT=/Users/huxing/Documents/myFFmpeg2/app/build/intermediates/ndk/debug/lib APP_ABI=armeabi

/Users/huxing/Downloads/android-ndk-r10e/ndk-build :你安裝的ndk目錄中的ndk-build命令 APP_BUILD_SCRIPT :工程中jni目錄下的android.mk的路徑
NDK_OUT : 輸出路徑
NDK_LIBS_OUT :庫檔案輸出路徑
APP_ABI : 輸出平臺
改成自己工程對應的目錄

6.執行工程

成功呼叫ffmpeg方法輸出資訊