iOS ijkplayer编译与支持https协议

环境

  • mac版本:MacBook Pro(Apple M1 Pro) M1芯片
  • Xcode版本:15.4

拉取代码

按照 blibili官方开源库ijkplayer README中iOS配置步骤进行配置。

# 先切到一个文件夹下
cd Desktop/

# 克隆ijkplayer的代码
git clone https://github.com/Bilibili/ijkplayer.git

# cd到拉下来的ijkplayer中
cd ijkplayer

# 切到最新版本k0.8.8(可在官方tags中查看最新版本)
git checkout -B latest k0.8.8

项目拉下来后文件结构如下:


拉下来的ijkplayer项目结构
克隆成功样式.png

配置解码器类型

  • module-default.sh 更多的编解码器/格式
  • module-lite-hevc.sh 较少的编解码器/格式(包括hevc)
  • module-lite.sh 较少的编解码器/格式(默认情况)
cd config
# 删除默认的解码器
rm module.sh

# 创建一个软连接指向 module-lite-hevc.sh,这个可根据自己需求进行选择
ln -s module-lite-hevc.sh module.sh

# 回到上一层目录
cd ..

# 进入ios目录
cd ios

# 将compile-ffmpeg.sh脚本清空,等待后期重新执行新的脚本
sh compile-ffmpeg.sh clean

注:sh compile-ffmpeg.sh clean./compile-ffmpeg.sh clean一样,都是在当前文件夹下执行脚本命令

配置ffmpeg内核版本

回到上一目录ijkplayer找到init-ios.sh文件进行编辑,可通过终端使用vi命令进入编辑环境,再输入i开始编辑,编辑结束后按键盘左上角上的esc键退出编辑,然后在终端中输入:wq进行保存并退出编辑环境, 或者找到该文件直接通过xcode打开开始修改。

# 回到上一目录ijkplayer
cd ..

# 编辑init-ios.sh文件
vi init-ios.sh

打开文件后可以看到如下内容,需要注意IJK_FFMPEG_COMMIT字段,该字段配置ffmpeg版本,如果不修改,则默认使用ff3.4--ijk0.8.7--20180103--001版本,我们需要将其修改为ff4.0--ijk0.8.25--20200221--001
原本bilibiliffmpeg库支持查看版本的,可惜现在看不到了。

#! /usr/bin/env bash
#
# Copyright (C) 2013-2015 Bilibili
# Copyright (C) 2013-2015 Zhang Rui <bbcallen@gmail.com>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# IJK_FFMPEG_UPSTREAM=git://git.videolan.org/ffmpeg.git
IJK_FFMPEG_UPSTREAM=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_COMMIT=ff4.0--ijk0.8.25--20200221--001
IJK_FFMPEG_LOCAL_REPO=extra/ffmpeg

IJK_GASP_UPSTREAM=https://github.com/Bilibili/gas-preprocessor.git

配置ffmpeg所依赖的环境

# 获取依赖的文件,这个会久一点,中途有失败再执行一下就可以了
./init-ios.sh

配置支持https协议(如果不需要支持https可以跳过)

编辑ijkplayer文件夹下的init-ios-openssl.sh文件

vi init-ios-openssl.sh

和升级ffmpeg类似,找到IJK_OPENSSL_COMMIT字段,将其默认值OpenSSL_1_0_2n替换成OpenSSL_1_0_2u

配置https所需的openssl环境

# 比较耗时,耐心等待
./init-ios-openssl.sh

成功后终端输出如下:


image.png

编辑config文件夹下的module.sh文件

vi config/module.sh

在文件的末尾加上如下两行:

# 支持https
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl"

# ffmpeg4.0 需要
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=eac3_core"

同时将以下两行注释掉:

#export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffserver"
#export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vda"

参考升级到ffmpeg到4.0

更改最低支持的版本到8.0

因为ffmpeg4.0使用的部分API是iOS8.0以上的,因此需要更改最低支持的版本超过8.0,否则编译ffmpeg时会出现如下错误:

libavcodec/videotoolbox.c:862:9: error: 'VTDecompressionSessionInvalidate' is only available on iOS 8.0 or newer
      [-Werror,-Wunguarded-availability]
        VTDecompressionSessionInvalidate(videotoolbox->session);

依次找到ios/tools目录下的do-compile-ffmpeg.shdo-compile-openssl.sh文件,打开文件并找到有关version-min小于8.0的统一改为8.0

更改version-min为8.0.png

取消支持armv7编译环境

因为使用Xcode15.4编译,已经弱化了对32位的支持,因此需要移除掉armv7环境。如果想支持armv7,请使用低版本Xcode 例:Xcode9编译打包。

找到ios目录下的compile-ffmpeg.shcompile-openssl.sh文件,打开文件并将FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"修改为FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64",否则可能会在编译ffmpeg的时候出现以下报错:

./libavutil/arm/asm.S:50:9: error: unknown directive
        .arch armv7-a
        ^
make: *** [libavcodec/arm/aacpsdsp_neon.o] Error 1

编译openssl

cd ios
# 先编译OpenSSL,如果不需要支持https可以跳过
./compile-openssl.sh all

编译openssl成功后终端输出如下:

编译openssl成功.png

编译openssl成功后项目在ios/build文件夹下多出了openssl-arm64openssl-i386openssl-x86_64universal四个文件夹,并在universal文件夹下的lib文件夹中多出了libcrypto.alibssl.a两个文件

image.png

编译ffmpeg

在编译ffmpeg之前需要在ios/tools目录中的do-compile-ffmpeg.sh文件中增加一行FFMPEG_CFLAGS="$FFMPEG_CFLAGS -Wno-error=incompatible-function-pointer-types",否则会在编译的时候提示指针问题。

# 编译ffmpeg遇到的error问题
libavcodec/aarch64/h264dsp_init_aarch64.c:84:38: error: incompatible function pointer types assigning to 'h264_weight_func' (aka 'void (*)(unsigned char *, long, int, int, int, int)') from 'void (uint8_t *, int, int, int, int, int)' (aka 'void (unsigned char *, int, int, int, int, int)') [-Wincompatible-function-pointer-types]
        c->weight_h264_pixels_tab[0] = ff_weight_h264_pixels_16_neon;
                                     ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

参考编译项目时 ffmpeg_arm64 指针类型报错

解决编译ffmpeg时提示错我.png

开始编译ffmpeg

# 编译ffmpeg
./compile-ffmpeg.sh all

编译ffmpeg成功后终端输出如下:

编译ffmpeg成功后.png

编译ffmpeg成功后项目在ios/build文件夹下多出了ffmpeg-arm64ffmpeg-i386ffmpeg-x86_64universal四个文件夹,并在universal文件夹下的lib文件夹中多出了libavcodec.alibavfilter.alibavformat.alibavutil.alibswresample.alibswscale.a六个文件。

image.png

检查项目

至此为止已经编译通过了,然后打开IJKMediaPlayer.xcodeproj文件查看ffmpeg所需要的库是否已正确引用上

项目位置.png

ffmpeg依赖的库.png

如果lib文件夹下各库文件为红色则表示未正确引用上,有可能是配置ffmpeg的步骤没弄好,需要清空opensslffmpeg脚本重新加载。

# 清空openssl.sh脚本
./compile-openssl.sh clean

# 清空ffmpeg.sh脚本
./compile-ffmpeg.sh clean 

# 重新加载openssl脚本
./compile-openssl.sh all

# 重新加载ffmpeg脚本 
./compile-ffmpeg.sh all 

检查通过后运行项目处理错误

IJKMediaFramework一运行发现demo中有一处方法没返回值编译不过去,添加上返回值。

image.png

如需支持https协议需在IJKMediaPlayer中增加上编译完openssl后生成的两个库文件

如果不增加这两个库文件,在运行IJKMediaDemo的时候会报错。

image.png

运行IJKMediaDemo

运行之后报错如下:

image.png

发现之前配置opensslffmpeg的时候设置最低8.0,由于demo中Minimum Deployments值是7.0,版本太低需将其提高(不知道为什么8.0不行,改为9.0正常了)

打包framework

配置为Release模式,使的编译状态即可打包出framework。

image.png
image.png

分别选择真机环境及模拟器环境编译一遍,然后在设置中的Locations分栏中点击箭头跳到编译后的目录,找到真机包和模拟器包。

image.png
image.png
image.png

lipo命令查看包支持的环境及合并包

  • lipo命令查看包支持的环境
    在终端中输入lipo -info framework地址获取该包支持的环境
lipo -info /Users/***/Library/Developer/Xcode/DerivedData/IJKMediaPlayer-flteyzdokpvvjrggfniynketqxrr/Build/Products/Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework
Architectures in the fat file: /Users/***/Library/Developer/Xcode/DerivedData/IJKMediaPlayer-flteyzdokpvvjrggfniynketqxrr/Build/Products/Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework are: arm64 x86_64 

可以看到该模拟器包支持arm64x86_64指令集

  • lipo命令合并真机与模拟器包
    在终端中输入lipo -create 真机包地址 模拟器包地址 -output 包名称将真机包与模拟器包合并为一个新的包同时支持两种编译环境。

值得注意的是:Apple发布M1芯片之前,一直使用Intel的芯片,没有出现什么问题。发布 M1芯片后,由于两者架构的不同(M1arm64架构,Intelx86_64的架构),导致lipo -create命令在执行的时候会出现如下错误:

lipo -create /Users/***/Library/Developer/Xcode/DerivedData/IJKMediaPlayer-flteyzdokpvvjrggfniynketqxrr/Build/Products/Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework  /Users/***/Library/Developer/Xcode/DerivedData/IJKMediaPlayer-flteyzdokpvvjrggfniynketqxrr/Build/Products/Release-iphoneos/IJKMediaFramework.framework/IJKMediaFramework  -output IJKMediaFramework
fatal error: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/lipo: /Users/***/Library/Developer/Xcode/DerivedData/IJKMediaPlayer-flteyzdokpvvjrggfniynketqxrr/Build/Products/Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework and /Users/***/Library/Developer/Xcode/DerivedData/IJKMediaPlayer-flteyzdokpvvjrggfniynketqxrr/Build/Products/Release-iphoneos/IJKMediaFramework.framework/IJKMediaFramework have the same architectures (arm64) and can't be in the same fat output file

在我们创建framework时,选择真机编译出来的包只包含arm64指令,选择模拟器编译出来的包会同时包含arm64x86_64指令。有网上教程说将模拟器部分的arm64指令移除,但是要支持M1机器正常跑模拟器环境,必须同时包含arm64x86_64指令。

解决方案:2019年的WWDC,苹果提供了一种新的框架封装格式XCFramework,简单理解就是之前用lipo命令合并不同指令集的包,现在改为使用心得指令合并成XCFramework格式的包。

xcodebuild指令

实验过很多次,仍旧无法解决在M1机器上编译出的arm64+x86_64指令同时存在的framework改为xcframework

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容