iOS 制作ijkplayer静态库

3,395 阅读2分钟

ijkplayer框架是B站开源的一款基于ffmpeg的轻量级视频播放器,同时支持 Android 和 iOS 平台。项目中使用了SJVideoPlayer视频播放三方中使用了ijkplayer,在此记录一下。

1. 从github上克隆ijkplayer

  cd Desktop/
  git clone https://github.com/Bilibili/ijkplayer.git ijkplayer

image.png

注意:此时的ffmpeg-arm64ffmpeg-armv7ffmpeg-i386ffmpeg-x86_64是没有的,如果执行IJKMediaDemo,则会报错找不到ffmpeg 框架中的库,需要下载ffmpeg

配置编解码器格式支持

默认为最少支持, 如果足够你使用, 可以跳过这一步. 否则可以改为以下配置:

  • 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-hevc.sh module.sh

升级FFmpeg4.0版本

到 bilibili fork 的 FFmpeg 项目中的 releases 查看当前支持的最新版本。

打开 init-ios.sh文件,修改 IJK_FFMPEG_COMMIT。例如

IJK_FFMPEG_COMMIT=ff4.0--ijk0.8.8--20210426--001

打开 config/module-lite.sh文件。修改以下内容

注释掉这两行:

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

增加:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=eac3_core"

# 增加 https 协议支持(可选)
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=https"

升级openssl版本(增加 https 协议支持的可用)

到 bilibili fork 的 openssl 项目中的 releases 查看当前支持的最新版本。

打开 init-ios-openssl.sh文件,修改 IJK_OPENSSL_COMMIT。例如

IJK_OPENSSL_COMMIT=OpenSSL_1_0_2u

iOS需要播放加密的m3u8文件,后台把每个ts地址进行加密,客户端进行解密后播放。

打开 config/module-lite.sh文件。修改以下内容

修改:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=crypto",支持crypto协议.

2. 下载ffmpeg

 cd ijkplayer
 git checkout -B latest k0.8.8
 ./init-ios.sh
 # 增加 https 协议支持(可选)
 ./init-ios-openssl.sh

注意:此过程会比较慢,下载完成之后在iOS的目录下则会出现ffmpeg文件。这时候我们的 ffmpeg就下载好了,此时再次运行IJKMediaDemo发现还是报错,因为执行init-ios.sh,只是下载ffmpeg源码,但是源码并没有参与编译,需要把源码编译成.a文件:

image.png

3. 编译ffmpeg

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

image.png

增加 https 协议支持(可选)

# 增加 https 协议支持(可选)
./compile-openssl.sh clean
./compile-openssl.sh all

打开IJKMediaFramework,如果没有下图的两个静态库,添加libcrypto.a和libssl.a这两个文件。

image.png

注意:1. 执行 ./compile-ffmpeg.sh clean ,目的是删除一些文件和文件夹,为编译ffmpeg.sh做准备,在编译ffmpeg.sh的时候,会自动创建刚刚删除的那些文件,为避免文件名冲突,因此在编译ffmpeg.sh之前先删除等会会自动创建的文件夹或文件
2. 执行 ./compile-ffmpeg.sh all 目的是编译各个平台的ffmpeg库,并生成所以平台的通用库。
3. 如果遇到此问题,表示不支持armv7:

  • 解决办法:
    • 打开ios目录下这个compile-ffmpeg.sh文件
    • 第24行 改为:FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"
    • 第120行 改为:if [ "$FF_TARGET" = "armv7s" -o "$FF_TARGET" = "arm64" ]; then
    • 第159行 改为:echo " compile-ffmpeg.sh arm64|i386|x86_64"
    • 再次执行./compile-ffmpeg.sh clean./compile-ffmpeg.sh all即可

4. 打包ijkplayer

通过以上3步,IJKMediaDemo已经可以运行了,接下来就可以将ijkplayer进行静态库打包了。 打开下图工程,打包静态库,具体可参考我的文章iOS打包静态库framework中的第七步即可。

image.png

5. Xcode 13 在打开IJKMediaPlayer时没有Products,解决方案如下:

  • 首先找到IJKMediaPlayer.xcodeproj双击显示包内容

WeChat7d7c474a21d40fb44f6e93dec71884db.png

  • 双击打开project.pbxproj,搜索 mainGroup,可以看到。mainGroup的值和productRefGroup的值不一样,将mainGroup的值替换掉productRefGroup的值即可显示Products文件

6. 真机command+B时报错 The linked library 'libavcodec.a' is missing one or more architectures required by this target: 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))

WeChate78418f8e75b26037e1d4f5f2097dee1.png

7. 解决硬解码解码m3u8格式视频,部分手机切换后台,进入前台,画面暂停,有声音,日志recovery error!!!!

  • 本人是使用IJKVideoToolBoxSync.m (注:上面链接解决方案中IJKVideoToolBox.m没有static int decode_video方法)中如下方法
static int decode_video(VideoToolBoxContext* context, AVCodecContext *avctx, AVPacket *avpkt, int* got_picture_ptr)
添加了下面这一句解决了问题
context->idr_based_identified = false

WeChat8002e303f034e85371026f1d5549f55b.png

8. 补充:IJKPlayer可以支持硬解码H265格式的视频

以下在IJKVideoToolBoxAsync.mIJKVideoToolBoxSync.m中操作

  1. 中注释掉vtbformat_init中的如下方法(我的默认是注释的)
//if (!validate_avcC_spc(extradata, extrasize, &fmt_desc->max_ref_frames, &sps_level, &sps_profile)) {
      //goto failed;
//}
  1. ff_isom_write_avcc替换方法如下
 //ff_isom_write_avcc(pb, extradata, extrasize);
 
 if (codec == AV_CODEC_ID_HEVC) {
 //hvcc isom is different from avcc'
    ff_isom_write_hvcc(pb, extradata, extrasize, 1); 
 } else {
    ff_isom_write_avcc(pb, extradata, extrasize);
 }
  1. 以上方法调整完后ff_isom_write_hvcc方法是报错的,需打开
    3.1 ijkplayer -ios-extra-ffmpeg-libavformat-Makefile文件 "HEADERS =" 加入 "hevc.h \ " “OBJS =” 中加入"hevc.o \ "
    3.2 ijkplayer -ios-ios-arm64-libavformat-Makefile文件
    "HEADERS =" 加入 "hevc.h \ " “OBJS =” 中加入"hevc.o \ "

  2. 再次编译并重新打包(编译时ff_isom_write_hvcc可能依然报错,此时需要在IJKVideoToolBoxAsync.mIJKVideoToolBoxSync.m中添加头文件#include "libavformat/hevc.h"

  cd iOS

  ./compile-ffmpeg.sh clean

  ./compile-ffmpeg.sh all
  1. 有人发现解H265数据时,如果带有HEVC_NAL_AUD帧会导致videotoolbox解码失败。有问题的朋友可排查一下

  2. 其他问题的朋友一起交流。

参考文章
1.ijkplayer iOS打包,支持HTTPS,升级ffmpeg4.0
2. IJKPlayer FFmpeg 4.x 编译
3. # 解决ijkplayer在iOS H265硬解码失败问题