iOS: FFmpeg编译和使用问题总结

  

  折磨了我近一周多时间的FFmpeg库编译问题终于解决了,必须得把这一段时间来遇到过的坑全写出来。如果急着解决问题,编译最新版本的FFmpeg库请直接看第二部分,编译较老版本(0.7)的FFmpeg库请直接跳至第七部分,那里有你想要的编译脚本,但别忘了抽空看看全文。

 

一、背景

  网上有很多FFmpeg编译配置的资料,大部分都是关于FFmpeg最新的版本(2.0)的,我一开始也想着编写一个2.0版本的,可以放到接手的那个项目中,发现各种问题(无法快进,没有声音),再看一下代码一堆警告,原因很简单,使用的FFMpeg库太新了,很多接口变动了。由于手上没有多少信息,不知道那个项目使用的是哪个版本的FFmpeg库,一点点找,终于知道原来使用的是0.7.x的。找到目标版本的FFmpeg本以为万事大吉了,后来才发现原来这才是坑的开始,有历经一系列磨难,最后终于把编译问题解决了。

  

二、FFmpeg最新版本的库编译

  FFmpeg最新版本的应该是2.1的,历史版本详见http://www.ffmpeg.org/releases/,在这个网站上我们可以下到所有历史版本的库。FFmpeg是一个跨平台的用C语言写成的库,包含了编码,解码,色彩空间转换等库。编译需要用到命令行,对于我们这些没搞过后台或者linux开发的脚本知识欠缺的人来说的确算是一个挑战。庆幸的是现在网络这么方便,不会做问Google,很快就找到了一个在xcode5下一键编译FFmpeg库的脚本。这个脚本是个老外写的,真心强大,从下载到编译到构建最后的Fat库一气呵成。

  脚本地址: https://gist.github.com/m1entus/6983547

  运行这个脚本需要依赖一个库Perl写的脚本,搜了一下网上目前编译FFmpeg库的帖子基本都会提到这个脚本,脚本地址如下: https://github.com/mansr/gas-preprocessor

  下载完这两个脚本后,编译FFmpeg库的准备工作就基本完成了,接着依次执行下面几步:

  1、拷贝gas-preprocessor.pl文件到 /usr/bin目录下。

  2、修改gas-preprocessor.pl文件的权限

  注:需要有读,写和执行的权限。具体操作为,首先在命令行下进入/usr/bin目录,然后执行chmod命令,如下图所示:

iOS: FFMpeg编译和使用问题总结

  3、切换build-ffmpeg.sh脚本的目录下,使用命令sh build-ffmpeg.sh 运行该脚本即可。

 

  注:  1) build-ffmpeg.sh脚本的父目录的名字不能包括空格,否则可能导致构建失败。

      2) build-ffmpeg.sh脚本中可以配置编译的FFMpeg版本,以及使用iOS SDK的版本,如下图所示:

 

iOS: FFMpeg编译和使用问题总结

  该脚本中默认采用的FFmpeg是2.0版本,使用iOS 7.0的SDK编译,c语言编译器采用clang,应用中可以根据实际项目需要选中不同的FFmpeg和iOS SDK版本。

  根据上面的步骤看来,编译工作也没有什么复杂的,为什么我会说踩了很多坑呢?这个问题我会一点点儿解释。

 

三、编译较早期版本的FFmpeg本库

  第二部分中我们介绍了一个牛逼的脚本,一键编译,这给我们造成了一种错觉,FFmpeg编译不过如此吗!如果我们尝试一下把脚本中的VERSION变成0.7试试,运行脚本,发现编译报错。如下图所示:

iOS: FFMpeg编译和使用问题总结

  提示位置选项--disable-iconv,根据提示我们输入./configure查看所有可用选项。命令行下切换到实际的FFmpeg源码目录下,查看帮助如下图:

iOS: FFMpeg编译和使用问题总结

  我们可以看到很多选项,英语不难,就是有些选项描述的太简洁了,所以实际使用时如果不确定的话,我们可以去问问google。

  好了回过头来看看这个configure文件到底有什么作用呢?

  1、裁剪

  我们知道FFmpeg库是一个非常庞大的库,包括编码,解码以及流媒体的支持等,如果不做裁剪全部编译进来的话,最后生成的静态库会很大。实际使用中我们可能只想用到解码(例如播放器),因此我们可以使用相关选项指定编译时禁用编码部分。当然我们还可以做进一步的裁剪,例如只打开部分常用格式的解码,禁用掉其他的解码,这样编译出来的静态库将会更小。

  要想裁剪,我们的先知道有哪些部分,使用下面的命令可以查看FFMpeg库支持的组件列表。

  --list-decoders          show all available decoders
  --list-encoders          show all available encoders
  --list-hwaccels          show all available hardware accelerators
  --list-muxers            show all available muxers
  --list-demuxers          show all available demuxers
  --list-parsers           show all available parsers
  --list-protocols         show all available protocols
  --list-bsfs              show all available bitstream filters
  --list-indevs            show all available input devices
  --list-outdevs           show all available output devices
  --list-filters           show all available filters

  我们可以根据实际需要把不用的部分都禁用掉,这样编译快,包也会比较小,常用的裁剪选项如下:

  --disable-doc            do not build documentation
  --disable-ffmpeg         disable ffmpeg build
  --disable-ffplay         disable ffplay build
  --disable-ffserver       disable ffserver build
  --disable-network        disable network support [no]
  --disable-encoder=NAME   disable encoder NAME
  --enable-encoder=NAME    enable encoder NAME
  --disable-encoders       disable all encoders
  --disable-decoder=NAME   disable decoder NAME
  --enable-decoder=NAME    enable decoder NAME
  --disable-decoders       disable all decoders
  --disable-hwaccel=NAME   disable hwaccel 

  举个例子,如果我们需要做一款本地视频播放器,那么我们可以使用如下配置:

  iOS: FFMpeg编译和使用问题总结

  当然你还可以根据帮助列表进行更细粒度的裁剪,例如只支持哪几种格式的解码等等。

 

  2、指定编译环境

  FFMpeg作为一个跨平台的库,不同的平台,不同的人的计算机上编译器的路径都可能不尽相同,所以我们需要为编译脚本指定编译器的路径。同事我们还可以指定其他编译选项,如是否交叉编译,目标平台系统,CPU架构,需要依赖的其他库的路径已经指定是否禁用汇编优化等。

  --enable-cross-compile   assume a cross-compiler is used
  --sysroot=PATH           root of cross-build tree
  --sysinclude=PATH        location of cross-build system headers
  --target-os=OS           compiler targets OS []
  --cc=CC                  use C compiler CC [gcc]
  --extra-cflags=ECFLAGS   add ECFLAGS to CFLAGS []
  --extra-ldflags=ELDFLAGS add ELDFLAGS to LDFLAGS []
  --arch=ARCH              select architecture []
  --cpu=CPU                select the minimum required CPU (affects
                           instruction selection, may crash on older CPUs)
  --disable-asm            disable all assembler optimizations

  sysroot即iOS SDK的路径,注意编译真机版本的库时需要使用iPhoneOS.platform中SDK的路径,编译模拟器版本的库使用iPhoneSimulator.platform中SDK的路径。target-os填写darwin(苹果系统的内核),arch可以根据具体的情况添加i386(模拟器),armv6,armv7等。cpu根据具体类型可填写cortex-a8,cortox-a9,i386等。   

 

  3、指定静态库的安装路径

  指定执行make install命令时编译好的静态库和相关头文件拷贝到的位置,即FFmpeg库编译后输出的路径。通常我们只需要设置“--prefix=PREFIX”选项即可。例如我们需要将最后生成静态库的路径指向“build/armv7”下,则设置--prefix="build/armv7";

   

四、FFmpeg0.7版本库一键编译脚本

  通过第三部分的介绍,相信我们应该对FFmpeg的配置都有了一个初步的认识,我们再回到第三部分开始时我们运行build-ffmpeg.sh的碰到的问题,经过查看configure的帮助,我们发现0.7这个版本的FFmpeg库却是没有"--disable-iconv"选项。这个牛逼的脚本是针对当前较新的FFmpeg库写的,在低版本中没有一些配置选项也是正常。

  下面给出经过修改后的脚本,脚本中对原先的脚本进行了精简,去掉了下载部分的代码。

#!/bin/sh

########################################################################
##################### copyright by smileEvday ##########################
##################### smileEvday.cnblogs.com ###########################
########################################################################

# FFMpeg,SDK版本号
VERSION="0.7.4"
SDKVERSION="6.1"

#最低支持的SDK版本号
MINSDKVERSION="5.0"

# 源文件路径
SRCDIR=$(pwd)
BUILDDIR="${SRCDIR}/build"
mkdir -p $BUILDDIR

# 获取xcode开发环境安装路径
DEVELOPER=`xcode-select -print-path`

# 要编译的架构列表
ARCHS="armv7 armv7s i386"
for ARCH in ${ARCHS}
do
    if [ "${ARCH}" == "i386" ];
    then
        PLATFORM="iPhoneSimulator"
        EXTRA_CFLAGS="-arch i386"
        EXTRA_LDFLAGS="-arch i386 -mfpu=neon"
        EXTRA_CONFIG="--arch=i386 --cpu=i386"
    else
        PLATFORM="iPhoneOS"
        EXTRA_CFLAGS="-arch ${ARCH} -mfloat-abi=softfp"
        EXTRA_LDFLAGS="-arch ${ARCH} -mfpu=neon -mfloat-abi=softfp"
        EXTRA_CONFIG="--arch=arm --cpu=cortex-a9 --disable-armv5te"
    fi
    
    make clean

    # you can do any clip here 
    ./configure --prefix="${BUILDDIR}/${ARCH}"         \
                --disable-doc                         \
                --disable-ffmpeg                     \
                --disable-ffplay                     \
                --disable-ffserver                     \
                --enable-cross-compile                 \
                --enable-pic                         \
                --disable-asm                        \
                --target-os=darwin                     \
                ${EXTRA_CONFIG}                        \
                --cc="${DEVELOPER}/Platforms/${PLATFORM}.platform/Developer/usr/bin/gcc"                                         \
                --as="/usr/bin/gas-preprocessor.pl"                                                                                \
                --sysroot="${DEVELOPER}/Platforms/${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDKVERSION}.sdk"                 \
                --extra-cflags="-miphoneos-version-min=${MINSDKVERSION} ${EXTRA_CFLAGS}"                                                        \
                --extra-ldflags="-miphoneos-version-min=${MINSDKVERSION} ${EXTRA_LDFLAGS} -isysroot ${DEVELOPER}/Platforms/${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDKVERSION}.sdk"

    make && make install && make clean
     
done

########################################################################################################################
##################################################### 生成fat库 #########################################################
########################################################################################################################
mkdir -p ${BUILDDIR}/universal/lib
cd ${BUILDDIR}/armv7/lib

for file in *.a
do

cd ${SRCDIR}/build
xcrun -sdk iphoneos lipo -output universal/lib/$file  -create -arch armv7 armv7/lib/$file -arch armv7s armv7s/lib/$file -arch i386 i386/lib/$file
echo "Universal $file created."

done
cp -r ${BUILDDIR}/armv7/include ${BUILDDIR}/universal/

echo "Done."
build-ffmpeg0.7

相关文章: