Linux下编译ffmpeg-4.1,arm32, arm64, x86

目录

目标

准备工作

编译arm版本

遇到的问题及解决方案

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 文件:

扫描二维码关注公众号,回复: 11551914 查看本文章
# 将上面的四行注释掉
#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    // 主要记录错误

猜你喜欢

转载自blog.csdn.net/qq_34732729/article/details/107761816