FFmpeg是一个跨平台的多媒体库,也是目前音视频领域应用最广泛的库。它包括llibavcodec、libavformat、libavutil、libavdevice、libavfilter、libswscale、libavresample、libswresample、libpostproc等模块,其中avcodec用于编解码,avformat用于解封装,avutil是提供工具类,avdevice用于各平台的设备接入(包括采集与录像,Android的mediacodec硬解,Intel的QSV硬件加速),avfilter提供滤镜操作,swscale提供图像缩放与像素格式转换,swresample提供音频重采样,postproc提供高级处理。
1、下载ffmpeg源码
使用git命令:git clone https://github.com/FFmpeg/FFmpeg.git。
2、下载ndk源码
在Android开发者文档可以下载到ndk源码,https://developer.android.com/ndk/downloads。根据实际需求选择对应ndk版本,建议下载ndk-r20b稳定版。mac电脑配置ndk系统环境变量步骤如下:
(1)、在命令行输入vim ~/.bash_profile
(2)、输入i进行编辑模式
(3)、编写export NDK_PATH=xxx/xxx/android-ndk-r20b
(4)、按下esc退出编辑模式,输入:wq保存并退出
4、编译ffmpeg源码
(1)、修改ffmpeg源码
在ffmpeg源码根目录下有个configure配置文件,默认编译出来的so库包括avcodec、avformat、avutil、avdevice、avfilter、swscale、avresample、swresample、postproc,编译出来so是个软链接,真正so名字后缀带有一长串主版本号与子版本号,这样的so名字在Adnroid平台无法识别。所以我们需要修改一下,打开该文件并搜索SLIBNAME,找到如下命令行:
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)'
替换为:
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
(2)、编译脚本
在ffmpeg源码根目录创建一个shell脚本,比如命名为build_ffmpeg.sh,以mac编译环境为例,ndk旧版本已经过时,google官方放弃了gcc交叉编译工具链,转而使用clang编译工具链,因为clang编译速度快、效率高。下面例子是采用ndk新版的clang进行编译,具体如下:
#!/bin/bash
make clean
set -e
archbit=64
if [ $archbit -eq 64 ];then
echo "build for 64bit"
#armv8-a
ARCH=aarch64
CPU=armv8-a
API=21
PLATFORM=aarch64
ANDROID=android
CFLAGS=""
LDFLAGS=""
else
echo "build for 32bit"
#armv7-a
ARCH=arm
CPU=armv7-a
API=16
PLATFORM=armv7a
ANDROID=androideabi
CFLAGS="-mfloat-abi=softfp -march=$CPU"
LDFLAGS="-Wl,--fix-cortex-a8"
fi
export NDK=/Users/xufulong/Library/Android/android-ndk-r20b
export TOOLCHAIN=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/bin
export SYSROOT=$NDK/toolchains/llvm/prebuilt/darwin-x86_64/sysroot
export CROSS_PREFIX=$TOOLCHAIN/$ARCH-linux-$ANDROID-
export CC=$TOOLCHAIN/$PLATFORM-linux-$ANDROID$API-clang
export CXX=$TOOLCHAIN/$PLATFORM-linux-$ANDROID$API-clang++
export PREFIX=../ffmpeg-android/$CPU
function build_android
{
./configure \
--prefix=$PREFIX \
--cross-prefix=$CROSS_PREFIX \
--target-os=android \
--arch=$ARCH \
--cpu=$CPU \
--cc=$CC \
--cxx=$CXX \
--nm=$TOOLCHAIN/$ARCH-linux-$ANDROID-nm \
--strip=$TOOLCHAIN/$ARCH-linux-$ANDROID-strip \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="$CFLAGS" \
--extra-ldflags="$LDFLAGS" \
--extra-ldexeflags=-pie \
--enable-runtime-cpudetect \
--disable-gpl \
--disable-static \
--enable-shared \
--enable-small \
--disable-neon \
--disable-yasm \
--disable-asm \
--disable-zlib \
--disable-ffprobe \
--disable-ffplay \
--disable-ffmpeg \
--disable-debug \
--disable-doc \
--disable-avdevice \
--disable-postproc \
--disable-avfilter \
--enable-avresample \
--disable-encoders \
--disable-hwaccels \
--disable-muxers \
--disable-bsfs \
--disable-indevs \
--disable-outdevs \
--disable-devices \
--disable-filters \
--disable-parsers \
--disable-protocols \
--disable-decoders \
--enable-decoder=mp3,aac,ac3,eac3,vorbis,dca,amrnb,amrwb,opus,truehd \
--disable-demuxers \
--enable-demuxer=avi,wav,matroska,threedostr,mov,mp3,ogg,asf,flac,flv,aac,amr,ac3 \
--enable-protocol=file,http,https \
$ADDITIONAL_CONFIGURE_FLAG
make
make install
}
build_android
按照上面shell脚本分为4段。第一段make clean清除缓存,set -e设置编译出错后马上退出,archbit=xx指定cpu架构是32位还是64位。第二段if...else...fi用来条件编译不同cpu架构对应字段的值。第三段用export关键字声明宏定义,其中PREFIX是指定输出文件路径。第四段是一个执行函数,按照ffmpeg的configure规范进行编写,具体可以参考:命令行输入cd ffmpeg,然后./configure --help。函数里面的enable代表开启,disable代表关闭,也就是对ffmpeg进行剪裁,根据我们需要的功能进行enable。为了编译我们需要的ffmpeg解码器,先--disable-decoders,然后--enable-decoder=mp3,aac,ac3,eac3,vorbis。make命令是执行编译,make install命令是执行安装。最后的build_android是执行函数。
初次执行shell脚本,需要修改脚本权限,使用linux命令:chmod 777 build_ffmpeg.sh。执行脚本只需要一行命令,即在命令行输入./build_ffmpeg.sh。编译过程中,命令行会不断打印编译日志,等待命令行输出INSTALL xxx关键字代表编译完成。