流程
一个流媒体平台主要分为一些几个部分
主要用途:对接监控摄像头、视频直播、多对多视频聊天器
系统架构由三个部分组成:
接口服务器(HTTP服务器)主要用于响应客户端的请求
信令服务器(SIP服务器)主要用于和流媒体服务器和视频设备交互,主要功能是管理摄像头之类的设备以及控制摄像头将视频流转发给流媒体服务器的哪个端口
流媒体服务器主要用于处理视频流的接收、转发和分发
接口服务器和信令服务器可以整合为一个服务器。
流媒体服务器最好单独部署,避免流媒体服务器压力过大,可以用ZLMediaKit代替。我们要开发的就是接口服务器和信令服务器。
实时码流点播采用SPI协议中的INVITE方法实现会话连接,采用RTP/RTCP协议实现媒体传输。
整个播放过程如下:
其通信流程如下:
视频流是怎么推流的
SIP视频流的获取是指解码器(ZLMediaKit)通过SIP协议向GB28181服务器获取视频流的过程
GB28181服务器(也就是SIP服务器)会像摄像头发送一些信令,主要是请求播放实时视频。
开启SIP服务器,服务器将会监听某个端口,可以从这个端口收到SDP信息
摄像机端发送Register消息后,然后服务端应答注册消息代码
SIP服务端响应注册命令后,发送Invite请求,请求catalog信息,也就是设备基本信息
摄像机端收到消息发送其自身的catalog消息,将会服务具体的具体的catalog消息。
SIP服务取都摄像机的信息后就可以发送请求视频信息到摄像头。下面看下SDP信息怎么写
static string createSDP(MediaContext& mediaContext)
{
char str[500] = { 0 };
pj_ansi_snprintf(str, 500,
"v=0\n"
"o=%s 0 0 IN IP4 %s\n"
"s=Play\n"
"c=IN IP4 %s\n"
"t=0 0\n"
"m=video %d RTP/AVP 96 98 97\n"
"a=recvonly\n"
"a=rtpmap:96 PS/90000\n"
"a=rtpmap:98 H264/90000\n"
"a=rtpmap:97 MPEG4/90000\n"
"y=0100000001\n",
mediaContext.GetDeviceId().c_str(),
mediaContext.GetRecvAddress().c_str(),
mediaContext.GetRecvAddress().c_str(),
mediaContext.GetRecvPort()
);
return str;
}
信令交互成功之后,摄像头(媒体流发送者)会将视频数据以rtp的方式推送到指定的端口 (端口在上面的invite消息指定)流到媒体服务器
媒体服务器(GB28181服务器)在指定的端口接收视频流
媒体服务器(GB28181服务器)将视频流转发给流媒体接收者(比如ZLMediaKit)
具体流程如下:
视频流格式
GB28181要求传输的视频流格式为PS流,或者H264流,或者MP4格式。
可以用wireshark抓包,数据报类型是RTP的PS流
国标流媒体服务器其实就是负责将GB28181设备或者平台推送的PS流转成ES流,然后提供RTSP、RTMP、FLV、HLS等格式进⾏分发。
PS流和ES流的区别
IP数据报有⾸部和数据两部分组成的,⾸部的前⼀部
分是固定长度20字节,是所有IP数据报必须具有的。⾸部包括:总长度、标识、MF、DF、⽚偏移。
数字信号实际传送的是数据流,⼀般数据流包括以下三种:
ES流(Elementary Stream):也叫基本码流,包含视频、⾳频或数据的连续码流。
PES流(Packet Elementary Stream):也叫打包的基本码流,是将基本的码流ES流根据需要分成长度不等的数据
包,并加上包头就形成了打包的基本码流PES流。
TS流:也叫传输流,是由固定长度为188字节的包组成,含有独⽴时基的⼀个或多个program, ⼀个program⼜可以包含多个视频、⾳频、和⽂字信息的ES流; 每个ES流会有不同的PID标⽰,为了可以分析这些ES流, TS有⼀些固定的PID⽤来间隔发送program和ES流信息的表格: PAT和PMT表。适⽤于误码较多的环境
ES 是直接从编码器出来的数据流,可以是编码过的视频数据流,⾳频数据流,或其他编码数据流的统称。 ES 流经过PES 打包器之后,被转换成 PES 包,再通过RTSP、RTMP、FLV、HLS格式分发出去,实现WEB、⼿机、PC、微信等多终端的播放
传播方式
GBT28181协议规定码流使用RTP包负载,推荐为PS流,也可以是ES流,对于媒体流的传输在原有UDP传输的基础中,增加了主动tcp和被动tcp的方式。
(1)UDP被动
这个是普遍的传输方式。
GB28181流媒体服务器监听单个UDP端口,然后发送一个SIP信令(INVITE),其携带的SDP中包含了接收媒体的端口
设备端收到信令后,解析该端口,然后设备主动通过UDP向流媒体服务端监听的那个端口上发送视频流
(2)TCP被动
有两种,一种是主动,一种是被动
对于主动: 设备端告知服务端自己的媒体流tcp端口,服务端主动去连接设备端的该端口,获取数据。。这种场景应用较少,可以忽略
对于被动:流媒体服务器监听单个TCP端口,然后通过SIP信令(INVITE)告诉设备端口,设备主动向当前流媒体服务端发送视频流,基本等同于UDP流
实时视频
流程
前提:注册成功>>>>>>心跳成功>>>>>>设备目录查询>>>>>实时视频观看
服务端步骤
不管是TCP方式看,还是UDP方式看,其步骤都为:
(1)打开视频端口
(2)发送实时视频请求
(3)等待设备回复200OK
(4)发送ACK
(5)播放码流
(6)停止视频请求
(7)关闭视频端口
(8)普通等待
抓包分析
测试设备IP:192.168.0.107
服务端IP:192.168.0.60
实时视频建立_UDP
第零步:【服务端】打开视频端口
第一步:【服务端>>客户端】请求播放视频
INVITE sip:34020000001310000002@4401020049 SIP/2.0
Call-ID: helloVideo
CSeq: 1 INVITE
From: <sip:44010200492000000001@4401020049>;tag=bccedfd0111
To: <sip:34020000001110000001@4401020049>
Max-Forwards: 70
Contact: <sip:34020000001310000002@4401020049>
Via: SIP/2.0/UDP 192.168.0.107:5060;branch=z9hG4bKee5c5d98-bff9-4f3000002
Content-Type: application/sdp
Content-Length: 225v=0
o=34020000001310000002 0 0 IN IP4 192.168.0.60
s=Play
c=IN IP4 192.168.0.60
t=0 0
m=video 6000 RTP/AVP 96 98 97
a=recvonly
a=rtpmap:96 PS/90000
a=rtpmap:98 H264/90000
a=rtpmap:97 MPEG4/90000
y=0100000001
f=
第二步:【客户端>>服务端】
先回复101
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.0.107:5060;branch=z9hG4bKee5c5d98-bff9-4f3000002
From: <sip:44010200492000000001@4401020049>;tag=bccedfd0111
To: <sip:34020000001110000001@4401020049>;tag=5f906952
Call-ID: helloVideo
CSeq: 1 INVITE
Server: Happytime Agent Ver 1.0
Content-Length: 0
再回复200
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.107:5060;branch=z9hG4bKee5c5d98-bff9-4f3000002
From: <sip:44010200492000000001@4401020049>;tag=bccedfd0111
To: <sip:34020000001110000001@4401020049>;tag=5f906952
Contact: <sip:34020000001110000001@4401020049>
Call-ID: helloVideo
CSeq: 1 INVITE
Max-Forwards: 70
Allow: ACK,BYE,CANCEL,INVITE,NOTIFY,REFER,UPDATE,INFO
Supported: timer
Session-Expires: 200;refresher=uac
Server: Happytime Agent Ver 1.0
Content-Type: application/sdp
Content-Length: 153v=0
o=34020000001110000001 0 0 IN IP4 192.168.0.107
s=Play
c=IN IP4 192.168.0.107
t=0 0
m=video 19002 RTP/AVP 96
a=rtpmap:96 PS/90000
a=sendonly
第三步:【服务端>>客户端】回复ACK
ACK sip:34020000001310000002@4401020049 SIP/2.0
Call-ID: helloVideo
CSeq: 1 ACK
From: <sip:44010200492000000001@4401020049>;tag=bccedfd0111
To: <sip:34020000001110000001@4401020049>
Max-Forwards: 70
Via: SIP/2.0/UDP 192.168.0.107:5060;branch=z9hG4bKee5c5d98-00003
Content-Length: 0
第四步:播放码流
第五步:【服务端>>客户端】停止视频请求
BYE sip:34020000001310000002@4401020049 SIP/2.0
From: <sip:44010200492000000001@4401020049>;tag=bccedfd0111
To: sip:34020000001110000001@4401020049;tag=5f906952
CSeq: 2 BYE
Call-ID: helloVideo
Via: SIP/2.0/UDP 192.168.0.107:5060;branch=z9hG4bKee5c5d98-00004
Max-Forwards: 70
Content-Length: 0
第六步:【客户端】回应200
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.107:5060;branch=z9hG4bKee5c5d98-00004
From: <sip:44010200492000000001@4401020049>;tag=bccedfd0111
To: sip:34020000001110000001@4401020049;tag=5f906952
Call-ID: helloVideo
CSeq: 2 BYE
Server: Happytime Agent Ver 1.0
Content-Length: 0
第七步:【服务端】关闭视频端口
实时视频建立_TCP
基本要求
信令流程
实时视频流点播的信令流程有两种:
客户端主动发起
第三方呼叫控制
联网系统可选择其中一种或两种结合的实现方式,第三方呼叫控制的第三方控制者宜采用背靠背用户代理实现
客户端主动发起实时音视频点播流程
流程
消息示范
抓包分析
【上级平台】订阅完所有的通道之后,就可以向【下级平台】发送Invite请求流了
INVITE sip:33072752001320080039@10.45.255.10:5060 SIP/2.0
Via: SIP/2.0/UDP 10.45.255.11:5060;rport;branch=z9hG4bK-469C18DE-28C36C5-T07h4NhO
From: <sip:33072700232000002456@3307270023>;tag=573748381
To: <sip:33072752001320080039@10.45.255.10:5060>
Call-ID: 743791906
CSeq: 20 INVITE
Contact: <sip:33072700232000002456@10.45.255.11:5060>
Content-Type: application/sdp
Max-Forwards: 70
User-Agent: videosvr 1.0
Subject: 33072752001320080039:1,33072700232000002456:1
Content-Length: 220v=0
o=33072752001320080039 0 0 IN IP4 10.45.255.11
s=Play // play表示播放
c=IN IP4 10.45.255.11
t=0 0
m=video 31000 RTP/AVP 96 98 97
a=recvonly
a=rtpmap:96 PS/90000
a=rtpmap:98 H264/90000
a=rtpmap:97 MPEG4/90000
y=0727000001
【下级平台也就是(信令服务器)】回应如下:
SIP/2.0 181 Call is being forwarded // 181表示我已经将请求转发给下级了
CSeq: 20 INVITE
Call-ID: 743791906
From: <sip:33072700232000002456@3307270023>;tag=573748381
To: <sip:33072752001320080039@10.45.255.10:5060>
Via: SIP/2.0/UDP 10.45.255.11:5060;rport=5060;branch=z9hG4bK-469C18DE-28C36C5-T07h4NhO;received=10.45.255.11
Content-Length: 0
如何点播
点播的基本流程
HTTP端—>GB28181信令服务器,发起点播请求
GB28181信令服务器—>设备,发起Invite(携带SDP消息体)的请求
设备—>GB28181信令服务器,回复200OK (携带SDP消息体)
GB28181信令服务器—>设备,发送ACK,成功建立一个会话
设备—> 流媒体服务器,发送实时流
流媒体服务器—>GB28181服务器,流改变事件
GB28181服务器—>设备,告知流播放地址
流媒体服务器—>GB28181服务器,无人观看事件
GB28181服务器—>设备,发送Bye消息
设备—>GB28181服务器,回复200OK
点播时可能的错误
(1)400错误
其流程如下:
HTTP端—>GB28181信令服务器,发起点播请求
GB28181信令服务器—>设备,发起Invite(携带SDP消息体)的请求
设备—>GB28181信令服务器,回复400OK (携带SDP消息体)
什么原因:
设备认为信令服务器发送了错误的消息给它,可能是消息不全或者错误,因此直接返回400
怎么解决:
抓包
直接联系设备/平台客服寻求解决
(2)500错误
什么原因:
500<= code <= 600的错误码,一般是设备内部出了问题
怎么解决:
怎么解决:
抓包
直接联系设备/平台客服寻求解决
点播时超时
点播超时的原因大致分为两种:点播超时和收流超时。
(1)点播超时
发生在哪里?
点播超时一般是因为信令超时,可能出现在“设备—>GB28181信令服务器,回复200OK (携带SDP消息体)”这一步,即我们发送了点播消息,但是设备没有回复。
可能的原因:
设备内部错误,没能回复消息
网络原因消息未到达设备
(2)收流超时
发生在哪里?
设备—> 流媒体服务器,发送实时流
流媒体服务器—>GB28181服务器,流改变事件
可能的原因:
消息发送了但是发送到来错误的IP和端口上
设备内部错误未能发送流
设备发送了流,但是流无法识别,可能存在流不规范和网络很差的情况下
设备发送了流,流媒体服务器也收到了,但是它没法通过hook通知wvp,可能是因为网络连不上
设备发送了流,但是开启了SSRC校验,设备的流不够规范采用错误的SSRC,导致流媒体服务器选择丢弃