编译环境
- macOS x 11.6
- android-ndk-r17c
- openssl-1.1.1l
- ffmpeg4.4
编译openssl
1. 创建openssl编译脚本
下载openssl解压后在openssl根目录新建compile-android-openssl.sh,编辑内容如下
#!/bin/bash
API=21
export NDK=/Users/patrick/CodeLibraries/ndk/android-ndk-r17c
compile() {
CPU=$1
PLATFORM=$2
CPU_ARCH=
if [[ $CPU = "arm" ]]; then
CPU_ARCH="armeabi-v7a"
elif [[ $CPU = "arm64" ]]; then
CPU_ARCH="arm64-v8a"
else
echo "\n======================================================================"
echo "[*] cpu arch error ..."
echo "======================================================================\n"
exit 1
fi
echo "\n======================================================================"
echo "[*] start compile openssl for android $CPU_ARCH ..."
echo "======================================================================\n"
echo "\n======================================================================"
echo "[*] make clean ..."
echo "======================================================================\n"
make clean
rm -rf $(pwd)/android/$CPU_ARCH
export ANDROID_NDK_HOME=$NDK
PATH=$ANDROID_NDK_HOME/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64/bin:$PATH
echo "\n======================================================================"
echo "[*] configure ..."
echo "======================================================================\n"
./Configure \
android-$CPU \
-D__ANDROID_API__=$API \
--prefix=$(pwd)/android/$CPU_ARCH \
--openssldir=$(pwd)/android/$CPU_ARCH \
no-shared no-ssl2 no-ssl3 no-comp no-hw no-engine
echo "\n======================================================================"
echo "[*] make ..."
echo "======================================================================\n"
make
echo "\n======================================================================"
echo "[*] make intall ..."
echo "======================================================================\n"
make install
echo "\n======================================================================"
echo "[*] openssl compile finished!"
echo "======================================================================\n"
}
# compile armeabi-v7a
compile arm arm-linux-androideabi
# compile arm64-v8a
compile arm64 aarch64-linux-android
2.执行编译
sh compile-android-openssl.sh
编译完成后在openssl根目录下会生成android/armeabi-v7a和android/arm64-v8a目录 include/openssl里面是头文件, lib里面是动态库.so和静态库.a,根据需要copy使用即可
编译FFmpeg with openssl
1. ffmpeg源码修改
因为ndk版本与ffmpeg版本的兼容问题,编译前需要将ffmpeg中的部分源码进行修改,以解决编译中会出现的错误:
-
错误1: 修改libavcodec/aaccoder.c 将其中的B0全部改为b0
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; -
错误2: 修改libavcodec/hevc_mvs.c 将其中的B0、xB0、yB0全部改为b0、xb0、yb0
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) && -
错误3: 修改libavcodec/opus_pvq.c 将其中的B0全部改为b0
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; -
修改configure将android的编译器从clang改为gcc
set_default target_os if test "$target_os" = android; then cc_default="gcc" fi
2. 创建带openssl的ffmpeg编译脚本
在ffmpeg源码根目录新建compile-android-ffmpeg-with-openssl.sh,编辑内容如下:
#!/bin/bash
set -e
echo_header_line() {
echo "\n======================================================================"
}
echo_foot_line() {
echo "======================================================================\n"
}
ANDROID_API=21
# set ndk root dir
export NDK=/Users/patrick/CodeLibraries/ndk/android-ndk-r17c
compile_android() {
CPU=$1
PLATFORM=$2
CPU_ARCH=
if [[ $CPU = "arm" ]]; then
CPU_ARCH="armeabi-v7a"
elif [[ $CPU = "arm64" ]]; then
CPU_ARCH="arm64-v8a"
else
echo_header_line
echo "[*] cpu arch error ..."
echo_foot_line
exit 1
fi
SYSROOT=$NDK/platforms/android-$ANDROID_API/arch-$CPU
TOOLCHAIN=$NDK/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64
CROSS_PREFIX=$TOOLCHAIN/bin/$PLATFORM-
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/$PLATFORM
PREFIX=$(pwd)/android/$CPU_ARCH
# 设置编译好的openssl目录
OPENSSL_DIR=/Users/patrick/CodeLibraries/ffmpeg/openssl-1.1.1l/android/$CPU_ARCH
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$OPENSSL_DIR/lib/pkgconfig
echo_header_line
echo "[*] ffmpeg compile for android $CPU_ARCH start ..."
echo_foot_line
# set config
FF_CONFIG=
FF_CONFIG="$FF_CONFIG --target-os=android"
FF_CONFIG="$FF_CONFIG --prefix=$PREFIX"
FF_CONFIG="$FF_CONFIG --enable-cross-compile"
FF_CONFIG="$FF_CONFIG --cross-prefix=$CROSS_PREFIX"
FF_CONFIG="$FF_CONFIG --enable-static"
FF_CONFIG="$FF_CONFIG --enable-small"
FF_CONFIG="$FF_CONFIG --enable-neon"
FF_CONFIG="$FF_CONFIG --enable-hwaccels"
FF_CONFIG="$FF_CONFIG --enable-openssl"
FF_CONFIG="$FF_CONFIG --pkg-config=pkg-config"
FF_CONFIG="$FF_CONFIG --enable-protocols"
FF_CONFIG="$FF_CONFIG --disable-shared"
FF_CONFIG="$FF_CONFIG --disable-doc"
FF_CONFIG="$FF_CONFIG --disable-ffmpeg"
FF_CONFIG="$FF_CONFIG --disable-ffplay"
FF_CONFIG="$FF_CONFIG --disable-ffprobe"
FF_CONFIG="$FF_CONFIG --disable-avdevice"
FF_CONFIG="$FF_CONFIG --disable-symver"
FF_CONFIG="$FF_CONFIG --arch=$CPU"
FF_CONFIG="$FF_CONFIG --sysroot=$SYSROOT"
# set cflags
FF_CFLAGS=
FF_CFLAGS="$FF_CFLAGS -I$ASM -isysroot $ISYSROOT"
FF_CFLAGS="$FF_CFLAGS -I$ASM -I$OPENSSL_DIR/include -fPIE -pie"
FF_CFLAGS="$FF_CFLAGS -D__ANDROID_API__=$ANDROID_API"
FF_CFLAGS="$FF_CFLAGS -U_FILE_OFFSET_BITS"
FF_CFLAGS="$FF_CFLAGS -Os -fPIC -DANDROID -Wno-deprecated"
if [[ $CPU = "arm" ]]; then
FF_CFLAGS="$FF_CFLAGS -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -marm"
elif [[ $CPU = "arm64" ]]; then
FF_CFLAGS="$FF_CFLAGS -march=armv8-a"
else
echo_header_line
echo "[*] cpu arch error ..."
echo_foot_line
exit 1
fi
# set ldflags
FF_LDFLAGS=
FF_LDFLAGS="$FF_LDFLAGS -L$OPENSSL_DIR/lib -lssl -lcrypto"
ADDITIONAL_FLAGS=
echo_header_line
echo "[*] configure ..."
echo_foot_line
./configure $FF_CONFIG \
--extra-cflags="$FF_CFLAGS" \
--extra-ldflags="$FF_LDFLAGS" \
$ADDITIONAL_FLAGS \
echo_header_line
echo "[*] clean output dir ..."
echo "[*] rm -rf $PREFIX"
echo_foot_line
rm -rf $PREFIX
echo_header_line
echo "[*] make clean ..."
echo_foot_line
make clean
echo_header_line
echo "[*] make ..."
echo_foot_line
make -j8
echo_header_line
echo "[*] make install ..."
echo_foot_line
make install
echo_header_line
echo "[*] ndk package ..."
echo_foot_line
$TOOLCHAIN/bin/$PLATFORM-ld \
-rpath-link=$SYSROOT/usr/lib \
-L$SYSROOT/usr/lib \
-L$PREFIX/lib -soname libffmpeg.so \
-shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o $PREFIX/libffmpeg.so \
libavcodec/libavcodec.a \
libavfilter/libavfilter.a \
libavformat/libavformat.a \
libavutil/libavutil.a \
libswresample/libswresample.a \
libswscale/libswscale.a \
-lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
$TOOLCHAIN/lib/gcc/$PLATFORM/4.9.x/libgcc.a
$TOOLCHAIN/bin/$PLATFORM-strip $PREFIX/libffmpeg.so
echo_header_line
echo "[*] ffmpeg compile finished!"
echo_foot_line
echo_header_line
echo "[*] $PREFIX"
echo_foot_line
}
# compile armeabi-v7a
compile_android arm arm-linux-androideabi
# compile arm64-v8a
compile_android arm64 aarch64-linux-android
4. 编译
sh compile-android-ffmpeg-with-openssl.sh
编译完成后在ffmpeg的根目录下会生成android/armeabi-v7a和android/arm64-v8a目录 .so文件和相关的.h文件就在对应的架构目录下
/Users/patrick/CodeLibraries/ffmpeg-4.4/android/armv7-a