【Android 音視頻開發打怪升級:FFmpeg音視頻編解碼篇】1、FFmpeg so庫編譯

【聲 明】

首先,這一系列文章均基於本身的理解和實踐,可能有不對的地方,歡迎你們指正。
其次,這是一個入門系列,涉及的知識也僅限於夠用,深刻的知識網上也有許許多多的博文供你們學習了。
最後,寫文章過程當中,會借鑑參考其餘人分享的文章,會在文章最後列出,感謝這些做者的分享。html

碼字不易,轉載請註明出處!linux

教程代碼:【Github傳送門

目錄

1、Android音視頻硬解碼篇:

2、使用OpenGL渲染視頻畫面篇

3、Android FFmpeg音視頻解碼篇

  • 1,FFmpeg so庫編譯
  • 2,Android 引入FFmpeg
  • 3,Android FFmpeg視頻解碼播放
  • 4,Android FFmpeg+OpenSL ES音頻解碼播放
  • 5,Android FFmpeg+OpenGL ES播放視頻
  • 6,Android FFmpeg簡單合成MP4:視屏解封與從新封裝
  • 7,Android FFmpeg視頻編碼

本文你能夠了解到

使用 GCCCLANG 交叉編譯出Android平臺可使用的FFmpeg so庫。爲了很好的邁出 FFmpeg 開發的第一步,不只要知其然,更要知其因此然。不只要知道怎麼樣能成功編譯,更要知道爲何能成功編譯。在開始動手以前,建議先通讀整篇文章,相信本文定可讓你有所感悟。android

1、前言

網上其實已經有不少的關於FFmpeg so庫編譯的分享,可是大部分都是直接把配置文件的內容貼出來。我想大部分去搜索 「如何編譯FFmpeg so庫」的人,對交叉編譯這個東東都是比較陌生的。git

特別對於移動端開發者來講,大部分人大多數時候都是在Java層作開發,不多接觸到NDK層的東西。若是直接去看一份交叉編譯的配置,估計會很上頭。github

一般狀況下,在一篇FFmpeg編譯的文章下面都會有不少的相似「爲何按照樓主的配置仍是沒法編譯成功?」的評論,那爲何人家能夠編譯成功,咱們copy下來卻不能夠呢?shell

緣由有很是多,大部分其實集中在如下幾個方面:bash

1. 無腦copy,祈求有一個傻瓜式的配置能夠成功編譯;
2. FFmpeg版本和NDK版本不少,每個版本均可能須要不同的配置;
3. 不瞭解每一個配置項的意義,即便好運配置對了, 可是稍微一修改,又沒法正常編譯了。
複製代碼

爲何FFmpeg讓人以爲很難搞?架構

我想主要是由於邁出第一步就很困難,連so庫都編譯不出來,後面的都是扯淡了。app

2、什麼是交叉編譯

定義

引自百度百科的定義:交叉編譯,是在一個平臺上生成另外一個平臺上的可執行代碼。cors

什麼意思呢?說白了,就是在一個機器上生成一個程序,這個程序能夠跑在另一個機器上。舉慄:在PC上編譯一個apk,這個apk能夠跑在Android手機上,這其實就是一個交叉編譯的過程。

爲何要交叉編譯

咱們知道,PC上的軟件是直接在PC上編譯生成的,那爲何Android上的軟件不能在Android上本身編譯生成呢?

理論上是能夠,可是Android手機上的資源有限啊,在PC上編譯一個apk都要那麼久,你能夠想象在Android手機上編譯一個apk要多久嗎?或者你能想象在手機上敲代碼的情景嗎?

那咱們會想既然PC上資源那麼豐富,那可不能夠利用PC來編譯出在手機上能夠運行的軟件呢?

因而,交叉編譯出現。

交叉編譯須要的什麼

編譯環境

咱們知道PC上的環境和手機上的運行環境是絕然不一樣的,若是使用PC上的環境直接編譯的話,能夠想象這個編譯出來的App,分分鐘就會掛掉。

因此,交叉編譯最重要的是,要配置好編譯過程當中使用到的相關的環境,而這個環境其實就是目標機器(好比Android手機)正在運行的環境。

編譯工具鏈

對於C/C++的編譯,一般有兩個工具 GCCCLANG

GCC 可能你們都有據說過,這是一個老牌的編譯工具,不只能夠編譯C/C++,也能夠編譯Java,Object-C,Go等語言。

CLANG 則是一個效率更高的C/C++編譯工具,而且兼容GCC,Google在很早之前就開始建議使用clang進行編譯,而且在 ndk 17 之後,把 GCC 移除了,全面推行使用 CLANG

3、如何交叉編譯FFmpeg

FFmpeg是什麼

鼎鼎大名的FFmpeg,不說在音視頻界如雷貫耳,就算一個不開發音視頻的開發者也都是略有耳聞。

官方簡介

A complete, cross-platform solution to record, convert and stream audio and video.

翻譯過來就是:FFmpeg是一套集錄制、轉換以及流化音視頻的完整的跨平臺解決方案。

從這段簡介能夠看到FFmpeg有如下特色:

  1. 功能強大:錄製、解碼、編碼、編輯、推流等等
  2. 跨平臺

編譯流程

從前面的介紹,基本上能夠總結出FFmepg編譯的基本流程:

  1. 選擇編譯工具
  2. 配置交叉編譯環境
  3. 配置編譯參數(好比去掉一些不須要的功能)
  4. 啓動編譯

流程就是這麼簡單,接下來就來詳細看看,如何經過 CLANGGCC 兩種方式來編譯。

4、使用CLANG編譯FFmpeg

注:本文編譯平臺爲Mac,建議使用Mac或者Linux進行編譯,聽說Windows有不少坑。

下載Android NDK

Android 的 NDK 已經迭代了不少版本,在 r17c 之後,Google正式移除 GCC ,再也不支持 GCC ,新版本的 NDK 都是使用 CLANG 進行編譯。

這裏就使用目前最新的 NDK r20b 版原本編譯。

NDK 下載地址:Android-NDK

NDK 目錄

NDK r20b 目錄

最主要的就是這兩個路徑:

編譯工具鏈目錄:
toolchains/llvm/prebuilt/darwin-x86_64/bin

交叉編譯環境目錄:
toolchains/llvm/prebuilt/darwin-x86_64/sysroot
複製代碼
  • 編譯工具路徑

編譯工具

根據不一樣的CPU架構區和不一樣的Android版本,區分了不一樣的clang工具,根據本身須要選擇就行了。

本文選擇 CPU 架構 armv7a,Android版本 21:

armv7a-linux-androideabi21-clang
armv7a-linux-androideabi21-clang++
複製代碼
  • 編譯環境路徑

toolchains/llvm/prebuilt/darwin-x86_64/sysroot 目錄下,包含了兩個目錄: usr/includeusr/lib,分別對應了 頭文件庫文件

庫文件和頭文件

下載FFmpeg源碼

FFmpeg官網下載,直接DownLoad便可。

本文使用的是目前最新的版本 ffmpeg-4.2.2

下載好源碼後,進入根目錄,找到一個名爲 congfigure 的文件,這是一個shell腳本,用於生成一些 FFmpeg 編譯須要的配置文件。

這個文件很是重要,FFmpeg 的編譯配置就是靠它完成的。 後面咱們將對其中一些重要的內容進行分析,這是理解 FFmpeg 編譯配置的關鍵。

有了以上基礎之後,就能夠對FFmpeg進行編譯了。

配置腳本

  • 修改 configure 腳本
  1. 新增 cross_prefix_clang 參數

打開(注:不是雙擊運行) ffmpeg-4.2.2 根目錄下的 configure 文件,搜索 CMDLINE_SET ,能夠找到如下代碼,而後新增一個命令行選項:cross_prefix_clang

CMDLINE_SET=" $PATHS_LIST ar arch as assert_level build_suffix cc objcc cpu cross_prefix # 新增命令行參數 cross_prefix_clang custom_allocator cxx dep_cc # 省略其餘..... "
複製代碼
  1. 修改編譯工具路徑設置

搜索 ar_default="${cross_prefix}${ar_default}" , 找到如下代碼

ar_default="${cross_prefix}${ar_default}"
cc_default="${cross_prefix}${cc_default}"
cxx_default="${cross_prefix}${cxx_default}"
nm_default="${cross_prefix}${nm_default}"
pkg_config_default="${cross_prefix}${pkg_config_default}"
複製代碼

將中間兩行修改成

ar_default="${cross_prefix}${ar_default}"
#------------------------------------------------
cc_default="${cross_prefix_clang}${cc_default}"
cxx_default="${cross_prefix_clang}${cxx_default}"
#------------------------------------------------
nm_default="${cross_prefix}${nm_default}"
pkg_config_default="${cross_prefix}${pkg_config_default}"
複製代碼

至於爲何這麼修改,將在後面的 configure 分析中詳細講解

  • 新建編譯配置腳本

ffmpeg-4.2.2 根目錄下新建 shell 腳本,命名爲: build_android_clang.sh

#!/bin/bash
set -x
# 目標Android版本
API=21
CPU=armv7-a
#so庫輸出目錄
OUTPUT=/Users/cxp/Desktop/FFmpeg/ffmpeg-4.2.2/android/$CPU
# NDK的路徑,根據本身的NDK位置進行設置
NDK=/Users/cxp/Desktop/FFmpeg/android-ndk-r20b
# 編譯工具鏈路徑
TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64
# 編譯環境
SYSROOT=$TOOLCHAIN/sysroot

function build
{
  ./configure \
  --prefix=$OUTPUT \
  --target-os=android \
  --arch=arm \
  --cpu=armv7-a \
  --enable-asm \
  --enable-neon \
  --enable-cross-compile \
  --enable-shared \
  --disable-static \
  --disable-doc \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-symver \
  --disable-ffmpeg \
  --sysroot=$SYSROOT \
  --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
  --cross-prefix-clang=$TOOLCHAIN/bin/armv7a-linux-androideabi$API- \
  --extra-cflags="-fPIC"

  make clean all
  # 這裏是定義用幾個CPU編譯
  make -j12
  make install
}

build
複製代碼

這個shell腳本,大致上其實仍是很容易懂的,好比

--disabble-static --enable-shared 分別用於禁止輸出靜態庫,以及輸出動態庫;

--arch --cpu 用於配置輸出的so庫是什麼架構的;

--prefix 用於配置輸出的so庫的存放路徑。

接下來重點來說一下幾個選項:

  • target-os

--target-os=android:在舊版本的 FFmpeg 中,對Android平臺的支持並非很完善,並無 android 這個target,因此在一些比較老的文章中都會提到,編譯Android平臺的so庫,須要對 configure 作如下修改,不然會按照 linux 標準的方式輸出so庫,其命名方式和Android的so不同,Android是沒法加載的。

SLIBNAME_WITH_VERSION='$(SLIBNAME).$(LIBVERSION)'
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_VERSION='$(SLIBNAME).$(LIBVERSION)'
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'  
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'  
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'  
SLIB_INSTALL_LINKS='$(SLIBNAME)'
複製代碼

可是在新版本的FFmpeg中,這個問題終於被解決了,FFmpeg加入了 android 這個 target因此咱們不再須要手動去修改了

  • sysroot

--sysroot=$SYSROOT: 用於配置交叉編譯環境的 根路徑 ,編譯的時候會默認從這個路徑下去尋找 usr/include usr/lib 這兩個路徑,進而找到相關的頭文件和庫文件。

r20b 版本的 NDK 系統的頭文件和庫文件就是在 $SYSYROOT/usr/include$SYSYROOT/usr/lib 中。

基本上不少新手在編譯的時候都會出現找不到各類頭文件,致使編譯失敗。因此當編譯出現找不到頭文件的時候,首先要檢查的就是這個路徑。

一點疑問

在使用最新的 ndk r20b 版本進行編譯的時候發現,即便不配置 sysroot 也能夠正常編譯,懷疑 Android 的 clang 工具是否通過了處理,會自動去尋找對應的路徑。 目前沒有從 configure 文件中找到緣由。
若有知情者的,還望告知呀~。

說到 sysroot 就不得不提到另一個參數 -isysyroot ,這個參數也讓我困惑了好久,由於不多文章會提到這個兩個參數的聯繫和區別,然而這個參數也很致使讓人很莫名奇妙的編譯失敗。

  • extra-cflags

介紹 -isysroot 以前,先看看這個 extra-cflags 選項。

這個選項的做用是,給編譯器指定除了 sysroot 以外的頭文件搜索路徑。好比:

--extra-cflags="-I$SYSROOT/usr/include"

# 其中 -I 用於區分不一樣的路徑
複製代碼

-isysroot 是這個選項的一個配置。好比

--extra-cflags="-isysroot $SYSROOT"
複製代碼

-isysroot 的做用就是,把後面的路徑設置爲默認的頭文件搜索路徑,這時候,前面 sysroot 配置路徑就再也不做爲 頭文件 默認的搜索路徑了,不過依然是 庫文件 默認的搜索路徑。

能夠看到,這兩個配置從某種程度上說是同樣的:

--extra-cflags="-I$SYSROOT/usr/include"

約等於

--extra-cflags="-isysroot $SYSROOT"

複製代碼
  • extra-ldflags

這個和上面的 extra-cflags 做用是相似的,不過是用於配置額外的 庫文件 搜索路徑,如

--extra-ldflags="-L$SYSROOT/usr/lib"
# 其中 -L 用於區分不一樣的路徑
複製代碼

能夠看到 extra-cflags extra-ldflags 結合起來能夠替代 sysroot

  • cross-prefix

這個選項直譯爲 交叉編譯前綴,指的是交叉編譯工具的前綴。

這個選項常常和另一個選項 cc 一塊兒出現搭配使用。

這是什麼意思呢?網上有的文章對於 cc 這個選項常常出現兩種配置方式:

一種是隻配置 cross-prefix ,沒有配置 cc ,好比本文。

另外一種是既配置 cross-prefix ,又配置 cc

好比:

--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
複製代碼

這是兩種徹底不一樣的配置方式,可是很神奇的是有時候他們都能成功編譯,有時候又會出現找不到編譯鏈工具的錯誤。

爲了搞明白 cross-prefix cc 這兩個選項的配置到底有什麼影響,到底應該怎麼使用這兩個配置,我特意仔細的去看了 FFmpeg 根目錄下的 configure 配置腳本,找到了一些蛛絲馬跡。

分析 configure 配置腳本

注:如下分析基於ffmpeg-4.2.2版本,其餘版本可能有所不一樣,掌握基本原理便可。

  • 獲取用戶配置選項

打開(注:不是雙擊運行)configure shell腳本,首先來看看 configure 是如何獲取用戶配置的編譯選項的。

搜索 for opt do,能夠找到如下代碼

for opt do
    optval="${opt#*=}"
    case "$opt" in
        --extra-ldflags=*)
            add_ldflags $optval
        ;;
        --extra-ldexeflags=*)
            add_ldexeflags $optval
        ;;
        --extra-ldsoflags=*)
            add_ldsoflags $optval
        ;;
        --extra-ldlibflags=*)
            warn "The --extra-ldlibflags option is only provided for compatibility and will be\n"\
                 "removed in the future. Use --extra-ldsoflags instead."
            add_ldsoflags $optval
        ;;
        --extra-libs=*)
            add_extralibs $optval
        ;;
        --disable-devices)
            disable $INDEV_LIST $OUTDEV_LIST
        ;;
        --enable-debug=*)
            debuglevel="$optval"
        ;;
        
        # 省略中間一些代碼...
        
        *)
            optname="${opt%%=*}"
            optname="${optname#--}"
            optname=$(echo "$optname" | sed 's/-/_/g')
            if is_in $optname $CMDLINE_SET; then
                eval $optname='$optval'
            elif is_in $optname $CMDLINE_APPEND; then
                append $optname "$optval"
            else
                die_unknown $opt
            fi
        ;;
    esac
done
複製代碼

這個shell腳本的代碼有不少特有的語法,也不用鑽牛角尖,能大概看明白就能夠了。

for循環的首行 經過分割 = 獲取到用戶設置的選項值 optval

下面除了一些特殊的選項,咱們看看最後的通配符 *) ,這段代碼的目的,其實就是把用戶配置的選項和值關聯起來。

好比 --cpu=armv7-a ,前面三行就是把 cpu 分割出來,賦值給 optname,再把 optval 賦值給 cpu,說白了就是初始化了 cpu 這個變量爲 armv7-a

  • Android相關的配置

搜索 android 關鍵字,能夠找到如下代碼

# ffmpeg-4.2.2/configure

if test "$target_os" = android; then
    cc_default="clang"
fi

ar_default="${cross_prefix}${ar_default}"
cc_default="${cross_prefix}${cc_default}"
cxx_default="${cross_prefix}${cxx_default}"
nm_default="${cross_prefix}${nm_default}"
pkg_config_default="${cross_prefix}${pkg_config_default}"
複製代碼

當你配置了 --target-os=android 的時候,FFmpeg默認的編譯工具爲 clang

cc_default 其實就是配置項 cc 的默認值,能夠看到 cc_default 在這裏和 cross_prefix 作了拼接。這裏就是爲何說 cross_prefix 是交叉編譯工具前綴。

拼接完是這樣的:

cc_defalut=$TOOLCHAIN/bin/arm-linux-androideabi-$cc
複製代碼

看下 ar_default cc_default cxx_default這些默認值是什麼。

搜索 cc_default 能夠找到如下代碼

# ffmpeg-4.2.2/configure

ar_default="ar"
cc_default="gcc"
cxx_default="g++"
host_cc_default="gcc"
複製代碼

能夠看到,FFmpeg 默認的編譯工具是 GCC

當你編譯 Android 平臺的庫時,因爲 configure 強制設置 cc_default="clang",因此:

  1. 當你使用 GCC 做爲編譯工具時,必須配置 cc 選項,或修改 configure 中的 cc_default="clang"cc_default="gcc" ;

  2. 當你使用 CLANG 做爲編譯工具時,能夠不配置 cc 選項。

仔細想一想會發現,爲何當 cc 配置爲下邊的值時,也能夠正常編譯呢?

--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc
複製代碼

這時 cc_defalut 不就等於

cc_defalut=$TOOLCHAIN/bin/arm-linux-androideabi-$TOOLCHAIN/bin/arm-linux-androideabi-gcc
複製代碼

這個路徑確定是錯的啊!

這就要來看到底 cc_default 是怎麼使用的了。

  • 初始化變量

搜索 set_default arch ,能夠看到如下代碼,在這裏 configure 從新設置了 cc 的默認值。

set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \
    target_exec x86asmexe nvcc
複製代碼

這裏調用了一個叫 set_default 的函數,來看看這個函數的實現

set_default(){
    for opt; do
        eval : \${$opt:=\$${opt}_default}
    done
}
複製代碼

這也是一個看不太懂的shell語法,大概的意思就是:for循環獲取全部的輸入參數變量,而後給這個變量賦值。

好比 set_default cc ,意思就是 cc=cc_default ,不過有一點要注意的是中間這個符號 :=

這個符號相似Java中的三目運算符:

opt != null? opt:opt_defalut
複製代碼

也就是說,若是參數爲空,將 xx_default 賦值給 xx

這就能夠解釋上面的疑問了。

  1. 當配置
--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc
複製代碼

set_default cc 等於沒有用了。由於通過 for 循環獲取了用戶的配置之後, cc 不爲空。 set_default 後,cc 的值是不會改變的。

  1. cc 不配置的時候,FFmpeg 根據默認的拼接方式,把拼接好的路徑設置給 cc

  2. 可是,不能配置 cc=gcc 這種,這樣,最後 cc 的值就只有 gcc ,確定是不能正確找到編譯工具的。

  • 爲何要加入 corss-prefix-clang 這個選項

如今能夠來解釋爲何前面須要修改 configure 配置腳本了。

原始的配置是這樣的

ar_default="${cross_prefix}${ar_default}"
cc_default="${cross_prefix}${cc_default}"
cxx_default="${cross_prefix}${cxx_default}"
nm_default="${cross_prefix}${nm_default}"
pkg_config_default="${cross_prefix}${pkg_config_default}"
複製代碼

也就是說,默認的 cc ar nm 路徑前綴是同樣的,可是 Android NDK 的路徑倒是這樣的

NDK clang路徑

看到了不?ar/nmcc的前綴是不同的,前者是 arm-linux-androideabi- , 後者是 armv7a-linux-androideabi16-

所以,須要對 cccxx 兩個前綴進行修改,爲此新加了 cross_prefix_clange 來進行單獨配置。

這裏只是針對 NDK r20b 的狀況,不一樣的 NDK 版本可能有所不一樣,根據這個原理去設置便可。

綜上,解釋了一些編譯 FFmpeg 經常使用的配置選項,而且從原理上弄明白爲什麼要這樣配置,基本上搞清楚了這些,想要組合兩個不一樣版本的FFmpeg和NDK來編譯,都會比較容易實現。

啓動編譯

打開cmd終端,cd 到 FFmpeg 所在目錄

輸入 ./build_android_clang.sh

等待編譯完成,將會在 ffmpeg/android/armv7-a目錄下獲得 includelib 兩個目錄,分別是 頭文件so庫文件

生成的so

生成的頭文件

5、使用 GCC 編譯FFmpeg

目前大部分網上的文章都是使用 GCC 來編譯 FFmpeg 的,下面就來看看如何配置 GCC 的編譯參數。

下載 Android NDK r17b

前面就說過,NDK r17c 之後,Googole 就移除了 GCC,因此要使用 GCC 只能下載 r17c 及之前的版本,本文使用 r17c 來編譯。

根據本身編譯平臺選擇對應的版本:NDK r17c

本文選擇的是 Mac 版本:Mac OS X。

NDK 相關的環境路徑

NDK r17c 目錄

NDK r20b 相比,NDK r17c的目錄稍微有些變化。

  • 交叉編譯環境路徑
# 庫文件路徑
android-ndk-r17c/platforms/android-21/arch-arm/usr/lib
複製代碼
# 頭文件路徑
android-ndk-r17c/sysroot/usr/include
複製代碼
  • GCC 工具鏈路徑
android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin
複製代碼

能夠看到,Google 將 頭文件庫文件 分離了,這也是不少新手在編譯的時候一直沒有配對路徑,致使編譯失敗的緣由。

新建編譯配置腳本

FFmpeg 的版本依然是使用上面的 ffmpeg-4.2.2 , 固然,此次不須要修改 configure 了。

根據前面介紹的知識,很容易就能寫出編譯配置了

ffmpeg-4.2.2 根目錄新建腳本: build_android_gcc.sh

#!/bin/bash
set -x
API=21
CPU=armv7-a
#so庫輸出目錄
OUTPUT=/Users/cxp/Desktop/FFmpeg/ffmpeg-4.2.2/android/$CPU
# NDK的路徑,根據本身的安裝位置進行設置
NDK=/Users/cxp/Desktop/FFmpeg/android-ndk-r17c
# 庫文件
SYSROOT=$NDK/platforms/android-$API/arch-arm
# 頭文件
ISYSROOT=$NDK/sysroot/usr/include
# 彙編頭文件
ASM=$ISYSROOT/arm-linux-androideabi
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64

function build
{
./configure \
  --prefix=$OUTPUT \
  --target-os=android \
  --arch=arm \
  --cpu=armv7-a \
  --enable-asm \
  --enable-cross-compile \
  --enable-shared \
  --disable-static \
  --disable-doc \
  --disable-ffplay \
  --disable-ffprobe \
  --disable-symver \
  --disable-ffmpeg \
  --sysroot=$SYSROOT \
  --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
  --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
  --extra-cflags="-I$ISYSROOT -I$ASM -fPIC"

make clean all
# 這裏是定義用幾個CPU編譯
make -j12
make
make install
}
build
複製代碼

能夠看到,在基本上配置和使用 CLANG 進行編譯差很少。

有如下不一樣:

  1. 多了 cc 配置。由於若是不配置 cc 默認爲 clang (參考前文的分析);
  2. 多了 extra-cflags 的配置,由於 SYSROOT 中只包含了 庫文件 ,須要額外配置 頭文件 的搜索路徑;彙編頭文件 的路徑也不在 SYSROOT 中,也須要額外配置 ASM

啓動編譯

打開 cmd 終端,cd 到 ffmpeg-4.2.2 目錄

執行 ./build_android_gcc.sh

6、總結

經過對 configure 的分析,可讓咱們更加清晰的理解每一個參數配置項的意義,以及如何搭配使用這些配置。只要清楚了各個配置的含義,不管版本怎麼變化,均可很快的寫出編譯腳本。

當了,本文只是介紹了最基礎的配置方案,你還能夠經過更多的 --disable-xxx 選項實現對 FFmpeg 的裁剪,或者經過 --enable-xxx 選項,開啓一些高級功能。

參考文章

FFmpeg源代碼簡單分析:configure

編譯 FFmpeg 之 clang

相關文章
相關標籤/搜索