Linux下编译ffmpeg-4.1,arm32, arm64, x86问题及解决方案
目录
目标
编译ffmpeg-4.1版本的 arm32, arm64, x86的动态库。
准备工作
新建目录,mkdir ffmpeg, cd ffmpeg, 下载ffmpeg4.1的源码,并解压。http://ffmpeg.org/releases/
# 下载
wget http://ffmpeg.org/releases/ffmpeg-4.2.3.tar.bz2
# 解压
tar xvf ffmpeg-4.2.3.tar.bz2
在同一个目录ffmpeg下,下载编译器:版本选择的是14b。https://developer.android.google.cn/ndk/downloads/older_releases
# 下载
wget https://dl.google.com/android/repository/android-ndk-r14b-linux-x86_64.zip
# 解压
unzip android-ndk-r21b-linux-x86_64.zip
修改ffmpeg4.1的 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)'
在ffmpeg4.1的根目录下,编写run.sh文件, run64.sh文件。
#run.sh, arm 32
#!/bin/bash
#modify those veriable based on your env
#===========================
NDK=/home/ht-dong/ffmpeg/android-ndk-r14b
#32 or 64
archbit=32
#===========================
echo "build for 32bit"
#32bit
abi='armeabi'
cpu='arm'
arch='arm'
android='androideabi'
SYSROOT=$NDK/platforms/android-24/arch-$arch/
TOOLCHAIN=$NDK/toolchains/$cpu-linux-$android-4.9/prebuilt/linux-x86_64
PREFIX=$(pwd)/android/$cpu
#ADDI_CFLAGS="-marm"
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--enable-yasm \
--cross-prefix=$TOOLCHAIN/bin/$cpu-linux-$android- \
--target-os=linux \
--arch=$cpu \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic -DANDROID" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
build_one
#run64.sh
#!/bin/bash
#modify those veriable based on your env
#===========================
NDK=/home/ht-dong/ffmpeg/android-ndk-r14b
#32 or 64
archbit=64
#===========================
#64bit
echo "build for 64bit"
abi='arm64-v8a'
cpu='aarch64'
arch='arm64'
android='android'
SYSROOT=$NDK/platforms/android-24/arch-$arch/
TOOLCHAIN=$NDK/toolchains/$cpu-linux-$android-4.9/prebuilt/linux-x86_64
PREFIX=$(pwd)/android/$cpu
#ADDI_CFLAGS="-marm"
function build_one
{
./configure \
--prefix=$PREFIX \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--enable-yasm \
--cross-prefix=$TOOLCHAIN/bin/$cpu-linux-$android- \
--target-os=linux \
--arch=$cpu \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic -DANDROID" \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
build_one
编译arm版本
先编译arm32位的库:
# 为run.sh 文件 授权
chmod 777 run.sh
# 运行
./run.sh
遇到的问题及解决方案
错误一:
libavformat/udp.c: In function 'udp_set_multicast_sources':
libavformat/udp.c:290:28: error: request for member 's_addr' in something not a structure or union
mreqs.imr_multiaddr.s_addr = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
^
libavformat/udp.c:292:32: error: incompatible types when assigning to type '__u32' from type 'struct in_addr'
mreqs.imr_interface= ((struct sockaddr_in *)local_addr)->sin_addr;
^
libavformat/udp.c:294:32: error: request for member 's_addr' in something not a structure or union
mreqs.imr_interface.s_addr= INADDR_ANY;
^
libavformat/udp.c:295:29: error: request for member 's_addr' in something not a structure or union
mreqs.imr_sourceaddr.s_addr = ((struct sockaddr_in *)&sources[i])->sin_addr.s_addr;
^
ffbuild/common.mak:59: recipe for target 'libavformat/udp.o' failed
make: *** [libavformat/udp.o] Error 1
注释掉udp.c中的那几行代码。 以后最好不用ffmpeg的udp, 否则,会有意想不到的惊喜。
解决好错误一之后,重新编译,出现错误二:
libavcodec/aaccoder.c: In function 'search_for_ms':
libavcodec/aaccoder.c:803:25: error: expected identifier or '(' before numeric constant
int B0 = 0, B1 = 0;
^
libavcodec/aaccoder.c:865:28: error: lvalue required as left operand of assignment
B0 += b1+b2;
^
libavcodec/aaccoder.c:866:25: error: 'B1' undeclared (first use in this function)
B1 += b3+b4;
重命名,把B0, 都改成了b0。
# 快捷键,全局搜索,一个一个进行更改确认。
:%s/B0/b0/gc
# 解释:
:% 全局。
s search,
B0, 关键字,
b0替换字,
gc每一行都判断。
y, 替换。 n不替换,继续下一个。
B1 其实是有初始化声明的,就是803行,但是866是在一个循环中使用。理论上来说,应该是能找到的。所以替换完B0,B1的错误就不再报了。
解决好错误二之后,重新编译,出现错误三:
libavcodec/hevc_mvs.c: In function 'derive_spatial_merge_candidates':
libavcodec/hevc_mvs.c:208:15: error: 'y0000000' undeclared (first use in this function)
((y ## v) >> s->ps.sps->log2_min_pu_size))
^
......
libavcodec/hevc_mvs.c:207:15: error: 'x0000000' undeclared (first use in this function)
TAB_MVF(((x ## v) >> s->ps.sps->log2_min_pu_size), \
^
......
libavcodec/hevc_mvs.c: In function 'ff_hevc_luma_mv_mvp_mode':
libavcodec/hevc_mvs.c:208:15: error: 'y0000000' undeclared (first use in this function)
((y ## v) >> s->ps.sps->log2_min_pu_size))
^
......
libavcodec/hevc_mvs.c:207:15: error: 'x0000000' undeclared (first use in this function)
TAB_MVF(((x ## v) >> s->ps.sps->log2_min_pu_size), \
^
......
ffbuild/common.mak:60: recipe for target 'libavcodec/hevc_mvs.o' failed
make: *** [libavcodec/hevc_mvs.o] Error 1
解决方法:将libavcodec/hevc_mvs.c文件的变量B0改成b0,xB0改成xb0,yB0改成yb0
输入命令: :%s/B0/b0/gc ,然后 y 或 n 进行替换或跳过。
20 substitutions on 18 lines(一共替换了这么多)
解决好错误三之后,重新编译,出现错误四:
libavcodec/opus_pvq.c: In function 'quant_band_template':
libavcodec/opus_pvq.c:498:9: error: expected identifier or '(' before numeric constant
int B0 = blocks;
^
libavcodec/opus_pvq.c:559:12: error: lvalue required as left operand of assignment
B0 = blocks;
^
ffbuild/common.mak:60: recipe for target 'libavcodec/opus_pvq.o' failed
make: *** [libavcodec/opus_pvq.o] Error 1
解决方法:将libavcodec/opus_pvq.c文件的变量B0改成b0
输入命令: :%s/B0/b0/gc ,然后 y 或 n 进行替换或跳过。
14 substitutions on 14 lines (修改的个数)
arm32, arm64, 成功
终于通过了,arm32版本的。
然后直接执行run64.sh的脚本,直接生成!
编译x86
在ffmpeg4.1的根目录下,直接新建脚本run_x86.sh, 然后执行,
#这个路径,就直接生成在根目录下了,根据自己情况酌情添加。
PREFIX=$(pwd)/ffmpeg_x86
./configure --enable-shared --prefix=$PREFIX
make
sudo make install
报错如下:
INSTALL libavdevice/libavdevice.a
LD libavutil/libavutil-56.so
/usr/bin/ld: libavutil/log2_tab.o: Relocations in generic ELF (EM: 183)
/usr/bin/ld: libavutil/log2_tab.o: Relocations in generic ELF (EM: 183)
libavutil/log2_tab.o: error adding symbols: File in wrong format
collect2: error: ld returned 1 exit status
ffbuild/library.mak:102: recipe for target 'libavutil/libavutil-56.so' failed
make: *** [libavutil/libavutil-56.so] Error 1
看来需要一份干净的ffmpeg源码,重新编译。所以,另起一个文件夹,重新解压,源文件并没有任何修改,直接编译生成。
内心的戏:arm的两个版本,改了这么多地方,这编译出来的库,会不会有很多坑呀  ̄□ ̄||
参考链接:
https://blog.csdn.net/qq_34732729/article/details/107690316 // 编译ffmpeg3.3版本的,这三个库
https://blog.csdn.net/qq_34902522/article/details/87879145 // 主要记录错误
本文地址:https://blog.csdn.net/qq_34732729/article/details/107761816