ffmpeg4.4 for Android 編譯 ndk(r21e)

最近也是準(zhǔn)備學(xué)習(xí)音視頻相關(guān)的內(nèi)容逮走,可在第一步--編譯就卡住了很久贯莺,遇到很多莫名其妙的坑,可謂編譯的血淚史怪与,但是在查閱幾十篇博客和逛爛StackOverFlow之后,終于算是成功的把ffmpeg給編譯出來(lái)了缅疟,現(xiàn)在分享給大家一些我踩過(guò)的坑分别。

編譯環(huán)境

本機(jī)系統(tǒng):macOS Big Sur 11.2.1

ffmpeg: 4.4

ndk:r21e

一、準(zhǔn)備工作

下載 FFmpeg

點(diǎn)擊這個(gè)

image-20210421180825019.png

下載完成之后解壓即可存淫。

下載ndk(需要翻墻)耘斩,如果是Android開(kāi)發(fā)者可以直接自己的Sdk目錄下找到ndk(無(wú)需重新下載)。打開(kāi)Android Studio去這個(gè)目錄下面找

image-20210421181344148.png

可以看到這個(gè)目錄下有個(gè)ndk的目錄

image-20210421181504187.png

二桅咆、編寫(xiě)編譯腳本

1.先進(jìn)入解壓好的ffmpeg文件夾括授,找到configure文件

image-20210421182246442.png

用記事本或者VSCode之類(lèi)的編輯器打開(kāi),找到以下代碼并進(jìn)行替換

# 注釋掉默認(rèn)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)'
注意第二行的 LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
$$(RANLIB)和"$(LIBDIR)/$(LIBNAME)"之間有一個(gè)空格岩饼,好像空格打掉了編譯會(huì)出問(wèn)題

改好之后記得保存

2.新建構(gòu)建腳本(重要)

在解壓出來(lái)的ffmpeg目錄下打開(kāi)命令行工具荚虚,輸入

touch build_android.sh

然后隨便找個(gè)編輯器打開(kāi)這個(gè)編譯文件,vim籍茧、Sublime版述、VSCode都行。

復(fù)制粘貼以下編譯代碼寞冯,對(duì)編譯代碼不熟悉的渴析,后面我會(huì)一步步的解析這個(gè)編譯腳本

#!/bin/bash
# 以下路徑需要修改成自己的NDK目錄
TOOLCHAIN=/xxxxxx/toolchains/llvm/prebuilt/darwin-x86_64
# 最低支持的android sdk版本
API=21

function build_android
{
echo "Compiling FFmpeg for $CPU"
./configure \
 --prefix=$PREFIX \
 --disable-neon \
 --disable-hwaccels \
 --disable-gpl \
 --disable-postproc \
 --enable-shared \
 --enable-jni \
 --disable-mediacodec \
 --enable-small \
 --enable-gpl \
 --disable-decoder=h264_mediacodec \
 --disable-static \
 --disable-doc \
 --disable-programs \
 --disable-ffmpeg \
 --disable-ffplay \
 --disable-ffprobe \
 --disable-avdevice \
 --disable-symver \
 --cross-prefix=$CROSS_PREFIX \
 --target-os=android \
 --arch=$ARCH \
 --cpu=$CPU \
 --cc=$CC \
 --cxx=$CXX \
 --enable-cross-compile \
 --sysroot=$SYSROOT \
 --extra-cflags="-mno-stackrealign -Os -fpic $OPTIMIZE_CFLAGS" \
 --extra-ldflags="$ADDI_LDFLAGS" \
 $ADDITIONAL_CONFIGURE_FLAG
make clean
make -j4
make install
echo "The Compilation of FFmpeg for $CPU is completed"
}

#armv8-a
ARCH=arm64
CPU=armv8-a
# r21版本的ndk中所有的編譯器都在/toolchains/llvm/prebuilt/darwin-x86_64/目錄下(clang)
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
# NDK頭文件環(huán)境
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
# so輸出路徑
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
build_android

# 交叉編譯工具目錄,對(duì)應(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-

# CPU架構(gòu)
#armv7-a
ARCH=arm
CPU=armv7-a
CC=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang
CXX=$TOOLCHAIN/bin/armv7a-linux-androideabi$API-clang++
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
build_android

#x86
ARCH=x86
CPU=x86
CC=$TOOLCHAIN/bin/i686-linux-android$API-clang
CXX=$TOOLCHAIN/bin/i686-linux-android$API-clang++
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/i686-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=i686 -mtune=intel -mssse3 -mfpmath=sse -m32"
build_android

#x86_64
ARCH=x86_64
CPU=x86-64
CC=$TOOLCHAIN/bin/x86_64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/x86_64-linux-android$API-clang++
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/x86_64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU -msse4.2 -mpopcnt -m64 -mtune=intel"
# 方法調(diào)用
build_android

選一個(gè)編譯單元來(lái)解析

#armv8-a
ARCH=arm64
CPU=armv8-a
# r21版本的ndk中所有的編譯器都在/toolchains/llvm/prebuilt/darwin-x86_64/目錄下(clang)
CC=$TOOLCHAIN/bin/aarch64-linux-android$API-clang
CXX=$TOOLCHAIN/bin/aarch64-linux-android$API-clang++
# NDK頭文件環(huán)境
SYSROOT=$TOOLCHAIN/sysroot
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
# so輸出路徑
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
build_android

ARCH、CPU简十、CC這些檬某,相當(dāng)于定義變量撬腾,后面可以通過(guò) $+變量名 進(jìn)行引用螟蝙。這個(gè)我相信大家有一點(diǎn)編程基礎(chǔ)的都不難理解。再變量定義過(guò)后最后一句build_android是執(zhí)行定義的方法民傻,也就是

function build_android
{
echo "Compiling FFmpeg for $CPU"
./configure \
 --prefix=$PREFIX \
 --disable-neon \
 --disable-hwaccels \
 --disable-gpl \
 --disable-postproc \
 --enable-shared \
 --enable-jni \
 --disable-mediacodec \
 --enable-small \
 --enable-gpl \
 --disable-decoder=h264_mediacodec \
 --disable-static \
 --disable-doc \
 --disable-programs \
 --disable-ffmpeg \
 --disable-ffplay \
 --disable-ffprobe \
 --disable-avdevice \
 --disable-symver \
 --cross-prefix=$CROSS_PREFIX \
 --target-os=android \
 --arch=$ARCH \
 --cpu=$CPU \
 --cc=$CC \
 --cxx=$CXX \
 --enable-cross-compile \
 --sysroot=$SYSROOT \
 --extra-cflags="-mno-stackrealign -Os -fpic $OPTIMIZE_CFLAGS" \
 --extra-ldflags="$ADDI_LDFLAGS" \
 $ADDITIONAL_CONFIGURE_FLAG
make clean
make -j4
make install
echo "The Compilation of FFmpeg for $CPU is completed"
}

這一段胰默。

需要注意的點(diǎn)是

編譯腳本最前面的TOOLCHAIN變量,路徑一定要寫(xiě)對(duì)漓踢,后面的變量如果有對(duì)TOOLCHAIN進(jìn)行拼接牵署,也一定要檢查該目錄下的文件路徑是否正確,以及拼接之后的文件是否存在喧半,因?yàn)椴煌姹緉dk可能里面的內(nèi)容或者位置不同奴迅,我不確定您看到這邊文章的時(shí)候里面的文件是否是和我當(dāng)前目錄下的文件一致。如果發(fā)現(xiàn)我給出的編譯腳本中的文件位置和您所使用的ndk文件位置有出入挺据,以自己ndk版本的文件位置為準(zhǔn)

接下來(lái)一起來(lái)解析一下build_android這個(gè)方法取具。

1.echo為打印輸出語(yǔ)句脖隶,沒(méi)什么可說(shuō)的,相當(dāng)于java中的print函數(shù)

2.make clean 每次編譯之前清空上次編譯的內(nèi)容

3.make -j4 使用4核編譯

4.make install 開(kāi)始編譯

重頭戲在這條參數(shù)鏈上暇检,也是我踩坑很久的地方

./configure 表示調(diào)用同級(jí)目錄的configure文件产阱,也就是我們最開(kāi)始修改了4行代碼的那個(gè)文件,后面的--xxxx-xxx 這些配置項(xiàng)具體的我就不細(xì)說(shuō)块仆,有興趣的可以直接用Sublime构蹬、VSCode等編譯器打開(kāi)configure文件,找到Help options 里面每個(gè)參數(shù)都有解釋?zhuān)@里我截取一小段悔据,雖然是英文庄敛,可能對(duì)英文不好的同學(xué)不太友好,但是這個(gè)年代不會(huì)還有人不會(huì)用翻譯軟件吧科汗,不會(huì)吧铐姚,不會(huì)吧?

image-20210422110213088.png

坑1

你會(huì)看到網(wǎng)上的有些編譯腳本是這樣的

image-20210422110414829.png

炸一看肛捍,好像沒(méi)有什么問(wèn)題隐绵,但是你開(kāi)始編譯,你就會(huì)發(fā)現(xiàn)你定義好的$PREFIX找不到文件或者目錄甚至--disable-neon: command not found拙毫。是電腦出問(wèn)題了依许?還是環(huán)境出問(wèn)題了?還是打開(kāi)的姿勢(shì)不對(duì)缀蹄?問(wèn)題的原因在于在整個(gè)參數(shù)配置鏈中不能有注釋及不該有的空格峭跳。我們看到的

# 指定輸出目錄
# 各種配置項(xiàng),想詳細(xì)了解的可以打開(kāi)configure文件找到Help options:查看

這類(lèi)的注釋都會(huì)影響編譯缺前。插入注釋?zhuān)诰幾g解析參數(shù)鏈的時(shí)候就會(huì)解析不到注釋后的那一項(xiàng)參數(shù)配置蛀醉,同理,亂加空格也會(huì)導(dǎo)致同樣的錯(cuò)誤衅码。所以拯刁,無(wú)論在用網(wǎng)上誰(shuí)的編譯腳本進(jìn)行編譯的時(shí)候,都應(yīng)該檢查參數(shù)鏈中是否有注釋或者是多余的空格逝段。

坑2

你可能會(huì)看到有些編譯腳本是這樣

image-20210422111929128.png

炸是一看是不是還是沒(méi)有什么問(wèn)題垛玻?但是你會(huì)發(fā)現(xiàn)你$CXX路徑找不到,此時(shí)你會(huì)去一個(gè)目錄一個(gè)目錄對(duì)這個(gè)文件路徑是否正確奶躯。最后你會(huì)發(fā)現(xiàn)你指定的文件路徑是完全正確的帚桩。那么問(wèn)題出在哪里了呢?問(wèn)題出在參數(shù)鏈如果要換行書(shū)寫(xiě)嘹黔,每個(gè)參數(shù)指定完成之后必須以\結(jié)尾账嚎,因?yàn)槟J(rèn)參數(shù)鏈?zhǔn)切枰恍袝?shū)寫(xiě)完成的,但是為了書(shū)寫(xiě)的美觀,我們選擇了換行郭蕉,所以每個(gè)參數(shù)指定完成后末尾記得加上\.

到此乏悄,編譯腳本就已經(jīng)解析完成

最后在shell中運(yùn)行編譯腳本,首先在macOS和linux下恳不,需要給編譯文件賦予權(quán)限檩小,不然在編譯過(guò)程中,會(huì)遇到一些權(quán)限問(wèn)題烟勋,這里我們直接最高權(quán)限拉滿

chmod -R 777 build_android.sh

然后為了方便查看日志规求,我們把編譯日志輸出到一個(gè)build_log下

./build_anroid.sh > build_log

編譯成功之后,會(huì)在ffmpeg目錄下出現(xiàn)一個(gè)android目錄卵惦,里面有我們編譯的.so文件阻肿。

至此,ffmpeg編譯已經(jīng)完成沮尿,音視頻的學(xué)習(xí)算是踏出了第一步丛塌,對(duì)于ffmpeg的編譯有什么問(wèn)題,也歡迎各位在評(píng)論區(qū)留言討論畜疾。

另外轉(zhuǎn)載請(qǐng)注明出處赴邻,peace !

參考文獻(xiàn)

http://www.reibang.com/p/117fe2ee048a

https://stackoverflow.com/questions/36664451/ffmpeg-android-build

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末啡捶,一起剝皮案震驚了整個(gè)濱河市姥敛,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌瞎暑,老刑警劉巖彤敛,帶你破解...
    沈念sama閱讀 211,743評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)静浴,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,296評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)袄秩,“玉大人,你說(shuō)我怎么就攤上這事嫂拴〔ゾ荆” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 157,285評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵筒狠,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我箱沦,道長(zhǎng)辩恼,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,485評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮灶伊,結(jié)果婚禮上疆前,老公的妹妹穿的比我還像新娘。我一直安慰自己聘萨,他們只是感情好竹椒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,581評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著米辐,像睡著了一般胸完。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上翘贮,一...
    開(kāi)封第一講書(shū)人閱讀 49,821評(píng)論 1 290
  • 那天赊窥,我揣著相機(jī)與錄音,去河邊找鬼狸页。 笑死锨能,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的芍耘。 我是一名探鬼主播址遇,決...
    沈念sama閱讀 38,960評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斋竞!你這毒婦竟也來(lái)了傲隶?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 37,719評(píng)論 0 266
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤窃页,失蹤者是張志新(化名)和其女友劉穎跺株,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體脖卖,經(jīng)...
    沈念sama閱讀 44,186評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡乒省,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,516評(píng)論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了畦木。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片袖扛。...
    茶點(diǎn)故事閱讀 38,650評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖十籍,靈堂內(nèi)的尸體忽然破棺而出蛆封,到底是詐尸還是另有隱情,我是刑警寧澤勾栗,帶...
    沈念sama閱讀 34,329評(píng)論 4 330
  • 正文 年R本政府宣布惨篱,位于F島的核電站,受9級(jí)特大地震影響围俘,放射性物質(zhì)發(fā)生泄漏砸讳。R本人自食惡果不足惜琢融,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,936評(píng)論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望簿寂。 院中可真熱鬧漾抬,春花似錦、人聲如沸常遂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,757評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)克胳。三九已至平绩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間毯欣,已是汗流浹背馒过。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,991評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留酗钞,地道東北人腹忽。 一個(gè)月前我還...
    沈念sama閱讀 46,370評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像砚作,于是被迫代替她去往敵國(guó)和親窘奏。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,527評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容