接入IPC已经有教程了 国产开源流媒体SRS4.0对视频监控GB28181的支持,下面的截图里也截取了摄像头端的配置。
SRS国标国标模块参考这个帮助文档理解 srs_code_note/srs_gb28181.md at master · xialixin/srs_code_note · GitHub
国标属于应用层协议,可以理解为A手里拿了一个视频流,B想要看A的视频,所以B肯定要让A把视频流传给自己,说话的过程就是sip交互过程,播放的过程就是媒体传输过程。
这些信令有的是自动执行的,也可以通过SRS-GB28181 API的方式调用,没什么区别。
理解一下配置参数
killall -9 srs
./objs/srs -c conf/push.gb28181.conf # daemon off;
tail -f ./objs/srs.log # 打印日志
http://192.168.10.44:8080/live/[email protected]
这里比较奇怪的就是播放地址,按道理NVR的播放地址应该是两个不同的国标编码拼接的。
奇怪的是就是开始播放了一会儿,后面就没有再切片了,就是./objs/nginx/html/live/目录下的切片没有变化 这是为什么呢?
群里有同学说:摄像头每次启动几十秒不能播放的问题我知道原因了,摄像头网络不稳定导致偶尔会断2秒,媒体通道超时关闭。后续发送的rtp数据中不包含ssrc的值,导致srs不能通过ssrc进行分包,所以就不能播放了。
打开接口调用前端页面 http://192.168.10.44:8080/players/srs_gb28181.html
按道理invite设备推流后,device就应该向srs的接收流端口发送rtp视频流数据了,然后srs应该把rtp数据再转换为hls数据,然后显示invite成功,但是并没有hls数据,显现如下截图:
一头雾水,还是从开始抓包吧。调试流程图如下图所示:
ip.src==192.168.10.71 or ip.dst==192.168.10.71 or ip.src==192.168.10.44 or ip.dst==192.168.10.44 and sip
ip.src==192.168.10.71 or ip.dst==192.168.10.71
用这个,因为Ubuntu是虚拟机,所以虚拟机还会和Windows主机有网络交互,所以我们只考虑实际的NVR的收发数据包
从头开始抓包,重新开启NVR的国标,就是NVR端取消勾选启用国标平台接入方式,然后再打开:
观察wireshark抓到的数据包,可以发现很多其他协议的数据包,所以都过滤掉,所以又得到一个更新过的抓包规则:
ip.src==192.168.10.71 or ip.dst==192.168.10.71 and !(ip.dst==239.255.255.250) and !(ip.dst==255.255.255.255) and !(ip.src==192.168.10.10) and !(ip.dst==192.168.10.10)
开启国标开始抓包:
等待设备重启完成,观察后续的抓包,可以发现Destination那里多了几个无关的ip地址,应该是NVR国标服务器程序的其他网络操作,过滤掉,具体的ip地址根据不同的实验环境而定:
ip.src==192.168.10.71 or ip.dst==192.168.10.71 and !(ip.dst==239.255.255.250) and !(ip.dst==255.255.255.255) and !(ip.src==192.168.10.10) and !(ip.dst==192.168.10.10) and !(ip.dst==224.0.0.22) and !(ip.dst==224.0.0.251)
我们登录 SRS-GB28181 WEB DEMO http://192.168.10.44:8080/players/srs_gb28181.html 看下状态吧
下面来调用请求推流接口,也就是向设备放松INVITE的数据包,按道理向9000端口推流后就应该能播放了,所以还是要抓下推流部分的数据包
但是并没有发现有rtp数据包???
参考这个 NodeJS版本基于GB28181的HTTP网关: NodeJS版本基于GB28181的HTTP网关,实现浏览器播放GB28181设备视频功能。
安防GB28181学习笔记1 SIP协议简介 把这篇博客读一下,其中有这样一副图,所以感觉应该是要建立媒体通道的意思:
但实际还是不能播放,主要是wireshark没看到媒体数据的收发:
从抓包的角度看,就是没有抓到视频流数据,因为之前单独接摄像头是可以播放的,所以现在回到单个摄像头,把NVR的国标停了,开起192.168.10.5这个IPC的国标:
ip.src==192.168.10.71 or ip.dst==192.168.10.71 and !(ip.dst==239.255.255.250) and !(ip.dst==255.255.255.255) and !(ip.src==192.168.10.10) and !(ip.dst==192.168.10.10) and !(ip.dst==224.0.0.22) and !(ip.dst==224.0.0.251)
改为
ip.src==192.168.10.5 or ip.dst==192.168.10.5 and !(ip.dst==239.255.255.250) and !(ip.dst==255.255.255.255) and !(ip.src==192.168.10.10) and !(ip.dst==192.168.10.10) and !(ip.dst==224.0.0.22) and !(ip.dst==224.0.0.251)
我们邀请拉流下,发现邀请后,IPC就开始发送视频数据到9000端口了:
再理解下推流数据吧:
决定把媒体通道理解下,媒体通道这次是自动生成的:
继续阅读国标博客安防GB28181学习笔记1 SIP协议简介
阅读GB28181学习笔记3 设备注册Server(基于nodejs sip库)
SIP结构
一个合法的SIP请求必须至少包含如下头域:TO,FROM,Cseq,Call-ID,Max-Forwards, Via;这些字段在所有SIP请求中必须包含。这6个字段是SIP消息的基本组成部分,他们提供了用于路由用的核心信息,包含了消息的地址,响应的路由,消息传递次数,详细的顺序,事务的唯一标志。
这些头域字段是必须包含在请求行之后的,请求行包含了请求的方法,Request-URI,SIP的版本号码。请求行例子:REGISTER sip:192.168.10.177:5060 SIP/2.0。
Call-ID: 202060657747
是一个在一系列消息中,区分一组消息的唯一标志。在对话中任一UA的所有请求和所有以后广大的Call-ID必须一致。在UA的每次注册中,都应该是一样的。在会话外的时候,UAC发起一个新的请求,这个Call-ID头域必须由UAC产生一个全局唯一的Call-ID,除非是请求的方法指定了别的产生方法。
阅读GB28181学习笔记6 解析invite命令,详细解释了invite流程
阅读GB28181学习笔记7 媒体流转推rtmp
这是由于GB28181的封包格式是RTP承载PS流。
阅读安防国标学习笔记8 NodeJS实现GB28181信令服务端,这里可以了解到国标架构就是一个信令服务器和一个媒体服务器,所谓信令就是一堆对话。
现在大概理解了国标的所谓流程了,下面我们还是回到NVR吧,看看为什么invite通道失败了:
实在不知道原因的,参考 NVR注册、国标级联接入流程_知识库_视频监控 - 阿里云
实在搞不懂为什么录像机没有推流,单个摄像头是正常的,这怎么搞?
可以看出来海康录像机也返回了响应,接下来应该推流啊,为什么推流通道没有推流呢?
实在搞不定了,不知道啥原因,不过找了一个能用的国标客户端,可以对比来看, 我们再打开一个wireshark进程进行抓包,很快就发现问题所在了:
IPC过滤规则
ip.src==192.168.10.5 or ip.dst==192.168.10.5 and !(ip.dst==239.255.255.250) and !(ip.dst==255.255.255.255) and !(ip.src==192.168.10.10) and !(ip.dst==192.168.10.10) and !(ip.dst==224.0.0.22) and !(ip.dst==224.0.0.251)
NVR过滤规则
ip.src==192.168.10.71 or ip.dst==192.168.10.71 and !(ip.dst==239.255.255.250) and !(ip.dst==255.255.255.255) and !(ip.src==192.168.10.10) and !(ip.dst==192.168.10.10) and !(ip.dst==224.0.0.22) and !(ip.dst==224.0.0.251)
正常过滤规则
ip.src==192.168.10.71 or ip.dst==192.168.10.71 and !(ip.dst==239.255.255.250) and !(ip.dst==255.255.255.255) and !(ip.dst==224.0.0.22) and !(ip.dst==224.0.0.251)
问题的根本就出在invite上面,通过对比我们一共发现了5处不同,我感觉可能是Contact这个问题,为了定位问题,决定使用单步调试:
潜在的断点空间可以用关键词搜索得到:
在VMware+Ubuntu端启动gdbserver
gdbserver localhost:1234 ./objs/srs -c conf/push.gb28181.conf
clion端更新Ubuntu上的srs代码:
clion连接到gdbserver
找下invite请求入口,我们从api入手,因为点击invite后调用的函数就是invite入库函数:
继续找,我们一路跟,可以发现是html->api->gb28181->sip
这个就是我们的断点了:
这个进入断点有点奇怪,好像要打开 Always parallel
clion这个单步调试总是报 Error running 'GDB Remote Debug': Unknown error ,只能每次都重启了,还没发现规律
修改代码,添加字段:
./configure --with-gb28181
make
./objs/srs -c conf/push.gb28181.conf
再次修改代码然后make:
好了这次终于有了