环境:ubuntu14.04
NDK:android-ndk-r17
ffmpeg:4.2.2
关于apt-get install部分不再赘述,文章较多,下面这条建议先执行
sudo apt-get install build-essential -y
1.配置NDK PATH
NDK_PATH=/home/zjs/android-ndk-r17
export PATH=${PATH}:${NDK_PATH}
2.目录结构
ffmpeg->ffmpeg-4.2.2
->ffmpeg_android.sh
3.脚本ffmpeg_android.sh
脚本内容有修改,没有动态适配,制作64bit时注意修改,中文注释为修改点
#!/bin/bash
# Don't forget to install yasm.
#set -e
# Set your own NDK here
NDK=/home/zjs/android-ndk-r17
ARM_PLATFORM=$NDK/platforms/android-21/arch-arm/
ARM_PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
ARM64_PLATFORM=$NDK/platforms/android-21/arch-arm64/
ARM64_PREBUILT=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64
X86_PLATFORM=$NDK/platforms/android-21/arch-x86/
X86_PREBUILT=$NDK/toolchains/x86-4.9/prebuilt/linux-x86_64
X86_64_PLATFORM=$NDK/platforms/android-21/arch-x86_64/
X86_64_PREBUILT=$NDK/toolchains/x86_64-4.9/prebuilt/linux-x86_64
#NDK r17 sysroot inlcude及lib相关移到了根目录,cflag中添加链接
ISYSROOT=$NDK/sysroot
ASM=$ISYSROOT/usr/include/arm-linux-androideabi
#生成的so及.h文件路径
BUILD_DIR=`pwd`/ffmpeg-android
#ffmpeg版本,后面pushd用,所以要建立第2步正确的目录结构
FFMPEG_VERSION="4.2.2"
function build_one
{
if [ $ARCH == "arm" ]
then
PLATFORM=$ARM_PLATFORM
PREBUILT=$ARM_PREBUILT
HOST=arm-linux-androideabi
elif [ $ARCH == "arm64" ]
then
PLATFORM=$ARM64_PLATFORM
PREBUILT=$ARM64_PREBUILT
HOST=aarch64-linux-android
elif [ $ARCH == "x86_64" ]
then
PLATFORM=$X86_64_PLATFORM
PREBUILT=$X86_64_PREBUILT
HOST=x86_64-linux-android
else
PLATFORM=$X86_PLATFORM
PREBUILT=$X86_PREBUILT
HOST=i686-linux-android
fi
#extra-cflags配置-I$ASM -isysroot $ISYSROOT,否则会报出.h找不到
pushd ffmpeg-$FFMPEG_VERSION
./configure --target-os=linux \
--incdir=$BUILD_DIR/include \
--libdir=$BUILD_DIR/lib/$CPU \
--enable-cross-compile \
--arch=$ARCH \
--cc=$PREBUILT/bin/$HOST-gcc \
--cross-prefix=$PREBUILT/bin/$HOST- \
--nm=$PREBUILT/bin/$HOST-nm \
--sysroot=$PLATFORM \
--extra-cflags="-I$ASM -isysroot $ISYSROOT -I$BUILD_DIR/include -fPIC -DANDROID -Wfatal-errors -Wno-deprecated $OPTIMIZE_CFLAGS" \
--enable-gpl \
--enable-small \
--extra-ldflags="-L$BUILD_DIR/lib/$CPU" \
--enable-shared \
--disable-doc \
--disable-programs \
--disable-stripping \
--disable-symver \
--disable-static \
--pkg-config=/usr/bin/pkg-config \
$ADDITIONAL_CONFIGURE_FLAG
make clean
make -j8
make install
popd
}
#arm v7vfpv3
#CPU=armv7-a
#ARCH=arm
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=$CPU -D__thumb__ -mthumb"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one
#arm v7vfp
#CPU=armv7-a
#ARCH=arm
#OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU "
#PREFIX=`pwd`/ffmpeg-android/$CPU-vfp
#ADDITIONAL_CONFIGURE_FLAG=
#build_one
#arm v7n
CPU=armv7-a
ARCH=arm
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -mfpu=neon -marm -march=$CPU -mtune=cortex-a8"
PREFIX=$BUILD_DIR/$CPU
ADDITIONAL_CONFIGURE_FLAG=
build_one
#arm64-v8a
#CPU=arm64-v8a
#ARCH=arm64
#OPTIMIZE_CFLAGS=
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one
#x86_64
#CPU=x86_64
#ARCH=x86_64
#OPTIMIZE_CFLAGS="-fomit-frame-pointer"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one
#x86
#CPU=i686
#ARCH=i686
#OPTIMIZE_CFLAGS="-fomit-frame-pointer"
#PREFIX=$BUILD_DIR/$CPU
#ADDITIONAL_CONFIGURE_FLAG=
#build_one
sysroot位置变动导致的编译错误如下:
/home/zjs/android-ndk-r17/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/lib/gcc/arm-linux-androideabi/4.9.x/include/stdint.h:9:26: fatal error: stdint.h: No such file or directory
# include_next <stdint.h>
^
这个stdint.h就在sysroot的include中,必须添加–extra-cflags="-I$ASM -isysroot $ISYSROOT……
4.修改configure
默认生成的so名称以版本做后缀,不适用于android app开发,修改如下:
#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)'
# For android
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
5.执行脚本
因为有些路径需要建立在/usr下,因此sudo执行。
chmod 777 ffmpeg_android.sh
sudo ffmpeg_android.sh
6.错误修正:
编译期间会报出以下三个错误:
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/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/opus_pvq.c: In function 'quant_band_template':
libavcodec/opus_pvq.c:498:9: error: expected identifier or '(' before numeric constant
int B0 = blocks;
^
问题原因在B0在ndk中被用作宏定义了:
androideabi/include/asm/termbits.h 中
#define B0 0000000
因此把文件中的B0全替换为b0即可。
7.生成so
├── ffmpeg-android
│ ├── include
│ │ ├── libavcodec
……
│ └── lib
│ └── armv7-a
│ ├── libavcodec-58.so
│ ├── libavcodec.so -> libavcodec-58.so
│ ├── libavdevice-58.so
│ ├── libavdevice.so -> libavdevice-58.so
│ ├── libavfilter-7.so
│ ├── libavfilter.so -> libavfilter-7.so
│ ├── libavformat-58.so
│ ├── libavformat.so -> libavformat-58.so
│ ├── libavutil-56.so
│ ├── libavutil.so -> libavutil-56.so
│ ├── libpostproc-55.so
│ ├── libpostproc.so -> libpostproc-55.so
│ ├── libswresample-3.so
│ ├── libswresample.so -> libswresample-3.so
│ ├── libswscale-5.so
│ ├── libswscale.so -> libswscale-5.so
│ └── pkgconfig