FFmpeg NDK交叉编译

文章目录

      • 编译环境
      • MacOS下ndk Android 编译脚本(两个都可以用)
      • 最新版本编译(NDK20 ffmpeg4.2.2 环境MAC OS)
      • MacOS系统使用的编译脚本
      • 问题1
      • 问题2
      • 问题3
      • 问题4
      • 问题5
      • 问题6
      • 问题7
      • 问题8
    • 总结 血泪史

编译环境

​ Mac 10.14.6

​ ffmpeg 4.0.5

​ NDK 16(不能用Android SDK那里下载的NDK)

​ 注意:因每个版本的编译脚本可能都不太一样,请谨慎使用。

MacOS下ndk Android 编译脚本(两个都可以用)

#!/bin/bash
# 清空上次的编译
make clean
set -x
API=14
# CPU
CPU=arm
# 你自己的NDK路径。
NDK=xxxx/Sdk/android-ndk-r16b
# 设置你的android平台编译器的版本 android4.0
SYSROOT=$NDK/platforms/android-$API/arch-arm/
# 编译使用的toolchain
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
# 这个是输出的路径
PREFIX=$(pwd)/android/$CPU

function build_android
{
./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=arm" \
  --enable-neon

make clean all
make
make install
}
build_android

另一个版本

#!/bin/bash
export TMPDIR=xxxx/Downloads/ffmpeg-4.0.5/android
#这句很重要,不然会报错 unable to create temporary file in

# NDK的路径,根据自己的安装位置进行设置
NDK=xxx/android-ndk-r16b
# 编译针对的平台,可以根据自己的需求进行设置
# 这里选择最低支持android-14, arm架构,生成的so库是放在
# libs/armeabi文件夹下的,若针对x86架构,要选择arch-x86
PLATFORM=$NDK/platforms/android-16/arch-arm

# 工具链的路径,根据编译的平台不同而不同
# arm-linux-androideabi-4.9与上面设置的PLATFORM对应,4.9为工具的版本号,
# 根据自己安装的NDK版本来确定,一般使用最新的版本
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64

function build_one
{
./configure \
    --prefix=$PREFIX \
    --enable-shared \
    --disable-static \
    --disable-doc \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-avdevice \
    --disable-doc \
    --disable-symver \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --target-os=linux \
    --arch=arm \
    --enable-cross-compile \
    --sysroot=$PLATFORM \
    --extra-cflags="-I$PLATFORM/usr/include" \
#    --extra-ldflags="-L$PLATFORM/usr/lib -nostdlib" \ #①这一句我注释掉了,不然会报 ld: -single_module: unknown option

$ADDITIONAL_CONFIGURE_FLAG
sed -i '' 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h
sed -i '' 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h
sed -i '' 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h
sed -i '' 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h
sed -i '' 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h
sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h

make clean
make -j4
make install

}

# arm v7vfp
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
PREFIX=./android/$CPU-vfp
ADDITIONAL_CONFIGURE_FLAG=
build_one

# CPU=armv
# PREFIX=$(pwd)/android/$CPU
# ADDI_CFLAGS="-marm"
# build_one

#arm v6
#CPU=armv6
#OPTIMIZE_CFLAGS="-marm -march=$CPU"
#PREFIX=./android/$CPU 
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

#arm v7vfpv3
# CPU=armv7-a
# OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=$CPU "
# PREFIX=./android/$CPU
# ADDITIONAL_CONFIGURE_FLAG=
# build_one

#arm v7n
#CPU=armv7-a
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -march=$CPU -mtune=cortex-a8"
#PREFIX=./android/$CPU 
#ADDITIONAL_CONFIGURE_FLAG=--enable-neon
#build_one

#arm v6+vfp
#CPU=armv6
#OPTIMIZE_CFLAGS="-DCMP_HAVE_VFP -mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU"
#PREFIX=./android/${CPU}_vfp 
#ADDITIONAL_CONFIGURE_FLAG=
#build_one

第三个版本

#!/usr/bin/env bash

# 当前系统
export HOST_TAG=darwin-x86_64
# 支持的 Android CUP 架构
# export ARCH=aarch64
# export CPU=armv8-a
export ARCH=armv7a
export CPU=armv7-a
# 支持的 Android 最低系统版本
export MIN=21
export ANDROID_NDK_PLATFORM=android-21

export PREFIX=$(pwd)/android/$CPU
# NDK 根目录
export NDK=xxxx/android-ndk-r20b

export MIN_PLATFORM=$NDK/platforms/android-$MIN
export SYSROOT=$NDK/sysroot
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/$HOST_TAG
export AR=$TOOLCHAIN/bin/arm-linux-androideabi-ar
export AS=$TOOLCHAIN/bin/arm-linux-androideabi-as
export CC=$TOOLCHAIN/bin/$ARCH-linux-androideabi$MIN-clang
export CXX=$TOOLCHAIN/bin/$ARCH-linux-androideabi$MIN-clang++
export LD=$TOOLCHAIN/bin/arm-linux-androideabi-ld
export NM=$TOOLCHAIN/bin/arm-linux-androideabi-nm
export RANLIB=$TOOLCHAIN/bin/arm-linux-androideabi-ranlib
export STRIP=$TOOLCHAIN/bin/arm-linux-androideabi-strip

FF_EXTRA_CFLAGS=""

# FF_CFLAGS="-O3 -Wall -pipe -ffast-math -fstrict-aliasing -Werror=strict-aliasing -Wno-psabi -Wa,--noexecstack -DANDROID  "
# FF_CFLAGS="-DANDROID -I$SYSROOT/usr/include"
# FF_LDFLAGS=" -shared -rpath-link=$MIN_PLATFORM/arch-arm64/usr/lib -L$MIN_PLATFORM/arch-arm64/usr/lib -nostdlib -fPIC -shared -pie -p  -shared"
# OPTIMIZE_CFLAGS="-I$NDK/sysroot/usr/include -mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU -DANDROID_PLATFORM=android-21"
OPTIMIZE_CFLAGS="-DANDROID -I$NDK/sysroot/usr/include/arm-linux-androideabi/"
# ADDI_LDFLAGS="-shared -rpath-link=$SYSROOT/usr/lib/aarch64-linux-android -L$SYSROOT/usr/lib/aarch64-linux-android -fuse-ld=bfd"
# ADDI_LDFLAGS="-Wl,-rpath-link=$MIN_PLATFORM/arch-arm/usr/lib -Wl,-rpath-link=$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a -L$MIN_PLATFORM/arch-arm/usr/lib -L$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/armv7-a"
ADDI_LDFLAGS="-Wl,-rpath-link=$MIN_PLATFORM/arch-arm/usr/lib -L$MIN_PLATFORM/arch-arm/usr/lib -nostdlib"

sed  -i "" "s/SLIBNAME_WITH_MAJOR='\$(SLIBNAME).\$(LIBMAJOR)'/SLIBNAME_WITH_MAJOR='\$(SLIBPREF)\$(FULLNAME)-\$(LIBMAJOR)\$(SLIBSUF)'/" configure
sed  -i "" "s/LIB_INSTALL_EXTRA_CMD='\$\$(RANLIB) \"\$(LIBDIR)\\/\$(LIBNAME)\"'/LIB_INSTALL_EXTRA_CMD='\$\$(RANLIB) \"\$(LIBDIR)\\/\$(LIBNAME)\"'/" configure
sed  -i "" "s/SLIB_INSTALL_NAME='\$(SLIBNAME_WITH_VERSION)'/SLIB_INSTALL_NAME='\$(SLIBNAME_WITH_MAJOR)'/" configure
sed  -i "" "s/SLIB_INSTALL_LINKS='\$(SLIBNAME_WITH_MAJOR) \$(SLIBNAME)'/SLIB_INSTALL_LINKS='\$(SLIBNAME)'/" configure
# sed  -i "" "s/SHFLAGS='-shared -Wl,-soname,\$(SLIBNAME)'/SHFLAGS='-shared -soname \$(SLIBNAME)'/" configure
# sed  -i "" "s/-Wl//g" configure


# --sysroot=$SYSROOT \
# --ld=$LD \
./configure \
--prefix=$PREFIX \
--ar=$AR \
--as=$AS \
--cc=$CC \
--cxx=$CXX \
--nm=$NM \
--ranlib=$RANLIB \
--strip=$STRIP \
--arch=$ARCH \
--target-os=android \
--enable-cross-compile \
--disable-asm \
--enable-shared \
--disable-static \
--disable-ffprobe \
--disable-ffplay \
--disable-ffmpeg \
--disable-debug \
--disable-symver \
--disable-stripping \
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS"

# --extra-cflags="$FF_EXTRA_CFLAGS  $FF_CFLAGS" \
# --extra-ldflags="$FF_LDFLAGS"

sed  -i "" "s/#define HAVE_TRUNC 0/#define HAVE_TRUNC 1/" config.h
sed  -i "" "s/#define HAVE_TRUNCF 0/#define HAVE_TRUNCF 1/" config.h
sed  -i "" "s/#define HAVE_RINT 0/#define HAVE_RINT 1/" config.h
sed  -i "" "s/#define HAVE_LRINT 0/#define HAVE_LRINT 1/" config.h
sed  -i "" "s/#define HAVE_LRINTF 0/#define HAVE_LRINTF 1/" config.h
sed  -i "" "s/#define HAVE_ROUND 0/#define HAVE_ROUND 1/" config.h
sed  -i "" "s/#define HAVE_ROUNDF 0/#define HAVE_ROUNDF 1/" config.h
sed  -i "" "s/#define HAVE_CBRT 0/#define HAVE_CBRT 1/" config.h
sed  -i "" "s/#define HAVE_CBRTF 0/#define HAVE_CBRTF 1/" config.h
sed  -i "" "s/#define HAVE_COPYSIGN 0/#define HAVE_COPYSIGN 1/" config.h
sed  -i "" "s/#define HAVE_ERF 0/#define HAVE_ERF 1/" config.h
sed  -i "" "s/#define HAVE_HYPOT 0/#define HAVE_HYPOT 1/" config.h
sed  -i "" "s/#define HAVE_ISNAN 0/#define HAVE_ISNAN 1/" config.h
sed  -i "" "s/#define HAVE_ISFINITE 0/#define HAVE_ISFINITE 1/" config.h
sed  -i "" "s/#define HAVE_INET_ATON 0/#define HAVE_INET_ATON 1/" config.h
sed  -i "" "s/#define getenv(x) NULL/\\/\\/ #define getenv(x) NULL/" config.h

第三个需要

# 编译
$ make -j 8
$ make install

最新版本编译(NDK20 ffmpeg4.2.2 环境MAC OS)

一个正确的编译文档,并且分析的很好
https://www.jianshu.com/p/350f8e083e82

重点

1.配置编译器
2.NDK交叉编译工具的选择 llvm

MacOS系统使用的编译脚本

./configure --prefix=/usr/local/ffmpeg --enable-gpl --enable-nonfree --enable-libass \
--enable-libfdk-aac --enable-libfreetype --enable-libmp3lame --enable-libopus \
--enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxvid --extra-ldflags=-L/usr/local/lib

sudo make && sudo make install

这里再加一个版本(这是根据brew的编译脚本修改,增加了几个常用的外部库)

./configure --prefix=/usr/local/ffmpeg --enable-shared --enable-pthreads --enable-version3 --enable-avresample --cc=clang --host-cflags='-I/Library/Java/JavaVirtualMachines/adoptopenjdk-12.0.1.jdk/Contents/Home/include -I/Library/Java/JavaVirtualMachines/adoptopenjdk-12.0.1.jdk/Contents/Home/include/darwin' --host-ldflags= --enable-ffplay --enable-gnutls --enable-gpl --enable-nonfree --enable-libaom --enable-libbluray --enable-libmp3lame --enable-libass --enable-libfdk-aac --enable-libopus --enable-librubberband --enable-libsnappy --enable-libtesseract --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libx265 --enable-libxvid --enable-lzma --enable-libfontconfig --enable-libfreetype --enable-frei0r --enable-libass --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libopenjpeg --enable-libspeex --enable-videotoolbox --enable-audiotoolbox --disable-libjack --disable-indev=jack --enable-libaom --enable-libsoxr

问题1

………android-ndk-r20b/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-clang is unable to create an executable file.
C compiler test failed.

问题2

默认编译出来的so库版本号是在.so之后,Android识别不了,所以要修改configure文件(有的也说不需要修改)

ranlib/usr/local/lib/libavdevice.a: No such file or directory
make: *** [install-libavdevice-static] Error 127

解决(好像高版本的都不用修改了)

对应的字段改为:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)' 

问题3

android-ndk-r20b/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.

问题4

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;

ffmpeg 4.2.2存在,把代码相应的修改一下就好了,网上有解决方案

https://www.jianshu.com/p/4503d6f81998

问题5

mkdir: cannot create directory ‘/usr/local/share/man/man1’: Permission denied
doc/Makefile:125: recipe for target 'install-man' failed
make: *** [install-man] Error 1

sudo chmod -R 777 给文件夹权限

问题6

MacOS环境下执行编译命令的时候如果没有直接用brew安装

brew install x265
#brew upgrade x265
brew install fdk-aac

问题7

ld: can't map file, errno=22 file '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/' for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
make: *** [doc/print_options] Error 1
make: *** Waiting for unfinished jobs....
6 warnings generated.
8 warnings generated.
STRIP	libavcodec/x86/vp9itxfm.o

这样引用才可以:
extern "C" { //C++中特殊处理
#include "libavutil/log.h"
#include "libavcodec/avcodec.h"
#include "sdl/sdl_videos.h"
}

问题8

java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file 
"/data/app/com.future.ffmpegmusic-IQyW2Tdvr3jtASN2O3GXng==/base.apk"],nativeLibraryDirectories=
[/data/app/com.future.ffmpegmusic-IQyW2Tdvr3jtASN2O3GXng==/lib/arm64, /system/lib64, 
/product/lib64]]] couldn't find "libnative-lib.so"

在app的build.gradle文件中增加

解决
splits {
        abi {
            enable true
            reset()
            include 'armeabi-v7a'
        }
    }

总结 血泪史

  • 1.如果想一次性成功找个靠谱的教程,严格按照他的版本和环境来操作。

  • 2.因为NDK和ffmpeg的版本更迭了很多,每个版本兼容性都不一样。从NDK17以后默认使用了clang进行编译,ffmpeg4以上好像都支持了。

  • 3.Mac和Linux 的编译脚本主要是工具的配置,一般Mac都是darwin开头 Linux 是liunx开头,最好在Linux下编译。

  • 4.ffmpeg 低版本的需要用 --target-os=linux 高版本的要使用 --target-os=android 因为已经添加了对他的支持

你可能感兴趣的:(Android进阶)