之前有開源了一個 ffmpeg shared library,其中是把 ffmpeg 2.6 源碼編譯為android 平臺可用的共享庫,在其中只介紹了如何編譯,但對于如何將這些共享庫轉(zhuǎn)變?yōu)?JNI 使用卻沒有講太多。本文就著重介紹一下思路,方便后續(xù)升級 ffmpeg 版本。
編譯 ffmpeg 共享庫
依據(jù) 使用 介紹下載 ffmpeg 源碼,配置編譯腳本進行編譯。build_android_arm.sh
和 build_android_x86.sh
兩個腳本分別是用來編譯用于 arm 平臺的庫文件和 x86 平臺的庫的,如果你只需要 arm 平臺的,那 x86 的可以不用管了。注意:
每次運行完腳本編譯之后,會在 ffmpeg 源碼目錄下生成一個 config.h 文件,這個也是后續(xù)編譯 jni 必需的,需要在運行另一個編譯腳本之前進行保存, 我這里采用的方式是將 config.h 重命名為不同的名字,在編譯 jni 時根據(jù) 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。
1 | sourceSets.main { |
準備文件
Android.mk
在module下新建 jni 目錄,在該目錄下新建 Android.mk
文件,內(nèi)容復(fù)制 這里,當然后續(xù)對該文件根據(jù)需要還有少許調(diào)整,后面會提到。
頭文件
將從 ffmpeg 源碼編譯得到的 arm 和 x86 的 include 文件夾 整個復(fù)制到 jni 目錄下,注意 arm和x86相同的文件直接覆蓋或略過都可以的,主要是要讓它們互相補充。
后續(xù)實際編譯你會發(fā)現(xiàn),這些頭文件并不夠,還會缺少很多.h文件,所以后續(xù)隨著編譯的過程,必須自己一點點從ffmpeg源碼目錄不斷補充頭文件。
prebuilt
在 jni 目錄下新建 prebuilt
目錄,然后在 prebuilt 目錄內(nèi),分別新建 armeabi
和 x86
目錄,然后將 ffmpeg 源碼編譯的出來的 arm 的幾個so庫文件復(fù)制到 armeabi 目錄下,同理,將 x86 的復(fù)制到 x86 目錄下。
接下來,修改 Android.mk 文件中的對應(yīng)的 so 名,都改成自己的對應(yīng)文件名。如下:
1 | nclude $(CLEAR_VARS) |
不同的 ffmpeg 版本,這些so的版本是不同的,體現(xiàn)在so文件名都有個數(shù)字尾巴,這里不要去掉這些尾巴,因為它們之間還有依賴。如果確實不想帶尾巴,那么就需要去改ffmpeg源碼的makefile了
復(fù)制源文件
ffmpeg
可執(zhí)行文件執(zhí)行命令的入口是 ffmpeg.c 文件的 main 函數(shù),所以我們的原理就是將個這個main函數(shù)修改為我們的jni函數(shù),那么java層調(diào)用這個jni接口就可以執(zhí)行命令了。
從ffmpeg 源碼目錄下的復(fù)制下面的文件到j(luò)ni目錄下
1 | ffmpeg.c |
調(diào)整 Android.mk
的 LOCAL_SRC_FILES
部分,將 jni 目錄下的 所有 .c 文件都加入其中,這樣才能參與編譯。
新建 config.h 文件
內(nèi)容如下:
1 | #if USE_ARM_CONFIG |
增加 jni 接口
如何增加jni這里不多講了,網(wǎng)上資料很多,也可以參考 library.
將 ffmpeg.c main函數(shù)修改為你的 jni接口,然后在 jni 目錄下執(zhí)行 build.sh
(windows下執(zhí)行 build.cmd) 進行手動編譯,一般這里你就會發(fā)現(xiàn)少很多頭文件,可以一點點試,缺少哪個頭文件就從ffmpeg源碼目錄copy到include的對應(yīng)目錄下,注意有些是需要保留目錄結(jié)構(gòu)的,沒有就新建。
java 部分
在java部分的jni文件中,使用static代碼塊加載lib庫,如下:
1 | static { |
注意名字,修改為你實際使用的版本,并且名字上不帶lib
,參考 FFmpegNativeHelper.java,
至此,從 android studio里編譯就可以將所有l(wèi)ib和jni庫都編譯到你的工程里去了。
附:
實際移植 ffmpeg3.0 的時候遇到的其他問題:
- 在編譯ffmpeg源碼時,編譯完 arm 的版本,去編 x86 版本的時候,提示 strtop 錯誤,這是由 ffmpeg 的makefile bug造成的,再
run build_android_x86.sh
之前先手動刪除compat/strtop.o & compat/strtop.d
文件。