前言
最近摊上了视频监控项目,一想到的就是ffmpeg这个Diao炸天的开源框架,但是这么拽的框架也不是一般人能驾驭得了的,还好有一群二班的人(Bilibili)基于ffmpeg封装了IJKPlayer,一样是开源的,但...是这个拽的框架也不是一般人能轻易编译成功的,所以有了三班的我来协助大家一同过五关斩六将来获得IJKMediaFramework.framework。
ijkplayer git网址:https://github.com/Bilibili/ijkplayer.git
附上我编译的framework:链接:IJKPlayer_Framework 密码:gw32
1、战前准备(Homebrew、git、yasm)
Homebrew:简称brew,OSX上必备的软件包管理工具
ruby -e"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
Git:代码管理工具
brew install git
Yasm:输出二进制的汇编器
brew install yasm
备注:如之前已安装过可以忽略,或如下命令检查是否有安装:
$ brew -v
Homebrew 1.7.1
Homebrew/homebrew-core (git revision 0c3af; last commit 2018-08-05)
$ git --version
git version 2.18.0
$ yasm --version
yasm 1.3.0
Compiled on Sep 15 2017.
Copyright (c) 2001-2014 Peter Johnson and other Yasm developers.
Run yasm --license for licensing overview and summary.
2、下载IJKPlayer
1、终端打开要存放ijkplayer项目的目录文件夹,并将代码克隆到本地:
//进入该目录中
$cd ~/文件夹
//克隆项目
$git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
//进入ijkplayer-ios
$cd ijkplayer-ios
//切换分支
$git checkout -B latest k0.8.8
备注:如有Git软件工具“Github、SourceTree”替代,可忽略以上命令
2、正常情况如下:
$ git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios
Cloning into 'ijkplayer-ios'...
remote: Counting objects: 24677, done.
Receiving objects: 100% (24677/24677), 7.81 MiB | 5.00 KiB/s, done.
remote: Total 24677 (delta 0), reused 0 (delta 0), pack-reused 24677
Resolving deltas: 100% (15703/15703), done.
$ cd /ijkplayer-ios
wangtingxiedeMacBook-Pro:ijkplayer-ios wangtingxie$ git checkout -B latest k0.8.8
Switched to a new branch 'latest'
3、配置支持RTSP
1、修改module-lite.sh文件
目录:~/config/module-lite.sh 将这一行:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=rtp"
修改为:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp"
接着在下面添加上:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=tcp"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mjpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl" (不需要https请忽略)
2、模块选择
//进入ijkplayer / config 目录
$ cd config
//移除module.sh文件
$ rm module.sh
//替换模块
$ ln -s module-lite.sh module.sh
备注:可根据具体情况加载模块:
偏好更多的解码器/视频格式支持, 则链接module-default.sh
偏好打包出来的库体积更小 (默认格式支持), 则链接module-lite.sh
偏好打包出来的库体积更小 (包含HEVC支持), 则链接module-lite-hevc.sh
3、修改ff_ffplay.c文件
目录:~/ijkmedia/ijkplayer/ff_ffplay 将这一方法:
static int packet_queue_get_or_buffering(FFPlayer *ffp, PacketQueue *q, AVPacket *pkt, int *serial, int *finished)
{
assert(finished);
if (!ffp->packet_buffering)
return packet_queue_get(q, pkt, 1, serial);
while (1) {
int new_packet = packet_queue_get(q, pkt, 0, serial);
if (new_packet < 0)
return -1;
else if (new_packet == 0) {
if (q->is_buffer_indicator && !*finished)
ffp_toggle_buffering(ffp, 1);
new_packet = packet_queue_get(q, pkt, 1, serial);
if (new_packet < 0)
return -1;
}
if (*finished == *serial) {
av_packet_unref(pkt);
continue;
}
else
break;
}
return 1;
}
修改为:
static int packet_queue_get_or_buffering(FFPlayer *ffp, PacketQueue *q, AVPacket *pkt, int *serial, int *finished){
if (!ffp->packet_buffering)
return packet_queue_get(q, pkt, 1, serial);
while (1) {
int new_packet = packet_queue_get(q, pkt, 1, serial);
if (new_packet < 0){
new_packet = packet_queue_get(q, pkt, 0, serial);
if(new_packet < 0)
return -1;
}else if (new_packet == 0) {
if (q->is_buffer_indicator && !*finished)
ffp_toggle_buffering(ffp, 1);
new_packet = packet_queue_get(q, pkt, 1, serial);
if (new_packet < 0)
return -1;
}
if (*finished == *serial) {
av_packet_unref(pkt);
continue;
}
else
break;
}
return 1;
}
4、下载ffmpeg并编译
1、执行ijkplayer目录下初始化ios脚本
$ ./init-ios.sh
$ ./init-ios-openssl.sh (不需要https请忽略openssl)
备注:ffmpeg比较大,而且又是国外网络,脚本运行需要一点时间,遇到失败需要多试几次, 等待操作完成, 再继续
2、编译ffmpeg
$ cd ios
$ ./compile-ffmpeg.sh clean
$ ./compile-openssl.sh all (不需要https请忽略openssl)
$ ./compile-ffmpeg.sh all
3、解决遇到的错误
错误1:
xcrun -sdk iphoneos clang is unable to create an executable file.
C compiler test failed.
If you think configure made a mistake, make sure you are using the latest
version from Git. If the latest version fails, report the problem to the
ffmpeg-user@ffmpeg.org mailing list or IRC #ffmpeg on irc.freenode.net.
Include the log file "ffbuild/config.log" produced by configure as this will help
solve the problem.
解决方法:sudo xcode-select --switch /Applications/Xcode.app/Contents/Developer/
错误2:
AS libavcodec/arm/aacpsdsp_neon.o
./libavutil/arm/asm.S:50:9: error: unknown directive
.arch armv7-a
^
make: *** [libavcodec/arm/aacpsdsp_neon.o] Error 1
make: *** Waiting for unfinished jobs....原因:最新的 Xcode 已经弱化了对 32 位的支持。
解决方法:修改./compile-ffmpeg.sh文件,
将这一行:FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"
修改为:FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"
再重新执行出现错误的命令: ./compile-ffmpeg.sh all
错误3:'openssl/ssl.h' file not found
#include <openssl/ssl.h> ERROR: openssl not found原因:编译ffmpeg软解码库,这个过程会生成各种架构的ffmpeg,编译ffmpeg前要先compile OpenSSL,对openssl进行编译,如果未执行可能会报错。必须先执行./compile-openssl.sh all
因为兼容指令集比较多,编译会比较慢一点,我们也可以只编译一个指令集版本(便于调试)
$ ./compile-ffmpeg.sh all x86_64
5、打包 framwork并合并
大家会发现除了IJKMediaFramework这个 target, 还有一个叫IJKMediaFrameworkWithSSL, 但是不推荐使用这个, 因为大部分基于 ijkplayer 的第三方框架都是使用的前者, 你把后者导入项目还是会报找不到包的错误, 就算你要支持 https 也推荐使用前者, 然后按照上一步添加 openssl 即可支持
1、配置 Release 模式如下图
2、打包真机 framework
选择Generic iOS Device
如图操作,然后按键command+b编译即可
如果之前的步骤删除了compile-ffmpeg.sh中armv7, 这里会报错, 我们直接注释掉就好
3、打包模拟器 framework
如图操作,然后command+b编译即可
4、合并 framework
如果只需要真机运行或者模拟器运行, 可以不用合并, 直接找到对应的 framework 导入项目即可; 一般我们为了方便会合并 framework, 这样就同时支持模拟器和真机运行.
先找到生成 framework 的目录:
准备合并:
打开终端, 先cd到Products目录下
然后执行:lipo -create 真机framework路径 模拟器framework路径 -output 合并的文件路径
lipo -create Release-iphoneos/IJKMediaFramework.framework/IJKMediaFramework Release-iphonesimulator/IJKMediaFramework.framework/IJKMediaFramework -output IJKMediaFramework
合并完成:
可以看到这里生成了一个大概两倍大小的文件, 将生成的IJKMediaFramework文件替换掉真机framework中的IJKMediaFramework文件,然后这个替换掉文件的真机framework就是我们需要的通用的framework了。
6、集成 framework 到项目中
导入 framework
直接将IJKMediaFramework.framework拖入到工程中即可
注意记得勾选Copy items if needed和 对应的target
7、添加下列依赖到工程
libc++.tbd( 编译器选 gcc 的请导入libstdc++.tbd)
libz.tbd
libbz2.tbd
AudioToolbox.framework
UIKit.framework
CoreGraphics.framework
AVFoundation.framework
CoreMedia.framework
CoreVideo.framework
MediaPlayer.framework
MobileCoreServices.framework
OpenGLES.framework
QuartzCore.framework
VideoToolbox.framework
导入 ijkplayer 头文件运行一下项目, 如果遇到了类似这样的错误:
可能是因为导入的依赖库不全, 比如缺少 libc++.tbd, 请再次对照添加好所有的依赖库:
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"