iOS 开发 ijkplayer-ios 编译 支持https ---看本文就够了
##1. 编译环境
Mac OS Catalina 10.15.6
Xcode 12.4
##2. 安装 homebrew, git, yasm工具
```
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
brew install git
brew install yasm
```
##3. 从github上下载ijkplayer源码
```
#进入到自己保存ijkplayer源代码位置路径
cd /Users/system/Workspace/Github
# 下载ijkplayer源代码
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
#进入源码目录
cd ijkplayer-ios
# 切换分支(目前最新版本为k0.8.8,可以在ijkplayer-ios根目录下找到NEWS.md文件可以查看最新版本号)
git checkout -B latest k0.8.8
```
##4. 配置编解码器格式
默认为最少支持, 如果足够你使用, 可跳过:
module-default.sh 更多的编解码器/格式
module-lite-hevc.sh 较少的编解码器/格式(包括hevc)
module-lite.sh 较少的编解码器/格式(默认情况)
```
# 进入 config目录
cd config
# 删除当前的 module.sh 文件
rm module.sh
# 可根据需要替换为`module-default.sh`,`module-lite-hevc.sh`,`module-lite.sh`
# 创建软链接 module.sh 指向 module-lite-hevc.sh
ln-s module-lite.sh module.sh
cd..
cd iOS
# 清空历史编译记录(如果有编译过)
sh compile-ffmpeg.sh clean
```
##5. 获取 ffmpeg 并初始化
###此过程需要从网上拉取ffmpeg,需要花些时间
```
cd ..
./init-ios.sh
```
##6. 获取 openssl 并初始化(增加HTTPS支持)
###编译完openssl后会生成支持 https 的静态文件 libcrypto.a 和 libssl.a,如不需要支持HTTPS可跳过此步骤:
```
./init-ios-openssl.sh
cd ios
# 在模块文件中添加一行配置 以启用 openssl 组件
# 模块文件:
# module-default.sh 更多的编解码器/格式
# module-lite-hevc.sh 较少的编解码器/格式(包括hevc)
# module-lite.sh 较少的编解码器/格式(默认情况)
echo 'export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl"' >> ../config/module.sh
./compile-ffmpeg.sh clean
```
##7. 编译
```
# 如果下一步提示错误`xcrun: error: SDK "iphoneos"cannot be located`,请执行`sudo xcode-select--switch/Applications/Xcode.app/Contents/Developer/`,再重新执行下一步
# 编译openssl, 如不需要https可跳过
./compile-openssl.sh all
# 编译ffmpeg
./compile-ffmpeg.sh all
```
###如果编译ffmpeg提示如下错误:
```
./libavutil/arm/asm.S:50:9: error: unknown directive
.arch armv7-a
^
make: *** [libavcodec/arm/aacpsdsp_neon.o] Error 1
```
###最新的 Xcode 环境中iOS SDK最低支持从iOS 8.0开始了,弱化了对 32 位iOS系统的支持,解决方法:
```
在compile-ffmpeg.sh中删除armv7, 修改如:
FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"
再重新执行出现错误的命令:
./compile-ffmpeg.sh all
```
##8. 打开 IJKMediaDemo 项目
```
open IJKMediaPlayer/IJKMediaPlayer.xcodeproj
```
也可以手动用 Xcode 打开 ios 目录下的 IJKMediaPlayer 项目.
##9.此步骤为了处理集成后,编译可能报错的问题处理
###按目录找到文件夹位置并删除
IJKMediaPlayer->Classes->IJKFFMoviePlayerController->ffmpeg->lib
###按照上面的可以看到该文件夹,然后鼠标右击delete->Remove References.
###接下来,重新把ffmpeg编译的库静态.a文件和include中的头文件拖进来,找到ijkplayer-ios存放的目录,我这里是:
/Users/system/Workspace/Project/ijkplayer-ios
###然后进入到ijkplayer-ios下的ios/build/universal,可以看到include和lib两个文件夹,然后把他们拖到IJKMediaDemo刚才的位置中:
IJKMediaPlayer->Classes->IJKFFMoviePlayerController->ffmpeg
###此步骤不执行,集成后编译运行将出现错误
##10.打包framwork并合并
大家会发现除了IJKMediaFramework这个目标,还有一个叫IJKMediaFrameworkWithSSL,但是不推荐使用这个,因为大部分基于ijkplayer的第三方框架都是使用的前者,你把后者导入项目还是会报找不到包的错误,就算你要支持https也推荐使用前者,然后按照上一步添加openssl即可支持
###10.1 配置发布模式如下图
###10.2 打包真机框架
如图操作,然后按键命令+ B编译即可
真机编译会出现如下错误
问题:链接库“xxx.a”缺少此目标所需的一个或多个体系结构:arm64、armv7
处理方法:
如上图,在Target-Build Settings-Excluded Architectures中添加以下代码
EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_simulator__NATIVE_ARCH_64_BIT_x86_64=arm64 arm64e armv7 armv7s armv6 armv8 EXCLUDED_ARCHS=$(inherited) $(EXCLUDED_ARCHS__EFFECTIVE_PLATFORM_SUFFIX_$(EFFECTIVE_PLATFORM_SUFFIX)__NATIVE_ARCH_64_BIT_$(NATIVE_ARCH_64_BIT))
###10.3 打包模拟器 framework
如图操作,然后命令+ B编译即可
###10.4 合并框架
如果只需要真机运行或者模拟器运行,可以不用合并,直接找到对应的框架导入项目即可; 一般我们为了方便会合并框架,这样就同时支持模拟器和真机运行。
先找到生成框架的目录:
打开终端, 先 cd 到 Products 目录下
然后执行: lipo -create 真机framework路径 模拟器framework路径 -output 合并的文件路径
```
lipo -create Release-iphoneos/IJKMediaFramework.framework/IJKMediaFramework Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework -output IJKMediaFramework
```
合并报错如图:
解决如图:
设置Build Setting --> Excluded Architectures --> Release --> 添加上 arm64
重新编译,再合并。
###10.5 合并完成
可以看到这里生成了一个大概两倍大小的文件, 将生成的 IJKMediaFramework 文件替换掉 真机framework 中的 IJKMediaFramework 文件,然后这个替换掉文件的 真机framework 就是我们需要的 通用的framework 了。
###10.6 导入 framework
直接将 IJKMediaFramework.framework 拖入到工程中即可
注意记得勾选 Copy items if needed 和 对应的 target
添加下列依赖到工程
###10.7 测试地址
点播
http://static.tripbe.com/videofiles/20121214/9533522808.f4v.mp4
http://img.ksbbs.com/asset/Mon_1703/05cacb4e02f9d9e.mp4
https://media.w3.org/2010/05/sintel/trailer.mp4
直播:
http://ivi.bupt.edu.cn/hls/cctv6hd.m3u8
##11. 在测试播放的时候,xcode会打印 Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState] 子线程刷新UI的问题。
解决方法:
Xcode 9以后增加了新特性“主线程检测器(Main Thread Checker)”,这样在运行IJK时,就会报IJKSDLGLView里面,子线程获取“UIApplication的applicationState”、layer。
有些人的做法是关闭检测器,但这并没有从根本上解决问题,就应该将这些操作改成使用主线程进行操作,下面是我的做法,直接修改IJKSDLGLView的源码。
###11.1 首先,增加个只在主线程操作的方法,这个方法里面就是先判断当前是否在主线程,如果是就直接执行,否则同步切换到主队列进行执行。
```
static void IJKHanleInMainThread(dispatch_block_t mainThreadblock) {
if ([NSThread currentThread] == [NSThread mainThread]){
mainThreadblock();
} else {
dispatch_sync(dispatch_get_main_queue(), ^{
mainThreadblock();
});
}
}
```
###11.2 其次将方法- (BOOL)isApplicationActive里面改成这样:
```
__block UIApplicationState appState = 0;
IJKHanleInMainThread(^{
appState = [UIApplication sharedApplication].applicationState;
});
```
将方法- (void)displayInternal: (SDL_VoutOverlay *) overlay里面改成这样
```
IJKHanleInMainThread(^{
[[self eaglLayer] setContentsScale:_scaleFactor];
});
IJKHanleInMainThread(^{
[_context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];
});
```
最后执行IJK的demo,发现子线程操作UI的那些警告就没有了。这样重新编译生成静态库。
##注:本文参考文章
https://www.jianshu.com/p/73d8f2b35cb4
https://www.jianshu.com/p/9a69af13835e
https://blog.csdn.net/qcx321/article/details/113527386