GB28181 协议是视频监控领域的国家标准,本文将解析如何在 FFmpeg 中增加对 GB28181 协议的支持,使其可以与支持 GB28181 协议的设备进行通信与控制,实现设备的注册、保活以及流媒体的传输。
GB28181 协议指的是国家标准 GB/T 28181—2016《公共安全视频监控联网系统信息传输、交换、控制技术要求》1,该标准规定了公共安全视频监控联网系统的互联结构, 传输、交换、控制的基本要求和安全性要求, 以及控制、传输流程和协议接口等技术要求,是视频监控领域的国家标准。GB28181 协议信令层面使用的是 SIP(Session Initiation Protocol)协议 2,流媒体传输层面使用的是实时传输协议(Real-time Transport Protocol,RTP)协议 3,因此可以理解为 GB28181 是在国际通用标准的基础之上进行了私有化定制以满足视频监控联网系统互联传输的标准化需求。本文旨在说明在 FFmpeg 中增加对 GB28181 协议的支持,使其可以与支持 GB28181 协议的设备进行通信与控制,实现设备的注册、保活以及流媒体的传输。
GB28181 协议会话通道实际上使用的是 SIP 协议,并且在 SIP 协议的基础之上做了些私有化处理。SIP 是一个由 IETF MMUSIC 工作组开发的协议,作为标准被提议用于创建,修改和终止包括视频,语音,即时通信,在线游戏和虚拟现实等多种多媒体元素在内的交互式用户会话。SIP 中一个比较重要的概念是用户代理(User Agent),指的是一个 SIP 逻辑网络端点,用于创建、发送、接收 SIP 消息并管理一个 SIP 会话。SIP 用户代理又可分为用户代理客户端 UAC(User Agent Client)和用户代理服务端 UAS(User Agent Server)。UAC 创建并发送 SIP 请求,UAS 接收处理 SIP 请求,发送 SIP 响应。SIP 协议会与许多其它的协议协同工作,如 SIP 报文内容发送会话描述协议(Session Description Protocol,SDP)4,SDP 协议描述了会话所使用流媒体细节,如:使用哪个 IP 端口,采用哪种编解码器等等。SIP 的一个典型用途是:SIP 会话传输一些简单的经过报文的实时传输协议流,RTP 本身才是语音或视频的载体。在 GB28181 协议中,联网系统在进行视音频传输及控制时应建立两个传输通道: 会话通道和媒体流通道。会话通道用于在设备之间建立会话并传输系统控制命令; 媒体流通道用于传输视音频数据, 经过压缩编码的视音频流采用流媒体协议 RTP/RTCP 传输。GB28181 协议中具体通信协议结构图如下图 1 所示:
图 1 通信协议结构图
会话通道中,注册、实时视音频点播、历史视音频的回放等应用的会话控制采用 SIP 协议 IETF RFC3261 中规定的 REGISTER、INVITE 等请求和响应方法实现, 历史视音频回放控制采用 SIP 扩展协议 IETF RFC29765 规定的 INFO 方法实现,前端设备控制、信息查询、报警事件通知和分发等应用的会话控制采用 SIP 扩展协议 IETF RFC34287 规定的 MESSAGE 方法实现。下面详细介绍下注册、保活和实时视音频点播的 SIP 消息结构。
注册指的是设备或系统进入联网系统时向 SIP 服务器(SIP UAS)进行注册登记的工作模式,在本文中 FFmpeg 即为一个 SIP 服务器,设备向 FFmpeg 发送注册请求,FFmpeg 在接收到设备的注册请求后返回相应的回复消息,则完成设备注册流程。GB28181 协议中基于数字摘要的挑战应答式安全技术进行注册流程如下图 2 所示:
图 2 基本注册流程示意图
注册流程描述如下:
(a) SIP 代理向 SIP 服务器发送 Register 请求;
(b) SIP 服务器向 SIP 代理发送响应 401,并在响应的消息头 WWW_Authenticate 字段中给出适合 SIP 代理的认证体制和参数;
(c) SIP 代理重新向 SIP 服务器发送 REGISTER 请求, 在请求的 Authorization 字段给出信任书,包含认证信息;
(d) SIP 服务器对请求进行验证,如果检查出 SIP 代理身份合法,向 SIP 代理发送成功响应 200OK,如果身份不合法则发送拒绝服务应答。
注册的请求消息内容范例如下:
1 REGISTER sip:34020000002000000001@3402000000 SIP/2.0
2 Via: SIP/2.0/UDP 192.168.137.11:5060;rport;branch=z9hG4bK1371463273
3 From: sip:34020000001320000003@3402000000;tag=2043466181
4 To: sip:34020000001320000003@3402000000
5 Call-ID: 1011047669
6 CSeq: 1 REGISTER
7 Contact: sip:34020000001320000003@192.168.137.11:5060
8 Max-Forwards: 70
9 User-Agent: IP Camera
10 Expires: 3600
11 Content-Length: 0
注册的回复消息内容范例如下,各头信息含义见上面:
1 SIP/2.0 200 OK
2 Via: SIP/2.0/UDP 192.168.137.11:5060;rport;branch=z9hG4bK1371463273
3 From: sip:34020000001320000003@3402000000
4 To: sip:34020000001320000003@3402000000
5 CSeq: 1 REGISTER
6 Call-ID: 1011047669
7 Contact: sip:34020000001320000003@192.168.137.11:5060
8 User-Agent: FFmpeg GB28181 v1.0
9 Expires: 3600
10 Content-Length: 0
当 UA 发现工作异常时, 应立即向本 SIP 监控域的 SIP 服务器发送状态信息; 无异常时,应定时向本 SIP 监控域的 SIP 服务器发送状态信息。状态信息报送采用 IETF RFC3427 中定义的方法 MESSAGE 实现。通过周期性的状态信息报送,实现注册服务器与源设备之间的状态检测即心跳机制。心跳发送方、接收方需统一配置“心跳间隔”参数,按照“心跳间隔”定时发送心跳消息,默认心跳间隔 60s。心跳发送方、接收方需统一配置“心跳超时次数”参数,心跳消息连续超时达到“心跳超时次数”则认为对方下线,默认心跳超时次数 3 次。心跳接收方在心跳发送方上线状态下检测到心跳消息连续超时达到商定次数则认为心跳发送方离线; 心跳发送方在心跳接收方上线状态下检测到心跳消息响应消息连续超时达到商定次数则认为心跳接收方离线。具体命令流程如图 3:
图 3 保活命令流程
命令流程描述如下:
(a) 源设备向 SIP 服务器发送设备状态信息报送命令。设备状态信息报送命令采用 MESSAGE 方法携带;
(b) SIP 服务器收到命令后返回 200 OK。
保活消息内容范例如下:
1 MESSAGE sip:34020000002000000001@3402000000 SIP/2.0
2 Via: SIP/2.0/UDP 192.168.137.11:5060;rport;branch=z9hG4bK1066375804
3 From: sip:34020000001320000003@3402000000;tag=1925919231
4 To: sip:34020000002000000001@3402000000
5 Call-ID: 1185236415
6 CSeq: 20 MESSAGE
7 Content-Type: Application/MANSCDP+xml
8 Max-Forwards: 70
9 User-Agent: IP Camera
10 Content-Length: 175
11 <?xml version="1.0" encoding="UTF-8"?>
12 <Notify>
13 <CmdType>Keepalive
14 <SN>1
15 <DeviceID>34020000001320000003
16 <Status>OK
17 <Info>
18 </Info>
19 </Notify>
MESSAGE 消息头 Content-type 头为 Content-type: Application/MANSCDP+xml。状态信息报送命令采用 MANSCDP(监控报警联网系统控制描述协议,Monitoringand Alarming Network System Control Description Protocol)协议格式定义, 详细描述见 GB/T 28181—2016 中 A.2.5 状态信息报送。状态信息报送命令应包括命令类型(CmdType)、设备/系统编码(DeviceID)、是否正常工作(Status)等, 采用 MESSAGE 方法的消息体携带。Message 消息的成功和错误应答均无消息体,Message 回复消息内容范例如下:
1 SIP/2.0 200 OK
2 Via: SIP/2.0/UDP 192.168.137.11:5060;rport;branch=z9hG4bK1066375804
3 From: sip:34020000001320000003@3402000000
4 To: sip:34020000002000000001@3402000000
5 CSeq: 20 MESSAGE
6 Call-ID: 1185236415
7 User-Agent: FFmpeg GB28181 v1.0
8 Content-Length: 0
实时视音频点播采用 SIP 协议中的 INVITE 方法实现会话连接,采用 RTP/RTCP 协议(IETF RFC3550)实现媒体传输。需要注意的是,实时视音频点播需要上述的媒体流保活机制。客户端主动发起的实时视音频点播流程见图 4:
图 4 客户端主动发起的实时视音频点播流程图
其中,信令 1、8、9、10、11、12 为 SIP 服务器接收到客户端的呼叫请求后通过 B2BUA 代理方式建立媒体流接收者与媒体服务器之间的媒体流信令过程,信令 2-7 为 SIP 服务器通过三方呼叫控制建立媒体服务器与媒体流发送者之间的媒体流信令过程,信令 13-16 为媒体流接收者断开与媒体服务器之间的媒体流信令过程,信令 17-20 为 SIP 服务器断开媒体服务器与媒体流发送者之间的媒体流信令过程。
命令流程描述如下:
(a) 媒体流接收者向 SIP 服务器发送 INVITE 消息, 消息头域中携带 Subject 字段, 表明点播的视频源 ID、发送方媒体流序列号、媒体流接收者 ID、接收端媒体流序列号等参数,SDP 消息体中 s 字段为“Play”代表实时点播。
(b) SIP 服务器收到 INVITE 请求后,通过三方呼叫控制建立媒体服务器和媒体流发送者之间的媒体连接。向媒体服务器发送 INVITE 消息,此消息不携带 SDP 消息体。
(c) 媒体服务器收到 SIP 服务器的 INVITE 请求后,回复 200 OK 响应,携带 SDP 消息体,消息体中描述了媒体服务器接收媒体流的 IP、端口、媒体格式等内容。
(d) SIP 服务器收到媒体服务器返回的 200 OK 响应后,向媒体流发送者发送 INVITE 请求,请求中携带消息 3 中媒体服务器回复的 200 OK 响应消息体,s 字段为“Play”代表实时点播, 增加 y 字段描述 SSRC 值,f 字段描述媒体参数。
(e) 媒体流发送者收到 SIP 服务器的 INVITE 请求后,回复 200 OK 响应,携带 SDP 消息体,消息体中描述了媒体流发送者发送媒体流的 IP、端口、媒体格式、SSRC 字段等内容。
(f) SIP 服务器收到媒体流发送者返回的 200 OK 响应后,向媒体服务器发送 ACK 请求,请求中携带消息 5 中媒体流发送者回复的 200 OK 响应消息体, 完成与媒体服务器的 INVITE 会话建立过程。
(g) SIP 服务器收到媒体流发送者返回的 200 OK 响应后,向媒体流发送者发送 ACK 请求,请求中不携带消息体,完成与媒体流发送者的 INVITE 会话建立过程。
(h) 完成三方呼叫控制后,SIP 服务器通过 B2BUA 代理方式建立媒体流接收者和媒体服务器之间的媒体连接。在消息 1 中增加 SSRC 值,转发给媒体服务器。
(i) 媒体服务器收到 INVITE 请求,回复 200OK 响应,携带 SDP 消息体,消息体中描述了媒体服务器发送媒体流的 IP、端口、媒体格式、SSRC 值等内容。
(j) SIP 服务器将消息 9 转发给媒体流接收者。
(k) 媒体流接收者收到 200 OK 响应后,回复 ACK 消息,完成与 SIP 服务器的 INVITE 会话建立过程。
(l) SIP 服务器将消息 11 转发给媒体服务器,完成与媒体服务器的 INVITE 会话建立过程。
(m) 媒体流接收者向 SIP 服务器发送 BYE 消息,断开消息 1、10、11 建立的同媒体流接收者的 INVITE 会话。
(n) SIP 服务器收到 BYE 消息后回复 200 OK 响应, 会话断开。
(o) SIP 服务器收到 BYE 消息后向媒体服务器发送 BYE 消息,断开消息 8、9、12 建立的同媒体服务器的 INVITE 会话。
(p) 媒体服务器收到 BYE 消息后回复 200 OK 响应, 会话断开。
(q) SIP 服务器向媒体服务器发送 BYE 消息,断开消息 2、3、6 建立的同媒体服务器的 INVITE 会话。
(r) 媒体服务器收到 BYE 消息后回复 200 OK 响应,会话断开。
(s) SIP 服务器向媒体流发送者发送 BYE 消息,断开消息 4、5、7 建立的同媒体流发送者的 INVITE 会话。
(t) 媒体流发送者收到 BYE 消息后回复 200 OK 响应, 会话断开。
上述流程较为复杂,原因是在实际视频监控系统中,用户不是直接跟前端监控设备交互,而是与监控管理平台交互。媒体流接收者通常是用户的客户端,SIP 服务器是单独的服务器,媒体服务器通常是监控系统中的媒体网关,媒体流发送者为前端摄像机。本文中 FFmpeg 既作为 SIP 服务器,也作为用户客户端向前端设备发送 INVITE 请求,因此可以简化为 FFmpeg 向前端设备发送 INVITE 请求后,前端设备向 FFmpeg 回复 200OK,然后 FFmpeg 再向前端设备回复 ACK,这样前端设备即开始发送媒体流。
INVITE 消息范例如下:
1 INVITE sip:34020000001320000003@3402000000 SIP/2.0
2 Via: SIP/2.0/UDP 39.100.155.146:15063;rport;branch=z9hG4bK34208805
3 From: sip:34020000002000000001@39.100.155.146:15063;tag=512358805
4 To: sip:34020000001320000003@3402000000
5 Call-ID: 200008805
6 CSeq: 20 INVITE
7 Content-Type: Application/SDP
8 Contact: sip:34020000001320000003@3402000000
9 Max-Forwards: 70
10 User-Agent: FFmpeg GB28181 v1.0
11 Subject: 34020000001320000003:630886,34020000002000000001:0
12 Content-Length: 164
13 v=0
14 o=34020000001320000003 0 0 IN IP4 39.100.155.146
15 s=Play
16 c=IN IP4 39.100.155.146
17 t=0 0
18 m=video 9000 RTP/AVP 96
19 a=recvonly
20 a=rtpmap:96 PS/90000
21 y=630886
SIP 消息头部分上述已经解释过了,这里解释下 SDP 相关字段含义。
INVITE 回复消息范例如下:
1 SIP/2.0 200 OK
2 Via: SIP/2.0/UDP 39.100.155.146:15063;rport=15063;branch=z9hG4bK34208805
3 From: sip:34020000002000000001@39.100.155.146:15063;tag=512358805
4 To: sip:34020000001320000003@3402000000;tag=1083111311
5 Call-ID: 200008805
6 CSeq: 20 INVITE
7 Contact: sip:34020000001320000003@192.168.137.11:5060
8 Content-Type: application/sdp
9 User-Agent: IP Camera
10 Content-Length: 263
11 v=0
12 o=34020000001320000003 1073 1073 IN IP4 192.168.137.11
13 s=Play
14 c=IN IP4 192.168.137.11
15 t=0 0
16 m=video 15060 RTP/AVP 96
17 a=setup:active
18 a=sendonly
19 a=rtpmap:96 PS/90000
20 y=0000630886
ACK 消息范例如下:
1 ACK sip:34020000001320000003@3402000000 SIP/2.0
2 Via: SIP/2.0/UDP 39.100.155.146:15063;rport;branch=z9hG4bK34208805
3 From: sip:34020000002000000001@39.100.155.146:15063;tag=512358805
4 To: sip:34020000001320000003@3402000000
5 Call-ID: 200008805
6 CSeq: 20 ACK
7 Max-Forwards: 70
8 User-Agent: FFmpeg GB28181 v1.0
9 Content-Length: 0
BYE 消息范例如下:
1 BYE sip:34020000001320000003@3402000000 SIP/2.0
2 Via: SIP/2.0/UDP 39.100.155.146:15063;rport;branch=z9hG4bK34208805
3 From: sip:34020000002000000001@3402000000;tag=512358805
4 To: sip:34020000001320000003@3402000000;tag=1083111311
5 Call-ID: 200008805
6 CSeq: 79 BYE
7 Max-Forwards: 70
8 User-Agent: FFmpeg GB28181 v1.0
9 Content-Length: 0
2.2 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 包结构如图 6 所示,其中 PESV 为视频 PES 包,PESA 为音频 PES 包,视频非关键帧的 PS 包结构中一般不包含系统头和 PSM。PS 包中各部分的具体数据结构参见 ISO/IEC13818-1:2000 中的相关描述。
图 5 典型的视频关键帧 PS 包结构
系统头应包含对 PS 包中码流种类的描述, 其中视频和音频的流 ID(stream_id)取值如下:
(a) 视频流 ID:0xE0;
(b) 音频流 ID:0xC0。
针对几种视音频格式,PSM 中流类型(stream_type)的取值如下:
(a) MPEG-4 视频流:0x10;
(b) H.264 视频流:0x1B;
(c) SVAC 视频流:0x80;
(d) G.711 音频流:0x90;
(e) G.722.1 音频流:0x92;
(f) G.723.1 音频流:0x93;
(g) G.729 音频流:0x99;
(h) SVAC 音频流:0x9B。
PS 包的 RTP 封装格式参照 IETF RFC2250,RTP 的主要参数设置如下:
(a) 负载类型(payloadtype):96;
(b) 编码名称(encoding_name):PS;
(c) 时钟频率(clockrate):90 kHz;
(d) SDP 描述中“m”字段的“media”项:video。
首先我们在 FFmpeg 中实现了 GB28181 协议的 demuxer,方案的框架图如图 6 所示。主要包含两个子模块,一个是 SIP stack 模块,负责 SIP 协议功能,一个 GB28181 demuxer 模块,负责调用 SIP 接口与前端设备 IPC 进行交互,同时解析 IPC 通过 RTP 发送过来的 MPEG2-PS 流,得到音视频数据流后以 packet 的形式返回给 lavf 上层,再依次往 FFmpeg 上层传。SIP stack 模块提供单一功能的 SIP 接口,比如发送回复消息,发送 INVITE/BYE/ACK 请求;GB28181 demuxer 模块需要按照 FFmpeg 上层接口调用顺序与 IPC 进行相关的交互,同时创建与设备之间的 RTP 链接,在拿到 MPEG2-PS 流后进行解析。
图 6 demuxer 方案的框架图
由于 FFmpeg 只有解析 PS 流封装的本地视频 demuxer,并没有解析 PS 流的 demuxer,因此本文也在本地 PS 流封装视频 demuxer 的基础之上实现了 PS 流的 demuxer。核心思路是从 RTP 包中解析 PS 头信息,再根据 PS 头信息找到 PES 头,从 PES 头中取出每个 PES 包的长度。由于 RTP 长度限制,一个 PES 包会被切分成很多份分成多个 RTP 包传输过来,因此 PS demuxer 需要缓存这些 PES 切片,等一个完整的 PES 包凑齐后再解析取出音视频流并以 packet 格式返回上 FFmpeg 上层模块。由于 IETF RFC22509 并没有规定 PS 流应该如何封装到 RTP 中,因此 PES 头可能出现在 RTP 包的任何位置,demuxer 也针对不同的情况做了处理。
上述方案存在局限性,只能对单一设备进行管理和拉流,但实际场景中一个 SIP 域中存在众多设备。因此在上述 GB28181 demuxer 的基础之上,我们也实现了 GB28181 server,方案的框架图如下图 7 所示。
图 7 server 方案的框架图
GB28181 server 功能包括:
GB28181 server 可以使用户不感知 GB28181 协议的存在,用户只需要对感兴趣的设备进行操作即可。具体实现中,我们对上述 GB28181 demuxer 进行了功能扩展,使其具备两种工作模式,一种就是上述的单一设备模式,一种就是多设备管理模式。后者将设备状态信息、发送拉流/停止拉流接口暴露出来供 GB28181 server 调用。因此当 GB28181 server 运行后,其自动会对发出注册请求的设备进行管理,监控设备是否在线或离线并更新设备信息。同时监听用户请求,当接收到用户的 HTTP 请求时做相应的拉流/停止拉流等操作。
[1] GB/T 28181—2016. 安全防范视频监控联网系统信息传输, 交换, 控制技术要求[D]. , 2016.
[2] Rosenberg J, Schulzrinne H, Camarillo G, et al. RFC3261: SIP: session initiation protocol[J]. 2002.
[3] Casner S, Frederick R, Jacobson V, et al. RFC 3550, RTP: A Transport Protocol for Real-Time Applications[J]. Network Working Group, 2003.
[4] Handley M, Jacobson V, Perkins C. RFC 4566: SDP: session description protocol[J]. 2006.
[5] Donovan S. IETF RFC 2976 the SIP INFO Method[J]. 2000.
[6] RFC3428 I. SIP extension for instant messaging[J]. 2002.
[7] Rosenberg J, Schulzrinne H. IETF RFC 3581[J]. An Extension to the Session Initiation, 2003.
[8] Rec I. H. 222.0| ISO/IEC 13818-1: 2000[J]. Information Technology—Generic coding of moving pictures and associated audio—Part, 1.
[9] Hoffman D, Fernando G, Goyal V, et al. RFC2250: RTP payload format for MPEG1/MPEG2 video[J]. 1998.
领取专属 10元无门槛券
私享最新 技术干货