内容简介:Fabrice Bellard在 2000 年的时开发出初版;后来发展到 2004 年,FFmpeg 可以通过以下方式自由获取源代码,具体方式如下:
前言
该篇文章起就正式进入音视频学习了,在进入音视频学习之前我们必须要先学习 FFmpeg 这个库,这个库非常强大,强大到什么地步呢 ?可以说只要做音视频的没有人不了解它,包括国内外一些比较出名的播放器也用到了 FFmpeg 这个库。
FFmpeg 定义
FFmpeg 既是一款音视频编解码工具,同时也是一组音视频编解码开发套件,作为编解码开发套件,他为开发者提供了丰富的音视频处理的调用接口。
FFmpeg 提供了多种媒体格式的封装和解封装,包括多种音视频编码、多种协议的流媒体、多种色彩格式转换、多种采样率转换、多种码率转换等; FFmpeg 框架提供了多种丰富的插件模块,包含封装与解封转的插件、编码与解码的插件等。
FFmpeg 历史
FFmpeg 由法国天才程序员
Fabrice Bellard在 2000 年的时开发出初版;后来发展到 2004 年, Fabrice Bellard 找到了接手人,这个人至今还在维护 FFmpeg 的 Michael Niedermayer 。Michael Niedermayer 对 FFmpeg 的贡献非常大,其将滤镜子系统 libavfilter 加入 FFmpeg 项目中,使得 FFmpeg 的多媒体处理更加多样、更加方便。在 FFmpeg 发布了 0.5 版本之后,很长一段时间没有进行新版本的发布,直到后来 FFmpeg 采用了 Git 作为版本控制服务器以后才开始继续进行代码更新、版本发布,当然也是时隔多年之后了;2011 年 3 月,在 FFmpeg 项目中有一些提交者对 FFmpeg的项目管理方式并不满意,因而重新创建了一个新的项目,命名为 Libav, 该项目尽管至今并没有 FFmpeg 发展这么迅速,但是提交权限相对 FFmpeg 更加开放;2015 年 8 月,Michael Niedermayer 主动辞去 FFmpeg 项目负责人的职务。Michael Niedermayter 从 Libav 中移植了大量的代码和功能到 FFmpeg 中,Michael Niedermayter 辞职的主要目的是希望两个项目最终能够一起发展,若能够合并则更好。时至今日,在大多数的 Linux 发行版本系统中已经使用 FFmpeg 来进行多媒体处理。
FFmpeg 可以通过以下方式自由获取源代码,具体方式如下:
FFmpeg 模块介绍
FFmpeg 框架的基本组成包含 libavcodec 、libavformat、libavfilter、libavdevice 、libavutil 等模块。
下面针对这些模块做一个大概的介绍。
-
libavcodec:
编解码库,封装了 Codec 层,但是有一些 codec 是具备自己的 License 的,FFmpeg 不会默认添加像 libx264、FDK-AAC、Lame 等库,但是 FFmpeg 像一个平台,可以将其他的第三方codec以插件的方式添加进来,为开发者提供统一接口
-
libavformat:
文件格式和协议库,封装了 Protocol 层和 Demuxer、Muxer 层,使得协议和格式对于开发者来说是透明的
-
libavfilter:
音视频滤镜库,该模块包含了音频特效和视频特效的处理,在使用 FFmpeg 的 API 进行编解码的过程中,可以使用该模块高效的为音视频数据做特效处理
-
libavdevice:
输入输出设备库,比如需要编译出播放声音或者视频的工具 ffplay,就需要确保该模块是打开的,同事也需要 libsdl 的预先编译,该设备模块播放声音和视频都又是使用libsdl 库
-
libavutil:
核心 工具 库,最基础模块之一,其他模块都会依赖该库做一些基本的音视频处理操作
-
libswresample:
用于音频重采样,可以对数字音频进行声道数、数据格式、采样率等多种基本信息的转换
-
libswscale
该模块用于图像格式转换,可以将 YUV 的数据转换为 RGB 的数据
-
libpostproc
该模块用于进行后期处理,当我们使用filter的时候,需要打开这个模块,filter会用到这个模块的一些基础函数
比较老的 ffmpeg 还会编译出 avresamle 模块,也是用于对音频原始出具进行重采样的,但是已经被废弃,推荐使用 libswresample 替代
另外,库里还可以包含对 H.264/MPEG-4 AVC 视频编码的 X264 库,是最常用的有损视频编码器,支持 CBR、VBR 模式,可以在编码的过程中直接改变码率的设置,在直播的场景中非常适用!可以做码率自适应的功能。
下载 FFmpeg
FFmpeg 官网 直接下载源码方式
在 linux 环境中,命令下载:
//1. 命令下载 wget https://ffmpeg.org/releases/ffmpeg-4.2.2.tar.bz2 //2. 安装解压缩工具 yum -y install bzip2 //3. 解压 FFmpeg tar -jxvf ffmpeg-4.2.2.tar.bz2
编译 FFmpeg
编译环境
- ffmpeg-4.2.2
- Centos 7
- android-ndk-r17c-linux-x86_64.zip
configure 脚本介绍
#!/bin/sh ... #帮组选项 Help options: --help print this message --quiet Suppress showing informative output --list-decoders show all available decoders --list-encoders show all available encoders --list-hwaccels show all available hardware accelerators --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-bsfs show all available bitstream filters --list-indevs show all available input devices --list-outdevs show all available output devices --list-filters show all available filters #标准选项 #--disable 代表关闭状态 ;--enable 代表开启状态 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 install in PREFIX [$prefix_default] --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] Configuration options: #开启静态库 --disable-static do not build static libraries [no] #关闭动态库 --enable-shared build shared libraries [no #可以优化库的大小 --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] Program options: #我们不需要使用程序,不需要在Windows中执行,某.exe程序,我们只需要在代码中使用 [此命令操作的是下面三项] --disable-programs do not build command line programs #使用FFmpeg命令 --disable-ffmpeg disable ffmpeg build #播放器 --disable-ffplay disable ffplay build --disable-ffprobe disable ffprobe build Documentation options: --disable-doc do not build documentation --disable-htmlpages do not build HTML documentation pages --disable-manpages do not build man documentation pages --disable-podpages do not build POD documentation pages --disable-txtpages do not build text documentation pages #模块选项 Component options: #可以操控我们的摄像头-(Android中是不支持)) --disable-avdevice disable libavdevice build #audio video codec(编码 和 解码) --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 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 #混合封装(音视频等于 一段音频 一段视频 合并在一起 就是.mp4,不想这样就可以关闭) --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 ...
编写 32/64 位 FFmpeg4.2.2 shell 脚本
#!/bin/bash echo ">>>>>>>>> 注意:该编译环境目前只在 NDK17c + ffmpeg4.2.2 测试过 <<<<<<<<" echo ">>>>>>>>> 注意:该编译环境目前只在 NDK17c + ffmpeg4.2.2 测试过 <<<<<<<<" echo ">>>>>>>>> 注意:该编译环境目前只在 NDK17c + ffmpeg4.2.2 测试过 <<<<<<<<" #NDK_ROOT 变量指向 ndk 目录 NDK_ROOT=$NDK_HOME #指定android api版本 ANDROID_API=21 #开始编译 在下面调用传入参数即可 function build_ffmpeg { echo "开始编译 $PREFIX_CPU" echo "开始编译 $PREFIX" echo "开始编译 $TOOLCHAIN" ./configure \ --prefix=$PREFIX \ --enable-small \ --disable-programs \ --disable-avdevice \ --disable-encoders \ --disable-muxers \ --disable-filters \ --enable-cross-compile \ --cross-prefix=$CROSS_PREFIX \ --disable-shared \ --enable-static \ --sysroot=$NDK_ROOT/platforms/android-$ANDROID_API/arch-$ARCH \ --extra-cflags="$CFLAGES" \ --arch=$ARCH \ --target-os=android #上面运行脚本生成makefile之后,使用make执行脚本 make clean make make install echo "$PREFIX_CPU 编译完成" echo "$PREFIX_CPU 编译完成" echo "$PREFIX_CPU 编译完成" } #armeabi-v7a PREFIX=./result/armeabi-v7a TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64 ARCH=arm CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi- CFLAGES="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=$ANDROID_API -U_FILE_OFFSET_BITS -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" build_ffmpeg #arm64-v8a PREFIX=./result/arm64-v8a TOOLCHAIN=$NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64 ARCH=arm64 CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android- CFLAGES="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/aarch64-linux-android -D__ANDROID_API__=$ANDROID_API -U_FILE_OFFSET_BITS -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC" build_ffmpeg #直接跳转到编译完成的路径 cd /result
编译遇见的坑:
-
arm-linux-androideabi-gcc is unable to create an executable file
原因 1:
FFmpeg 4.2.2 版本默认使用了 clang 进行编译
解决:
//1. 修改 configure 文件 vim configure //2. 把 默认的 clang 修改为 gcc if test "$target_os" = android; then # cc_default="clang" cc_default="gcc" fi
原因 2:
检查路径是否正确
-
nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.
分析:yasm 是汇编编译器,ffmpeg 为了提高效率使用了汇编指令,如 MMX 和 SSE等。
所以系统中未安装yasm时,就会报上面错误。
解决错误:安装yasm编译器。安装方法如下: 1)下载:[yasm的下载链接] wget http://www.tortall.net/projects/yasm/releases/yasm-1.3.0.tar.gz 2)解压:把下载下来的压缩包进行解压 tar -zxvf yasm-1.3.0.tar.gz 3)切换路径: cd yasm-1.3.0 4)执行配置: ./configure 5)编译: make 6)安装: make install
-
解决 " lib64 libc so 6 version `GLIBC_2 18' not found (required by lib...
curl -O http://ftp.gnu.org/gnu/glibc/glibc-2.18.tar.gz tar zxf glibc-2.18.tar.gz cd glibc-2.18/ mkdir build cd build/ ../configure --prefix=/usr --disable-profile --enable-add-ons --with-headers=/usr/include --with-binutils=/usr/bin make make install 安装完成后,查看是否成功 ll /lib64/libc* 然后可以继续查看 glibc 支持的版本 strings /lib64/libc.so.6 | grep GLIBC //------------------------------------------------------------ //下面可以不用参考,这个是我在升级 glibc 的时候把 libc-2.17.so 给误删除了,导致基本上瘫痪了,可以使用以下命令恢复 //ll cp 等命令失效请用以下进行软连接 LD_PRELOAD=/lib64/libc-2.17.so ln -s /lib64/libc-2.17.so /lib64/libc.so.6 //如果不小心定义了错误环境变量可以通过以下命令删除 unset LD_LIBRARY_PATH
-
config.mak 文件没有生成
解决:
执行
./configure --disable-x86asm
生成 config.mak 文件错误解决完之后,按下回车键,如果出现如下输出,就开始在编译了:
大概等 10 分钟左右就会编译完成,如下所示就代表编译静态库成功了:
如果想编译动态库,仅仅修改下参数就行了,如下所示:
#开启动态库 --enable-shared \ #关闭静态库 --disable-static \
压缩:
tar -zcvf ffmpeg_android.tar.gz android
利用 FileZill 工具 从服务器端把编译好的静态文件导出到电脑本地,导出完之后我们就在 AS 中测试编译的 .a 文件是否有误。
Android 集成交叉编译之后的 FFmpeg 静态库
-
创建一个 C/C++ 项目的 Android 工程,并把编译好的静态库导入项目中,如下结构:
-
编写 JNI 代码
#include <jni.h> // 有坑,会报错,必须混合编译 //#include <libavutil/avutil.h> extern "C" { #include <libavutil/avutil.h> } /** * 拿到 ffmpeg 当前版本 * @return */ const char *getFFmpegVer() { return av_version_info(); } extern "C" JNIEXPORT jstring JNICALL Java_com_devyk_ffmpeg_MainActivity_getFFmpegVersion(JNIEnv *env, jclass type) { return env->NewStringUTF(getFFmpegVer()); }
-
编写 CMakeLists.txt 脚本
#指定 Cmake 最低版本 cmake_minimum_required(VERSION 3.4.1) #找到包含所有的cpp文件 file(GLOB allCpp *.cpp) #打印当前 cmakeLists 的路径 message("当前cmakel路径: ${CMAKE_SOURCE_DIR} \n cpu架构:${CMAKE_ANDROID_ARCH_ABI}") add_library( ffmpeg_lib SHARED ${allCpp}) find_library( log-lib log) # 引入FFmpeg的头文件 include_directories(${CMAKE_SOURCE_DIR}/include) # 引入FFmpeg的库文件,设置内部的方式引入,指定库的目录是 -L 指定具体的库-l set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/${CMAKE_ANDROID_ARCH_ABI}") target_link_libraries( ffmpeg_lib # 具体的库文件,链接到总库 # 这样写会报错,有坑 # avcodec avfilter avformat avutil swresample swscale # 先把有依赖的库,先依赖进来 avformat avcodec avfilter avutil swresample swscale ${log-lib})
-
app/build.gradle 配置
apply plugin: 'com.android.application' android { compileSdkVersion 29 buildToolsVersion "29.0.2" ... defaultConfig { ... externalNativeBuild(){ cmake{ abiFilters "armeabi-v7a" //指定编译为 armeabi-v7a } } } ... externalNativeBuild(){ cmake{ //指定构建 C++ 代码脚本 path 'src/main/cpp/CMakeLists.txt' } } } ...
-
MainActivity 测试代码
public class MainActivity extends AppCompatActivity { static { System.loadLibrary("ffmpeg_lib"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView ffmpegVer = findViewById(R.id.ffmpeg_ver); ffmpegVer.setText("当前 FFmpeg 版本为:" + getFFmpegVersion()); } /** * @return 返回当前 */ public native static String getFFmpegVersion(); }
效果:
到这里 FFmpeg 编译及导入 AS 使用已经全部介绍完了,动态库编译及使用需要自己动手去实践了,使用方式都大同小异。
总结
在编译 FFmpeg 的时候会出现很多坑,基本上每个版本的 shell 脚本编写都不一样,所以如果对 Shell 不太了解的,建议先去复习一下。
该篇文章下来咱们用到了交叉编译、 Shell 脚本、 JNI 、Cmake 的知识,如果对这些基础还不了解的一定要先去把基础学好。也可以看我之前系列基础文章。
感谢
以上所述就是小编给大家介绍的《音视频学习 (六) FFmpeg4.2.2 交叉编译动态静态库》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- Android NDK秘籍--编译静态库、调用静态库
- 用 Xcode 编译 Cocoapods 静态库
- Qt 5.9.0 MinGW 静态编译版本
- 音视频学习 (四) 交叉编译和动态库、静态库入门
- 编译型语言、解释型语言、静态类型语言、动态类型语言概念与区别
- 详解64位静态编译程序的fini_array劫持及ROP攻击
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python for Everyone
Cay S. Horstmann、Rance D. Necaise / John Wiley & Sons / 2013-4-26 / GBP 181.99
Cay Horstmann's" Python for Everyone "provides readers with step-by-step guidance, a feature that is immensely helpful for building confidence and providing an outline for the task at hand. "Problem S......一起来看看 《Python for Everyone》 这本书的介绍吧!
XML、JSON 在线转换
在线XML、JSON转换工具
HEX HSV 转换工具
HEX HSV 互换工具