1 . FFMPEG 下载 :
① FFMPEG 源码下载地址 : http://ffmpeg.org/download.html#releases
② 本博客使用的源码下载地址 : https://ffmpeg.org/releases/ffmpeg-4.0.2.tar.bz2
( 也可以直接从博客资源中下载 )
2 . 解压源码 : 使用 tar xvf ffmpeg-4.0.2.tar.bz2 命令 , 解压源码 ;
root@octopus:~# cd FFMPEG/
root@octopus:~/FFMPEG# ls
ffmpeg-4.0.2.tar.bz2
root@octopus:~/FFMPEG# tar xvf ffmpeg-4.0.2.tar.bz2
ffmpeg-4.0.2/
...
解压后的内容 :
root@octopus:~/FFMPEG/ffmpeg-4.0.2# ls
Changelog COPYING.LGPLv3 libavdevice libswscale RELEASE_NOTES
compat CREDITS libavfilter LICENSE.md tests
configure doc libavformat MAINTAINERS tools
CONTRIBUTING.md ffbuild libavresample Makefile VERSION
COPYING.GPLv2 fftools libavutil presets
COPYING.GPLv3 INSTALL.md libpostproc README.md
COPYING.LGPLv2.1 libavcodec libswresample RELEASE
1 . NDK 下载 : 使用 NDK 17 版本 ;
① NDK 地址列表 : https://developer.android.google.cn/ndk/downloads/older_releases.html
② 直接下载地址 : https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip?hl=zh_cn
2 . Ubuntu Linux 操作系统下载 : 使用 18.04.4 版本的系统 ;
Ubuntu 下载地址 : http://releases.ubuntu.com
1 . Shell 脚本 : 由第一行 Shell 解释器声明 #!/bin/sh
代码 , 可以看出 configure 是 Shell 脚本 ;
2 . configure 脚本作用 : 该脚本用于生成 make 工具的构建脚本 Makefile 文件 ;
3 . configure 脚本执行 : 该脚本需要进行配置才能执行 , 如果直接执行 , 肯定会出错 ;
4 . configure 帮助命令 :
① 脚本复杂 : C/C++ 开源库都会提供一个 configure 脚本 , 该脚本的配置非常复杂 , 但一般都提供一个帮助选项 ;
② 帮助信息 : 执行 ./configure --help 命令 , 即可查看帮助信息 , 建议先将帮助信息熟悉一遍再进行编译 ;
博客资源中有一份完整的 configure 帮助信息内容 , 我对使用到的文档进行了注释 , 仅做参考
1 . FFMPEG 编译流程 :
① 配置 : 使用 configure 脚本进行相关参数配置 ; ( 下面会详细讲解 需要配置的 5 个类型的参数 )
② 编译 : 配置完毕后 , 直接执行 make 命令 , 开始进行编译 ;
2 . 配置的内容 :
① 输出配置 : 配置生成的相关文件输出路径 ;
② 函数库配置 : 配置静态库 , 动态库 , 函数库优化等相关参数 ;
③ 命令行程序配置 : 配置是否生成命令行程序 , FFMPEG 自带 3 个命令行程序 ;
④ 编译组件配置 : FFMPEG 有 22 个可选的独立组件配置 , 可以选择性编译或不编译某些组件 ;
⑤ 编码解码配置 : 配置 FFMPEG 编解码相关功能 ;
⑥ 交叉编译配置 ( 重点 ) : 配置交叉编译工具链 , 头文件与库文件查找路径参数 , GCC 编译器参数 , CPU 指令集架构等参数 ;
下面介绍的所有配置命令都是在 FFMPEG 源码根目录层级中执行 ;
1 . 生成文件的输出目录 : FFMPEG 编译后需要生成一系列的函数库 , 及头文件等 ; 需要为这些生成的文件指定输出目录 ;
2 . 指定生成的文件输出位置 :
① 定义变量 : 使用 PREFIX=./android/armeabi-v7a 命令 , 定义输出目录根目录变量 ;
② 路径配置 : 使用 ./configure --prefix=PREFIX 命令 , 指定输出文件的根目录为 ./android/armeabi-v7a ;
# 将输出目录存储到 PREFIX 变量中
PREFIX=./android/armeabi-v7a
# 执行 configure 脚本配置输出文件的根目录
./configure --prefix=$PREFIX
3 . 自动生成其它目录 : 指定了 --prefix 选项 , 那么其它生成 bin 可执行文件目录 , lib 函数库目录 等类型的文件输出目录会在 --prefix 配置的目录基础上生成 ;
① 根目录 : 指定了 --prefix 目录为 ./android/armeabi-v7a ;
② 可执行文件目录 : 自动生成的可执行文件输出目录为 PREFIX/bin , 即 ./android/armeabi-v7a/bin ;
③ 函数库目录 : 自动生成的函数库数据目录为 PREFIX/lib , 即 ./android/armeabi-v7a/lib ;
其它的标准选项配置 ( Standard options ) 请仔细阅读下面的 configure 帮助文档内容 ;
Standard options: # 标准选项
--logfile=FILE log tests and output to FILE [ffbuild/config.log]
--disable-logging do not log configure debug information
--fatal-warnings fail if any configure warning is generated
# 生成的文件输出目录 , 这里只需要指定一个 PREFIX 即可
# 指定好 PREFIX 后面的一系列目录就会自动设置好 ;
--prefix=PREFIX install in PREFIX [/usr/local]
# 生成的可执行文件输出目录 , 指定好 PREFIX 后面的一系列目录就会自动设置好
--bindir=DIR install binaries in DIR [PREFIX/bin]
--datadir=DIR install data files in DIR [PREFIX/share/ffmpeg]
--docdir=DIR install documentation in DIR [PREFIX/share/doc/ffmpeg]
--libdir=DIR install libs in DIR [PREFIX/lib]
--shlibdir=DIR install shared libs in DIR [LIBDIR]
--incdir=DIR install includes in DIR [PREFIX/include]
--mandir=DIR install man page in DIR [PREFIX/share/man]
--pkgconfigdir=DIR install pkg-config files in DIR [LIBDIR/pkgconfig]
--enable-rpath use rpath to allow installing libraries in paths
not part of the dynamic linker search path
use rpath when linking programs (USE WITH CARE)
--install-name-dir=DIR Darwin directory name for installed targets
Licensing options:
--enable-gpl allow use of GPL code, the resulting libs
and binaries will be under GPL [no]
--enable-version3 upgrade (L)GPL to version 3 [no]
--enable-nonfree allow use of nonfree code, the resulting libs
and binaries will be unredistributable [no]
1 . 函数库配置 : FFMPEG 编译时 , 可以选择编译静态库或动态库 , 及设置编译函数库的行为 ;
2 . 默认编译的函数库 : FFMPEG 默认编译静态库 , 此处也推荐在 Android 中使用 FFMPEG 静态库开发音视频功能 , 保持默认状态即可 ;
3 . 优化函数库 :
① 设置后效果 : FFMPEG 编译时可以选择优化函数库大小 , 让编译出来的函数库尽可能小 , 但相应的编译速度会降低很多 ;
② 设置的要性 : 由于是在 Android 中进行开发 , 为了使打包后的 APK 文件尽可能小 , 这里我们需要开启该选项 ;
③ 设置命令 : 调用 ./configure --enable-small 命令 , 启用优化函数库大小的功能 ;
# 启用函数库大小优化
./configure --enable-small
其它的配置选项 ( Configuration ) 请仔细阅读下面的 configure 帮助文档内容 ;
Configuration options: #配置选项
# 是否关闭静态库编译 , 默认值是 no 会编译静态库
# 如果设置该选项 , 编译时不会编译静态库 ;
# 这里使用默认值 , 即要编译出静态库在 Android 中使用 ;
--disable-static do not build static libraries [no]
# 是否编译动态库 , 默认 no 即不会编译动态库 ; 这里也使用默认值
--enable-shared build shared libraries [no]
# 优化函数库大小 , 但是编译速度很慢 ;
# 如果设置该选项 , 因为 Android 中的函数库越小越好
--enable-small optimize for size instead of speed
--disable-runtime-cpudetect disable detecting CPU capabilities at runtime (smaller binary)
--enable-gray enable full grayscale support (slower color)
--disable-swscale-alpha disable alpha channel support in swscale
--disable-all disable building components, libraries and programs
--disable-autodetect disable automatically detected external libraries [no]
程序配置选项 :
① FFMPEG 命令行程序 : FFMPEG 提供了一些可执行的命令行程序 , 如 ffmpeg.exe , ffplay.exe , ffprobe.exe 等程序 ;
② 使用情况 : 在 Android 开发中只需要 FFMPEG 的函数库 , 不需要这些程序 , 建议关闭命令行程序编译选项 ;
③ 配置命令 : 调用 ./configure --disable-programs 命令 , 关闭编译命令行程序的功能 ;
# 关闭编译命令行程序
./configure --disable-programs
其它的配置选项 ( Configuration ) 请仔细阅读下面的 configure 帮助文档内容 ;
Program options: #程序选项
#关闭命令行程序编译 : FFMPEG 提供了一些可执行的命令行程序
# 如 ffmpeg.exe , ffplay.exe , ffprobe.exe 等程序 ;
# 但是我们只需要 FFMPEG 的函数库 , 不需要这些程序
# 建议关闭编译命令行程序选项 ;
--disable-programs do not build command line programs
# 下面是分别设置 3 个命令行程序是否进行编译
--disable-ffmpeg disable ffmpeg build
--disable-ffplay disable ffplay build
--disable-ffprobe disable ffprobe build
1 . 组件配置选项 :
默认状态 : FFMPEG 组件选项 , 默认都是打开的 , 如果需要关闭某一个需要单独配置 ;
2 . FFMPEG 常用组件 :
① avdevice 组件 : 操作摄像头等视频设备 , Android 中是不支持该操作 , 需要手动关闭 ;
② avcodec 组件 : 声音 / 图像编解码组件 ;
③ avformat 组件 : 音视频封装格式生成或解析 ;
④ swresample 组件 : 音频重采样 , 修改音频参数 ;
⑤ swscale 组件 : 视频场景比例缩放 , 色彩映射转换 ;
⑥ postproc 组件 : 后期效果处理 , 这里不需要 , 需要手动关闭 ;
⑦ avfilter 组件 : 过滤器 , 添加字幕水印 ;
3 . 关闭 avdevice 配置命令 : 调用 ./configure --disable-avdevice 命令 , 关闭 avdevice 模块编译 ;
# 关闭编译命令行程序
./configure --disable-avdevice
其它的组件配置选项 ( Configuration ) 请仔细阅读下面的 configure 帮助文档内容 ;
Component options: # FFMPEG 组件选项 , 默认都是打开的 , 如果需要关闭某一个需要单独配置
# FFMPEG 由以下组件构成 , 可以定制是否编译这些组件 ;
# 操作摄像头等视频设备 , Android 中是不支持该操作 , 需要手动关闭 ;
--disable-avdevice disable libavdevice build
# 声音 / 图像编解码
--disable-avcodec disable libavcodec build
# 音视频封装格式生成或解析
--disable-avformat disable libavformat build
# 音频重采样 , 修改音频参数
--disable-swresample disable libswresample build
# 视频场景比例缩放 , 色彩映射转换
--disable-swscale disable libswscale build
# 后期效果处理 , 这里不需要 , 需要手动关闭 ;
--disable-postproc disable libpostproc build
# 过滤器 , 添加字幕水印
--disable-avfilter disable libavfilter build
--enable-avresample enable libavresample build (deprecated) [no]
--disable-pthreads disable pthreads [autodetect]
--disable-w32threads disable Win32 threads [autodetect]
--disable-os2threads disable OS/2 threads [autodetect]
--disable-network disable network support [no]
--disable-dct disable DCT code
--disable-dwt disable DWT code
--disable-error-resilience disable error resilience code
--disable-lsp disable LSP code
--disable-lzo disable LZO decoder code
--disable-mdct disable MDCT code
--disable-rdft disable RDFT code
--disable-fft disable FFT code
--disable-faan disable floating point AAN (I)DCT code
--disable-pixelutils disable pixel utils in libavutil
1 . 提供的编码配置 :
① 编码器 : 关闭指定编码器 , 关闭所有编码器 , 打开指定编码器 ;
# 关闭指定编码
--disable-encoder=NAME disable encoder NAME
# 打开指定编码
--enable-encoder=NAME enable encoder NAME
# 关闭所有编码
--disable-encoders disable all encoders
② 解码器 : 关闭指定解码器 , 关闭所有解码器 , 打开指定解码器 ;
# 关闭指定解码
--disable-decoder=NAME disable decoder NAME
# 打开指定解码
--enable-decoder=NAME enable decoder NAME
# 关闭所有解码
--disable-decoders disable all decoders
2 . 关闭编码配置命令 : 调用 ./configure --disable-encoders 命令 , 关闭编码器模块编译 ;
# 关闭编译编码器
./configure --disable-encoders
3 . 关闭混合封装配置命令 : 调用 ./configure --disable-muxers 命令 , 关闭混合封装模块编译 ;
# 关闭混合封装
./configure --disable-muxers
2 . 关闭视频滤镜配置命令 : 调用 ./configure --disable-filters 命令 , 关闭视频滤镜模块编译 ;
# 关闭视频滤镜
./configure --disable-filters
其它的单个组件配置选项 ( Configuration ) 请仔细阅读下面的 configure 帮助文档内容 ;
Individual component options: # 单个组件配置
--disable-everything disable all components listed below
# 关闭指定编码
--disable-encoder=NAME disable encoder NAME
# 打开指定编码
--enable-encoder=NAME enable encoder NAME
# 关闭所有编码
--disable-encoders disable all encoders
# 关闭指定解码
--disable-decoder=NAME disable decoder NAME
# 打开指定解码
--enable-decoder=NAME enable decoder NAME
# 关闭所有解码
--disable-decoders disable all decoders
--disable-hwaccel=NAME disable hwaccel NAME
--enable-hwaccel=NAME enable hwaccel NAME
--disable-hwaccels disable all hwaccels
--disable-muxer=NAME disable muxer NAME
--enable-muxer=NAME enable muxer NAME
# 关闭混合封装 , 混合封装就是将音频与视频封装一个视频文件
--disable-muxers disable all muxers
--disable-demuxer=NAME disable demuxer NAME
--enable-demuxer=NAME enable demuxer NAME
--disable-demuxers disable all demuxers
--enable-parser=NAME enable parser NAME
--disable-parser=NAME disable parser NAME
--disable-parsers disable all parsers
--enable-bsf=NAME enable bitstream filter NAME
--disable-bsf=NAME disable bitstream filter NAME
--disable-bsfs disable all bitstream filters
--enable-protocol=NAME enable protocol NAME
--disable-protocol=NAME disable protocol NAME
--disable-protocols disable all protocols
--enable-indev=NAME enable input device NAME
--disable-indev=NAME disable input device NAME
--disable-indevs disable input devices
--enable-outdev=NAME enable output device NAME
--disable-outdev=NAME disable output device NAME
--disable-outdevs disable output devices
--disable-devices disable all devices
--enable-filter=NAME enable filter NAME
--disable-filter=NAME disable filter NAME
--disable-filters disable all filters
1 . 开启交叉编译 : 调用 ./configure --enable-cross-compile 命令 , 开启交叉编译选项 ;
# 关闭视频滤镜
./configure --enable-cross-compile
2 . 设置交叉编译工具链前缀 :
① 定义 NDK 根目录变量 :
NDK_ROOT=/root/NDK/android-ndk-r17c
② 定义 TOOLCHAIN 交叉编译工具链目录变量 :
TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
③ 设置交叉编译工具链前缀 :
./configure --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi-
实际的前缀为 : /root/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-
3 . 配置头文件与库文件查找路劲 :
./configure --sysroot=$NDK_ROOT/platforms/android-21/arch-arm
4 . 配置编译器参数 :
① 先定义编译器参数变量 :
FLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -isystem $NDK_ROOT/sources/android/support/include -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC"
② 配置编译器参数 :
./configure --extra-cflags=$FLAGS
5 . 配置编译平台 :
./configure --arch=arm
6 . 配置编译后的应用平台 : 编译后的函数库要在 Android 平台使用 ;
./configure --target-os=android
其它的编译工具链配置选项 ( Configuration ) 请仔细阅读下面的 configure 帮助文档内容 ;
Toolchain options: # 工具链配置选项
# 指定编译 CPU 指令集架构 , arm
--arch=ARCH select architecture []
--cpu=CPU select the minimum required CPU (affects
instruction selection, may crash on older CPUs)
# 指定交叉编译工具链 , 即 NDK 目录下的交叉编译工具目录 , 其中有一系列的 arm-linux-androideabi-XX 工具
# PREFIX 配置完整的路径/NDK路径/工具前缀
# /root/NDK/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-
# 后面的 gcc , g++ , ar 等工具由脚本自己补充 , 这里我们指定 gcc 前面的前缀内容
--cross-prefix=PREFIX use PREFIX for compilation tools []
--progs-suffix=SUFFIX program name suffix []
# 开启交叉编译
--enable-cross-compile assume a cross-compiler is used
# 头文件与库文件查找目录 , 这里要指定 NDK 中 platform 中的头文件与库文件目录
# 注意 : 每个 NDK 版本的头文件与库文件目录不一致 , 注意灵活配置 , 如果找不到头文件与库文件肯定报错
# 注意版本兼容 , 要配置最低兼容版本的 NDK 头文件 库文件 目录
--sysroot=PATH root of cross-build tree
--sysinclude=PATH location of cross-build system headers
# 指定编译的库运行的操作系统 , android
--target-os=OS compiler targets OS []
--target-exec=CMD command to run executables on target
--target-path=DIR path to view of build directory on target
--target-samples=DIR path to samples directory on target
--tempprefix=PATH force fixed dir/prefix instead of mktemp for checks
--toolchain=NAME set tool defaults according to NAME
(gcc-asan, clang-asan, gcc-msan, clang-msan,
gcc-tsan, clang-tsan, gcc-usan, clang-usan,
valgrind-massif, valgrind-memcheck,
msvc, icl, gcov, llvm-cov, hardened)
--nm=NM use nm tool NM [nm -g]
--ar=AR use archive tool AR [ar]
--as=AS use assembler AS []
--ln_s=LN_S use symbolic link tool LN_S [ln -s -f]
--strip=STRIP use strip tool STRIP [strip]
--windres=WINDRES use windows resource compiler WINDRES [windres]
--x86asmexe=EXE use nasm-compatible assembler EXE [nasm]
--cc=CC use C compiler CC [gcc]
--cxx=CXX use C compiler CXX [g++]
--objcc=OCC use ObjC compiler OCC [gcc]
--dep-cc=DEPCC use dependency generator DEPCC [gcc]
--nvcc=NVCC use Nvidia CUDA compiler NVCC [nvcc]
--ld=LD use linker LD []
--pkg-config=PKGCONFIG use pkg-config tool PKGCONFIG [pkg-config]
--pkg-config-flags=FLAGS pass additional flags to pkgconf []
--ranlib=RANLIB use ranlib RANLIB [ranlib]
--doxygen=DOXYGEN use DOXYGEN to generate API doc [doxygen]
--host-cc=HOSTCC use host C compiler HOSTCC
--host-cflags=HCFLAGS use HCFLAGS when compiling for host
--host-cppflags=HCPPFLAGS use HCPPFLAGS when compiling for host
--host-ld=HOSTLD use host linker HOSTLD
--host-ldflags=HLDFLAGS use HLDFLAGS when linking for host
--host-libs=HLIBS use libs HLIBS when linking for host
--host-os=OS compiler host OS []
# 传递给 gcc 编译器的参数
--extra-cflags=ECFLAGS add ECFLAGS to CFLAGS []
# 传递给 g++ 编译器的参数
--extra-cxxflags=ECFLAGS add ECFLAGS to CXXFLAGS []
--extra-objcflags=FLAGS add FLAGS to OBJCFLAGS []
--extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS []
--extra-ldexeflags=ELDFLAGS add ELDFLAGS to LDEXEFLAGS []
--extra-ldsoflags=ELDFLAGS add ELDFLAGS to LDSOFLAGS []
--extra-libs=ELIBS add ELIBS []
--extra-version=STRING version string suffix []
--optflags=OPTFLAGS override optimization-related compiler flags
--nvccflags=NVCCFLAGS override nvcc flags [-gencode arch=compute_30,code=sm_30 -O2]
--build-suffix=SUFFIX library name suffix []
--enable-pic build position-independent code
--enable-thumb compile for Thumb instruction set
--enable-lto use link-time optimization
--env="ENV=override" override the environment variables
1 . 将本博客内容汇总后 , 编写成 Shell 脚本如下 : 在 FFMPEG 源码根目录下 , 创建 build_ffmpeg.sh 文件 , 内容如下 ;
#!/bin/bash
# NDK 根目录
NDK_ROOT=/root/NDK/android-ndk-r17c
# TOOLCHAIN 变量指向 gcc g++ 等交叉编译工具所在的目录
TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
# gcc 编译器参数
FLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -isystem $NDK_ROOT/sources/android/support/include -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC"
# 编译结果输出路径
PREFIX=./android/armeabi-v7a
# 执行 configure 脚本生成 Makefile 构建脚本
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--sysroot=$NDK_ROOT/platforms/android-21/arch-arm \
--extra-cflags="$FLAGS" \
--arch=arm \
--target-os=android
# 清除之前的编译内容
make clean
# 开启新的 FFMPEG 编译
make install
2 . 修改 Shell 脚本权限 :
chmod +x build_ffmpeg.sh
3 . 执行 Shell 脚本 :
./build_ffmpeg.sh
4 . 编译结果 :