EasyDarwin源码分析(三)——rtsp-client

rtsp-client.go

这个模块主要实现了客户端的拉流功能。也就是在网页上点击“拉流分发”按钮后,easydarwin会向用户填写的源地址拉流,然后再转发出去,在向源地址拉流的时候,easydarwin相当于是一个rtsp客户端。所以这里使用rtsp-client.go。

EasyDarwin中有两个模块分别是rtsp-server和rtsp-client,rtsp-server分析见:rtsp-server源码分析
乍一看这两个模块,一个server一个cilent,好像正好是一对服务器和客户端,其实两者关系不大,各自完成不同的功能。
rtsp-server是EasyDarwin提供rtsp服务,监听554端口(默认)。而rtsp-client的作用是主动向某个音视频源地址进行拉流,在拉流的过程中充当客户端的角色,所以叫client。

这个功能的开始是从网页上点击“拉流分发”开始的,这么说其实并不是完全正确,因为前端点击“拉流分发”后是向后端发送了一个http请求,你从别的地方发这个请求也是可以的。所以我们从接收http请求开始讲起。

routers/routers.go

routers.go主要就是用来接收前端发来的请求,这里使用的是第三方包gin,其实主要看以下代码就行。第一行Group,对请求做了一个分组,也就是api接收的请求都是/api/v1/xxx形式的。

下面就是具体的请求,第一个参数:请求路径,第二个参数:处理这个请求的函数。

“拉流分发”处理的请求是/stream/start
在这里插入图片描述

请添加图片描述

首先定义一个结构体,用来接收前端发来的数据。

请添加图片描述

给这个client创建一个pusher,当easydarwin作为一个客户端向第三方源拉流后,得把这个媒体流再次转发出去,供用户拉取,所以这里的pusher(推流者),就是将client拉取到的流转发、再次推送出去。

请添加图片描述

client.Start(),启动这个向第三方源拉流的rtsp客户端。
将上面new的pusher添加到rtsp-server的pusher队列中。
在client成功从第三方源拉到媒体流后,会将这些媒体流数据添加到pusher中,等待用户来拉取。

下面分析刚才提到的那些函数(在rtsp/rtsp-client.go中)

NewRTSPClient()

请添加图片描述

函数的主体部分就是对RTSPClient的实例化。RTSPClient结构体如下(部分)

请添加图片描述

client.Start()

请添加图片描述

可以看到Start()函数里面主要就调用了另外两个方法。requestStream()主要负责RTSP命令交互,startStream()负责媒体流的收发(rtp)

requestStream()

请添加图片描述

首先解析客户端的URL,我在这里打了个断点,当我在页面上点击拉流分发、输入好摄像头源地址等信息,最后点击确定时,到达此断点。
这里的client.URL是摄像头的源地址。url.Parse对这个地址进行了解析,这是一个工具包,返回的 l 不是一个字符串而是一个结构体。如下

在这里插入图片描述
在这里插入图片描述
请添加图片描述

建立Tcp连接,准备进行命令交互。为客户端client创建Reader和Writer,用来读写连接conn中的数据。

请添加图片描述

发送OPTIONS请求,这里的Request()是一个封装好的,用于RTSP命令交互的接口,该接口发送报文,并且接受响应。两个返回值,分别是RTSP响应和错误,在代码里,每一个请求都判断了错误。

请添加图片描述

发送DESCRIBE请求,并接受响应。使用第三方包解析响应中的SDP信息。

请添加图片描述

在一般情况下,视频和音频各有一个媒体流。上面的代码根据客户端使用TCP/UDP来给首部字段的"Transport"字段赋值。

请添加图片描述

然后发送SETUP请求:

请添加图片描述

最后发送发送PLAY命令

startStream()

请添加图片描述

初始化,这里的OptionIntervalMillis是心跳间隔,如果设置了这个值,则以这个值为周期,定时发送OPTIONS请求。

请添加图片描述

connRW是之前已经初始化的读写器

ReadByte()函数:读取一个字节。如果是 0×24 ,则是rtp数据,不然就是rtsp命令。
如果看了之前的rtsp-server源码分析会发现很眼熟,没错,他把处理rtsp命令和rtp包的代码,在这里又写了一遍,也就是说通过ffmpeg推来的流,和easydarwin通过rtsp-client主动去拉的流,虽然这些都是音视频流,但是在代码里却在不同的模块里分别处理了(但是代码内容基本相似),并没有使用同一份代码。

请添加图片描述

请添加图片描述

这里是RTP包的解析过程,可以看到,首先收取一个包的长度,然后根据这个长度,接收完成所有的一整包。再去解析包的内容,最后将包回调出去。RTP包有四种类型,VIDEO、AUDIO、VIDEOCONTROL、AUDIOCONTROL,这些类型通过channel来区分开来。

最后处理这些pack的是RTPHandles,详解:EasyDarwin源码分析(四)—— RTPHandles

非RTP数据包的接收,就比较简单了。由于RTSP是文本协议,逐行读取文本,直到读出一个长度为0的行。同时判断是否包括Content-Length, 如果有的话,再读取Content-Length长度的数据包。否则接收完成。

总结:

在用EasyDarwin之前就知道他就是一个流媒体服务器,在分析完rtsp-client和rtsp-server之后,我们可以总结他的功能为“拉转推”和“收转推”,也就是一个是主动拉流(使用rtsp-client),一个是被动接收流再转推出去(使用rtsp-server和rtsp-session)。

当初学习这一部分时一篇很重要的文章:EasyDarwinGo拉转推功能之拉流

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值