MAC平台编译ffmpeg生成so文件(总结遇到的问题)

一、编译脚本

1. Arm平台编译脚本

ADDI_CFLAGS="-marm"
API=26
PLATFORM=arm-linux-androideabi
CPU=armv7-a
NDK=/Users/a360/Library/Android/sdk/ndk-bundle # 修改成自己本地的ndk路径。
SYSROOT=$NDK/platforms/android-$API/arch-arm/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
OUTPUT=/Users/a360/Android/Video/ffmpeg-4.0.3/android/arm-v7  #自己指定一个输出目录,用来放生成的文件的。

function build {
./configure \
--prefix=$OUTPUT \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=android \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic -marm" \
--extra-ldflags="-marm" \
$ADDITIONAL_CONFIGURE_FLAG

make clean
make
make install
}
build

2. x86平台编译脚本

API=26
CPU=x86
NDK=/Users/a360/Library/Android/sdk/ndk-bundle # 修改成自己本地的ndk路径。
SYSROOT=$NDK/platforms/android-$API/arch-x86/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/x86_64-linux-android
TOOLCHAIN=$NDK/toolchains/x86-4.9/prebuilt/darwin-x86_64
OUTPUT=/Users/a360/Android/Video/ffmpeg-4.0.3/android/$CPU  #自己指定一个输出目录,用来放生成的文件的。

function build {
./configure \
--prefix=$OUTPUT \
--enable-shared \
--disable-static \
--disable-doc \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-avdevice \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/i686-linux-android- \
--target-os=android \
--arch=$CPU \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-I$ASM -isysroot $ISYSROOT -Os -fpic " \
$ADDITIONAL_CONFIGURE_FLAG

make clean
make -j8
make install
}

build

3. 编译成一个so文件

ADDI_CFLAGS="-marm"
API=21
PLATFORM=arm-linux-androideabi
CPU=armv7-a
NDK=/Users/a360/Library/Android/sdk/android-ndk-r14b # 修改成自己本地的ndk路径。
SYSROOT=$NDK/platforms/android-$API/arch-arm/
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
PREFIX=./ff-onelib/$CPU  #自己指定一个输出目录,用来放生成的文件的。
function build {
./configure \
--prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--arch=arm \
--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--disable-stripping \
--target-os=android \
--enable-gpl --enable-static --disable-shared --enable-nonfree --enable-version3 --enable-small \
--enable-neon --enable-mediacodec --enable-asm \
--enable-zlib --disable-ffprobe --disable-ffplay --enable-ffmpeg --disable-debug \
--enable-jni \
--sysroot=$SYSROOT \
--extra-cflags="-fpic -mfpu=neon -marm -march=armv7-a" \

make clean
make -j16
make install
}

build


$TOOLCHAIN/bin/arm-linux-androideabi-ld \
-rpath-link=$SYSROOT/usr/lib \
-L$SYSROOT/usr/lib \
-soname libffmpeg.so \
-shared -nostdlib  \
-Bsymbolic \
--whole-archive --no-undefined \
-o $PREFIX/libffmpeg.so \
$PREFIX/lib/libavcodec.a \
$PREFIX/lib/libavfilter.a \
$PREFIX/lib/libswresample.a \
$PREFIX/lib/libavformat.a \
$PREFIX/lib/libavutil.a \
$PREFIX/lib/libswscale.a \
$PREFIX/lib/libpostproc.a \
$PREFIX/lib/libavdevice.a \
-lc -lm -lz -ldl -llog \
$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a

二、遇到的问题总结

1. API设置为26时编译出来的so文件,在6.0及以上版本的手机上运行没有问题,6.0以下的版本就崩溃了,出现java.lang.UnsatisfiedLinkError

解决办法:编译so文件的时候要把API设置到23以下,这样才能兼容6.0以前到版本。原因是so库中需要符号stdout,stderr,而在"\ndk\platforms\android-23\arch-arm\usr\lib\libc.so"中,是可以查看到stdout这个符号的,但是在低于android-23版本的libc中是没有这个符号的,为了兼容低于android-23的系统,ndk编译的程序,需要设置API小于23

2. 设置为API小于23到时候,编译so库时出现了链接问题

cmdutils.o:cmdutils.c:function log_callback_help: error: undefined reference to 'stdout'
ffmpeg_opt.o:ffmpeg_opt.c:function assert_file_overwrite: error: undefined reference to 'stderr'
ffmpeg.o:ffmpeg.c:function check_keyboard_interaction: error: undefined reference to 'stderr'
ffmpeg.o:ffmpeg.c:function print_sdp: error: undefined reference to 'stdout'
ffmpeg.o:ffmpeg.c:function print_report.part.7: error: undefined reference to 'stderr'
ffmpeg.o:ffmpeg.c:function main: error: undefined reference to 'stderr'
libavfilter/libavfilter.a(vf_psnr.o):vf_psnr.c:function init: error: undefined reference to 'stdout'
libavfilter/libavfilter.a(vf_psnr.o):vf_psnr.c:function uninit: error: undefined reference to 'stdout'

解决办法:编译时,NDK的版本要低于14,高于14的版本没有stdrr和stdout的定义

3. 当使用NDK14版本编译生成.a文件之后,合并成.so文件(只是在编译x86的时候遇到了),出现了/tmp/77a95b0085967f7191ad958665724b6f/sysroot/usr/include/unistd.h:173: error: undefined reference to '__page_size'的错误

解决办法:可能是NDK 14的问题,换一个平台合成就好了

你可能感兴趣的:(Android)