用NDK编译FFmpeg4.1.3

2019-07-01 12:34:16 浏览数 (1)

一、准备环境

操作系统:Mac

NDK版本:r17c

FFmpeg版本:4.1.3

二、编译脚本

首先我们需要修改下FFmpeg目录下的configure文件的内容,

代码语言:txt复制
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)'

替换为

代码语言:txt复制
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'

然后在FFmpeg目录下新建一个build.sh文件,这个将作为编译脚本使用。

编译脚本内容是:

代码语言:txt复制
#!/bin/bash
set -x
API=14
CPU=armv7-a
NDK=/Users/chenqidian/android-ndk-r17c
SYSROOT=$NDK/platforms/android-$API/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
PREFIX=$(pwd)/android/$CPU

function function_one
{
./configure 
  --prefix=$PREFIX 
  --enable-shared 
  --disable-static 
  --disable-doc 
  --disable-ffplay 
  --disable-ffprobe 
  --disable-symver 
  --disable-ffmpeg 
  --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc 
  --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- 
  --target-os=android 
  --arch=arm 
  --enable-cross-compile 
  --sysroot=$SYSROOT 
  --extra-cflags="-I$NDK/sysroot/usr/include/arm-linux-androideabi -isysroot $NDK/sysroot -fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a" 
  --enable-neon

make clean all
make
make install
}

function_one

注意:

这里有几个参数需要根据实际情况来配置的;

APICPUNDK以及TOOLCHAIN这个路径最后的文件夹名称(Mac下是darwin-x86_64、linux可能叫linux-x86_64、Windows也不一样);

最后生成的库在PREFIX这个路径下。

三、操作步骤

代码语言:txt复制
# 巴拉巴拉一堆,然后agree就可以
sudo xcodebuild -license
# 这一步很关键,不然跑编译脚本会有一堆文件找不到的错误
./configure
# 真正编译
./build.sh

四、过程踩坑

哪有那么容易的事,以为用了上面那三个命令行就可以编译出FFmpeg,这里记录下上面三个命令行中踩到的坑。

问题一:

首先是./configure执行后:

代码语言:txt复制
nasm/yasm not found or too old. Use --disable-x86asm for a crippled build.

这个还比较简单只要安装下yasm就能将解决

代码语言:txt复制
brew install yasm

问题二:

代码语言:txt复制
Unknown option "--prefix=/Users/chenqidian/ffmpeg/android/arm".

See ./configure --help for available options.

解决办法:

复制网上的sh脚本时,将./configure --prefix=$PREFIX 写在同一行了,换行写就可以了,记得后面去掉空格

问题三:

代码语言:txt复制
Unknown option "--disable-ffserver".

解决办法:新版的FFmpeg已经没有这个参数了,去掉就可以了。相关命令参数可以通过./configure --help来查看。

问题四:

代码语言:txt复制
/bin/sh: ranlib/usr/local/lib/libavdevice.a: No such file or directory

make: *** [install-libavdevice-static] Error 127

原因和解决办法:

由于LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'这个命令少打了一个空格,应该改为`LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'。

之后要重新执行下./configure,不然还是报这个错。

问题五:

代码语言:txt复制
/Users/chenqidian/android-ndk-r20/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-gcc is unable to create an executable file.

**C compiler test failed.**

原因和解决办法:

我之前使用的是ndk-r20时报的这个错误,原因是没有arm-linux-androideabi-gcc这个文件了。

代码语言:txt复制
chenqidiandeMacBook-Pro:~ chenqidian$ cd /Users/chenqidian/android-ndk-r20/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin
chenqidiandeMacBook-Pro:bin chenqidian$ ls
arm-linux-androideabi-addr2line	arm-linux-androideabi-ld.gold
arm-linux-androideabi-ar	arm-linux-androideabi-nm
arm-linux-androideabi-as	arm-linux-androideabi-objcopy
arm-linux-androideabi-c  filt	arm-linux-androideabi-objdump
arm-linux-androideabi-dwp	arm-linux-androideabi-ranlib
arm-linux-androideabi-elfedit	arm-linux-androideabi-readelf
arm-linux-androideabi-gprof	arm-linux-androideabi-size
arm-linux-androideabi-ld	arm-linux-androideabi-strings
arm-linux-androideabi-ld.bfd	arm-linux-androideabi-strip

cd到这个目录下看,确实没有gcc这个文件。

原来是ndk在R19C中把GCC,最后一个有gcc的版本是r17c,偷了个懒,换这个有gcc版本的ndk(就是现在的r17c这个版本)。

问题六:

代码语言:txt复制
/Users/chenqidian/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/include/stdint.h:9:26: fatal error: stdint.h: No such file or directory

原因和解决办法:

头文件找不到,是因为r17c这个版本把头文件分离出来了,需在–extra-cflags中添加 “-isysroot $NDK/sysroot”

问题七:

代码语言:txt复制
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;
                         ^
compilation terminated due to -Wfatal-errors.
make: *** [libavcodec/aaccoder.o] Error 1

原因和解决办法:变量名冲突了,修改FFmpeg/libavcodec/aaccoder.c 文件B0改成b0或者其他不会冲突的变量名

问题八:

代码语言:txt复制
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:204:14: note: in definition of macro 'TAB_MVF'
     tab_mvf[(y) * min_pu_width   x]
              ^
libavcodec/hevc_mvs.c:274:16: note: in expansion of macro 'TAB_MVF_PU'
     (cand && !(TAB_MVF_PU(v).pred_flag == PF_INTRA))
                ^
libavcodec/hevc_mvs.c:368:23: note: in expansion of macro 'AVAILABLE'
     is_available_b0 = AVAILABLE(cand_up_right, B0) &&
                       ^
compilation terminated due to -Wfatal-errors.
make: *** [libavcodec/hevc_mvs.o] Error 1

原因和解决方法:变量名冲突了,将FFmpeg/libavcodec/hevc_mvs.c文件的变量B0改成b0,xB0改成xb0,yB0改成yb0;

问题九:

代码语言:txt复制
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;
         ^
compilation terminated due to -Wfatal-errors.
make: *** [libavcodec/opus_pvq.o] Error 1

原因和解决办法:变量名冲突了,将FFmpeg/libavcodec/opus_pvq.c文件的变量B0改成b0;

问题十:

编译完一看都是后缀.a的库,不是我们要的so库?

解决办法:看下你的编译脚本,要这么写

代码语言:txt复制
  --enable-shared 
  --disable-static 

五、参考文章

https://blog.csdn.net/qq_34902522/article/details/87879145

http://alientechlab.com/how-to-build-ffmpeg-for-android/

0 人点赞