详细的FFmpeg编译流程与脚本分析

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关键字代表编译完成。

上一篇:FFmpeg一些结构体


下一篇:ffmpeg系列--音频相关知识简介--未完