標籤:

將 ffmpeg 編譯為 android JNI 庫 | 挨踢的甘蔗

dxjia

憋說話,好好乾,你想要的時間都會給你

將 ffmpeg 編譯為 android JNI 庫

Programmer

  • Android
  • ffmpeg
  • 之前有開源了一個 ffmpeg shared library,其中是把 ffmpeg 2.6 源碼編譯為android 平台可用的共享庫,在其中只介紹了如何編譯,但對於如何將這些共享庫轉變為 JNI 使用卻沒有講太多。本文就著重介紹一下思路,方便後續升級 ffmpeg 版本。

    編譯 ffmpeg 共享庫

    依據 使用 介紹下載 ffmpeg 源碼,配置編譯腳本進行編譯。build_android_arm.shbuild_android_x86.sh 兩個腳本分別是用來編譯用於 arm 平台的庫文件和 x86 平台的庫的,如果你只需要 arm 平台的,那 x86 的可以不用管了。注意:每次運行完腳本編譯之後,會在 ffmpeg 源碼目錄下生成一個 config.h 文件,這個也是後續編譯 jni 必需的,需要在運行另一個編譯腳本之前進行保存, 我這裡採用的方式是將 config.h 重命名為不同的名字,在編譯 jni 時根據 target 不同引用不同的頭文件,即:運行完 build_android_arm.sh 之後,將 config.h 重命名為 arm_config.h,運行完 build_android_x86.sh之後,重命名為 x86_config.h

    編譯 jni

    新建一個android項目,並新建一個 library module,也可以直接在你的 app 項目里,看自己的需要了。

    禁用 android studio JNI 自動編譯

    在 你的 build.gradle 中增加下面幾行代碼,來禁用 as 對 jni 的自動編譯,因為我們需要自己手動編譯 jni。參考 build.gradle。

    1234

    sourceSets.main { jni.srcDirs = [] //disable automatic ndk-build jniLibs.srcDirs = ["libs"]}

    準備文件Android.mk

    在module下新建 jni 目錄,在該目錄下新建 Android.mk 文件,內容複製 這裡,當然後續對該文件根據需要還有少許調整,後面會提到。

    頭文件

    將從 ffmpeg 源碼編譯得到的 arm 和 x86 的 include 文件夾 整個複製到 jni 目錄下,注意 arm和x86相同的文件直接覆蓋或略過都可以的,主要是要讓它們互相補充。

    後續實際編譯你會發現,這些頭文件並不夠,還會缺少很多.h文件,所以後續隨著編譯的過程,必須自己一點點從ffmpeg源碼目錄不斷補充頭文件。

    prebuilt

    在 jni 目錄下新建 prebuilt 目錄,然後在 prebuilt 目錄內,分別新建 armeabix86 目錄,然後將 ffmpeg 源碼編譯的出來的 arm 的幾個so庫文件複製到 armeabi 目錄下,同理,將 x86 的複製到 x86 目錄下。接下來,修改 Android.mk 文件中的對應的 so 名,都改成自己的對應文件名。如下:

    1234

    nclude $(CLEAR_VARS)LOCAL_MODULE:= avcodec-prebuilt-$(LIB_NAME_PLUS)LOCAL_SRC_FILES:= prebuilt/$(LIB_NAME_PLUS)/libavcodec-56.soinclude $(PREBUILT_SHARED_LIBRARY)

    不同的 ffmpeg 版本,這些so的版本是不同的,體現在so文件名都有個數字尾巴,這裡不要去掉這些尾巴,因為它們之間還有依賴。如果確實不想帶尾巴,那麼就需要去改ffmpeg源碼的makefile了

    複製源文件

    ffmpeg 可執行文件執行命令的入口是 ffmpeg.c 文件的 main 函數,所以我們的原理就是將個這個main函數修改為我們的jni函數,那麼java層調用這個jni介面就可以執行命令了。從ffmpeg 源碼目錄下的複製下面的文件到jni目錄下

    123456789

    ffmpeg.cffmpeg.harm_config.hx86_config.hcmdutils.ccmdutils.hcmdutils_common_opts.hffmpeg_filter.cffmpeg_opt.c

    調整 Android.mkLOCAL_SRC_FILES 部分,將 jni 目錄下的 所有 .c 文件都加入其中,這樣才能參與編譯。

    新建 config.h 文件

    內容如下:

    12345

    #if USE_ARM_CONFIG#include "arm_config.h"#elif USE_X86_CONFIG#include "x86_config.h"#endif

    增加 jni 介面

    如何增加jni這裡不多講了,網上資料很多,也可以參考 library.將 ffmpeg.c main函數修改為你的 jni介面,然後在 jni 目錄下執行 build.sh (windows下執行 build.cmd) 進行手動編譯,一般這裡你就會發現少很多頭文件,可以一點點試,缺少哪個頭文件就從ffmpeg源碼目錄copy到include的對應目錄下,注意有些是需要保留目錄結構的,沒有就新建。

    java 部分

    在java部分的jni文件中,使用static代碼塊載入lib庫,如下:

    12345678910

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

    注意名字,修改為你實際使用的版本,並且名字上不帶lib,參考 FFmpegNativeHelper.java,

    至此,從 android studio里編譯就可以將所有lib和jni庫都編譯到你的工程里去了。

    附: 實際移植 ffmpeg3.0 的時候遇到的其他問題:

    1. 在編譯ffmpeg源碼時,編譯完 arm 的版本,去編 x86 版本的時候,提示 strtop 錯誤,這是由 ffmpeg 的makefile bug造成的,再 run build_android_x86.sh 之前先手動刪除 compat/strtop.o & compat/strtop.d 文件。

    本文標題:將 ffmpeg 編譯為 android JNI 庫

    文章作者:dxjia

    發布時間:2016-07-27, 15:14:38

    最後更新:2016-08-09, 12:53:43

    原始鏈接:http://dxjia.cn/2016/07/27/how_to_compile_ffmpeg_for_android/

    許可協議: "署名-非商用-相同方式共享 4.0" 轉載請保留原文鏈接及作者。

    文章目錄

    1. 1. 編譯 ffmpeg 共享庫
    2. 2. 編譯 jni
      1. 2.1. 禁用 android studio JNI 自動編譯
      2. 2.2. 準備文件
        1. 2.2.1. Android.mk
        2. 2.2.2. 頭文件
        3. 2.2.3. prebuilt
        4. 2.2.4. 複製源文件
        5. 2.2.5. 新建 config.h 文件
        6. 2.2.6. 增加 jni 介面
        7. 2.2.7. java 部分

    推薦閱讀:

    法意編譯 | 特朗普現象:民主過盛還是民主不足?
    梭羅和隱逸的《瓦爾登湖》(王淑霞 編譯)
    中央編譯局
    經略編譯 | 怒從何來?「劍橋分析」與我們的時代
    獨家編譯 | 五千年歷史耶路撒冷 到底是誰的「首都」?

    TAG:編譯 | 甘蔗 |