想学习FFmpeg 库,可是工欲善其事必先利其器,因此,这里先从基础做起,编译FFmpeg,并集成到ios项目中.
这里从github上找地址(https://github.com/kewlbear/FFmpeg-iOS-build-script) 我测试的环境是xcode10.1 ffmpeg的版本是4.1 .亲自测试好用
该脚本依赖
- gas-preprocessor
- yasm
gas-preprocessor 安装 可网上查询
yasm安装
brew install yams
下载脚本.进入该脚本文件夹
运行命令
./build-ffmpeg.sh
经过一段时间 编译结束.
当前文件夹的文件有
到这里很顺利编译结束.
集成新工程
创建新工程
这里需要注意 要是我们路径 $(PROJECT_DIR)/TestFFmpeg/include 模式是 non-recursive. 那么我们引用头文件的格式是#import "libavformat/avformat.h"
脚本解释
#!/bin/sh
# directories
FF_VERSION="4.1"
#FF_VERSION="snapshot-git"
if [[ $FFMPEG_VERSION != "" ]]; then
FF_VERSION=$FFMPEG_VERSION
fi
SOURCE="ffmpeg-$FF_VERSION"
FAT="FFmpeg-iOS"
SCRATCH="scratch"
# must be an absolute path
THIN=`pwd`/"thin"
# absolute path to x264 library
#X264=`pwd`/fat-x264
#FDK_AAC=`pwd`/../fdk-aac-build-script-for-iOS/fdk-aac-ios
CONFIGURE_FLAGS="--enable-cross-compile --disable-debug --disable-programs \
--disable-doc --enable-pic"
if [ "$X264" ]
then
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-gpl --enable-libx264"
fi
if [ "$FDK_AAC" ]
then
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-libfdk-aac --enable-nonfree"
fi
# avresample
#CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-avresample"
ARCHS="arm64 armv7 x86_64 i386"
COMPILE="y"
LIPO="y"
DEPLOYMENT_TARGET="8.0"
if [ "$*" ]
then
if [ "$*" = "lipo" ]
then
# skip compile
COMPILE=
else
ARCHS="$*"
if [ $# -eq 1 ]
then
# skip lipo
LIPO=
fi
fi
fi
if [ "$COMPILE" ]
then
if [ ! `which yasm` ]
then
echo 'Yasm not found'
if [ ! `which brew` ]
then
echo 'Homebrew not found. Trying to install...'
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" \
|| exit 1
fi
echo 'Trying to install Yasm...'
brew install yasm || exit 1
fi
if [ ! `which gas-preprocessor.pl` ]
then
echo 'gas-preprocessor.pl not found. Trying to install...'
(curl -L https://github.com/libav/gas-preprocessor/raw/master/gas-preprocessor.pl \
-o /usr/local/bin/gas-preprocessor.pl \
&& chmod +x /usr/local/bin/gas-preprocessor.pl) \
|| exit 1
fi
if [ ! -r $SOURCE ]
then
echo 'FFmpeg source not found. Trying to download...'
curl http://www.ffmpeg.org/releases/$SOURCE.tar.bz2 | tar xj \
|| exit 1
fi
CWD=`pwd`
for ARCH in $ARCHS
do
echo "building $ARCH..."
mkdir -p "$SCRATCH/$ARCH"
cd "$SCRATCH/$ARCH"
CFLAGS="-arch $ARCH"
if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ]
then
PLATFORM="iPhoneSimulator"
CFLAGS="$CFLAGS -mios-simulator-version-min=$DEPLOYMENT_TARGET"
else
PLATFORM="iPhoneOS"
CFLAGS="$CFLAGS -mios-version-min=$DEPLOYMENT_TARGET -fembed-bitcode"
if [ "$ARCH" = "arm64" ]
then
EXPORT="GASPP_FIX_XCODE5=1"
fi
fi
XCRUN_SDK=`echo $PLATFORM | tr '[:upper:]' '[:lower:]'`
CC="xcrun -sdk $XCRUN_SDK clang"
# force "configure" to use "gas-preprocessor.pl" (FFmpeg 3.3)
if [ "$ARCH" = "arm64" ]
then
AS="gas-preprocessor.pl -arch aarch64 -- $CC"
else
AS="gas-preprocessor.pl -- $CC"
fi
CXXFLAGS="$CFLAGS"
LDFLAGS="$CFLAGS"
if [ "$X264" ]
then
CFLAGS="$CFLAGS -I$X264/include"
LDFLAGS="$LDFLAGS -L$X264/lib"
fi
if [ "$FDK_AAC" ]
then
CFLAGS="$CFLAGS -I$FDK_AAC/include"
LDFLAGS="$LDFLAGS -L$FDK_AAC/lib"
fi
TMPDIR=${TMPDIR/%\/} $CWD/$SOURCE/configure \
--target-os=darwin \
--arch=$ARCH \
--cc="$CC" \
--as="$AS" \
$CONFIGURE_FLAGS \
--extra-cflags="$CFLAGS" \
--extra-ldflags="$LDFLAGS" \
--prefix="$THIN/$ARCH" \
|| exit 1
make -j3 install $EXPORT || exit 1
cd $CWD
done
fi
if [ "$LIPO" ]
then
echo "building fat binaries..."
mkdir -p $FAT/lib
set - $ARCHS
CWD=`pwd`
cd $THIN/$1/lib
for LIB in *.a
do
cd $CWD
echo lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB 1>&2
lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB || exit 1
done
cd $CWD
cp -rf $THIN/$1/include $FAT
fi
echo Done
以上是完整脚本摘录,下面依次解释.
FF_VERSION="4.1"
这个是ffmpeg的realease的版本可以从github地址中查看
if [[ $FFMPEG_VERSION != "" ]]; then
FF_VERSION=$FFMPEG_VERSION
fi
判断是否配置了变量FFMPEG_VERSION,配置就赋值给变量FF_VERSION
SOURCE="ffmpeg-$FF_VERSION"
FAT="FFmpeg-iOS"
声明两个变量
SOURCE 源码指向的tag
FAT 代表的最后输出的fat文件所在的文件夹名字
SCRATCH="scratch"
THIN=`pwd`/"thin"
也是两个路径
#X264=`pwd`/fat-x264
#FDK_AAC=`pwd`/../fdk-aac-build-script-for-iOS/fdk-aac-ios
CONFIGURE_FLAGS="--enable-cross-compile --disable-debug --disable-programs \
--disable-doc --enable-pic"
if [ "$X264" ]
then
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-gpl --enable-libx264"
fi
if [ "$FDK_AAC" ]
then
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-libfdk-aac --enable-nonfree"
fi
这里的x264 和FDK_AAC 两个变量默认是注释掉的.如果需要库x264 和aac音频.这里需要打开
# avresample
#CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-avresample"
要是需要配置avresample 可以打开该选项
ARCHS="arm64 armv7 x86_64 i386"
编译的结构体
COMPILE="y"
LIPO="y"
DEPLOYMENT_TARGET="8.0"
COMPILE 代表编译
LIPO 代表合并
y 应该是获取yes的首字母,方便记忆吧
DEPLOYMENT_TARGET 编译库的最低版本
if [ "$*" ]
then
if [ "$*" = "lipo" ]
then
# skip compile
COMPILE=
else
ARCHS="$*"
if [ $# -eq 1 ]
then
# skip lipo
LIPO=
fi
fi
fi
脚本名称叫test.sh 入参三个: 1 2 3
运行test.sh 1 2 3后
$为"1 2 3"(一起被引号包住)
$@为"1" "2" "3"(分别被包住)
$#为3(参数数量)
这里因为我们没有传入参数因此,这里$ 是空.不会跳入该函数中
传入参数lipo,那么就不需要进行编译
其他的参数就是arch了,要是参数是一个,就不需要lipo命令 了
if [ "$COMPILE" ]
then
....
fi
这段是判断是否需要编译
if [ ! `which yasm` ]
then
echo 'Yasm not found'
if [ ! `which brew` ]
then
echo 'Homebrew not found. Trying to install...'
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" \
|| exit 1
fi
echo 'Trying to install Yasm...'
brew install yasm || exit 1
fi
依赖yasm ,要是没有安装yasm,那么安装yasm.而yasm依赖brew,没有brew,那么安装brew命令
if [ ! `which gas-preprocessor.pl` ]
then
echo 'gas-preprocessor.pl not found. Trying to install...'
(curl -L https://github.com/libav/gas-preprocessor/raw/master/gas-preprocessor.pl \
-o /usr/local/bin/gas-preprocessor.pl \
&& chmod +x /usr/local/bin/gas-preprocessor.pl) \
|| exit 1
fi
同理加载gas-preprocessor.pl 命令
if [ ! -r $SOURCE ]
then
echo 'FFmpeg source not found. Trying to download...'
curl http://www.ffmpeg.org/releases/$SOURCE.tar.bz2 | tar xj \
|| exit 1
fi
判断是否有源码,没有那么就需要去github下载源码.
-r 是读取当前目录文件
! 取反
tar xj 就是解压文件
CWD=`pwd`
代表当前路径
for ARCH in $ARCHS
do
.....
done
循环生成所需要的结构体.这中间的内容就是生成结构体
echo "building $ARCH..."
mkdir -p "$SCRATCH/$ARCH"
cd "$SCRATCH/$ARCH"
- 打印当前build的结构体
- 生成文件夹,路径是$SCRATCH/$ARCH 其实就是scratch/arm64等
- 进入该路径
CFLAGS="-arch $ARCH"
编译参数,选择生成的结构体类型
if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ]
then
PLATFORM="iPhoneSimulator"
CFLAGS="$CFLAGS -mios-simulator-version-min=$DEPLOYMENT_TARGET"
else
PLATFORM="iPhoneOS"
CFLAGS="$CFLAGS -mios-version-min=$DEPLOYMENT_TARGET -fembed-bitcode"
if [ "$ARCH" = "arm64" ]
then
EXPORT="GASPP_FIX_XCODE5=1"
fi
fi
这里是根据结构体类型选择PLATFORM 和 编译参数
i386 和x86_64 是模拟器结构体
arm64 armv7 是真机结构体
-fembed-bitcode bitcode指令
XCRUN_SDK=`echo $PLATFORM | tr '[:upper:]' '[:lower:]'`
CC="xcrun -sdk $XCRUN_SDK clang"
XCRUN_SDK 是编译所需的sdk连接地址 结果是iphonesimulator 和 iphoneos
CC 参数是编译命令
if [ "$ARCH" = "arm64" ]
then
AS="gas-preprocessor.pl -arch aarch64 -- $CC"
else
AS="gas-preprocessor.pl -- $CC"
fi
声明一个变量AS
CXXFLAGS="$CFLAGS"
LDFLAGS="$CFLAGS"
两个变量
if [ "$X264" ]
then
CFLAGS="$CFLAGS -I$X264/include"
LDFLAGS="$LDFLAGS -L$X264/lib"
fi
if [ "$FDK_AAC" ]
then
CFLAGS="$CFLAGS -I$FDK_AAC/include"
LDFLAGS="$LDFLAGS -L$FDK_AAC/lib"
fi
是否需要变量这两个库
到目前为止.
CC = "xcrun -sdk iphonesimulator clang"
AS = "gas-preprocessor.pl -- $CC"
CXXFLAGS = -arch x86_64 -mios-simulator-version-min=8.0
CFLAGS = -arch x86_64 -mios-simulator-version-min=8.0
LDFLAGS = -arch x86_64 -mios-simulator-version-min=8.0
TMPDIR = /var/folders/xz/ndlv58rj50q3v260h8lnyngh0000gn/T/
CONFIGURE_FLAGS = --enable-cross-compile --disable-debug --disable-programs --disable-doc --enable-pic
TMPDIR=${TMPDIR/%\/} $CWD/$SOURCE/configure \
--target-os=darwin \
--arch=$ARCH \
--cc="$CC" \
--as="$AS" \
$CONFIGURE_FLAGS \
--extra-cflags="$CFLAGS" \
--extra-ldflags="$LDFLAGS" \
--prefix="$THIN/$ARCH" \
|| exit 1
${TMPDIR/%/} 临时路径 这里其实就是执行ffmpeg的 configure命令
这里我们看看configure的最终结果是啥
configure --target-os=darwin --arch=x86_64 --cc=xcrun -sdk iphonesimulator clang --as=gas-preprocessor.pl -- $CC --enable-cross-compile --disable-debug --disable-programs --disable-doc --enable-pic --extra-cflags= -arch x86_64 -mios-simulator-version-min=8.0 --extra-ldflags= -arch x86_64 -mios-simulator-version-min=8.0 --prefix=./thin/x86_64
make -j3 install $EXPORT || exit 1
安装
cd $CWD
退出到根目录
if [ "$LIPO" ]
then
echo "building fat binaries..."
mkdir -p $FAT/lib
set - $ARCHS
CWD=`pwd`
cd $THIN/$1/lib
for LIB in *.a
do
cd $CWD
echo lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB 1>&2
lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB || exit 1
done
cd $CWD
cp -rf $THIN/$1/include $FAT
fi
这里就是lipo命令的简单使用
1.首先创建文件夹FFmpeg-iOS/lib
2 设置参数
3.进入 目录thin/x86_64/lib
- 依次寻找该目录下的.a 文件
1.跳转到 根目录
- 打印lipo 需要执行的命令
3.lipo 命令执行.(从thin文件夹中找 .a文件,输出到FFmpeg-iOS/lib/中,命名查找的.a文件)
5.进入根目录
6.将thin/x86_64/include 的文件拷贝到FFmpeg-iOS/lib/include
编译参数选择
1 生成参数
参数 | 功能 | 注释 |
---|---|---|
--arch | 编译架构 | |
--help | 打印帮助信息 | |
-prefix | 安装路径 | Linux默认为/usr/local |
--libdir | 库安装路径 | 默认PREFIX/lib |
--shlibdir | 共享库安装路径 | 默认PREFIX/lib |
--incdir | 头文件安装路径 | 默认PREFIX/include/ffmpeg |
--mandir | 指定man page路径 | 默认PREFIX/man |
--cc | 指定编译器 | 默认gcc |
--make | 指定何种make | |
--source-path | 源码路径 | |
--pkg-config | 指定pkg-config | 默认pkg-config |
--pkg-config-flags | 指定pkg-config参数 | 默认--static |
--extra-cflags | 添加额外的CFLAG | ECFLAGS |
--extra-ldflags | 添加额外的LDFLAG | ELDFLAGS |
--extra-libs | 添加额外的LIB | ELIBS |
--cpu | 指定最小的CPU版本 | |
--nm | 指定NM工具 | |
--ar | 指定AR工具 | |
--as | 指定汇编工具 | |
--ld | 指定LD链接器 |
2 交叉参数
参数 | 功能 | 注释 |
---|---|---|
-cross-prefix | 指定编译工具 | 交叉编译 |
--cross-compile | 假定使用交叉编译 | |
--target-os | 目标系统 | |
--sysroot | 交叉编译树的根 | libc |
--sysinclude | 交叉编译头文件 | |
--target-exec | 目标系统上的运行命令 | |
--target-path | 目标系统上的模拟构建路径 |
3 性能参数
以下参数使用--enable-foo启用或使用--disable-foo禁用时使用--e/d-代替。
参数 | 功能 | 注释 | |
---|---|---|---|
--e/d-debug | 是否调试 | enable时可指定level | |
--e/d-optimizations | 编译器优化 | ||
--samples | 制定测试示例位置 | ||
--e/d-stripping | 是否剥离可执行程序与共享库 | ||
--e/d-asm | 汇编优化 | ||
--e/d-yasm | 是否使用yasm汇编器 |
其他的可更改优化方案:AltiVec、3DNow! 、MMX、MMX2、SSE、SSE3、armv5te、armv6、armv6t2、ARM VFP、iwmmxt、MMI、neon、VIS
4 功能选项
使用--enable-foo启用或使用--disable-foo禁用需要的功能插件,使用--e/d-代替。某些部件(如decoder)enable时需要明确指明,例:--enable-decoder=libdavs2。
参数 | 功能 | 注释 |
---|---|---|
--e/d-static | 静态库构建 | 默认:no |
--e/d-shared | 共享库构建 | 默认:no |
--e/d-pic | 代码非位置依赖 | 默认:no |
--e/d-gpl | GPL代码使用 | |
--e/d-nonfree | 非免费得代码使用 | 默认:no |
--e/d-doc | 文档构造 | 默认:yes |
--e/d-pthreads | pthreads | 默认:yes |
--disable-decoder | 禁用所有解码器 | 同理其他 |
--enable-decoder=DEC | 打开某个解码器 | 同理其他 |
--enable-libdavs2 | 启用avs2解码器 | 同理其他 |
注:打开与启用非等同
其他默认开启但可以关闭的部分:ffmpeg、ffprobe、ffplay、ffserver、avdevice、avcodec、avcore、avformat、swscale、特定部件(如某个编解码器等)
可选择禁用的编码:AAN DCT、DCT、Golomb、FFT、Golomb、LPC、MDCT、RDFT、VAAPI、VDPAU、DXVA2
查看./configure 的参数,我们可以通过 ./configure --help 查看