FFmpeg在编译成ios库并集成到项目中

想学习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
经过一段时间 编译结束.
当前文件夹的文件有


ffmpeg结果文件夹

到这里很顺利编译结束.

集成新工程

创建新工程


FFmpeg在编译成ios库并集成到项目中_第1张图片
新工程
FFmpeg在编译成ios库并集成到项目中_第2张图片
添加ffmpeg库
FFmpeg在编译成ios库并集成到项目中_第3张图片
修改搜索头文件

这里需要注意 要是我们路径 $(PROJECT_DIR)/TestFFmpeg/include 模式是 non-recursive. 那么我们引用头文件的格式是#import "libavformat/avformat.h"

FFmpeg在编译成ios库并集成到项目中_第4张图片
添加六个依赖库

脚本解释

#!/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地址中查看


FFmpeg在编译成ios库并集成到项目中_第5张图片
image.png
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

  1. 依次寻找该目录下的.a 文件

1.跳转到 根目录

  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 查看

参数编译
ffmpeg-github
kxmovie
官方文档
脚本地址

你可能感兴趣的:(FFmpeg在编译成ios库并集成到项目中)