iOS IJKPlayer 项目集成(支持RTSP,支持https)

前言

最近摊上了视频监控项目,一想到的就是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

[email protected] 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 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 模式如下图

iOS IJKPlayer 项目集成(支持RTSP,支持https)_第1张图片
配置 Release 模式1
iOS IJKPlayer 项目集成(支持RTSP,支持https)_第2张图片
配置 Release 模式2



2、打包真机 framework

选择Generic iOS Device

编译真机

如图操作,然后按键command+b编译即可

如果之前的步骤删除了compile-ffmpeg.sh中armv7, 这里会报错, 我们直接注释掉就好

iOS IJKPlayer 项目集成(支持RTSP,支持https)_第3张图片
armv7错误
iOS IJKPlayer 项目集成(支持RTSP,支持https)_第4张图片
armv7错误

3、打包模拟器 framework

iOS IJKPlayer 项目集成(支持RTSP,支持https)_第5张图片
编译模拟器

如图操作,然后command+b编译即可

4、合并 framework

如果只需要真机运行或者模拟器运行, 可以不用合并, 直接找到对应的 framework 导入项目即可; 一般我们为了方便会合并 framework, 这样就同时支持模拟器和真机运行.

先找到生成 framework 的目录:

iOS IJKPlayer 项目集成(支持RTSP,支持https)_第6张图片
文件路径
iOS IJKPlayer 项目集成(支持RTSP,支持https)_第7张图片
文件路径

准备合并:

打开终端, 先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了。

iOS IJKPlayer 项目集成(支持RTSP,支持https)_第8张图片
合并


iOS IJKPlayer 项目集成(支持RTSP,支持https)_第9张图片
合并完成

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 头文件运行一下项目, 如果遇到了类似这样的错误:

iOS IJKPlayer 项目集成(支持RTSP,支持https)_第10张图片
导入错误

可能是因为导入的依赖库不全, 比如缺少 libc++.tbd, 请再次对照添加好所有的依赖库:

iOS IJKPlayer 项目集成(支持RTSP,支持https)_第11张图片
依赖库


export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"

你可能感兴趣的:(iOS IJKPlayer 项目集成(支持RTSP,支持https))