28181协议全称为GB/T28181《安全防范视频监控联网系统信息传输、交换、控制技术要求》,是由公安部科技信息化局提出,由全国安全防范报警系统标准化技术委员会(SAC/TC100)归口,公安部一所等多家单位共同起草的一部国家标准(以下简称28181)。
28181协议在全国平安城市、交通、道路等监控中广泛采用,若想做统一的大监控平台,则支持28181协议接入是必不可少的。如今很多客户都是想在之前使用的28181平台的基础上进行拓展。
EasyDSS云平台目标支持市面上绝大多数监控设备接入,所以支持28181协议也是必然的要求;结合EasyDSS云平台的标准设备接入能解决市面上绝大多数设备以及平台的接入。
说明
GB28181流媒体服务器是EasyDSS云平台提供的流转发服务器,负责将GB28181设备/平台推送的PS流转成ES流,然后推送给EasyDSS流媒体服务器进行分发。
同时,GB28181流媒体服务器对外提供HTTP API接口,通过接口可以获知流媒体转发服务的运行状态信息,转发会话信息,服务器配置和版本信息等;
GB28181流媒体服务器提供以下功能:
1. 接受和处理GB28181接入服务器的推流请求(如有推流权限验证则调用验证服务器接口);
2. 接受和处理GB28181设备的推流;
3. 实时流媒体处理,PS(TS)转ES;
4. 推送ES流到EasyDSS流媒体服务器;
5. 接受和处理GB28181接入服务器的断开推流请求;
6. 对外提供服务器获取状态、信息,控制等http API接口;
GB28181流媒体服务器对接EasyDSS云平台整体框架
流媒体点播详细流程
1 接入服务器发送Invite请求
接入服务器向流媒体服务器发送Invite请求,请求流媒体服务返回携带SDP 消息体,消息体中
描述了媒体服务器接收媒体流的IP、端口、媒体格式等内容;
Invite请求代码如下:
const options = {
serialServer: serialServer,
serialDevice: code,
method: common.SIP_INVITE,
contentType: common.CONTENT_NONE,
content: sdp,
host: hostip,
port: hostport,
rtpovertcp: (
parseInt(rtpovertcp)===
0?
\'UDP\':
\'TCP\')
};
console.log(
\'inviteMediaServer......sendRequest\' +
JSON.stringify(options));
uas.sendRequest(options);
2 流媒体服务接受Invite请求处理并ACK应答
流媒体服务接受Invite请求,并在回调函数中处理请求,js代码如下:
uas.
on(
\'invite\', async ctx
=> {
const request = ctx.request;
const content = JSON.parse(request.content);
const status =
200;
const serial = sip.parseUri(request.uri).user;
const host = config.server.serverHost;
let ssid = serial.substring(
16,
20);
// PrefixInteger(sessionid,
4);
let sirialid = serial.substring(
3,
8);
const ssrc =
"0"+sirialid+ssid;
console.log(
"ssrc = "+ssrc);
let sdp =
\'\';
//如果已存在
let bHas =
this.session_.has(serial);
console.log(bHas);
if (bHas) {
console.log(
\'this.session_ has exist serial: \'+serial);
sdp =
\'\';
}
else{
let port = config.server.udpPort;
//流媒体接收TCP端口
let transport =
\'RTP/AVP\';
let a =
"a=recvonly\r\n";
if(content.rtpovertcp ===
\'TCP\' )
{
port = config.server.tcpPort;
//流媒体接收TCP端口
transport =
\'TCP/RTP/AVP\';
a =
"a=recvonly\r\na=setup:passive\r\n";
}
sdp =
"v=0\r\n" +
`
o=${serial} 0 0 IN IP4 ${host}\r\n` +
"s=Play\r\n" +
`
c=IN IP4 ${host}\r\n` +
"t=0 0\r\n" +
`
m=video ${port} ${transport} 96 98 97\r\n` +
"a=rtpmap:96 PS/90000\r\n" +
"a=rtpmap:98 H264/90000\r\n" +
"a=rtpmap:97 MPEG4/90000\r\n" +
`
${a}`+
//`
a=connection:new\r\n` +
`
y=${ssrc}\r\n`;
// A
new channel
is coming,
delete the old
rtpserver.deleteChannels(parseInt(ssrc));
// Create a
new stram,
and add to redis
this.registerStream(parseInt(ssrc),uuidv4(),
true);
}
let response = sip.makeResponse(request, status, common.messages[status]);
uas.sendAckEx(response, sdp);
});