GB28181
主要内容
-
国标的20位id是按照标准来定的,前8位是地域信息,9-10位是行业信息,11-13是设备类型、14是网络标识、后6位为序号
-
约定以SIP协议作为会话通道的使用标准,以RTP作为语言和视频的载体。联网系统在进行音视频传输及控制时需要建立两个通道:会话通道(传输信令)和流媒体通道
协议架构:
注册
注册过程:
1. SIP代理向SIP服务器发送Register请求; 2. SIP服务器向SIP代理发送响应401,并在响应的消息头WWW_Authenticate字段中给出适合SIP代理的认证体制和参数; 3. SIP代理重新向SIP服务器发送REGISTER请求, 在请求的Authorization字段给出信任书,包含认证信息; 4. SIP服务器对请求进行验证,如果检查出SIP代理身份合法,向SIP代理发送成功响应200OK,如果身份不合法则发送拒绝服务应答。
参数解读:
REGISTER sip:34020000002000000001@3402000000 SIP/2.0
Via: SIP/2.0/UDP 192.168.137.11:5060;rport;branch=z9hG4bK1371463273
From: sip:34020000001320000003@3402000000;tag=2043466181
To: sip:34020000001320000003@3402000000
Call-ID: 1011047669
CSeq: 1 REGISTER
Contact: sip:34020000001320000003@192.168.137.11:5060
Max-Forwards: 70
User-Agent: IP Camera
Expires: 3600
Content-Length: 0
=================
第1行表明这条SIP消息的方法(Method)是REGISTER,34020000002000000001是SIP服务器的国标ID,国标ID指的是由中心编码(8位) 、行业编码(2位) 、类型编码(3位)和序号(7位)四个码段共20位十进制数字字符构成,具体国标ID的编码方法可以参考GB/T 28181—2016中的附录D。3402000000指的是SIP服务器的域国标ID,SIP/2.0指的是SIP协议版本。
第2行为Via头,Via头中包含了发送请求方的相关信息,后续需要使用这些信息进行回复。SIP/2.0/UDP表示使用的是2.0版本的SIP协议,使用的传输协议是UDP,也可以使用TCP协议。192.168.137.11:5060为请求发送方的IP地址和端口号。Via头中必须包含branch参数,具体值是一个在整个SIP通信过程中不重复的数值。branch是一个事务ID(Transaction ID),用于区分同一个UA所发起的不同Transaction,它不会对未来的request或者是response造成影响,对于遵循IETF RFC3261规范的实现,这个branch参数的值必须用”z9hG4bK”打头. 其它部分是对To, From, Call-ID头域和Request-URI按一定的算法加密后得到。rport字段表示使用rport机制路由响应,即发送的响应时,按照rport中的端口发送SIP响应,也就是说IP和端口均完全遵照从哪里来的,发回哪里去的原则,如果没有rport字段时,服务端的策略是IP使用UDP包中的地址,即从哪里来回哪里去,但是端口使用的是via中的端口,详情见IETF RFC35818。
第3行为From头,From头中包含了请求发送方的逻辑标识,在GB28181协议中是发送请求的设备国标ID和域国标ID信息。tag参数是为了身份认证的,值为随机数字字符。
第4行为To头,To头在SIP协议中是为了标明请求接收方的逻辑标识的,在GB28181协议中填写的是发送请求的设备国标ID和域国标ID信息。
第5行为Call-ID头,Call-ID头是全局唯一的,在同一个session中保持一致,在不同session中不同。
第6行为CSeq头,CSeq头又叫Command Seqence(命令队列),用于标识命令顺序,值为序号+Method,序号部分为无符号整数,最大值为2^31。序号起始值是随机的,后续在同一个session中依次递增,比如发1 REGISTER没返回--->再发2 REGISTER--->没返回--->再发3 REGISTER--->这时返回了2 REGISTER就知道是第2个请求得到了响应。对于ACK和CANCLE中的CSeq与INVITE中的Cseq保持一致。
第7行为Contact头,Contact头包含源的URI信息,用来给响应消息直接和源建立连接用。在GB28181协议中为SIP设备编码@源IP地址端口。
第8行为Max-Forwards头,Max-Forwards头用于设置包最大中转次数,默认是70。
第9行为User-Agent头,User-Agent头用于设置关于UA的信息,用户可以自定义。
第10行为Expires头,Expires头表示超时时间。
第11行为Content-Length头,Content-Length头表示SDP消息的长度,因为REGISTER消息不需要SDP,因此为0。
保活
当UA发现工作异常时, 应立即向本SIP监控域的SIP服务器发送状态信息; 无异常时,应定时向本SIP监控域的SIP服务器发送状态信息。
SIP协议
SIP(Session Initiation Protocol,会话初始协议)是由IETF(Internet Engineering Task Force,因特网工程任务组)制定的多媒体通信协议。
会话模式
SIP协议有两种会话模式:会话中消息体内容大于1300字节时采用session mode,不大于时采用pager mode
消息体
SIP的消息体结构与HTTP协议结构十分相似:
-
请求行or状态行
-
请求行格式:Method Request-URI SIP-Version CRLF,举例:INVITE sip:bob@zte.com SIP/2.0 /r/n
-
-
消息体
-
body
请求方法
-
REGISTER:注册联系信息
-
INVITE:发起会话请求
-
ACK:INVITE请求的响应的确认
-
CANCEL:取消请求
-
BYE:终止会话
-
OPTIONS:查询服务器能力
-
MESSAGE:传递不超过1300字节的数据
状态码
状态码 | msg | 含义 |
---|---|---|
100 | Trying | 试呼叫 |
180 | Ringing | 振铃 |
181 | Call is Being Forwarded | 呼叫正在前转 |
200 | OK | 成功响应 |
302 | Moved Temporarily | 临时迁移 |
400 | Bad Request | 错误请求 |
401 | Unauthorized | 未授权 |
403 | Forbidden | 禁止 |
404 | Not Found | 用户不存在 |
408 | Request Timeout | 请求超时 |
480 | Temporarily Unavailable | 暂时无人接听 |
486 | Busy Here | 线路忙 |
504 | Server Time-out | 服务器超时 |
600 | Busy Everywhere | 全忙 |
SDP协议
内容
SDP是会话描述协议的缩写,是描述流媒体初始化参数的格式,由IETF作为RFC 4566颁布。流媒体是指在传输过程中看到或听到的内容
SDP通常包括如下信息:
-
会话信息
-
会话名和目的
-
会话活动时间
-
会话使用的宽带信息
-
会话负责人信息
-
-
媒体信息
-
媒体类型:视频or音频
-
传输协议:RTP/UDP/TCP
-
媒体格式:H.264/MPEG
-
传输地址和传输端口
-
格式
SDP会话描述由一个会话级描述(session_level description)和多个媒体级描述(media_level description)组成。会话级(session_level)的作用域是整个会话。其位置是从’v=’行开始到第一个媒体描述为止。媒体级(media_level)描述是对单个的媒体流进行描述(例如传送单个音频或者视频的vlc sdp文件只有短短的几句话,从m=开始,这其实就是个媒体机描述),其位置是从’m=’行开始到下一个媒体描述为止。
v= (协议版本)
o= (所有者/创建者和会话标识符)
s= (会话名称)
i=* (会话信息)
u=* (URI 描述)
e=* (Email 地址)
p=* (电话号码)
c=* (连接信息 ― 如果包含在所有媒体中,则不需要该字段)
b=* (带宽信息)
一个或更多时间描述(如下所示):
z=* (时间区域调整)
k=* (加密密钥)
a=* (0个或多个会话属性线路)
0个或多个媒体描述(如下所示)
时间描述
t= (会话活动时间)
r=* (0或多次重复次数)
媒体描述
m= (媒体名称和传输地址)
i=* (媒体标题)
c=* (连接信息 — 如果包含在会话层则该字段可选)
b=* (带宽信息)
k=* (加密密钥)
a=* (0个或多个会话属性线路)
================
SDP字段说明:
v字段:协议版本
o字段:-
a字段:a=rtpmap:<payload type> <encoding name>/<clock rate> [/<encoding parameters>] 中的<encoding name>,利用该属性携带编码器厂商名称。该属性表明该流为某厂商编码器编码且是不符合gb28181规定的媒体流,符合国标的媒体流不需要该属性。
例如:a=rtpmap:96 DAHUA/90000
a=rtpmap:96 HIKVISION/90000
a字段有下列格式:
a字段可携带倍数参数,用于文件下载时控制下载速度。格式: a=downloadspeed:下载倍数(整型)
a字段可携带文件大小参数,用于文件下载时的进度计算。格式: a=filesize:文件大小 (单位:Byte)
a字段可携带setup、connection作为TCP连接协商参数。 a=setup:TCP连接方式(表示本SDP发送者在建立RTP over TCP连接时是主动还是被动发起TCP连接,“active”为主动,“passive”为被动)
a字段可携带SVC参数,用于视频传输时的分辨率或者帧频控制。a=svcspace:空域编码方式 【取值整型。 0:不使用 1:1级增强 2:2级增强 3:3级增强 】 a = svctime:时域编码方式
s字段:表示请求媒体流的操作类型,“Play”标识为点播请求 “Playback”标识回播请求 “Download”表示文件下载 “Talk”表示语音对讲;
u字段:u行应填写视音频文件的URL。该URL的取值有两种:简捷方式和普通方式。简捷方式直接采用产生该历史媒体的媒体源(如某个摄像头)的设备ID以及相关参数,参数用“:”分隔;普通方式采样http://储存设备ID[/文件夹]*/文件名;
m字段:描述媒体的媒体类型、端口、传输层协议、负载类型等内容。媒体类型采样“video”标识视频或者视音频混合内容,采样“audio”标识传输音频内容;传输方式采用“RTP/AVP”标识传输层协议为 RTP over UDP,采用“TCP/RTP/AVP”标识传输层协议为RTP over TCP;
t字段:当回放或者下载时,t行值为开始时间,结束时间,采样“ ”分隔;
y字段:十进制整数字符串,标识SSRC值。其中第一位为历史或者实时媒体流的标识位,0为实时,1为历史;第2位到第6位取20位SIP监控域ID之中的4-8位作为域标识;第7-10位作为域内媒体流标识,是一个与当前域内产生的媒体流SSRC值后4位不充分的四位十进制整数;
f字段:f=v/编码格式/分辨率/帧率/码率类型/码率大小 a/编码格式/码率大小/采样率 其中v表示video a表示audio
SDP实例
# 请求视频流
INVITE sip:00000000001310018021@192.168.40.66:7100 SIP/2.0
Via: SIP/2.0/UDP 192.168.40.55:7100;rport;branch=z9hG4bK2480933505
From: <sip:120105110228023020@192.168.40.55:7100>;tag=2249831759
To: <sip:00000000001310018021@192.168.40.66:7100>
Call-ID: 821763613 // Call-ID:使用该字段标识一路视频
CSeq: 20 INVITE
Contact: <sip:120105110228023020@192.168.40.55:7100>
Content-Type: Application/SDP
Max-Forwards: 70
User-Agent: NCG V2.6.0.299938
Subject: 00000000001310018021:0,120105110228023020:0
Content-Length: 239
v=0
o=00000000001310018021 0 0 IN IP4 192.168.40.55
s=Play //Play标识为点播请求 Playback标识回播请求
c=IN IP4 192.168.40.55 //192.168.40.55:音视频流目的地址
t=0 0 //t行第一参数为视频开始时间 第二个参数为结束时间 t = 0 0表示实时视音频点播
m=video 5552 RTP/AVP 96 97 98 //video:表示请求音视频流 audio:表示请求音频流 5522:音视频流目的端口 RTP/AVP:视频流使用协议 96 97 98:客户端支持码流格式
a=rtpmap:96 PS/90000
a=rtpmap:97 MPEG4/90000
a=rtpmap:98 H264/90000
a=recvonly
a=streamMode:MAIN
y=0999999999
# 返回100 trying
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.40.55:7100;rport=7100;branch=z9hG4bK2480933505
From: <sip:120105110228023020@192.168.40.55:7100>;tag=2249831759
To: <sip:00000000001310018021@192.168.40.66:7100>
Call-ID: 821763613
CSeq: 20 INVITE
User-Agent: NCG V2.6.0.299938
Content-Length: 0
# 携带sdp返回 200
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.40.55:7100;rport=7100;branch=z9hG4bK2480933505
From: <sip:120105110228023020@192.168.40.55:7100>;tag=2249831759
To: <sip:00000000001310018021@192.168.40.66:7100>;tag=2885333649
Call-ID: 821763613
CSeq: 20 INVITE
Contact: <sip:161128022553273720@192.168.40.66:7100>
Content-Type: Application/SDP
User-Agent: NCG V2.6.0.299938
Content-Length: 165
v=0
o=00000000001310018021 0 0 IN IP4 192.168.40.55
s=Play
c=IN IP4 192.168.40.66 //192.168.40.66:音视频流源地址 注:视音频源与目的地址不局限于级联服务器本身
t=0 0
m=video 5268 RTP/AVP 96 // video:表示请求视频流 audio:表示请求音频流 5268:音视频流源端口 RTP/AVP:视频流使用协议 96:服务端所选择的码流格式 音视频所使用端口统一使用偶数端口 port+1为rtcp端口
a=rtpmap:96 PS/90000
a=sendonly
y=0100005268
SDP和SIP的关系
SDP一般作为SIP消息的body部分,SIP消息和SDP没有硬性的附属关系,SIP是用来传输信令的,SDP是用来描述流媒体信息的
RTP协议
RTP是一个网络传输协议,IETF RFC3550详细描述了RTP协议内容。GB28181协议中规定了两种方式传输媒体流,一种是将音视频数据打包成MPEG2-PS流然后再通过RTP协议传输,另外一种是直接使用RTP传输裸的音视频流,在实际应用中主要以第一种方式为主
基于RTP的PS封装首先按照ISO/IEC13818-1:20008将视音频流封装成PES包,然后再将PES包封装成PS包, 再将PS包以负载的方式封装成RTP包。进行PS封装时,应将每个视频帧封装为一个PS包,且每个关键帧的PS包中应包含系统头(System Header)和PSM(Program Stream Map),系统头和PSM放置于PS包头之后、第一个PES包之前。典型的视频关键帧PS包结构如图所示,其中PESV为视频PES包,PESA为音频PES包,视频非关键帧的PS包结构中一般不包含系统头和PSM。
ZLMediaKit
基于C++开发的高性能开源流媒体服务器,特点如下:
-
支持多种协议(RTSP/RTMP/HLS/HTTP-FLV/WebSocket-FLV/GB28181/HTTP-TS/WebSocket-TS/HTTP-fMP4/WebSocket-fMP4/MP4/WebRTC)
-
使用多路复用、多线程、异步网络模式开发,性能优越
-
低延时(100-500ms)
-
功能完善:支持集群、按需转协议、按需推拉流、先播后推、断连续推等功能
-
支持多种平台:Windows、Linux、macOS
-
全面支持H265/H264/AAC/G711/OPUS
-
支持sdk二次开发
-
支持0开发直接使用
部署
ZLMediaKit的部署比较简单,根据官方文档部署即可
可参考:
【精选】国标视频平台搭建(二)ZMLMediaKit部署_zmlmedia 国际协议-CSDN博客
快速开始 · ZLMediaKit/ZLMediaKit Wiki (github.com)
部署完成即可以进行视频推流,这里使用大华摄像头为例
因为还没有部署SIP信令服务器,无法接收/下达信令给摄像头所以这里使用RTMP来做测试
设置以上信息后流媒体服务器打印以下信息说明推流成功!
RTMP拉流地址拼接(具体参考链接):
拉流地址四元组:
-
协议
-
虚拟主机名vhost
-
应用名:live
-
流id:0、test
如果有一个RtmpMediaSource,它的4元组分别为 rtmp(RtmpMediaSource固定为rtmp)、somedomain.com、live、0 那么播放这个流媒体源的url对应为:
rtmp://somedomain.com/live/0 rtmps://somedomain.com/live/0 rtmp://127.0.0.1/live/0?vhost=somedomain.com rtmps://127.0.0.1/live/0?vhost=somedomain.com
我们这里的vhost是__defaultVhost__
所以我们的拉流地址是rtmp://10.14.2.7/live/test?vhost=__defaultVhost__
(10.14.2.7是流媒体服务器的地址)
目测使用rtmp推流的延时在3s左右,现在我们的流媒体服务器已经搭建成功!
开始实施
整体逻辑
实时视音频点播采用SIP协议中的INVITE方法实现会话连接,采用RTP/RTCP协议(IETF RFC3550)实现媒体传输。需要注意的是,实时视音频点播需要上述的媒体流保活机制。客户端主动发起的实时视音频点播流程见下图
部署信令服务器
部署完流媒体服务器之后还需要一个sip信令服务器来接受国标设备信息和下达指令,这里采用开源的基于C++的Sip Server作为demo部署
项目地址:BXC_SipServer: 基于C++开发的国标GB28181流媒体信令服务器。 采用BXC_SipServer+ZLMediaKit。完整搭建一个可以接收,摄像头通过国标协议推流到国标GB28181流媒体服务器,然后进行RTSP/RTMP/HTTP-FVL/HLS/WS/SRT等协议分发。 (gitee.com)
参考项目中的教程很轻松的就完成了部署,并再main.cpp文件中找到sip服务器所绑定的信息
#include "SipServer.h"
#include "Utils/Log.h"
int main(int argc, char *argv[]) {
LOGI("");
ServerInfo info(
"BXC_SipServer", //name
"1234567890123456", //
"10.14.2.7", // ip
15060, // sip服务器的端口
10000, // 流媒体服务器的端口
"34020000002000000001", //sip服务器编号
"3402000000", // 域
"123456789",
1800,
3600);
SipServer sipServer(&info);
sipServer.loop();
return 0;
根据以上信息来配置大华摄像头的国标服务器信息:
配置好之后服务器会接收到sip的相关请求,注册成功之后大华平台摄像头的状态会变为绿色
GB28181推流/拉流
信令服务器部署后会告诉摄像头接收国标28181推流的端口10000,结合前面我们已经部署了ZLMediaKit,所以我们现在已经将大华摄像头的视频内容通过GB28181的形式推送到了我们的流媒体服务器了,流传输采用RTP的形式。(这里注意如果rtmp和国标28181都配置了,好像只有一个生效)
拉流时只需要将__defaulthost__
改为流媒体服务器的ip即可,地址:rtsp://10.14.2.7/rtp/05F5E101
目测延时在1.7s左右,如果关闭音频推流则在1.5-1.6左右,比rtmp推流的延时更低,但是长时间拉流发现存在延时累积情况,使用vlc拉流3小时后延时增加到4秒左右
参考文章
技术解码 | GB28181/SIP/SDP 协议 - 知乎 (zhihu.com)
【精选】国标视频平台搭建(二)ZMLMediaKit部署_zmlmedia 国际协议-CSDN博客
快速开始 · ZLMediaKit/ZLMediaKit Wiki (github.com)