专栏首页用户4669341的专栏IOS 下实现一对一直播平台系统 libRtmp 推拉流
原创

IOS 下实现一对一直播平台系统 libRtmp 推拉流

前言

今天向大家介绍一下如何使用 librtmp 库推拉音视频直播流。虽然Adobe已经宣布不在维护 flash 了,但 flash使用的 rtmp 协议目前仍然是直播系统中最常用的传输协议。

目前实现 rtmp 协议的有很多库,但在众多 rtmp 协议的实现中,librtmp 无疑是最好的一个。

今天我们就向大家介绍一下,如何在 iOS 中使用 librtmp。

交叉编译 librtmp

在开发移动端程序时,我们都会用到交叉编译。那么什么是交叉编译呢?交叉编译就是指在一种 CPU类型/操作系统 的机子上编译出另一种 CPU类型/操作系统 的机子上可以运行的程序就称为交叉编译。

以 iOS 为例,我们在 Mac 环境上(CPU类型为 Intel)编译出 iPhone 手机(CPU类型为 ARM)可执行的程序。这个工作我们几乎每天都在做,只是大家没有观注而已。

同样,我们想在 iOS 程序中使用 librtmp 库,就必须先将 librtmp 编译成 ARM 架构 的可执行的程序(也就是 iPhone 手机可执行的程序),这样才能在 iOS 程序中使用它。

Xcode 为我们提供了交叉编译的工具。可以通过 xcode-select --print-path 可获取交叉编译工具目录,在该目录的 user/bin 下就可以找到交叉编译的工具。最主要的两个工具是 gcc 编译器和 ld 链接器。

下面我们来详细介绍一下 gcc 及 ld 参数的含义:

  • isysroot: 指定目标机SDK位置,也就是iPhone手机开发SDK的位置。
  • arch: 指定目标机 CPU 架构。
  • miphoneos-version-min: 指定可用的操作系统最小版本。
  • fembed-bitcode: 苹果自带的参数。从 iOS7.0 开始支持。有兴趣的同学在线上查一上资料吧。

下面是编译 librtmp 的部分关键脚本:

DEVELOPER=$(xcode-select --print-path)

SDK_VERSION=$(xcrun -sdk iphoneos --show-sdk-version)
echo $SDK_VERSION
SDK_VERSION_MIN=7.0

DEVICE_PLATFORM="${DEVELOPER}/Platforms/iPhoneOS.platform"
SIMULATOR_PLATFORM="${DEVELOPER}/Platforms/iPhoneSimulator.platform"
DEVICE_SDK="${DEVICE_PLATFORM}/Developer/SDKs/iPhoneOS${SDK_VERSION}.sdk"
SIMULATOR_SDK="${SIMULATOR_PLATFORM}/Developer/SDKs/iPhoneSimulator${SDK_VERSION}.sdk"

...

CROSS_COMPILE="${DEVELOPER}/usr/bin/" \
XCFLAGS="-g -O2 -isysroot ${SDK} -I${IOS_OPENSSL}/include -arch $ARCH -miphoneos-version-min=${SDK_VERSION_MIN} -fembed-bitcode" \
XLDFLAGS="-isysroot ${SDK} -arch $ARCH -L${IOS_OPENSSL}/lib -lssl" \
make SYS=darwin

make SYS=darwin prefix="/tmp/librtmp-$ARCH" install &> "/tmp/librtmp-$ARCH.log"

执行该脚本后,它就指定好了做交叉编译的编译器及链接器。并指定好了编译参数和链接参数。最后,Makefile 会使用指定的编译器对代码进行编译,生成可以在iPhone上运行的程序。

使用 librtmp 拉流

使用 librtmp 接流的基本步骤:

  1. 分配 RTMP 对象,并初始化 RTMP *rtmp=RTMP_Alloc(); RTMP_Init(rtmp);
  2. 设置 rtmp URL RTMP_SetupURL(rtmp,"rtmp://live.hkstv.hk.lxdns.com/live/hks")
  3. 设置缓冲区大小 //1hour RTMP_SetBufferMS(rtmp, 3600*1000);
  4. 连接流媒体服务器 ... RTMP_Connect(rtmp,NULL) ... RTMP_ConnectStream(rtmp,0) ...
  5. 拉流 while((nRead=RTMP_Read(rtmp,buf,bufsize)) > 0 { ... }
  6. 关闭连接 RTMP_Close(rtmp); RTMP_Free(rtmp);

librtmp 推流

使用 librtmp 推流与拉流的流程差不多。刚开始时也是分配并初始化 RTMP, 只是在连接流媒体服务器时需要打开写开关。代码如下:

//if unable,the AMF command would be 'play' instead of 'publish'
RTMP_EnableWrite(rtmp);

if (!RTMP_Connect(rtmp,NULL)){
    ...
}

if (!RTMP_ConnectStream(rtmp,0)){
    ...
}

连接到流媒体服务器后,设置并初始化 RTMPPacket,RTMPPacket 里边存放要发送的数据包。代码如下:

packet=(RTMPPacket*)malloc(sizeof(RTMPPacket));
RTMPPacket_Alloc(packet,1024*64);
RTMPPacket_Reset(packet);

packet->m_hasAbsTimestamp = 0;
packet->m_nChannel = 0x04;
packet->m_nInfoField2 = rtmp->m_stream_id;

下面开始将 FLV 文件推到流媒体服务器上。首先,跳过 FLV 头。

//jump over FLV Header
fseek(fp,9,SEEK_SET);

FLV 文件格式是由 FLV Header + FLV Body组成的。其中 FLV Header一共 9 个字节。FLV Body 由 Tag Header + Tag Body 组成。

然后,在一个 while 循环中不停的分析Tag,从 Tag Header 和 Tag Body中取出数据,构造好 RTMPPacket 后 push 到流媒体服务器。

...

if(fread(packet->m_body,1,datalength,fp)!=datalength)
    break;

packet->m_headerType = RTMP_PACKET_SIZE_LARGE;
packet->m_nTimeStamp = timestamp;
packet->m_packetType = type;
packet->m_nBodySize  = datalength;
pre_frame_time=timestamp;

if (!RTMP_IsConnected(rtmp)){
  ...
}
if (!RTMP_SendPacket(rtmp,packet,0)){
  ...
}

...

最后,将 flv 文件全部推送到媒体服务器后,关闭 rtmp 连接。

小结

本文首先介绍了如何在 Mac 上编译出可以在 iOS 上可运行的 librtmp 库,然后介绍了如何从流媒体服务器上拉流,最后介绍了如何使用 librtmp 将 flv 文件推送到流媒体服务器上。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • IOS开发:一对一直播系统中视频录制切换前后摄像头后方向错误解决办法

    最近发现项目里,切换前后摄像头几次之后,会出现录制的视频方向上下颠倒,可是明明已经在切换摄像头后,给videoconnection重新设置了录制方向,我项目视频...

    布谷鸟网络科技
  • 解析视频直播平台源码中对-世界杯超大规模场景下的码率控制

    在本月的重庆云栖大会飞天技术汇专场中,阿里云高级算法专家黄海宇分享了题为《超大规模直播码率控制》的议题,从生产的链路角度来说世界杯怎么让观众看到更加清晰的视频。

    布谷鸟网络科技
  • 分析一下H5直播、微信直播、抓玩偶、低延时的方案

    1,基于hls切片直播,前前是应用的主流,服务器可以选fms,wowza,nginx,srs之类

    布谷鸟网络科技
  • Android RTMP推流之MediaCodec硬编码二(RTMPDump推流)

    在前面的两篇文章中:Android RTMP推流之MediaCodec硬编码一(H.264进行flv封装)介绍了如何MediaCodec进行H264硬编码,然后...

    用户2929716
  • Android平台下RTMPDump的使用简介

    RTMPDump是一个用来处理RTMP流媒体的工具包,是一个C++的开源工程。而我们需要将Android平台下直接使用RTMPDump来进行RTMP推流,这里就...

    用户2929716
  • 一日一技:炸掉你的内存—— itertools.tee 的缺陷

    在上一篇文章中,我们讲到了,使用itertools.tee可以让一个生成器被多次完整遍历:

    青南
  • (翻译)LearnVSXNow! #11- 测试package

    在前面的文章里,当我们创建package的时候,总是在向导那里勾掉测试选项,从而不采用自动测试的方式,只是手动的测试它:把package运行起来,并且...

    明年我18
  • TiKV源码解析系列文章(十五)表达式计算框架

    上一篇 《TiKV 源码解析系列文章(十四)Coprocessor 概览》讲到了 TiDB 为了最大化利用分布式计算能力,会尽量将 Selection 算子、聚...

    CNCF
  • 出行大数据:金融人5点下班,互联网人你们颤抖了吗

    近期,滴滴联合几大数据机构发布了一份《中国智能出行2015大数据报告》,这份报告显示,截止到2015年底,中国智能出行平台(包含除滴滴以外的叫车平台)总共有3...

    灯塔大数据
  • django框架使用mysql报错,及两种解决方法

       error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C...

    用户1558882

扫码关注云+社区

领取腾讯云代金券