iOS编译IJKPlayer,自定义制作IJKMediaFramework

准备IJKPlayer资源

  1. 查看IJKPlayer项目文档
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
cd ijkplayer-ios
git checkout -B latest k0.8.8

./init-ios.sh
cd iOS
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all

是不是很简单的样子?只需要下载到本地,然后检出到k0.8.8版本,然后执行几个脚本就结束了!然而,如果你在这时候放松下来,想要泡个咖啡溜溜号,等你回来的时候将会有许多个大惊喜等着你。

  1. 愉悦的踩坑之旅
    首先根据文档将IJKPlayer资源克隆到本地
// 选择本地目录
 cd /Users/username/Desktop/myswift 
// 克隆项目代码到指定位置(为了保证目录的统一性,克隆位置命名为ijkplayer-ios)
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios

根据文档,下一步将执行git checkout -B latest k0.8.8。分析git语法,我们知道这一句的意思,是检出分支latest,版本号为k0.8.8。
分支latest是一个编译稳定的分支,也就是开发中的发布分支,所以除非发生重大变故,这个分支的名称基本不会发生变化。但是,后面的版本号却会随着开发者的发布不断改变。所以我们再执行这段语句时,需要先查看最新发布的版本号。
查看ijkplayer的最新realease版本,截止到现在的最新版本为k0.8.8。如果你没有特定的需要的话,强烈建议使用最新版本。毕竟衣不如新,我们如果一直拿着老旧的轮子做任务,难免会在遇到新问题的时候翻车,到时候需要解决的问题将会越来越复杂,也越来越难以处理。
事实上,我们所使用的任何第三方框架,都应该在开发者发布最新的稳定版本时进行更新。以免在因为xcode版本更新,或ios版本更新造成项目瘫痪,对我们的开发工作重大损失。

// 切换到ijkplayer目录
cd ijkplayer-ios
// 检出到最新稳定编译打包的版本(目前最新发布版为k0.8.8)
git checkout -B latest k0.8.8

接下来就要执行init-ios.sh脚本了,如果没有特殊需要的话,建议你查看一下最新支持的ffmpeg版本。bilibili/ffmpeg是IJKPlayer的核心,开发小伙伴也在非常努力的更新,我们千万不要辜负了他们的苦心哦。
查看bilibili/ffmpeg最新的realease版本,根据ffmpeg的版本号选择最新的版本(目前存在的两个更新版本分别ff3.4和ff4.0)。
目前ffmpeg已发布到4.3.1版本,稳定发布并自动编译到ios的版本为4.2,因此我选择了ff4.0,查看最新发布版本为ff4.0--ijk0.8.25--20200221--001。
拷贝版本名称,并打开ijkplayer-ios/init-ios.sh文件,将最新版本更新到文件中。

IJK_FFMPEG_UPSTREAM=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git
// 这一句已修改到ffmpeg4.0最新realease
IJK_FFMPEG_COMMIT=ff4.0--ijk0.8.25--20200221--001
IJK_FFMPEG_LOCAL_REPO=extra/ffmpeg

值得一提的是,随着xcode版本的提升,对arm7,arm7s的支持越来越弱,原因就是这些架构的手机几乎已经全部退出市场了,在APPStore的上架过程中,已经明确拒绝使用arm7架构编译的内容了。
我在新的项目中,已经抛弃了这两种架构的编译,只选择支持arm64与x86_64,由于我们的app只和行车记录仪交互,厂商提供的SDK又放弃了对模拟器的支持,所以我们只需要支持arm64架构即可。在init-ios.sh中,我又删除了FF_ALL_ARCHS_IOS6_SDK和FF_ALL_ARCHS_IOS7_SDK(这两个变量已经没有用处了),FF_ALL_ARCHS_IOS8_SDK也删除到只包含arm64架构。如果没有特殊需要,建议保留x86_64架构的内容,以免未来想要在模拟器上测试时,发现根本无法编译。

...
set -e
TOOLS=tools

FF_ALL_ARCHS_IOS8_SDK="arm64"
FF_ALL_ARCHS=$FF_ALL_ARCHS_IOS8_SDK
FF_TARGET=$1

function echo_ffmpeg_version() {
    echo $IJK_FFMPEG_COMMIT
}
...
#----------
case "$FF_TARGET" in
    ffmpeg-version)
        echo_ffmpeg_version
    ;;
    arm64)
        pull_common
        pull_fork $FF_TARGET
    ;;
    all|*)
        pull_common
        pull_fork_all
    ;;
esac

sync_ff_version

如果你和我一样删除了ijkplayer-ios/init-ios.sh中不需要的架构,那么ijkplayer-ios/iOS/compile-ffmpeg.sh和ijkplayer-ios/iOS/compile-openssl.sh也要一起修改,否则后面编译的时候会找不到对应的地址。
修改了这些内容,基本上就可以执行init-ios.sh脚本,如下所示内容。
但如果你的项目需要执行https播放的话,还要执行init-ios-openssl.sh,请跳转到下一步。

./init-ios.sh
cd iOS
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all

如果不需要播放https内容,则跳过本步骤。我们知道,https协议大致就是http协议+ssl协议,这里也是一样,需要集成openssl模块。与ffmpeg相似,IJKPlayer团队对openssl做打包处理时,也会随着openssl的升级不断升级版本。查看最新realease版本,目前看到的最新版本为OpenSSL_1_0_2u
修改 ijkplayer-ios/init-ios-openssl.sh 文件内容如下:

IJK_OPENSSL_UPSTREAM=https://github.com/openssl/openssl
IJK_OPENSSL_FORK=https://github.com/Bilibili/openssl.git
// 修改openssl为最新版本
IJK_OPENSSL_COMMIT=OpenSSL_1_0_2u
IJK_OPENSSL_LOCAL_REPO=extra/openssl

set -e
TOOLS=tools

echo "== pull openssl base =="
sh $TOOLS/pull-repo-base.sh $IJK_OPENSSL_UPSTREAM $IJK_OPENSSL_LOCAL_REPO

function pull_fork()
{
    echo "== pull openssl fork $1 =="
    sh $TOOLS/pull-repo-ref.sh $IJK_OPENSSL_FORK ios/openssl-$1 ${IJK_OPENSSL_LOCAL_REPO}
    cd ios/openssl-$1
    git checkout ${IJK_OPENSSL_COMMIT} -B ijkplayer
    cd -
}
// 由于我的项目只支持arm64架构,其余部分均已删除
pull_fork "arm64"

到这里基本已经完全修改完毕,现在只需要再简单配置一下编解码器,就可以放心的执行初始化脚本了。在ijkplayer-ios/config中,我们可以看到module-default.sh,module-lite-hevc.sh,module-lite.sh和一个链接文件module.sh,这个module.sh默认是连接在module-lite.sh中的,基本满足普通开发需要。但我的项目因为要支持多种车载行车记录仪录像格式,所以选择将链接更改到module-default.sh文件中。

cd config
rm module.sh
ln -s module-default.sh module.sh

需要注意的是,如果你选择了ff4.0xxx版本,在module.sh链接的对象中,需要将--disable-ffserver取消,因为ffserver在ffmpeg3.4版本被移除。

...
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-programs"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffmpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffplay"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffprobe"
#export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffserver"
...
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-dxva2"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vaapi"
#export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vda"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vdpau"
...

如果你在项目中,除了IJKPlayer的基本操作之外,还使用了FFmpeg相关内容,如编码解码等,则需要开放指定的功能,否则将无法使用。以下是我开放的相关功能。

...
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-avdevice"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avcodec"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avformat"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avutil"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-swresample"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-swscale"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-postproc" // 开放
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avfilter"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-avresample" // 开放
...
# Individual component options:
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-everything"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-encoders" // 开放
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoders" // 开放
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-hwaccels"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-muxers" // 开放
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxers" // 开放
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-parsers" // 开放
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsfs"
# export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocols"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-devices"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-filters" // 开放
...
// 以下为新增兼容内容
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=tcp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=sdp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtp"

另外,videotoolbox是ios8.0引入的模块,如果编译时最低支持到ios7,则会出现以下的报错内容。


截屏2020-10-01 下午7.57.24.png

这时,我们就需要修改编译脚本ijkplayer-ios/ios/tools/do-compile-ffmpeg.sh,将ios最低版本限制在9.0(现在iOS已经更新到14.0了,理论上我们只需要支持到ios11.0即可满足使用需要)。如下图所示(事实上,arm7,arm7s,i386架构内容完全可以删除):


截屏2020-10-01 下午8.20.10.png

至此,准备工作已全部完成,愉快的执行以下的代码吧:
./init-ios.sh
// 如果你的项目不需要支持https,则 不需要执行openssl的初始化
// ./init-ios-openssl.sh
cd iOS
./compile-openssl.sh clean
./compile-ffmpeg.sh clean
./compile-openssl.sh all
./compile-ffmpeg.sh all

打包IJKMediaFramework

  1. 打开ijkplayer-ios/ios/IJKMediaPlayer/IJKMediaPlayer.xcodeproj
  2. 选择scheme->IJKMediaFramework
    在执行编译时,如果发现头文件缺失,请在ijkplayer-ios/extra/ffmpeg文件夹中找到对应缺失的文件,并拷贝到ijkplayer-ios/iOS/build/universal/includ中。
    我在编译时,就缺失了libavformat/avio_internal.h,libavformat/id3v2.h,只要按说明解决文件冲突即可。
  3. 分别选择真机和模拟器,编译出指定的framework,然后执行合并操作即可。合并framework在网络上可以很简单的查询到相关操作,这里就不再叙述了。

你可能感兴趣的:(iOS编译IJKPlayer,自定义制作IJKMediaFramework)