FFMPEG-Android利用ndk(r20)編譯最新版本ffmpeg4.2.1

聲明:轉(zhuǎn)載別人的:https://juejin.im/post/5d831333f265da03c61e8a28

編譯ffmpeg真是太痛苦了,尤其是網(wǎng)上能搜到的所有同類文章皆告訴我一個道理--不要用最新版本的NDK去編譯最新版的FFMPEG。但作為一個喜新厭舊的程序員,怎么能夠忍受用這么舊的版本呢!故,我花了1.6天的工作時間成功編譯了目前最新版的ffmpeg(當(dāng)前官網(wǎng)為4.2.1),而且用的是最新版的ndk(當(dāng)前為r20

使用NDK(r20)編譯FFmpeg

前兩天在論壇上看到一個問題,大意是怎么在UBUNTU下使用NDK-r20編譯FFmpeg。我第一反應(yīng)是不該用r20,因?yàn)槲以诤茉缜坝眠^沒有g(shù)cc版本的NDK,發(fā)現(xiàn)有很多問題不能編譯,就立馬回復(fù)了個使用r12b來編譯?;氐郊椅壹?xì)想了一下,如果我就是想要用r20的NDK編譯最新的FFmpeg呢?不如我們花點(diǎn)時間來折騰下。

NDK不知道從什么版本徹底改革,使用了clang來編譯,這還不是最關(guān)鍵的,在新的NDK里sysroot也改變了(關(guān)鍵是google在NDK根目錄里建了一個sysroot--錯誤的sysroot),這就導(dǎo)致FFmpeg過不了cc檢測。常見的報錯都是沒有crtbegin_so.o或者找不到系統(tǒng)庫連接。

所以sysroot其實(shí)是罪魁禍?zhǔn)祝绻覀兪褂谜_的sysroot一切就好辦了。我用了個取巧的方式來查看sysroot,在AS里建一個c++項目,故意寫錯一段代碼就能看到grade的log里面明確標(biāo)出了使用的sysroot($NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot)這才是我們需要的。

準(zhǔn)備工作

本來打算用windows編譯的,但是看了網(wǎng)上的教程。。。。放棄了,轉(zhuǎn)戰(zhàn)Linux。

準(zhǔn)備以下編譯環(huán)境:

VMware Workstation

Ubuntu

(PS:剛整了這虛擬系統(tǒng)的時候有點(diǎn)好奇,各種折騰,搞語言包,搞輸入法,搞各種沒用的軟件,然后成功把系統(tǒng)搞崩了,又刪掉重新安裝了(*′???`)? )

下載最新的ffmpeg壓縮文件

(ubuntu系統(tǒng)自帶FireFox瀏覽器)

ffmpeg4.2.1

下載最新的ndk

(ubuntu系統(tǒng)自帶FireFox瀏覽器)

NDKr20

解壓下載的兩個文件

/home/junt/Documents/android-ndk-r20

/home/junt/Documents/ffmpeg-4.2.1

開始編譯

這里前面一部分都是老套路,很多文章里都有,簡單帶過

替換最終生成的so文件名

這里文件的編輯可以用(vim編輯的話需要先安裝vim)

# 將ffmpeg-4.2.1目錄中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)'復(fù)制代碼

創(chuàng)建編譯腳本文件

右擊ffmpeg-4.2.1文件夾中的空白處-Open in Terminal

然后利用touch命令創(chuàng)建一個Shell腳本文件用來進(jìn)行編譯工作

將以下shell代碼粘貼到build_android.sh文件中

#!/bin/bashNDK=/home/junt/Documents/android-ndk-r20TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/API=29functionbuild_android{echo"Compiling FFmpeg for$CPU"./configure \? ? --prefix=$PREFIX\? ? --disable-neon \? ? --disable-hwaccels \? ? --disable-gpl \? ? --disable-postproc \? ? --enable-shared \? ? --enable-jni \? ? --disable-mediacodec \? ? --disable-decoder=h264_mediacodec \? ? --disable-static \? ? --disable-doc \? ? --disable-ffmpeg \? ? --disable-ffplay \? ? --disable-ffprobe \? ? --disable-avdevice \? ? --disable-doc \? ? --disable-symver \? ? --cross-prefix=$CROSS_PREFIX\? ? --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"\$ADDITIONAL_CONFIGURE_FLAGmake cleanmakemake installecho"The Compilation of FFmpeg for$CPUis completed"}#armv8-aARCH=arm64CPU=armv8-aCC=$TOOLCHAIN/bin/aarch64-linux-android$API-clangCXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysrootCROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-PREFIX=$(pwd)/android/$CPUOPTIMIZE_CFLAGS="-march=$CPU"build_android#armv7-aARCH=armCPU=armv7-aCC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clangCXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysrootCROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-PREFIX=$(pwd)/android/$CPUOPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU"build_android#x86ARCH=x86CPU=x86CC=$TOOLCHAIN/bin/i686-linux-android$API-clangCXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysrootCROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-PREFIX=$(pwd)/android/$CPUOPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"build_android#x86_64ARCH=x86_64CPU=x86-64CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clangCXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++SYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysrootCROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-PREFIX=$(pwd)/android/$CPUOPTIMIZE_CFLAGS="-march=$CPU-msse4.2 -mpopcnt -m64 -mtune=intel"build_android復(fù)制代碼

編譯

在ffmpeg-4.2.1文件夾中打開終端

賦予文件讀寫權(quán)限

執(zhí)行編譯文件

編譯完成查看文件

在/ffmpeg-4.2.1/android/目錄下

對于build_android.sh文件的說明

為什么新版本的ffmpeg搭配新版本的ndk編譯很容易出錯呢?其實(shí)關(guān)鍵點(diǎn)主要還是新舊版本ndk中的交叉編譯工具不一樣導(dǎo)致的。比如舊版本(r17及之前)的ndk中的編譯器用的是gcc,而網(wǎng)上大部分的同類文章中用的也是gcc,而新版本的ndk文件已經(jīng)棄用gcc編譯器改用clang了,所以照著網(wǎng)上的文章做當(dāng)然編譯不起來)

#!/bin/bashNDK=/home/junt/Documents/android-ndk-r20TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/linux-x86_64/#這里修改的是最低支持的android sdk版本(r20版本ndk中armv8a、x86_64最低支持21,armv7a、x86最低支持16)API=29functionbuild_android{#相當(dāng)于Android中Log.iecho"Compiling FFmpeg for$CPU"#調(diào)用同級目錄下的configure文件./configure \#指定輸出目錄--prefix=$PREFIX\#各種配置項,想詳細(xì)了解的可以打開configure文件找到Help options:查看--disable-neon \? ? --disable-hwaccels \? ? --disable-gpl \? ? --disable-postproc \#配置跨平臺編譯,同時需要disable-static--enable-shared \? ? --enable-jni \? ? --disable-mediacodec \? ? --disable-decoder=h264_mediacodec \#配置跨平臺編譯,同時需enable-shared? --disable-static \? ? --disable-doc \? ? --disable-ffmpeg \? ? --disable-ffplay \? ? --disable-ffprobe \? ? --disable-avdevice \? ? --disable-doc \? ? --disable-symver \#關(guān)鍵點(diǎn)1.指定交叉編譯工具目錄--cross-prefix=$CROSS_PREFIX\#關(guān)鍵點(diǎn)2.指定目標(biāo)平臺為android--target-os=android \#關(guān)鍵點(diǎn)3.指定cpu類型--arch=$ARCH\#關(guān)鍵點(diǎn)4.指定cpu架構(gòu)--cpu=$CPU\#超級關(guān)鍵點(diǎn)5.指定c語言編譯器--cc=$CC--cxx=$CXX#關(guān)鍵點(diǎn)6.開啟交叉編譯--enable-cross-compile \#超級關(guān)鍵7.配置編譯環(huán)境c語言的頭文件環(huán)境--sysroot=$SYSROOT\? ? --extra-cflags="-Os -fpic$OPTIMIZE_CFLAGS"\? ? --extra-ldflags="$ADDI_LDFLAGS"\$ADDITIONAL_CONFIGURE_FLAGmake cleanmakemake installecho"The Compilation of FFmpeg for$CPUis completed"}#armv8-aARCH=arm64CPU=armv8-a#r20版本的ndk中所有的編譯器都在/android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/目錄下(clang)CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clangCXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++#頭文件環(huán)境用的不是/android-ndk-r20/sysroot,而是編譯器//android-ndk-r20/toolchains/llvm/prebuilt/linux-x86_64/sysrootSYSROOT=$NDK/toolchains/llvm/prebuilt/linux-x86_64/sysroot#交叉編譯工具目錄,對應(yīng)關(guān)系如下(不明白的可以看下圖)# armv8a -> arm64 -> aarch64-linux-android-# armv7a -> arm -> arm-linux-androideabi-# x86 -> x86 -> i686-linux-android-# x86_64 -> x86_64 -> x86_64-linux-android-CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-#輸出目錄PREFIX=$(pwd)/android/$CPUOPTIMIZE_CFLAGS="-march=$CPU"#方法調(diào)用build_android復(fù)制代碼

其他

其他的可能碰到的錯誤,比如無法創(chuàng)建文件,目錄不存在等等大多都是權(quán)限以及系統(tǒng)缺少相關(guān)庫導(dǎo)致的,百度一下大多都能解決。

提示:這里編譯出來的so文件是不能直接用的,還需要在AndroidStudio構(gòu)建native方法,重新編譯。

作者:xiaojigugu

鏈接:https://juejin.im/post/5d831333f265da03c61e8a28

來源:掘金

著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容