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

轉自:https://juejin.im/post/5e130df55188253a8b42ebac

目錄

一、Android音視頻硬解碼篇:

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

三、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 開發的第一步,不僅要知其然,更要知其所以然。不僅要知道怎麼樣能成功編譯,更要知道爲什麼能成功編譯。在開始動手之前,建議先通讀整篇文章,相信本文定可以讓你有所感悟。

一、前言

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

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

通常情況下,在一篇FFmpeg編譯的文章下面都會有很多的類似「爲什麼按照樓主的配置還是無法編譯成功?」的評論,那爲什麼人家可以編譯成功,我們copy下來卻不可以呢?

原因有非常多,大部分其實集中在以下幾個方面:

1. 無腦copy,祈求有一個傻瓜式的配置可以成功編譯;
2. FFmpeg版本和NDK版本很多,每一個版本都可能需要不一樣的配置;
3. 不瞭解每個配置項的意義,即使好運配置對了, 但是稍微一修改,又無法正常編譯了。
複製代碼

爲什麼FFmpeg讓人覺得很難搞?

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

二、什麼是交叉編譯

定義

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

什麼意思呢?說白了,就是在一個機器上生成一個程序,這個程序可以跑在另外一個機器上。舉慄:在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

三、如何交叉編譯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 兩種方式來編譯。

四、使用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

 

 

 

生成的頭文件

 

 

五、使用 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

六、總結

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

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

參考文章

FFmpeg源代碼簡單分析:configure

編譯 FFmpeg 之 clang

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章