老生常談-FFmpeg 的編譯問題輕松搞定
前幾天發(fā)了一篇 FFmpeg 調(diào)用 Android MediaCodec 進行硬解碼 的文章,這里面的技術(shù)點不算太難,也還是調(diào)用 FFmpeg 的常用接口操作,但重點在于 FFmpeg 的版本選擇以及編譯選項要開啟 MediaCodec 才行。
關于 FFmpeg 的編譯,是個老生常談的話題了,很多初學者都會卡在怎么編譯動態(tài)庫 so 的問題上,這其實也是 Android 開發(fā)轉(zhuǎn)音視頻的一大攔路虎,一行 FFmpeg 代碼都沒來得及寫呢,就得先折騰好久編譯問題。
當然了,編譯麻煩肯定是 FFmpeg 的鍋。因為它的不斷升級,從早期 2.x 版本到現(xiàn)在的 4.x 版本,調(diào)用接口發(fā)生了變化,編譯選項也調(diào)整了不少,但網(wǎng)上的各種 Android so 動態(tài)庫編譯文章可沒有對應更新哦,有的教程還停留在 2.x 版本上,如果你照著去編譯了,這里面肯定會有兼容性問題的。
舉幾個例子:
FFmpeg 源碼里面的文件要修改嗎?
早期的編譯版本還要在 FFmpeg 里面修改一些源碼才行,最常見的就是下面的代碼:
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)'
以前需要修改編譯后庫名字的連接方式,但是在最新版本中是不用了(最新版指的是 ffmpeg 的 release/4.4 分支版本)。
另外,在實際編譯中也不需要修改任何 FFmpeg 源碼的。
Android NDK 要用哪個版本?
這也是個常見的兼容性問題。
選擇 NDK 版本實際上是在選擇編譯器,早先編譯可能用的是 GCC 編譯,后來 Google 在 NDK r18b 版本移除了 GCC 編譯工具,具體可以參考如下鏈接:
NDK 修訂歷史記錄
https://developer.android.com/ndk/downloads/revision_history?hl=zh-Cn?
所以現(xiàn)在最新的動態(tài)庫編譯都是用 Clang 進行操作的,為了跟上時代步伐,也就不要用之前的 NDK 版本了,直接上最新的。
為了避免大家把精力消耗在 FFmpeg 的編譯上,直接就給出一個 Github Repo ,將編譯腳本都放在這個倉庫上了。
地址如下:
https://github.com/glumes/ffmpeg_android

其中 FFmpeg 源碼是作為該倉庫的一個子模塊 Submodules 的形式加載進來的,在下載時要注意一下:
git?clone?--recursive?https://github.com/glumes/ffmpeg_android
下載后,進入到 build_android.sh 文件中,將 NDK 替換成你自己的路徑,最好也用 r20b 版本的,保持一致。
#!/bin/bash
?
#你的NDK路徑
NDK=/Users/glumes/Downloads/android-ndk-r20b
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
API=21
替換后,給腳本可執(zhí)行權(quán)限就能運行了,編譯后的動態(tài)庫在 ffmpeg_library 文件夾中,目前僅編譯了 armeabi-v7a 架構(gòu)的。
android 文件夾內(nèi)對應加載 so 的 Android 工程,也是 FFmpeg 調(diào)用 Android MediaCodec 的源碼。
這個工程目錄也是不需要修改 FFmpeg 的,并且關于 FFmpeg 的很多編譯選項開關放在了 config-env.sh 目錄中,有需要可以在文件內(nèi)做修改,目前的選項是開啟了 mediacodec 編碼的,但它的修改不影響主的編譯腳本運行。
順便貼一下源碼:
這里是具體執(zhí)行編譯的函數(shù),函數(shù)用到的一些參數(shù)要在外面定義好:
function?build_android
{
echo?"Compiling?FFmpeg?for?$CPU"
./configure?\
????--prefix=$PREFIX?\
????--libdir=$LIB_DIR?\
????--enable-shared?\
????--disable-static?\
????--enable-jni?\
????--disable-doc?\
????--disable-symver?\
????--disable-programs?\
????--target-os=android?\
????--arch=$ARCH?\
????--cpu=$CPU?\
????--cc=$CC?\
????--cxx=$CXX?\
????--enable-cross-compile?\
????--sysroot=$SYSROOT?\
????--extra-cflags="-Os?-fpic?$OPTIMIZE_CFLAGS"?\
????--extra-ldflags="$ADDI_LDFLAGS"?\
????--disable-asm?\
????#?這些編譯參數(shù)在?config-env.sh?文件中定義了
????$COMMON_FF_CFG_FLAGS
make?clean
make?-j8?#?這里是定義用幾個CPU編譯
make?install
echo?"The?Compilation?of?FFmpeg?for?$CPU?is?completed"
}
接下來定義好相關參數(shù),就可以執(zhí)行了:
//?編譯的?configure?可執(zhí)行文件在?ffmpeg?源碼目錄中,要先進入到目錄里
cd?ffmpeg
//?定義好編譯的架構(gòu)
OUTPUT_FOLDER="armeabi-v7a"
ARCH="arm"
CPU="armv7-a"
TOOL_CPU_NAME=armv7a
TOOL_PREFIX="$TOOLCHAIN/bin/arm-linux-androideabi"
?
CC="$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang"
CXX="$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++"
SYSROOT="$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot"
PREFIX="${PWD}/../ffmpeg_library/android/$OUTPUT_FOLDER"
LIB_DIR="${PWD}/../ffmpeg_library/android/libs/$OUTPUT_FOLDER"
OPTIMIZE_CFLAGS="-march=$CPU"
build_android
由于我們的編譯腳本不放在 FFmpeg 源碼目錄中,所以要對路徑做一些修改,這樣可以絕對地不改動任何 FFmpeg 內(nèi)容了。
通過上述的參數(shù)設定,應該就可以編譯出正確的 Android 動態(tài)庫了,如果你在編譯過程中有任何問題,歡迎加我微信 ezglumes 聯(lián)系我,及時調(diào)整保證輕松搞定編譯過程。

技術(shù)交流,歡迎加我微信:ezglumes ,拉你入技術(shù)交流群。
推薦閱讀:
開通專輯 | 細數(shù)那些年寫過的技術(shù)文章專輯
覺得不錯,點個在看唄~

