在Amdroid直播开发之旅(5):详解ffmpeg编译与在Android平台上的移植和Android直播开发之旅(12):初探FFmpeg开源框架文章中,我们分别探讨了FFmpeg的编译移植、FFmpeg框架和相关重要结构体。本文就在此基础上,将详细阐述FFmpeg的裁剪移植,以便剔除不必要的功能,达到为APK"瘦身"的效果,同时,写了一个将网络流保存到本地文件的实战案例,以加深对FFmpeg相关结构体、功能函数的理解。
1 . FFmpeg裁剪移植
在详解ffmpeg编译与在Android平台上的移植一文中,我们简单地讲解了下如何在Linux系统中编译FFmpeg,但是编译出来的so体积太大,而且得到的多个so不便于使用。本节在此基础上,将详细讲解在编译FFmpeg时如何对相关模块作裁剪以精简so的体积,并且编译只生成一个so文件。首先,我们来看下在配置编译选项时,configure
的具体配置信息,可以进入FFmpeg源码根目录执行./configure --help
命令可得到,部分配置选项如下:
- Standar Options
--logfile=FILE 指定日志文件输出路径[ffbuild/config.log]
--disable-logging 不记录配置调试信息
--fatal-warnings 如果配置出现警告,就认为失败
--prefix=PREFIX 编译得到的库文件输出路径[/usr/local]
--bindir=DIR 二进制文件输出路径 [PREFIX/bin]
--datadir=DIR 数据输出路径[PREFIX/share/ffmpeg]
--docdir=DIR 文档输出路径[PREFIX/share/doc/ffmpeg]
--libdir=DIR libs输出路径[PREFIX/lib]
--shlibdir=DIR 动态库输出路径 [LIBDIR]
--incdir=DIR 头文件输出路径 [PREFIX/include]
--mandir=DIR 帮助文档输出路径 [PREFIX/share/man]
--pkgconfigdir=DIR pkg-config文件输出路径[LIBDIR/pkgconfig]
- Configuration options
--disable-static 禁止编译静态库
--enable-shared 开启编译动态库
--enable-small 开启优化大小
--disable-runtime-cpudetect 禁用在运行时检测CPU功能
--enable-gray 启用全灰度支持(slower color)
--disable-swscale-alpha 禁止在swscale中支持alpha通道
--disable-all 禁止编译所有组件(components)、库(libraries)、程序(programs)
--disable-autodetect 禁用自动检测到的外部库
这里用得较多的是--disable-static
、--enable-shared
和--enable-small
选项,其中,--disable-static
用于是否使能编译静态库文件(.a);--enable-shared
用于使能编译动态库文件(.so)。
- Program options
--disable-programs 禁止编译programs
--disable-ffmpeg 禁止编译ffmpeg
--disable-ffplay 禁止编译ffplay
--disable-ffprobe 禁止编译ffprobe
通常,我们会使用禁止编译ffmpeg、ffplay和ffprobe,其中,ffplay
是一个使用了FFmpeg和SDL库的、简单的、可移植的媒体播放器;ffprobe
用于查看多媒体文件的信息。
- Component options
--disable-avdevice 禁止编译libavdevice模块
--disable-avcodec 禁止编译libavcodec模块
--disable-avformat 禁止编译libavformat模块
--disable-swresample 禁止编译libswresample模块
--disable-swscale 禁止编译libswscale模块
--disable-postproc 禁止编译libpostproc模块
--disable-avfilter 禁止编译libavfilter模块
--enable-avresample 该模块已被弃用
--disable-pthreads 禁止pthreads [autodetect]
--disable-w32threads 禁止Win32 threads [autodetect]
--disable-os2threads 禁止OS/2 threads [autodetect]
--disable-network 禁止network支持
--disable-dct 禁止DCT代码模块
--disable-dwt DWT代码模块
--disable-error-resilience error resilience code
--disable-lsp 禁止LSP代码模块
--disable-lzo 禁止LZO decoder代码模块
--disable-mdct 禁止MDCT代码模块
--disable-rdft 禁止RDFT代码模块
--disable-fft 禁止FFT代码模块
--disable-faan 禁止floating point AAN (I)DCT代码模块
--disable-pixelutils 禁止libavutil模块中的pixel工具
这部分类似一个全局开关,用于对模块进行管控,假如我们非常明确编译的ffmpeg有明确的功能(不考虑未来扩展),那么,就可以对某些模块进行裁剪,以最大化精简so的大小、功能。
- Individual component options
--disable-everything 禁止所有的组件,就是下面列出来的这些
--disable-encoder=NAME 禁用名称为NAME的编码器
--enable-encoder=NAME 使能名称为NAME的编码器
--disable-encoders 禁用所有编码器,可通过指定NAME具体开启
--disable-decoder=NAME 禁用名称为NAME的解码器
--enable-decoder=NAME 使能名称为NAME的解码器
--disable-decoders 禁用所有解码器,可通过指定NAME具体开启
--disable-hwaccel=NAME 禁用名称为NAME的hwaccel
--enable-hwaccel=NAME 使能名称为NAME的hwaccel
--disable-hwaccels 禁用所有hwaccel,可通过指定NAME具体开启
--disable-muxer=NAME muxer NAME
--enable-muxer=NAME enable muxer NAME
--disable-muxers 禁用所有复用器,可通过指定NAME具体开启
--disable-demuxer=NAME demuxer NAME
--enable-demuxer=NAME enable demuxer NAME
--disable-demuxers 禁用所有解复用器,可通过指定NAME具体开启
--enable-parser=NAME enable parser NAME
--disable-parser=NAME parser NAME
--disable-parsers 禁用所有解析器,可通过指定NAME具体开启
--enable-bsf=NAME enable bitstream filter NAME
--disable-bsf=NAME bitstream filter NAME
--disable-bsfs 禁用所有位流过滤器,可通过指定NAME具体开启
--enable-protocol=NAME enable protocol NAME
--disable-protocol=NAME protocol NAME
--disable-protocols 禁用所有协议,可通过指定NAME具体开启
--enable-indev=NAME enable input device NAME
--disable-indev=NAME input device NAME
--disable-indevs 禁用所有输入设备,可通过指定NAME具体开启
--enable-outdev=NAME enable output device NAME
--disable-outdev=NAME output device NAME
--disable-outdevs 禁用所有输出设备,可通过指定NAME具体开启
--disable-devices 禁用所有设备,包括输入、输出
--enable-filter=NAME enable filter NAME
--disable-filter=NAME filter NAME
--disable-filters 禁用所有过滤器,可通过指定NAME具体开启
本部分的配置主要是选择那些组件需要编译,比如编码器、解码器、复用器、解复用器等等。举个栗子:
–disable-encoders
–enable-encoder=h263
–enable-encoder=libx264
–enable-encoder=aac
–enable-encoder=mpeg4
–enable-encoder=mjpeg
–enable-encoder=png
–enable-encoder=gif
–enable-encoder=bmp
–disable-muxers
–enable-muxer=h264
–enable-muxer=flv
–enable-muxer=gif
–enable-muxer=mp3
–enable-muxer=dts
–enable-muxer=mp4
–enable-muxer=mov
–enable-muxer=mpegts
–disable-decoders
–enable-decoder=aac
–enable-decoder=aac_latm
–enable-decoder=mp3
–enable-decoder=h263
–enable-decoder=h264
–enable-decoder=mpeg4
–enable-decoder=mjpeg
–enable-decoder=gif
–enable-decoder=png
–enable-decoder=bmp
–enable-decoder=yuv4
–disable-demuxers
–enable-demuxer=image2
–enable-demuxer=h263
–enable-demuxer=h264
–enable-demuxer=flv
–enable-demuxer=gif
–enable-demuxer=aac
–enable-demuxer=ogg
–enable-demuxer=dts
–enable-demuxer=mp3
–enable-demuxer=mov
–enable-demuxer=m4v
–enable-demuxer=concat
–enable-demuxer=mpegts
–enable-demuxer=mjpeg
–enable-demuxer=mpegvideo
–enable-demuxer=rawvideo
–enable-demuxer=yuv4mpegpipe
–enable-demuxer=rtsp
–disable-parsers
–enable-parser=aac
–enable-parser=ac3
–enable-parser=h264
–enable-parser=mjpeg
–enable-parser=png
–enable-parser=bmp
–enable-parser=mpegvideo
–enable-parser=mpegaudio
–disable-protocols
–enable-protocol=file
–enable-protocol=hls
–enable-protocol=concat
–enable-protocol=rtp
–enable-protocol=rtmp
–enable-protocol=rtmpt
–disable-filters
–disable-filters
–enable-filter=aresample
–enable-filter=asetpts
–enable-filter=setpts
–enable-filter=ass
–enable-filter=scale
–enable-filter=concat
–enable-filter=atempo
–enable-filter=movie
–enable-filter=overlay
–enable-filter=rotate
–enable-filter=transpose
–enable-filter=hflip
- External library support
--enable-libopencv enable video filtering via libopencv [no]
--enable-libopenh264 enable H.264 encoding via OpenH264 [no]
--enable-libopenjpeg enable JPEG 2000 de/encoding via OpenJPEG [no]
--enable-libx264 enable H.264 encoding via x264 [no]
--enable-libx265 enable HEVC encoding via x265 [no]
--enable-librtmp enable RTMP[E] support via librtmp [no]
...
FFmpeg框架中集成了非常多的第三方库,本部分选项主要是开启是否使用某些第三方库,以完成特定的功能。
- Toolchain options
--arch=ARCH 指定架构
--cpu=CPU 指定CPU型号
--cross-prefix=PREFIX 交叉编译工具的前缀(PREFIX)
--progs-suffix=SUFFIX program name suffix []
--enable-cross-compile 使能交叉编译
--sysroot=PATH root of cross-build tree
--sysinclude=PATH cross-build系统头文件路径
--target-os=OS 指定编译的系统类型
--target-exec=CMD 指定在系统上运行可执行程序的命令
--target-path=DIR 指定系统上查看编译路径
--target-samples=DIR 指定系统上samples的目录
--toolchain=NAME 根据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 指定nm工具,名称为NM
--ar=AR 指定ar工具,名称为ARuse archive tool AR [ar]
--as=AS 指定汇编程序assembler AS []
--ln_s=LN_S 指定符号连接工具 LN_S [ln -s -f]
--strip=STRIP 指定strip工具STRIP [strip]
--windres=WINDRES 指定windows资源编译器WINDRES [windres]
--x86asmexe=EXE 指定nasm-compatible汇编EXE [nasm]
--cc=CC 指定C编译器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 []
--extra-cflags=ECFLAGS add ECFLAGS to CFLAGS []
--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 []
...
这部分用于配置编译选项,比如配置交叉编译工具、指定编译架构、CPU型号以及其他编译参数等。对于比较常见的选项,我大概列举了一下,具体介绍如下:
–arch=ARCH
用于指定CPU的架构,常见的架构有arm
、arm64
、x86
等,其中,arm对应的CPU型号分为armv7-a
、armv5te
、armv6
等;arm64
对应的CPU型号为armv8-a
。
–cpu
用于指定CPU的型号,比如armv7-a
、armv5te
、armv8-a
等。
–target-os
用于指定编译的系统平台,比如linux、win32等。
–cross-prefix
用于指定编译工具前缀,比如–cross-prefix=/home/jiangdg/opt/android-ndk-r14b/toolchains/arm-linux-androideabi-4.9
/prebuilt/linux-x86_64/bin/arm-linux-androideabi
-
–sysroot
用于指定Android平台的目录,便于在编译过程中需要引用相关的库或者头文件,就会在--sysroot
指定的目录下去搜索,如:–sysroot=/home/jiangdg/opt/android-ndk-r14b/platforms/