Linux下ffmpeg4.x版本编译
前言
最近由于项目要求,需要为android系统机顶盒(32位)的应用提供libffmpeg.so,因此总结了一下编译方法与遇到的坑。
一、编译环境
操作系统:Ubuntu 5.4.0
ffmpeg源码版本:ffmpeg-cd04bb4
---->下载链接:https://git.ffmpeg.org/gitweb/ffmpeg.git/commit/cd04bb4afea111aa85afbaf806ae747103a843fd
ndk使用版本:android-ndk-r17c
---->下载链接:https://developer.android.google.cn/ndk/downloads/older_releases
二、编译步骤
1.修改configure文件内容
刚下载的ffmpeg源码,直接编译出来的so会带有版本号的后缀,无法使用,需要修改configure文件内容去除版本号:
将:
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'
修改为:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
2.新建build_android.sh文件
新建build_android.sh文件,用于编译生成libavcodec.a、libavfilter.a、libswresample.a、libavformat.a、libavutil.a、libswscale.a、libavdevice.a、libpostproc.a,并将它们打包生成最终的libffmpeg.so;根据自己的需要修改ndk版本和so生成的路径来修改build_android.sh中的内容:
#!/bin/bash
NDK=/data_ex/qcs/zjz/tools/android-ndk-r17c/
ISYSROOT=$NDK/sysroot
#修改点1
PLATFORM=$NDK/platforms/android-19/arch-arm
#修改点2:如果是Mac系统编译路径则是:xxx/darwin-x86_64/xxx
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
#修改点3:
PREFIX=../
function build_one
{
./configure \
--prefix=$PREFIX \
--target-os=android \
--enable-cross-compile \
--disable-doc \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--arch=arm \
--sysroot=$PLATFORM \
--extra-cflags="-I$ISYSROOT/usr/include -isystem $ISYSROOT/usr/include/arm-linux-androideabi" \
--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
--nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
--enable-static \
--disable-shared \
--enable-runtime-cpudetect \
--enable-gpl \
--enable-small \
--enable-ffplay \
--enable-ffprobe \
--enable-ffmpeg \
--disable-debug \
--disable-symver \
--disable-stripping \
--extra-cflags="-Os -pie -fPIE -fpic $ADDI_CFLAGS -U_FILE_OFFSET_BITS -D__ANDROID_API__=19" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make -j4
make install
$TOOLCHAIN/bin/arm-linux-androideabi-ld \
-rpath-link=$PLATFORM/usr/lib \
-L$PLATFORM/usr/lib \
-L$PREFIX/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
libavcodec/libavcodec.a \
libavfilter/libavfilter.a \
libswresample/libswresample.a \
libavformat/libavformat.a \
libavutil/libavutil.a \
libswscale/libswscale.a \
libavdevice/libavdevice.a \
libpostproc/libpostproc.a \
-lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a #修改点4: 4.8 or 4.9
echo "编译结束!"
}
# arm v7vfp
echo "编译不支持neon和硬解码"
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
ADDI_CFLAGS="-marm"
build_one #build first task
echo "编译支持neon和硬解码"
CPU=armv7-a
PREFIX=./android/armv7-a-neon-hard
CFLAG="-I$INCLUDE -I$INCLUDE/arm-linux-androideabi -fPIC -DANDROID -mfpu=neon -mfloat-abi=softfp"
ADD="--enable-asm \
--enable-neon \
--enable-jni \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
--enable-hwaccel=h264_mediacodec "
build_one #build second task
3.常见编译错误
1.报错一:format/udp.c:290 error: request for member ‘s_addr‘ in something not a structure or union
----试了ndk10-17版本,发现ndk 10-15版本会出现错误,换用高版本(最好是r17c)之后就不会报此问题
2.报错二:xxxxx/include/stdint.h:9:26: fatal error: stdint.h: No such file or directory
----出现这个错误是因为NDK r17c版本将头文件和库文件进行了分离,指定的sysroot文件夹下只有库文件,而头文件放在了NDK目录下的sysroot内. 在build_android.sh文件的–extra-cflags中添加 “-isysroot $NDK/sysroot”即可
3.报错三:libavcodec/aaccoder.c:803:25: error: expected identifier or ‘(’ before numeric constant int B0 = 0, B1 = 0;
----将里面的B0都改为其他变量(如b0)即可;后续其他文件也会报类似错误,都是把B0改为b0或其他变量
4.报错四:在编译完毕32位libffmpeg.so后,使用盒子无法加载动态库,报出dlopen("/data/app-lib/com.example.freeviewpoint_demo-2/libffmpeg.so") failed: dlopen failed: cannot locate symbol “mmap64” referenced by “libffmpeg.so”…
----这是因为盒子为Android4.4版本,对应android platform版本为19,而之前编译使用的是21
5.报错五(接报错四)修改build_android.sh中android platform版本为19后编译,报出libavcodec/v4l2_buffers.c:434:44: error: call to ‘mmap’ declared with attribute error: mmap is not available > with _FILE_OFFSET_BITS=64 when using GCC until android-21. Either raise your minSdkVersion, disable > _FILE_OFFSET_BITS=64, or switch to Clang.
----21版本以下,需要取消 _FILE_OFFSET_BITS宏定义。添加编译参数: -U_FILE_OFFSET_BITS
总结
编译ffmpeg竟然遇到这么多坑,也是服了,不过网上查了n多资料,加上自己试验总算编译成功。最后附上自己编译的32位libffmpeg.so链接:https://download.csdn.net/download/qq_31366471/15174217