参考
https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/FFmpeg_compile_shell.md

1.准备工作

1.下载NDK并配置好环境,参考
2.下载ffmpeg,然后解压到文件夹
3.安装make,编译脚本要用到
3.1、进入root权限:su root
3.2、更新安装列表:apt-get update
3.3、安装make:apt-get install make

2.修改configure配置

在FFmpeg源码目录有个configure配置脚本,,可以看到如下结构的编译选项:
在FFmpeg源码目录有个configure配置脚本,使用./configure —help进行查看,可以看到如下结构的编译选项:
Tips:因为版本的问题可能会有不同的地方

Help options: Description
—help print this message
—list-decoders show all available decoders
—list-encoders show all available encoders
—list-hwaccels show all available hardware
—list-demuxers show all available demuxers
—list-muxers show all available muxers
—list-parsers show all available parsers
—list-protocols show all available protocols
—list-filters show all available filters
Licensing options: Description
—enable-gpl allow use of GPL code
—enable-version3 upgrade (L)GPL to version 3
—enable-nonfree allow use of nonfree code
Configuration options: Description
—prefix=PREFIX install in PREFIX
—disable-static do not build static libs
—enable-shared build shared libraries [no]
—enable-small optimize for size
—disable-all disable components, libs
—disable-autodetect disable detect external libs
Program options: Description
—disable-programs don’t build command line
—disable-ffmpeg disable ffmpeg build
—disable-ffplay disable ffplay build
—disable-ffprobe disable ffprobe build
Component options: Description
—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
—disable-pthreads disable pthreads
—disable-network disable network support
Individual component: Description
—disable-everything disable all components
—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-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-protocol=NAME enable protocol NAME
—disable-protocol=NAME disable protocol NAME
—disable-protocols disable all protocols
—enable-filter=NAME enable filter NAME
—disable-filter=NAME disable filter NAME
—disable-filters disable all filters
External library: Description
—disable-avfoundation disable Apple AVFoundation framework
—enable-jni enable JNI support [no]
—enable-libaom enable AV1 video codec via libaom [no]
—enable-libass enable libass subtitles rendering [no]
—enable-libdav1d enable AV1 decoding via libdav1d [no]
—enable-libfdk-aac enable AAC de/encoding via libfdk-aac
—enable-libfontconfig enable libfontconfig [no]
—enable-libfreetype enable libfreetype, needed for drawtext
—enable-libfribidi enable libfribidi, improves drawtext
—enable-libmp3lame enable MP3 encoding via libmp3lame [no]
—enable-libopencv enable video filtering via libopencv [no]
—enable-libopenh264 enable H.264 encoding via OpenH264 [no]
—enable-libopus enable Opus de/encoding via libopus [no]
—enable-librtmp enable RTMP[E] support via librtmp [no]
—enable-libshine enable fixed-point MP3 encoding
—enable-libsoxr enable Include libsoxr resampling [no]
—enable-libspeex enable Speex de/encoding via libspeex
—enable-libtensorflow enable TensorFlow as a DNN module [no]
—enable-libvorbis enable Vorbis en/decoding via libvorbis
—enable-libvpx enable VP8 and VP9 de/encoding via libvpx
—enable-libx264 enable H.264 encoding via x264 [no]
—enable-libx265 enable HEVC encoding via x265 [no]
—enable-mediacodec enable Android MediaCodec support [no]
—enable-opengl enable OpenGL rendering [no]
—enable-openssl enable openssl, needed for https support
Toolchain options: Description
—arch=ARCH select architecture
—cpu=CPU select the minimum CPU
—cross-prefix=PREFIX use PREFIX for compile tool
—enable-cross-compile assume a cross-compiler
—sysroot=PATH root of cross-build tree
—target-os=OS compiler targets OS
—toolchain=NAME set tool according to name
—nm=NM use nm tool NM [nm -g]
—ar=AR use archive tool AR [ar]
—as=AS use assembler AS
—strip=STRIP use strip tool STRIP [strip]
—cc=CC use C compiler CC [gcc]
—cxx=CXX use C compiler CXX [g++]
—ld=LD use linker LD
—host-cc=HOSTCC use host C compiler HOSTCC
—host-cflags=HCFLAGS use HCFLAGS when compiling
—host-ld=HOSTLD use host linker HOSTLD
—host-ldflags=HLDFLAGS use HLDFLAGS when linking
—host-extralibs=HLIBS use libs HLIBS when linking
—host-os=OS compiler host OS
—extra-cflags=ECFLAGS add ECFLAGS to CFLAGS
—extra-cxxflags=ECFLAGS add ECFLAGS to CXXFLAGS
—extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS

默认编译出来的so库包括
avcodec、avformat、avutil、avdevice、avfilter、swscale、avresample、swresample、postproc,
编译出来so是个软链接,真正so名字后缀带有一长串主版本号与子版本号,
这样的so名字在Adnroid平台无法识别。
所以我们需要修改一下,打开该文件并搜索SLIBNAME,找到如下命令行:
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)’

3.编写脚本并编译

在ffmpeg源码根目录创建一个shell脚本,比如命名为build_ffmpeg.sh,以mac编译环境为例,
ndk旧版本已经过时,google官方放弃了gcc交叉编译工具链,转而使用clang编译工具链,因为clang编译速度快、效率高。
下面例子是采用ndk新版的clang进行编译(如果是使用虚拟机在linux环境交叉编译FFmpeg,下面的darwin改为linux)。具体如下:
=========================分割线不要========================

!/bin/bash
make clean
set -e
archbit=64

if [ $archbit -eq 64 ];then
echo “build for 64bit”
ARCH=aarch64
CPU=armv8-a
API=21
PLATFORM=aarch64
ANDROID=android
CFLAGS=””
LDFLAGS=””

else
echo “build for 32bit”
ARCH=arm
CPU=armv7-a
API=16
PLATFORM=armv7a
ANDROID=androideabi
CFLAGS=”-mfloat-abi=softfp -march=$CPU”
LDFLAGS=”-Wl,—fix-cortex-a8”
fi

export NDK=/Users/xufulong/Library/Android/android-ndk-r20b
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin
export SYSROOT=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot
export CROSS_PREFIX=$TOOLCHAIN/$ARCH-linux-$ANDROID-
export CC=$TOOLCHAIN/$PLATFORM-linux-$ANDROID$API-clang
export CXX=$TOOLCHAIN/$PLATFORM-linux-$ANDROID$API-clang++
export PREFIX=../ffmpeg-android/$CPU

function build_android {
./configure \
—prefix=$PREFIX \
—cross-prefix=$CROSS_PREFIX \
—target-os=android \
—arch=$ARCH \
—cpu=$CPU \
—cc=$CC \
—cxx=$CXX \
—nm=$TOOLCHAIN/$ARCH-linux-$ANDROID-nm \
—strip=$TOOLCHAIN/$ARCH-linux-$ANDROID-strip \
—enable-cross-compile \
—sysroot=$SYSROOT \
—extra-cflags=”$CFLAGS” \
—extra-ldflags=”$LDFLAGS” \
—extra-ldexeflags=-pie \
—enable-runtime-cpudetect \
—disable-static \
—enable-shared \
—disable-ffprobe \
—disable-ffplay \
—disable-ffmpeg \
—disable-debug \
—disable-doc \
—enable-avfilter \
—enable-avresample \
—enable-decoders \
$ADDITIONAL_CONFIGURE_FLAG

  1. make<br /> make install<br />}<br />build_android<br />=========================分割线不要========================<br />按照上面shell脚本分为4段。第一段make clean清除缓存,set -e设置编译出错后马上退出,archbit=xx指定cpu架构是32位还是64位。<br />第二段if...else...fi用来条件编译不同cpu架构对应字段的值。第三段用export关键字声明宏定义,其中PREFIX是指定输出文件路径。<br />第四段是一个执行函数,按照ffmpegconfigure规范进行编写。函数里面的enable代表开启,disable代表关闭,也就是对ffmpeg进行剪裁,<br />根据我们需要的功能进行enablemake命令是执行编译,make install命令是执行安装。最后的build_android是执行函数。<br />初次执行shell脚本,需要修改脚本权限,使用linux命令:chmod 777 build_ffmpeg.sh。执行脚本只需要一行命令,<br />即在命令行输入./build_ffmpeg.sh。编译过程中,命令行会不断打印编译日志,等待命令行输出INSTALL xxx关键字代表编译完成。

编译过程中,可能会出现这样那样的问题,比如ndk配置不对、脚本语法不对。但不用慌,编译输出窗口会描述出错原因,
在ffbuild/config.log会告诉你问题的具体原因所在,顺着思路一般可以找到问题的答案。

tips:
注意ndk目录改成自己的
export NDK=/Users/xufulong/Library/Android/android-ndk-r20b
错误2
出现$’\r’: command not found 是因为window下出现空格,要输入下面的指令去除空格
sed -i “s/\r//“ build_ffmpeg.sh
错误3
Unknown option “—enable-avresample”.
最新的版本好像没有了,删除这个

so库剪裁

ffmpeg强大之处在于支持按需编译,进行弹性剪裁。可以使用—disable-everything关闭所有模块,
可以使用enable/disable来开启关闭某个模块,或者某个编解码器、某个封装器、某个协议。

1、encoders与decoders

encoder和decoder在libavcodec模块,可以用./configure —list-encoders或者ffmpeg —encoders查看支持的编码器。
同样地,可以用./configure —list-decoders或者ffmpeg —decoders查看支持的解码器。我们可以先—disable-encoders,
—enable-encoder=aac,h264 其中lib开头的表示第三方库。

2、muxers与demuxers

muxer和demuxer在libavformat模块,可用./configure —list-muxers或者ffmpeg —muxers查看支持的封装器。
同样地,可用./configure —list-demuxers或者ffmpeg —demuxers查看支持的解封装器。先—disable-muxers,再—enable-muxer=mp3

3、protocols

protocol也是在libavformat模块中,./configure —list-protocols或者ffmpeg —protocols查看支持的协议,

4、parsers

parser在libavfilter模块中,提供各种filter,比如音频:amix、atempo,视频:rotate、hflip,
我们可以根据需求—enable-parser来开启,可使用./configure —list-parsers查看具体列表。

大概编译过程:

编译过程包括:预编译、编译、汇编、链接。详细可以查阅书籍<程序员的自我修养>

1、预编译

预编译处理(.c/.cpp->.i),对源文件的伪指令进行处理。 伪指令包括:宏定义(#define)、条件编译指令(#ifdef #elseif #endif)、头文件包含指令(#include)

2、编译

编译(.i->.s),对经过预编译处理文件进行语法分析,编译为汇编文件。

3、汇编

汇编(.i->.o),把汇编代码翻译为机器码,也就是二进制的目标文件。

4、链接

链接(.o->.so/.a/.lib),把所有目标文件链接成动态库、静态库文件。