ffmpeg4.1 Android arm64位库裁剪移植
目录
ffmpeg4.1 Android arm64位库裁剪移植
1、绪言:
2、编译环境:
3、源代码下载:
4、编写编译脚本:
4.1 编译脚本
4.2 常见问题
5、库裁剪:
5.1 裁剪原理
5.2 裁剪方法
5.3 编译配置脚本
5.4 裁剪结果
6、引用
1、绪言:
ffmpeg是一个很强大的多媒体开源框架,几乎所有的音视频播放、编辑软件都用到,如抖音、斗鱼、学习强国等。因为他的强大所以造就了他的复杂。手头有个项目刚好需要用到ffmpeg。
google将在2019年8月份强制要求所有Android设备支持64位的库,之前32位的库可以很好的兼容64位的手机,很快所有含有jni库的APP都要支持起来。姑且不论中美贸易战结果如何,华为等手机是否放弃android。
鉴于上述原因,所以要重新编译裁剪ffmpeg,在这个过程中遇到了一些问题顺便记录下来。
2、编译环境:
操作系统:ubuntu 14.04
交叉编译工具:android-ndk-r14b
Android NDK 下载地址
这里推荐使用ubuntu而不是用cygwin,因为ffmpeg是C语言,编译脚本是MakeFIle,很多文件对空格换行等其他字符编码敏感。
3、源代码下载:
下载地址:
(1) ffmpeg官网下载地址 (2)github上FFmpeg的下载地址
4、编写编译脚本:
4.1 编译脚本
在编译之前需要配置很多项,最基本的配置是要:
(1)指定工具链;
(2)一些target-os的头文件;
(3)输出的路径;
(4)输出的可执行程序和库;
这些内容是通过根目录下的configure脚本配置的,因为配置项比较多所以最好写成一个脚本。下面是一个简单例子:
#!/bin/bash
API=14
NDK=/NDK安装位置/android-ndk-r14b
SYSROOT=$NDK/platforms/android-$API/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
function build_one
{
./configure \
--prefix=$PREFIX \
--disable-shared \
--enable-static \
--cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv8-a" \
--enable-neon
make clean all
make
make install
}
CPU=armv64
PREFIX=$(pwd)/android/$CPU
build_one
在根目录下新建一个文件build_android.sh,将上述脚本文本复制到这个脚本中
chmod a+x build_android.sh
4.2 常见问题
(1) 这个过程中一般会遇到一些comand not found的问题,
导致原因及解决办法:
a、脚本在Windows系统下生成。这类问题可一在linux 下执行doc2unix build_android.sh;
b、主要是上述脚本中在有不合法的空格,如:“--prefix=$PREFIX \ ”后面有空格。这个需要删除空格;
c、在configure 配置项中有#注释的类容。configure是一条命令,后面都是参数,参数之间不能注释,否则无法解析。
(2)configure会在编译之前检验编译器是否正确如图4-1。当target-os=android时候,ffmpeg选择clang编译器,但是在ndk的交叉工具链中没有aarch64-linux-android-clang。
图4-1 编译器错误
解决办法:修改configure如下
set_default target_os
if test "$target_os" = android; then
#cc_default="clang"
cc_default="gcc"
fi
关于其他的一些配置问题,通过看ffbuild/config.log和configure脚本都可以找到解决办法。
5、库裁剪:
5.1 裁剪原理
ffmpeg裁剪就是把ffmpeg中你不需要用到的逻辑在编译时候去掉,每个项目的需求都不尽相同,所以完成这个工作的前提是要对自己项目业务有足够的了解,并且也要清楚ffmpeg处理的逻辑。
FFmpeg是一套可以用来记录、转换、分析处理数字音频、视频,并能将其转化为流或文件的跨平台开源计算机程序。ffmpeg常用的多媒体编解码处理方面,处理流程如图5-1.
图5-1 ffmpeg编解码流程图
按照蓝色箭头指向的顺序,从外部协议接收下来的数据依次经过解协议,解封装,解码,像素转换,编码,封装,发送这几个步骤。这些步骤按照处理数据类型的不同,可以分成几个层次:
协议层(Protocol Layer):该层处理的数据为符合特定流媒体协议规范的数据,例如http,rtmp,file等。
封装层(Container Layer):该层处理的数据为符合特定封装格式规范的数据,例如mkv,mp4,flv,mpegts,avi等。
编码层(Codec Layer):该层处理的数据为符合特定编码标准规范的数据,例如h264,h265,mpeg2,mpeg4等。
像素层(Pixel Layer):该层处理的数据为符合特定像素格式规范的数据,例如yuv420p,yuv422p,yuv444p,rgb24等。
由于多媒体协议格式复杂,所以强大的ffmpeg在以上各层都支持了很多,ffmpeg裁剪就是把上面不需要支持的协议格式在编译时候禁用。
5.2 裁剪方法
在ffmpeg根目录下执行:
./configure --help
可以看到很多配置项,裁剪的具体方法就是依次按照上面四层设置启用/禁用这些配置项。这里以decoder配置为例介绍一下:
..
--disable-decoders \
--enable-decoder=aac \
--enable-decoder=flv \
--enable-decoder=h264 \
--enable-decoder=mp3* \
--enable-decoder=hevc \
..
首先通过--disable-decoders 禁用所有解码器,然后依次启用你所需要的解码器。协议层,封装层、像素层都是类似的配置。
关于configure 的配置项一些中文翻译可以参考ffmpeg裁剪。
5.3 编译配置脚本
下面是我完成版裁剪配置编译脚本,可按照第4章方法添加到工程。
#!/bin/bash
# build_android.sh
NDK=/home/xxx/Android/android-ndk-r14b
function build_android {
echo "Compiling FFmpeg for $CPU"
./configure \
--prefix=$PREFIX \
--enable-neon \
--enable-shared \
--enable-jni \
--enable-mediacodec \
--enable-decoder=h264_mediacodec \
--disable-static \
--disable-doc \
--enable-small \
--disable-gpl \
--disable-programs \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-doc \
--disable-symver \
--disable-filters \
--disable-avdevice \
--disable-network \
--disable-zlib \
--disable-bsfs \
--disable-muxers \
--enable-muxer=mp4 \
--disable-demuxers \
--disable-decoders \
--enable-decoder=aac \
--enable-decoder=flv \
--enable-decoder=h264 \
--enable-decoder=mp3* \
--enable-decoder=hevc \
--disable-encoders \
--enable-encoder=png \
--enable-encoder=jpeg2000 \
--enable-encoder=mpeg4 \
--enable-version3 \
--cross-prefix=$CROSS_PREFIX \
--sysroot=$SYSROOT \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--enable-cross-compile \
--extra-cflags="-Os -fpic $OPTIMIZE_CFLAGS " \
--extra-ldflags="$ADDI_LDFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
echo "configure finished"
make clean
make -j4
make install
}
#arm64-v8a
ARCH=arm64
CPU=armv8-a
TOOLCHAIN=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64
SYSROOT=$NDK/platforms/android-21/arch-arm64/
CROSS_PREFIX=$TOOLCHAIN/bin/aarch64-linux-android-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-march=$CPU"
#armeabi-v7a
ARCH=arm
CPU=armv7-a
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
SYSROOT=$NDK/platforms/android-19/arch-arm/
CROSS_PREFIX=$TOOLCHAIN/bin/arm-linux-androideabi-
PREFIX=$(pwd)/android/$CPU
OPTIMIZE_CFLAGS="-marm"
export TMPDIR=$(pwd)/temp
build_android
当执行以上脚本时会在终端输出配置结果如图5-2,这个结果和脚本中一致。
图5-2 裁剪库配置结果
5.4 裁剪结果
运行第4章脚本和5.3章脚本库大小结果对比如图5-3.
图5-3 库裁剪前后大小对比
6、引用
https://www.jianshu.com/p/9ee83933009a