I have been compiling the FFmpeg library for the past two days. To be honest, I have stepped on a lot of pitfalls. I also know how to troubleshoot problems, so I still plan to record them, which can be regarded as a summary.
Baidu understands FFmpeg
Environment and Downloads
1. CentOs 8
2. android-ndk-r17c
3. ffmpeg-4.2.2
Pay attention to download the ndk of the linux version. When obtaining the download link, download it to linux through wget
Configure Help Options
view help options ./configure --help
Usage: configure [options]
Options: [defaults in brackets after descriptions]
帮助选项
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
标准选项
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 [/usr/local]
--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]
--disable 代表关闭状态
--enable 代表开启状态
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:
--disable-programs do not build command line programs == 默认是关闭的,如果我们开启
--disable-ffmpeg disable ffmpeg build == 使用FFmpeg命令
--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
FFmpeg 是由多个模块组成的:
Component options:
--disable-avdevice disable libavdevice build == 模块之一(可以操控我们的摄像头-(Android中是不支持))
--disable-avcodec disable libavcodec build == audio video codec(编码 和 解码)
--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
--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
...
When writing FFmpeg scripts, it needs to be configured according to the above help options, so it is pasted on it. Compiling FFmpeg is a modification of its configuration.
#!/bin/bash
#NDK_ROOT 变量指向ndk目录
NDK_ROOT=/root/android-ndk-r17c
#TOOLCHAIN 变量指向ndk中的交叉编译gcc所在的目录
TOOLCHAIN=$NDK_ROOT/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64
#指定android api版本
ANDROID_API=21
#此变量用于编译完成之后的库与头文件存放在哪个目录
PREFIX=./android/arm64
#执行configure脚本,用于生成makefile
#--prefix : 安装目录
#--enable-small : 优化大小
#--disable-programs : 不编译ffmpeg程序(命令行工具),我们是需要获得静态(动态)库。
#--disable-avdevice : 关闭avdevice模块,此模块在android中无用
#--disable-encoders : 关闭所有编码器 (播放不需要编码)
#--disable-muxers : 关闭所有复用器(封装器),不需要生成mp4这样的文件,所以关闭
#--disable-filters :关闭视频滤镜
#--enable-cross-compile : 开启交叉编译
#--cross-prefix: gcc的前缀 xxx/xxx/xxx-gcc 则给xxx/xxx/xxx-
#disable-shared enable-static 不写也可以,默认就是这样的。
#--sysroot:
#--extra-cflags: 会传给gcc的参数
#--arch --target-os : 必须要给
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--disable-yasm \
--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/aarch64-linux-android- \
--enable-shared \ # 开启动态库
--disable-static \ # 关闭静态库
--sysroot=$NDK_ROOT/platforms/android-$ANDROID_API/arch-arm64 \
--extra-cflags="-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" \
--arch=arm64 \
--target-os=android
#上面运行脚本生成makefile之后,使用make执行脚本
make clean
make install
This script can be dynamically configured according to your own needs.
stepped on the pit
1 . arm-linux-androideabi-gcc is unable to create an executable file
Reason: FFmpeg 4.2.2 uses clang to compile by default. Solution:
//1. 修改 configure 文件
vim configure
//2. 把 默认的 clang 修改为 gcc
if test "$target_os" = android; then
# cc_default="clang"
cc_default="gcc"
fi
2. The .config.mak file is not generated
Solution: Execute ./configure --disable-x86asm
to generate the config.mak file
generate object file
I generated the abi architecture of arm64-v8a, and I will post the script of armeabi-v7a later, which is available for personal testing. Basically, the two abi architectures used now
lib directory
include directory
share directory
If the library file is not generated in the target directory, it must be a configuration problem. At this time, you can ffbuild/config.log
check the error message. Generally, it will tell you where there is a problem at the end, and then modify the corresponding file.
Build library file download
You can use other tools to download the generated library file. I am too lazy to download the software here. I downloaded it directly with lrzsz
the command. It needs to be installed for the first time.
yum -y install lrzsz
Library file compression
tar -zcvf ffmpeg_android.tar.gz android
download
sz ffmpeg_android.tar.gz
Ported to android for testing
file copy
The files in lib need to be copied to arm64-v8a, and the header files are copied to the include directory
Modify CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
file(GLOB allCpp *.cpp)
add_library(
native-lib
SHARED
${allCpp})
find_library(
log-lib
log)
# 引入FFmpeg的头文件
include_directories(${CMAKE_SOURCE_DIR}/include)
#message("CMAKE_ANDROID_ARCH_ABI版本是:" + ${CMAKE_ANDROID_ARCH_ABI})
# 引入FFmpeg的库文件,设置内部的方式引入,指定库的目录是 -L 指定具体的库-l
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/${CMAKE_ANDROID_ARCH_ABI}")
target_link_libraries(
native-lib
# 具体的库文件,链接到总库
# 这样写会报错,有坑
# avcodec avfilter avformat avutil swresample swscale
# 先把有依赖的库,先依赖进来
avformat avcodec avfilter avutil swresample swscale
${log-lib})
Modify the build.gradle file
The configuration in the cmake closure is to specify the ABI output in CmakeList.
The configuration in the ndk closure is to prevent the abi architecture from being packaged into a package. When I use a 32-bit (mobile phone 64-bit) library, there is no Add the closure configuration of ndk, resulting in a crash all the time, just add it
Add code test in cpp
#include <jni.h>
#include <string>
// 有坑,会报错,必须混合编译
// #include <libavutil/avutil.h>
extern "C" {
#include <libavutil/avutil.h>
}
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_ffmpegdemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = av_version_info();
return env->NewStringUTF(hello.c_str());
}
run test
At this time, the version of the underlying FFmpeg library can be obtained at the java layer, which means that the library is compiled and transplanted successfully.
armeabi-v7a script
#!/bin/bash
#NDK_ROOT 变量指向ndk目录
NDK_ROOT=/root/android-ndk-r17c
#TOOLCHAIN 变量指向ndk中的交叉编译gcc所在的目录
TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
#指定android api版本
ANDROID_API=17
#此变量用于编译完成之后的库与头文件存放在哪个目录
PREFIX=./android/armeabi-v7a
#执行configure脚本,用于生成makefile
#--prefix : 安装目录
#--enable-small : 优化大小
#--disable-programs : 不编译ffmpeg程序(命令行工具),我们是需要获得静态(动态)库。
#--disable-avdevice : 关闭avdevice模块,此模块在android中无用
#--disable-encoders : 关闭所有编码器 (播放不需要编码)
#--disable-muxers : 关闭所有复用器(封装器),不需要生成mp4这样的文件,所以关闭
#--disable-filters :关闭视频滤镜
#--enable-cross-compile : 开启交叉编译
#--cross-prefix: gcc的前缀 xxx/xxx/xxx-gcc 则给xxx/xxx/xxx-
#disable-shared enable-static 不写也可以,默认就是这样的。
#--sysroot:
#--extra-cflags: 会传给gcc的参数
#--arch --target-os : 必须要给
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--disable-shared \
--enable-static \
--sysroot=$NDK_ROOT/platforms/android-$ANDROID_API/arch-arm \
--extra-cflags="-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" \
--arch=arm \
--target-os=android
#上面运行脚本生成makefile之后,使用make执行脚本
make clean
make install
Summarize
There will be many pitfalls when compiling FFmpeg. Basically, the shell scripting of each version is different, so if you don't know much about Shell, it is recommended to review it first .
reference
1. Audio and video learning (6) FFmpeg 4.2.2 cross-compilation
2. Clang compilation FFmpeg FAQ
3. FFmpeg installation and compilation - tutorial and pitfalls
Original FFmpeg4.2.2 cross compilation
★The business card at the end of the article can receive audio and video development learning materials for free, including (FFmpeg, webRTC, rtmp, hls, rtsp, ffplay, srs) and audio and video learning roadmaps, etc.
see below!