文章目录
学习文章 :
https://ffmpeg.xianwaizhiyin.net/build-ffmpeg/configure-args.html
源码
去掉一些说明文件后
~/ffmpeg-4.2.2 $ ls
compat fftools libavformat libswresample presets
configure libavcodec libavresample libswscale tests
doc libavdevice libavutil Makefile tools
ffbuild libavfilter libpostproc
- doc/build_system.txt,编译 FFmpeg 的一些教程。
- doc/filter_design.txt ,filter 滤镜的设计原理。
- doc/writing_filters.txt,如何自己写一个滤镜加进去 FFmpeg。
- doc/issue_tracker.txt,FFmpeg 的 bug 或者 feature 的跟踪流程
- doc/multithreading.txt,FFmpeg 里面的多线程,有两种,Slice threading 跟 Frame threading
- doc/optimization.txt ,编解码器的优化方法,FFmpeg 还有一部分函数是可以用汇编 SIMD 优化,他的一些函数如果被优化得晦涩难懂,可以查看早期的
gitlog
。 - doc/rate_distortion.txt,对失真率的简单讨论。
编译参数
环境目录
-
prefix
代表前缀目录 -
libdir
代表静态库目录 -
shlibdir
是动态库的安装目录默认会把动态库安装到系统的动态库目录。 -
pkgconfigdir
代表pkg
文件的安装目录。 -
pkg
是用来给第三方软件找到 FFmpeg 静态库,动态库的安装目录的。
链接库
--disable-static
\--enable-shared
, FFmpeg 默认会生成静态库--extra-cflags
,传递 标识选项 给 C 编译器--extra-cxxflags
,传递 标识选项 给 C++ 编译器--extra-ldflags
,传递 标识选项 给 LD 链接器--extra-ldexeflags
,生成 exe 的时候传递给 链接器 的 选项--extra-ldsoflags
,生成 so 动态库的时候传递给 链接器 的 选项--extra-libs
,指定额外的库,实际上就是往链接器加选项--env="ENV=override"
这个是最重要的,可以覆盖环境变量
编译速度、程序大小
-
--enable-small
,把 FFmpeg 的体积减少。 -
--disable-doc
,不编译生成文档,可以节省编译时间。 -
--disable-programs
,开启\关闭的可执行文件(ffmpeg
)。针对某个不生成--disable-ffplay
,如果全部关闭则只生成静态库\动态库。 -
--disable-avdevice
,--disable-avcodec
,--disable-avformat
,--disable-swresample
,--disable-swscale
,--disable-postproc
,--disable-avfilter
。开启\关闭的库,如果只需要可执行文件,可以指定不生成这些库,但是可能程序会缺少某个库的功能。(在开发filter模块的时候可以手动的关闭一些库,会减少很多编译时间) -
--disable-indevs
--disable-outdevs
--disable-bsfs
--disable-protocols
--disable-filters
--disable-encoders
--disable-decoders
--disable-muxers
--disable-demuxers
--disable-parsers
这十个对应的设备,我们先全部关闭然后再放开我们需要的,主要还是为了缩小代码体积。如果没有后面的配置,ffmpeg编译出是最小的体积,只是没有任何功能。
由于 默认的编译会给 ffmpeg.exe 加上很多的编/解码器跟解/复用器,在嵌入式设备\或者零时开发上为了使程序体积更小、编译更快,可以采用此种方法。其他的 滤镜,协议,也可以如此裁剪。
-
可执行程序属性
-
--disable-pthreads
,--disable-w32threads
,--disable-os2threads
关闭多线程。如果禁用了性能会下降非常多 -
--disable-network
,如不需要处理网络协议,可以启动这个选项,可以减小软件大小 跟节省编译时间。
-
-
编码器
--enable-libx264
,启用x264
作为h.264
的编解码器。--enable-libx265
,启用x265
作为h.265
的编解码器。(现在一般是这2个,以前就有h262)--enable-encoder=rawvideo
--enable-encoder=mpeg4
使能编码器rawvideo对应yuv,mpeg4对应mp4--enable-decoder=rawvideo
--enable-decoder=mpeg4
--enable-decoder=movtext
使能解码器,这里需要开启movtext才能解压mp4--enable-muxer=aiff --enable-muxer=h263 --enable-muxer=mp4 --enable-muxer=rawvideo
使能合成器--enable-demuxer=aac --enable-demuxer=aiff --enable-demuxer=h263 --enable-demuxer=mov --enable-demuxer=rawvideo
使能分离器--enable-parser=aac --enable-parser=h263 --enable-parser=mpegaudio --enable-parser=mpeg4video
使能解析器--enable-indev=v4l2 --enable-outdev=v4l2
使能输入设备,输出设备(如果不使能就只能编解码不能采集视频)--enable-filter=scale
使能过滤器,这个是用来转换yuv的格式,yuv有多种格式要互相转换。
-
环境工具(不同平台使用不同工具)
--cc=CC
指定 C 程序的编译器。--cxx=CXX
指定 C++ 的编译器。--ld=LD
指定链接器。--custom-allocator
,自定义内存分配器,可以把malloc
换成jemalloc
之类的。--arch=x86_32/i386/x86_64/arm64
,
-
协议
--enable-protocol=file
使能文件协议,这个必须放开
编译脚本(下文简称为configure
)
~/ffmpeg-4.2.2 $ cat load.sh
#!/bin/bash
if [ -d build ];then
mkdir build
fi
./configure \
--prefix=build \
--enable-gpl \
--enable-nonfree \
--enable-debug=3 \
--disable-optimizations \
--disable-asm \
--disable-stripping \
--disable-ffprobe \
--disable-ffplay
通过git控制代码版本,在执行configure
后产生的新文件如下:
~/ffmpeg-4.2.2 $ git status
On branch master
Untracked files:
(use "git add <file>..." to include in what will be committed)
config.h
doc/config.texi
ffbuild/.config
ffbuild/config.fate
ffbuild/config.log
ffbuild/config.mak
ffbuild/config.sh
libavcodec/bsf_list.c
libavcodec/codec_list.c
libavcodec/parser_list.c
libavdevice/indev_list.c
libavdevice/outdev_list.c
libavfilter/filter_list.c
libavformat/demuxer_list.c
libavformat/muxer_list.c
libavformat/protocol_list.c
libavutil/avconfig.h
永远再执行一遍configure
也同样可以看到主要的配置文件如下
License: nonfree and unredistributable
config.h is unchanged
libavutil/avconfig.h is unchanged
libavfilter/filter_list.c is unchanged
libavcodec/codec_list.c is unchanged
libavcodec/parser_list.c is unchanged
libavcodec/bsf_list.c is unchanged
libavformat/demuxer_list.c is unchanged
libavformat/muxer_list.c is unchanged
libavdevice/indev_list.c is unchanged
libavdevice/outdev_list.c is unchanged
libavformat/protocol_list.c is unchanged
ffbuild/config.sh is unchanged
之后再过滤下执行configure
后的打印信息,这里的打印信息就是告诉你执行make编译后:会得到的程序和它会具有的功能信息
~/ffmpeg-4.2.2 $ cat log | grep :
External libraries:
External libraries providing hardware acceleration:
Libraries:
Programs:
Enabled decoders:
Enabled encoders:
Enabled hwaccels:
Enabled parsers:
Enabled demuxers:
Enabled muxers:
Enabled protocols:
Enabled filters:
Enabled bsfs:
Enabled indevs:
Enabled outdevs:
License: nonfree and unredistributable
然后执行make -j16
编译运行,这里的16表示用16个子线程同时编译,我只了解一点shell多线程技术,对于make
这个工具不是特别了解,国内文章对它的解释也比较模糊,其中有一篇文章说道**“j后面的数字应该为CPU核心数的两倍”**不知道是不是准确的,至此我还特意用shell分别对16线程和无限制线程测试(我的电脑是8核心的),很明显无限制线程花费的时间要比16少的多(可能是我不太明白shell多线程和程序进程多线程的区别吧),有兴趣的可以自己研究一下
make后再看看文件变化情况,还是一样通过git status
这里加上configurtion
前的文件后新产生的基本都是.d和.o
文件,有3533个文件变化或产生
~/ffmpeg-4.2.2 $ git status | wc -l
3533
编译后的信息:
~/ffmpeg-4.2.2 $ du ffmpeg ffmpeg_g
68M ffmpeg
68M ffmpeg_g
~/ffmpeg-4.2.2 $ ldd ffmpeg_g
linux-vdso.so.1 (0x00007ffea3f66000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f4c782ef000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007f4c782d3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f4c780ab000)
/lib64/ld-linux-x86-64.so.2 (0x00007f4c7a510000)
~/ffmpeg-4.2.2 $ file ffmpeg_g
ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=5a51fa6f5eb1997656814577ef36b945fd21a07b, for GNU/Linux 3.2.0, with debug_info, not stripped
可以看到还是依赖了系统的一些动态库,即使是静态链接情况下(前面脚本里面没有加 --enable-shared
就是使用静态库编译)
完整静态编译
需要再加上3个静态标志
~/ffmpeg-4.2.2 $ cat load.sh
#!/bin/bash
if [ ! -d build ];then
mkdir build
fi
#在执行 这条命令之前,需要安装一些必备的静态库,因为操作系统为了节省硬盘空间,默认可能只有动态库,一些静态库需要手动安装的
#sudo apt install libc6-dev build-essential -y
./configure \
--prefix=build \
--enable-gpl \
--enable-nonfree \
--enable-debug=3 \
--disable-optimizations \
--disable-asm \
--disable-stripping \
--disable-ffprobe \
--disable-ffplay \
--extra-cflags="-static" \
--extra-ldflags="-static" \
--pkg-config-flags="--static"
编译后信息
~/ffmpeg-4.2.2 $ file ffmpeg_g
ffmpeg_g: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, BuildID[sha1]=9d75510c5c79ba9e47b1ea617e4f97308c75795e, for GNU/Linux 3.2.0, with debug_info, not stripped
~/ffmpeg-4.2.2 $ du ffmpeg_g
69M ffmpeg_g
下载-编译脚本(Android)
#!/bin/bash
cd ~/
if [ ! -f "ffmpeg-4.2.2.tar.bz2" ];then
wget https://ffmpeg.org/releases/ffmpeg-4.2.2.tar.bz2
tar -xjvf ffmpeg-4.2.2.tar.bz2
fi
cd ffmpeg-4.2.2
path=($(ls ~/Library/Android/sdk/ndk/))
export NDK=$HOME/Library/Android/sdk/ndk/${path[0]}
echo -e "🌟\033[31m 检测ndk-build 版本,将使用${NDK}进行编译\033[0m"
echo -e "\n请选择要编译的版本架构:[64/32]"
read archbit
if [[ $archbit = 64 ]];then
echo "start build for 64bit..."
ARCH=aarch64
CPU=armv8-a
API=23
PLATFORM=aarch64
ANDROID=android
CFLAGS=""
LDFLAGS=""
elif [[ $archbit = 32 ]];then
echo "start build for 32bit..."
ARCH=arm
CPU=armv7-a
API=23
PLATFORM=armv7a
ANDROID=androideabi
CFLAGS="-mfloat-abi=softfp -march=$CPU"
LDFLAGS="-Wl,--fix-cortex-a8"
else
exit
fi
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-debug \
--disable-doc \
--enable-avfilter \
--enable-decoders \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make -j16
make install
}
build_android
同样.需要的功能自行在上面取消 .这里的脚本只是实现的自动化编译功能,具体你要使用的ffmpeg功能还的按需所取