赞
踩
当我们欣赏一部电影、观看一段视频或者享受一首音乐时,很少有人会停下来思考这一切是如何呈现在我们眼前的。然而,在每一帧的画面、每一秒的声音背后,有着一个不可思议的技术世界
这个充满音视频的世界的核心之一,就是FFmpeg。FFmpeg是一个强大而复杂的多媒体处理工具,它为视频和音频编解码、流媒体传输、格式转换等提供了优秀的解决方案。在这个系列博客中,我们将深入探讨FFmpeg源码,解析它的工作原理。
后续将会每周更新一到两次,希望能得到你的关注,如果有看不懂的地方,一定是我表述的不够清楚,如果您能指出将是我莫大的荣幸。
FFmpeg,全称"Fast Forward MPEG",是一个功能强大、开源的多媒体框架,它提供了广泛的音频和视频处理功能,使得多媒体数据的解码、编码、转换、封装以及流媒体传输变得更加容易。
随着数字媒体在我们日常生活中的普及,FFmpeg在多领域得到了广泛的应用。它可以用于:
视频编辑和转码: 你可以使用FFmpeg来剪切、合并、转码、添加滤镜等,从而编辑和处理视频文件。这对于视频制作、后期制作以及视频分享平台非常重要。
音频处理: FFmpeg不仅支持视频,还可以用于音频文件的处理,包括音频转码、剪切、合并以及添加效果。
流媒体处理: FFmpeg支持各种网络协议和流媒体传输,使其成为在线直播、视频会议和实时音视频传输的理想工具。
多格式支持: FFmpeg可以处理多种音视频编解码格式和容器格式,包括常见的MP4、MKV、AVI、以及H.264、AAC等流行的编码标准。
在本系列博客中,我们将深入探讨FFmpeg的内部工作原理,从源代码级别理解其架构和功能。我们将解析其各个组件、编解码器、滤镜和功能,帮助你理解如何使用FFmpeg以及如何在自己的应用程序中集成它。此外,我们还会关注性能优化、安全性和最佳实践,以确保你能够有效地利用这一强大的多媒体处理工具。
https://github.com/FFmpeg/FFmpeg
FFmpeg 是一个开源多媒体框架,用于处理音频、视频和多媒体数据。其目录结构在不同版本中可能有细微的差异,但通常包含以下主要目录:
doc: 这个目录包含关于 FFmpeg 的离线文档,包括开发文档、API 文档、示例等。在线文档可以访问 https://trac.ffmpeg.org/
fftools: 这是一些用于测试和辅助工具的目录,如 ffmpeg
命令行工具的源代码以及一些其他小工具。
libavcodec: 这个目录包含了 FFmpeg 的编解码库,用于处理各种音频和视频编解码器。
libavformat: 实现流协议、封装格式以及基本的I/O访问。
libavutil: 这个目录包含了一些通用的实用工具和功能,它们被不同部分的 FFmpeg 使用。
libswscale: 这个库用于图像缩放和颜色空间转换。
libswresample: 用于音频混音、重采样的库。
libavdevice:提供一层采集设备和播放设备的抽象,包括一些特定设备相关的接口实现,比如sdl、opengl等
libavfilter: 这是 FFmpeg 的滤镜库,允许你应用各种滤镜效果到音频和视频流。
libpostproc: 这个库包含一些后处理滤镜,用于改善视频质量。
compat: 兼容性代码,用于支持不同平台和系统。
tests: 包含各种自动化测试脚本和测试数据,用于确保 FFmpeg 的正常运作。
presets: 这里存储了一些编码器的预设配置文件,可以用于不同的编码任务。
tools: 包含一些辅助工具,如 ffmpeg
用于命令行处理音视频, ffplay
用于媒体文件播放,ffprobe
用于媒体文件的简单分析
build: 在这个目录下,你可以找到构建 FFmpeg 的脚本和相关文件。
这些目录包含了 FFmpeg 的核心组件和工具,帮助开发者处理多媒体数据、编码和解码各种多媒体格式,以及应用各种滤镜和效果。需要注意的是,具体的目录结构可能会因不同版本的 FFmpeg 而有所不同,但通常会包含上述核心组件。
ffmpeg的编译流程很简单
先根据需要对ffmpeg进行配置,然后编译即可
./configure --help
--list-decoders 展示所有的解码器
--list-encoders 展示所有的编码器
--list-hwaccels 展示所有硬件加速器
--list-demuxers 展示所有解复用器
--list-muxers 展示所有复用器
--list-parsers 展示所有解析器
--list-protocols 展示所有协议
--list-bsfs 展示所有比特流过滤器
--list-indevs 展示所有的输入设备
--list-outdevs 展示所有的输出设备
--list-filters 展示所有的过滤器
--logfile=FILE 将测试结果和输出记录到FILE文件中 [ffbuild/config.log]
--disable-logging 禁止记录配置调试信息
--fatal-warnings 如果生成任何配置警告,则失败
--prefix=PREFIX 安装到PREFIX目录 [/usr/local]
--bindir=DIR 将可执行文件安装到DIR目录 [PREFIX/bin]
--datadir=DIR 将数据文件安装到DIR目录 [PREFIX/share/ffmpeg]
--docdir=DIR 将文档安装到DIR目录 [PREFIX/share/doc/ffmpeg]
--libdir=DIR 将库文件安装到DIR目录 [PREFIX/lib]
--shlibdir=DIR 将共享库文件安装到DIR目录 [LIBDIR]
--incdir=DIR 将包含文件安装到DIR目录 [PREFIX/include]
--mandir=DIR 将手册页安装到DIR目录 [PREFIX/share/man]
--pkgconfigdir=DIR 将pkg-config文件安装到DIR目录 [LIBDIR/pkgconfig]
--enable-rpath 使用rpath以允许在动态链接器搜索路径之外的位置安装库(谨慎用)
--install-name-dir=DIR 用于已安装目标的Darwin目录名称
--enable-gpl 允许使用GPL代码,生成的库和可执行文件将受GPL许可协议限制 [否]
--enable-version3 将(L)GPL升级为版本3 [否]
--enable-nonfree 允许使用非免费代码,生成的库和可执行文件将不可重新分发 [否]
--disable-static 不构建静态库 [否]
--enable-shared 构建共享库 [否]
--enable-small 优化尺寸(注意不是优化速度)
--disable-runtime-cpudetect 禁止在运行时检测CPU能力(生成较小的二进制文件)
--enable-gray 启用完全灰度支持
--disable-swscale-alpha 禁用swscale中的Alpha通道支持
--disable-all 禁用构建组件、库和程序
--disable-autodetect 禁用自动检测的外部库 [否]
--disable-programs 不构建命令行程序
--disable-ffmpeg 禁用ffmpeg的构建
--disable-ffplay 禁用ffplay的构建
--disable-ffprobe 禁用ffprobe的构建
--disable-doc 不构建文档
--disable-htmlpages 不构建HTML文档页面
--disable-manpages 不构建man文档页面
--disable-podpages 不构建POD文档页面
--disable-txtpages 不构建文本文档页面
组件选项: --disable-avdevice 禁用libavdevice的构建 --disable-avcodec 禁用libavcodec的构建 --disable-avformat 禁用libavformat的构建 --disable-swresample 禁用libswresample的构建 --disable-swscale 禁用libswscale的构建 --disable-postproc 禁用libpostproc的构建 --disable-avfilter 禁用libavfilter的构建 --enable-avresample 启用libavresample的构建(不推荐) [否] --disable-pthreads 禁用pthreads [自动检测] --disable-w32threads 禁用Win32线程 [自动检测] --disable-os2threads 禁用OS/2线程 [自动检测] --disable-network 禁用网络支持 [否] --disable-dct 禁用DCT代码 --disable-dwt 禁用DWT代码 --disable-error-resilience 禁用错误恢复代码 --disable-lsp 禁用LSP代码 --disable-lzo 禁用LZO解码器代码 --disable-mdct 禁用MDCT代码 --disable-rdft 禁用RDFT代码 --disable-fft 禁用FFT代码 --disable-faan 禁用浮点AAN(I)DCT代码 --disable-pixelutils 禁用libavutil中的像素工具
单个组件选项: --disable-everything 禁用下面列出的所有组件 --disable-encoder=NAME 禁用编码器NAME --enable-encoder=NAME 启用编码器NAME --disable-encoders 禁用所有编码器 --disable-decoder=NAME 禁用解码器NAME --enable-decoder=NAME 启用解码器NAME --disable-decoders 禁用所有解码器 --disable-hwaccel=NAME 禁用硬件加速器NAME --enable-hwaccel=NAME 启用硬件加速器NAME --disable-hwaccels 禁用所有硬件加速器 --disable-muxer=NAME 禁用复用器NAME --enable-muxer=NAME 启用复用器NAME --disable-muxers 禁用所有复用器 --disable-demuxer=NAME 禁用解复用器NAME --enable-demuxer=NAME 启用解复用器NAME --disable-demuxers 禁用所有解复用器 --enable-parser=NAME 启用解析器NAME --disable-parser=NAME 禁用解析器NAME --disable-parsers 禁用所有解析器 --enable-bsf=NAME 启用比特流过滤器NAME --disable-bsf=NAME 禁用比特流过滤器NAME --disable-bsfs 禁用所有比特流过滤器 --enable-protocol=NAME 启用协议NAME --disable-protocol=NAME 禁用协议NAME --disable-protocols 禁用所有协议 --enable-indev=NAME 启用输入设备NAME --disable-indev=NAME 禁用输入设备NAME --disable-indevs 禁用所有输入设备 --enable-outdev=NAME 启用输出设备NAME --disable-outdev=NAME 禁用输出设备NAME --disable-outdevs 禁用所有输出设备 --disable-devices 禁用所有设备 --enable-filter=NAME 启用过滤器NAME --disable-filter=NAME 禁用过滤器NAME --disable-filters 禁用所有过滤器
使用以下任何开关将允许FFmpeg链接到相应的外部库。如果满足它们的所有其他依赖项并且它们没有被明确禁用,那么依赖于该库的所有组件将被启用。例如,–enable-libwavpack将启用与libwavpack的链接,并允许构建libwavpack编码器,除非使用–disable-encoder=libwavpack明确禁用它。
请注意,只有系统库会自动检测。所有其他外部库必须显式启用。
还请注意,以下帮助文本描述了库本身的目的,而不一定所有功能都一定可供FFmpeg使用。
第三方库比较多,不一一列举
--disable-alsa 禁用ALSA支持 [自动检测]
--disable-appkit 禁用苹果AppKit框架 [自动检测]
--disable-avfoundation 禁用苹果AVFoundation框架 [自动检测]
--enable-avisynth 启用读取AviSynth脚本文件 [否]
--disable-bzlib 禁用bzlib [自动检测]
--disable-coreimage 禁用苹果CoreImage框架 [自动检测]
--enable-chromaprint 启用使用chromaprint进行音频指纹处理 [否]
--enable-frei0r 启用frei0r视频滤镜 [否]
--enable-gcrypt 启用gcrypt,用于rtmp(t)e支持,如果未使用openssl、librtmp或gmp [否]
--enable-gmp 启用gmp,用于rtmp(t)e支持,如果未使用openssl或librtmp [否]
--enable-gnutls 启用gnutls,用于https支持,如果未使用openssl、libtls或mbedtls [否]
.
.
.
工具链选项(根据目标平台选择对应工具链)
编译选项: --arch=ARCH 选择体系结构 [] --cpu=CPU 选择所需的最小CPU(影响指令选择,可能在旧的CPU上崩溃) --cross-prefix=PREFIX 使用PREFIX作为编译工具 [] --progs-suffix=SUFFIX 程序名称后缀 [] --enable-cross-compile 假定正在使用交叉编译器 --sysroot=PATH 交叉构建树的根目录 --sysinclude=PATH 交叉构建系统头文件的位置 --target-os=OS 编译器目标的操作系统 [] --target-exec=CMD 运行目标上可执行文件的命令 --target-path=DIR 目标上构建目录的路径 --target-samples=DIR 目标上样本目录的路径 --tempprefix=PATH 强制固定的dir/prefix,而不是使用mktemp进行检查 --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 [nm -g] --ar=AR 使用存档工具AR [ar] --as=AS 使用汇编程序AS [] --ln_s=LN_S 使用符号链接工具LN_S [ln -s -f] --strip=STRIP 使用strip工具STRIP [strip] --windres=WINDRES 使用Windows资源编译器WINDRES [windres] --x86asmexe=EXE 使用兼容nasm的汇编程序EXE [nasm] --cc=CC 使用C编译器CC [gcc] --cxx=CXX 使用C编译器CXX [g++] --objcc=OCC 使用ObjC编译器OCC [gcc] --dep-cc=DEPCC 使用依赖生成器DEPCC [gcc] --nvcc=NVCC 使用Nvidia CUDA编译器NVCC或clang [] --ld=LD 使用链接器LD [] --pkg-config=PKGCONFIG 使用pkg-config工具PKGCONFIG [pkg-config] --pkg-config-flags=FLAGS 传递附加标志到pkgconf [] --ranlib=RANLIB 使用ranlib RANLIB [ranlib] --doxygen=DOXYGEN 使用DOXYGEN生成API文档 [doxygen] --host-cc=HOSTCC 使用主机C编译器HOSTCC --host-cflags=HCFLAGS 在为主机编译时使用HCFLAGS --host-cppflags=HCPPFLAGS 在为主机编译时使用HCPPFLAGS --host-ld=HOSTLD 使用主机链接器HOSTLD --host-ldflags=HLDFLAGS 链接主机时使用HLDFLAGS --host-extralibs=HLIBS 链接主机时使用libs HLIBS --host-os=OS 编译器主机操作系统 [] --extra-cflags=ECFLAGS 将ECFLAGS添加到CFLAGS [] --extra-cxxflags=ECFLAGS 将ECFLAGS添加到CXXFLAGS [] --extra-objcflags=FLAGS 将FLAGS添加到OBJCFLAGS [] --extra-ldflags=ELDFLAGS 将ELDFLAGS添加到LDFLAGS [] --extra-ldexeflags=ELDFLAGS 将ELDFLAGS添加到LDEXEFLAGS [] --extra-ldsoflags=ELDFLAGS 将ELDFLAGS添加到LDSOFLAGS [] --extra-libs=ELIBS 添加ELIBS [] --extra-version=STRING 版本字符串后缀 [] --optflags=OPTFLAGS 重写与优化相关的编译器标志 --nvccflags=NVCCFLAGS 重写nvcc标志 [] --build-suffix=SUFFIX 库名称后缀 [] --enable-pic 构建位置无关的代码 --enable-thumb 编译Thumb指令集 --enable-lto 使用链接时优化 --env="ENV=override" 覆盖环境变量
--malloc-prefix=PREFIX 使用PREFIX作为malloc和相关名称的前缀
--custom-allocator=NAME 使用支持的自定义分配器
--disable-symver 禁用符号版本控制
--enable-hardcoded-tables 使用硬编码的表格而不是运行时生成
--disable-safe-bitstream-reader
禁用位读取器中的缓冲区边界检查(更快,但可能会崩溃)
--sws-max-filter-size=N swscale使用的最大滤波器大小 [256]
涉及指令比较多,不一一列举
--disable-asm 禁用所有汇编优化
--disable-altivec 禁用AltiVec优化
--disable-vsx 禁用VSX优化
--disable-power8 禁用POWER8优化
--disable-amd3dnow 禁用3DNow!优化
--disable-amd3dnowext 禁用3DNow!扩展优化
--disable-mmx 禁用MMX优化
--disable-mmxext 禁用MMXEXT优化
--disable-sse 禁用SSE优化
--disable-sse2 禁用SSE2优化
--disable-sse3 禁用SSE3优化
--disable-ssse3 禁用SSSE3优化
。。。
开发者选项: --disable-debug 禁用调试符号 --enable-debug=LEVEL 设置调试级别 [] --disable-optimizations 禁用编译器优化 --enable-extra-warnings 启用更多的编译器警告 --disable-stripping 禁用剥离可执行文件和共享库 --assert-level=level 0(默认)、1或2,断言测试的数量, 2会导致运行时减速。 --enable-memory-poisoning 使用任意数据填充堆中未初始化的分配空间 --valgrind=VALGRIND 通过valgrind运行“make fate”测试以检测内存泄漏和错误,使用指定的valgrind二进制文件。不能与--target-exec组合使用 --enable-ftrapv 捕获算术溢出 --samples=PATH 用于FATE的测试样本位置,如果未设置,则在进行make时使用$FATE_SAMPLES。 --enable-neon-clobber-test 检查NEON寄存器是否被覆盖(仅用于调试目的) --enable-xmm-clobber-test 检查XMM寄存器是否被覆盖(仅适用于Win64;仅用于调试目的) --enable-random 随机启用/禁用组件 --disable-random --enable-random=LIST 随机启用/禁用特定组件或 --disable-random=LIST 组件组。LIST是一个逗号分隔的列表 NAME[:PROB]条目,其中NAME是一个组件 (组)和与NAME相关联的概率 NAME的(默认为0.5)。 --random-seed=VALUE 用于--enable/disable-random的种子值 --disable-valgrind-backtrace 不在Valgrind下打印回溯 (仅适用于--disable-optimizations构建) --enable-ossfuzz 启用fuzzer工具的构建 --libfuzzer=PATH libfuzzer的路径 --ignore-tests=TESTS 忽略结果的测试的逗号分隔列表(不带“fate-”前缀 在名称中) --enable-linux-perf 启用Linux性能监视器API 注意:对象文件在configure启动的地方构建。
cd ~/ffmpeg_sources && \ wget -O ffmpeg-snapshot.tar.bz2 https://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2 && \ tar xjvf ffmpeg-snapshot.tar.bz2 && \ cd ffmpeg && \ PATH="$HOME/bin:$PATH" PKG_CONFIG_PATH="$HOME/ffmpeg_build/lib/pkgconfig" ./configure \ --prefix="$HOME/ffmpeg_build" \ --pkg-config-flags="--static" \ --extra-cflags="-I$HOME/ffmpeg_build/include" \ --extra-ldflags="-L$HOME/ffmpeg_build/lib" \ --extra-libs="-lpthread -lm" \ --ld="g++" \ --bindir="$HOME/bin" \ --enable-gpl \ --enable-gnutls \ --enable-libaom \ --enable-libass \ --enable-libfdk-aac \ --enable-libfreetype \ --enable-libmp3lame \ --enable-libopus \ --enable-libsvtav1 \ --enable-libdav1d \ --enable-libvorbis \ --enable-libvpx \ --enable-libx264 \ --enable-libx265 \ --enable-nonfree && \ PATH="$HOME/bin:$PATH" make && \ make install && \ hash -r
总体来看,FFmpeg的编译系统比较庞大,它允许用户根据其需求和系统配置来构建自定义的多媒体处理工具。
它有以下优点
高度可定制性:FFmpeg的编译系统提供了大量的配置选项,允许用户根据其需求启用或禁用不同的组件、功能和编解码器。这使得它非常容易裁剪。
跨平台支持:FFmpeg的编译系统在各种操作系统上都能正常工作,包括Linux、macOS和Windows。并且在各个平台上提供了优化选项
尽管FFmpeg的编译系统具有众多优点,但也存在一些缺点:
依赖管理:在构建FFmpeg之前,需要安装各种外部依赖项,这可能会涉及到一些手动工作,尤其是在不同操作系统上。
配置选项繁多:FFmpeg的配置选项众多,有时会有重复或者让人感到困惑的地方。用户需要仔细阅读文档以理解每个选项的含义和作用。
总体而言,ffmpeg的编译尽管可能需要一些时间来学习和配置,但一旦掌握,它可以提供卓越的多媒体处理能力。对于那些需要定制多媒体处理工具的用户来说,FFmpeg编译系统是一个不可或缺的资源。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。