GB28181协议详解
第一部分:协议基础与设备注册
1.1 协议分层架构
层级 | 协议/规范 | 功能说明 |
---|---|---|
信令控制层 | SIP (RFC 3261) + GB扩展 | 设备注册、目录订阅、实时点播、云台控制等控制信令 |
媒体传输层 | RTP/RTCP (RFC 3550) + PS封装 | 音视频数据封装传输,支持H.264/H.265/G.711/AAC等编码 |
1.2 设备注册流程(含鉴权算法)
1.2.1 完整信令交互
[设备] [SIP服务器]
|---- REGISTER (无鉴权) -------->|
|<---- 401 Unauthorized --------| WWW-Authenticate: Digest realm="3402000000", nonce="abcd1234"
|---- REGISTER (带鉴权头) ------>| Authorization: Digest username="34020000001320000001", response="xxxx"
|<---- 200 OK ------------------| Expires: 3600
1.2.2 鉴权算法实现
-
输入参数:
username
:设备ID(如34020000001320000001
)realm
:服务器返回的域(如3402000000
)password
:设备预设密码(如123456
)nonce
:服务器生成的随机数(如abcd1234
)method
:请求方法(REGISTER
)uri
:请求URI(如sip:34020000002000000001@192.168.1.100
)
-
计算步骤:
- 计算
HA1 = MD5(username:realm:password)
- 计算
HA2 = MD5(method:uri)
- 最终
response = MD5(HA1:nonce:HA2)
- 计算
-
代码示例(Python):
import hashlib
def calculate_response(username, realm, password, nonce, method, uri):
ha1 = hashlib.md5(f"{username}:{realm}:{password}".encode()).hexdigest()
ha2 = hashlib.md5(f"{method}:{uri}".encode()).hexdigest()
return hashlib.md5(f"{ha1}:{nonce}:{ha2}".encode()).hexdigest()
第二部分:实时点播(2025年02月21日场景)
2.1 信令交互全流程
[Client] [Device]
|-------- INVITE (SDP Offer) ------------>|
|<------- 100 Trying ---------------------| # 临时响应
|<------- 200 OK (SDP Answer) ------------| # 携带设备媒体参数
|-------- ACK --------------------------->| # 确认建立会话
|<------- RTP Stream (Port 6000) -------- | # 媒体流开始传输
|-------- BYE --------------------------->| # 结束会话
|<------- 200 OK -------------------------|
2.2 SDP详解(客户端Offer)
v=0
o=34020000002000000001 0 0 IN IP4 192.168.1.100 # 会话发起者标识
s=Play # 会话名称(可自定义)
c=IN IP4 192.168.1.100 # 客户端接收地址
t=0 0 # 时间范围(0表示实时)
m=video 6000 RTP/AVP 96 # 媒体行:视频,端口6000,负载类型96
a=rtpmap:96 PS/90000 # PS封装,时钟频率90kHz
a=sendonly # 客户端仅接收(设备发送)
a=control:streamid=1 # 流标识符(多码流时使用)
a=range:clock=20250221T000000- # 时间范围("-"表示持续到结束)
SDP字段逐项解析
字段 | 说明 |
---|---|
o= | 格式:<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address> |
s= | 会话描述名称(如Play/Live/Playback) |
c= | 连接信息:IN 表示Internet,IP4 为IPv4地址,192.168.1.100 为客户端接收IP |
t= | 时间范围:<start-time> <stop-time> ,0 0 表示永久会话 |
m= | 媒体行:<media> <port> <proto> <fmt> ,video 表示视频,6000 为端口,RTP/AVP 为传输协议 |
a=rtpmap | 负载映射:<payload_type> <encoding>/<clock_rate> ,96 对应动态类型,PS 为封装格式 |
a=range | 时间范围:clock=YYYYMMDDThhmmss-YYYYMMDDThhmmss ,实时流可省略结束时间 |
第三部分:录像回放与下载
3.1 录像查询(MESSAGE信令)
3.1.1 请求消息
<?xml version="1.0"?>
<Query>
<CmdType>RecordInfo</CmdType> <!-- 固定指令类型 -->
<SN>16777216</SN> <!-- 序列号(递增) -->
<DeviceID>34020000001320000001</DeviceID>
<StartTime>20250221T120000</StartTime> <!-- 起始时间 -->
<EndTime>20250221T123000</EndTime> <!-- 结束时间 -->
<Secrecy>0</Secrecy> <!-- 保密级别(0-普通,1-机密) -->
<Type>time</Type> <!-- 录像类型:time/alarm/manual -->
</Query>
3.1.2 响应消息
<?xml version="1.0"?>
<Response>
<CmdType>RecordInfo</CmdType>
<SN>16777216</SN>
<DeviceID>34020000001320000001</DeviceID>
<Name>Camera-01</Name>
<SumNum>1</SumNum> <!-- 录像片段总数 -->
<RecordList>
<Item>
<DeviceID>34020000001320000001</DeviceID>
<Name>Channel-1</Name>
<StartTime>20250221T120000</StartTime>
<EndTime>20250221T123000</EndTime>
<FilePath>/videos/20250221_1200.mp4</FilePath> <!-- 可选字段 -->
</Item>
</RecordList>
</Response>
3.2 录像回放(INVITE信令)
3.2.1 SDP关键参数
a=range:clock=20250221T120000-20250221T123000 # 精确时间段
a=control:streamid=2 # 区分实时流与回放流
3.2.2 回放控制(MESSAGE信令)
<?xml version="1.0"?>
<Control>
<CmdType>DeviceControl</CmdType>
<SN>789</SN>
<DeviceID>34020000001320000001</DeviceID>
<Scale>4.0</Scale> <!-- 回放速率(1.0=正常,2.0=2倍速) -->
<Range>20250221T121500-20250221T122000</Range> <!-- 拖动到指定位置 -->
</Control>
第四部分:音视频RTP打包规范
4.1 视频封装(H.264/H.265)
4.1.1 PS封装结构
PS Header (0x000001BA)
→ System Header (0x000001BB)
→ PES Header (视频流)
→ H.264/H.265 NALU
→ PES Header (音频流)
→ G.711/AAC数据
4.1.2 RTP分片规则
帧类型 | 分片策略 |
---|---|
I帧 | 强制分片,每包≤1400字节,FU-A模式(分片头:0x1C + 0x80→首包,0x1C + 0x00→中间包) |
P/B帧 | 单包发送(若NALU≤1400字节)或分片发送 |
H.264分片头示例:
RTP Header | FU Indicator (0x1C) | FU Header (0x80) | NALU分片数据 # 首包
RTP Header | FU Indicator (0x1C) | FU Header (0x00) | NALU分片数据 # 中间包
RTP Header | FU Indicator (0x1C) | FU Header (0x40) | NALU分片数据 # 末包(Mark=1)
4.2 音频封装
4.2.1 PS封装音频
- PES结构:
PES Header (Stream ID=0xC0) | PCM数据(G.711) # 音频PES包
- 时间戳同步:音频PTS与视频PTS基于同一90kHz时钟对齐
4.2.2 独立RTP流封装
RTP Header | PCM数据(G.711) # 直接封装,无分片
SDP声明示例:
m=audio 6002 RTP/AVP 8 # G.711U负载类型8
a=rtpmap:8 PCMA/8000/1 # 编码格式与采样率
第五部分:开发注意事项
5.1 时间同步
- NTP同步:设备与服务器时间误差需<1秒,否则回放请求可能失败
- RTP时间戳:视频基于90kHz时钟,音频基于采样率(如G.711=8kHz)
5.2 网络适应性
传输模式 | 适用场景 | 优化建议 |
---|---|---|
UDP | 低延迟、允许少量丢包 | 增加Jitter Buffer(≥500ms) |
TCP | 高可靠性、弱网络环境 | 启用RTP over RTSP(需SDP中声明a=rtcp-mux ) |
5.3 错误处理
- 注册失败:检查
Digest
算法实现及设备ID格式(20位数字) - 媒体流中断:监控RTCP RR包的丢包率,动态调整码率
- 时间戳溢出:每26小时重置RTP时间戳(90kHz时钟溢出周期)
附录:关键协议头字段速查
SIP头字段
字段 | 示例值 | 说明 |
---|---|---|
Call-ID | 123456789@192.168.1.100 | 会话唯一标识(需全局唯一) |
CSeq | 1 INVITE | 命令序列号(递增) |
Contact | <sip:34020000001320000001@192.168.1.200> | 设备实际通信地址 |
SDP属性字段
属性 | 示例值 | 说明 |
---|---|---|
rtpmap | 96 PS/90000 | 定义负载类型与编码格式 |
fmtp | 96 profile-level-id=42E0 | H.264编码参数(可选) |
control | streamid=1 | 流标识符(多码流切换) |
第六部分:信令表
GB28181 信令全表
信令类型 | SIP方法 | 关键字段/消息体 | 典型场景 | 响应码 |
---|---|---|---|---|
设备注册 | REGISTER | Expires (有效期)、Authorization (鉴权头)、Contact (设备地址) | 设备上线 | 200 OK / 401 Unauthorized |
心跳保活 | MESSAGE | <CmdType>Keepalive</CmdType> 、<Status>OK</Status> | 维持在线状态 | 200 OK |
实时点播请求 | INVITE | SDP中的m=video 、a=rtpmap:96 PS/90000 、a=range (时间范围) | 发起实时视频流 | 200 OK + SDP |
录像回放请求 | INVITE | SDP中的a=range:clock=起始时间-结束时间 、a=control:streamid=N | 请求历史录像流 | 200 OK + SDP |
目录查询 | MESSAGE | <CmdType>Catalog</CmdType> 、<DeviceID> 、<SumNum> (通道数) | 获取设备通道列表 | 200 OK + 通道列表 |
报警通知 | NOTIFY | <CmdType>Alarm</CmdType> 、<AlarmType> (报警类型)、<AlarmTime> | 移动侦测/遮挡事件上报 | 200 OK |
云台控制 | MESSAGE | <CmdType>DeviceControl</CmdType> 、<PTZCmd> (十六进制指令) | 摄像头转动/变焦 | 200 OK |
录像查询 | MESSAGE | <CmdType>RecordInfo</CmdType> 、<StartTime> 、<EndTime> 、<RecordList> | 检索设备存储的录像片段 | 200 OK + 录像列表 |
回放控制 | MESSAGE | <CmdType>DeviceControl</CmdType> 、<Scale> (倍速)、<Range> (跳转时间) | 快进/快退/拖动进度条 | 200 OK |
语音对讲 | INVITE | SDP中的m=audio 、a=rtpmap:8 PCMA/8000 (音频编码) | 双向语音通信 | 200 OK + SDP |
设备信息查询 | MESSAGE | <CmdType>DeviceInfo</CmdType> 、<DeviceID> | 获取设备型号/版本信息 | 200 OK + 设备信息 |
订阅事件通知 | SUBSCRIBE | Event: catalog (目录订阅)、Expires (订阅有效期) | 实时接收设备状态变化 | 200 OK + NOTIFY消息 |
停止媒体流 | BYE | Call-ID (对应会话ID)、CSeq (递增序列号) | 结束实时预览或回放 | 200 OK |
文件下载请求 | MESSAGE | <CmdType>Download</CmdType> 、<FilePath> (文件路径)、<StartTime> | 下载指定录像文件 | 200 OK + 文件流 |
网络配置修改 | MESSAGE | <CmdType>ConfigDownload</CmdType> 、<IPAddress> 、<GateWay> | 远程修改设备网络参数 | 200 OK |
关键说明
-
SDP字段扩展:
a=control:streamid=N
:用于区分多码流(主码流=1,子码流=2)。a=range:clock=YYYYMMDDThhmmss-YYYYMMDDThhmmss
:时间格式必须精确到秒。a=rtpmap:96 PS/90000
:强制要求视频流使用PS封装,时钟频率90kHz。
-
XML消息体规范:
- 公共字段:
<SN>
(序列号)、<DeviceID>
(20位设备ID)必须唯一且递增。 - 错误码:
<StatusCode>
(如200
成功,400
参数错误,404
无录像文件)。
- 公共字段:
-
特殊场景处理:
- 分页查询:当录像片段过多时,通过
<SumNum>
和分页参数分批获取。 - 鉴权失败:服务器返回
401 Unauthorized
时,设备需重发带正确Authorization
头的请求。
- 分页查询:当录像片段过多时,通过
信令交互示例图
[设备注册]
Device -> Server: REGISTER
Server -> Device: 401 Unauthorized
Device -> Server: REGISTER (带鉴权)
Server -> Device: 200 OK
[实时点播]
Client -> Device: INVITE (SDP Offer)
Device -> Client: 200 OK (SDP Answer)
Client -> Device: ACK
Device -> Client: RTP流传输
[录像回放控制]
Client -> Device: MESSAGE (Scale=2.0)
Device -> Client: 200 OK + 媒体流加速
附:常用CmdType值
CmdType | 用途 | 关联信令 |
---|---|---|
Keepalive | 心跳保活 | MESSAGE |
Catalog | 目录查询 | MESSAGE |
DeviceControl | 云台/回放控制 | MESSAGE |
RecordInfo | 录像查询 | MESSAGE |
Alarm | 报警通知 | NOTIFY |
DeviceInfo | 设备信息查询 | MESSAGE |
Download | 文件下载 | MESSAGE |