前面已经介绍了RTMP推流的整个流程,今天我们再来梳理一下拉流端以及播放的整个过程。
我们先来看一下拉流端整个流程的抓包数据,然后分析一下每一个数据包的具体内容。
从上面的抓包数据可以看出,和推流端的整个流程基本上是一致的,只是在connect结束之后有一点不一样的操作,推流端是发送publish命令,而拉流端发送的是play命令。
play
既然如此,那其他的数据包我在这里就不再一一分析,可以参考我之前写的推流详解这篇博客,现在我主要来解析一样play这个命令。
结合下面的代码来说明一下
|
|
其实和publish命令差不多的 ,只是将关键字改为 play.
SetBufferTime
代码如下
|
|
在收到play的回调消息,我们还需要设置一下发送时间,这一句很重要哦,设置不成功或者不设置的话服务器是不会给你推音视频的数据的。
视频流的解析
ok 现在我们开始收到源源不断的视频流数据,那么我们怎么把他们解析成原始的数据格式播放出来呢,下面来分析一下这个过程。
如上图,我们先来看一下一帧视频流数据长啥样吧。
首先是头部信息,在rtmp格式中已经详细的分析了,这里不再介绍。
重点来看一下Body中的数据:
Control : 0x17(keyframe H.264)
这个0X17是个啥呢,如果还记得推流时我们怎么封装数据的应该对这个有印象
|
|
就是这行代码所表示的数据了。
通过这个数据,我们就能分析当前帧是不是关键帧,需不需要解析里面的SPS和PPS信息。
video data
这个里面就是我们想要的视频数据了,但是又并不全是我们想要的视频数据,因为我们在推流封装的时候,是根据AVC格式来,所以其实这个body data里面还有一部分AVC的数据,我们需要把这一部分的数据剔除掉,剩下的才是我们需要的原始的视频流数据(好复杂的感觉有木有)。
先把代码贴上来
|
|
从最上面开始分析
packetBuffer 即为上图中的RTMP Body数据,注意这里是剔除了RTMP Head的哦。
怎么剔除Head可以参考我的demo中下面这个方法。
|
|
|
|
然后我们取出Control信息 它可能包括0x17或者是0x27,其中17是关键帧,27不是关键帧。
|
|
然后是AVCType字段。
如果Type = 0 ,我们需要取出的是SPS和PPS信息,如果没有这部分信息是无法将H.264文件解码的。
当Type = 1,我们获取当前avc的NALU单元信息,这个数据就是我们需要显示的视频数据了。
然后我把取到的数据用下面方法解码为CVPixelBufferRef数据进行显示(播放)。
|
|
播放
这里我用的是苹果官网给的一个类AAPLEAGLLayer。