GB28181录像回放实战:从SIP信令到PS流解析,一个完整抓包案例的拆解
GB28181录像回放全链路解析从SIP信令到PS流解包实战手册在视频监控系统集成领域GB28181协议堪称普通话级别的存在。但当我们真正动手实现录像回放功能时往往会陷入协议细节的迷宫——为什么设备不响应我的时间范围请求PS流里的时间戳到底怎么解析INFO消息控制播放暂停的机制是什么这些问题在文档中往往语焉不详。本文将带您亲历一次完整的协议侦探之旅。我们从一个真实的Wireshark抓包文件出发逐帧拆解从发起回放请求到接收媒体流的全过程。不同于简单的流程复述这里每个环节都配有原始报文截图和关键字段注释最后还会用Python代码演示如何拆解PS流中的视频帧。准备好您的协议分析工具我们开始这次逆向工程。1. 环境准备与抓包配置在开始抓包前需要确保测试环境具备以下要素网络拓扑摄像机IPC与客户端处于同一局域网IPC已注册到SIP服务器抓包工具Wireshark 3.6支持GB28181解析插件过滤规则(sip || rtp || rtcp) ip.addr 192.168.1.100替换为您的设备IP关键配置技巧# 在Linux系统下建议使用dumpcap降低丢包率 dumpcap -i eth0 -f udp port 5060 or udp portrange 30000-60000 -w gb28181.pcapng提示GB28181通常使用UDP传输SIP信令RTP流端口范围建议设置为30000-600002. SIP信令交互全解析2.1 INVITE请求时间范围的艺术客户端发起INVITE请求时最关键的差异体现在SDP报文中的两个字段INVITE sip:34020000001320000001192.168.1.100 SIP/2.0 ... Content-Type: application/sdp v0 o34020000002000000001 0 0 IN IP4 192.168.1.50 sPlayback cIN IP4 192.168.1.50 t1697264152 1697266715 ← 这里 mvideo 6000 RTP/AVP 96 artpmap:96 PS/90000时间戳字段详解字段示例值说明t1697264152起始时间Unix时间戳格式1697266715结束时间0表示实时流在实时点播中这个字段通常显示为t0 0而回放模式必须指定具体时间范围。时间戳转换技巧from datetime import datetime start datetime.fromtimestamp(1697264152) # 输出2023-10-14 14:15:522.2 设备响应200 OK的玄机设备返回的200 OK响应中SDP的afilesize字段常被忽视SIP/2.0 200 OK ... v0 o34020000001320000001 1080 1080 IN IP4 192.168.1.100 sPlayback afilesize:1893027 ← 录像文件大小字节 mvideo 15060 RTP/AVP 96 asendonly状态码对照表状态码含义常见原因200成功-400无效时间范围结束时间早于开始时间481录像不存在指定时间段无录像数据488不接受的媒体格式不支持的RTP payload类型3. 媒体流控制INFO消息详解播放控制通过SIP INFO消息实现其消息体采用XML格式?xml version1.0? Notify CmdTypePlayback/CmdType SN174/SN DeviceID34020000001320000001/DeviceID OperateTypePause/OperateType ← 控制类型 Scale1.0/Scale /Notify控制类型对照OperateType等效RTSP命令说明PlayPLAY开始播放可带ScalePausePAUSE暂停播放StopTEARDOWN停止播放ContinuePLAY从暂停恢复注意Scale参数支持0.25-4.0的倍速播放但需要设备端支持4. PS流解析实战接收到的RTP负载是PS封装数据解析流程如下RTP重组根据序列号处理乱序包PS头解析定位系统头和PES包视频提取分离H.264/H.265裸流Python解析示例import struct def parse_ps_header(ps_packet): # 解析PS头 start_code, struct.unpack(!I, ps_packet[0:4]) if start_code ! 0x000001ba: # PS头魔术字 raise ValueError(Invalid PS packet) # 解析系统头 sys_header ps_packet[14:] while True: pes_start sys_header.find(b\x00\x00\x01) if pes_start -1: break stream_id sys_header[pes_start3] if stream_id in (0xe0, 0xc0): # 视频/音频流 pes_header sys_header[pes_start:pes_start9] payload_len int.from_bytes(pes_header[4:6], big) print(fFound PES: stream_id{hex(stream_id)}, len{payload_len})PS流结构示意图RTP Packet ├── RTP Header (12 bytes) └── PS Payload ├── PS Header (14 bytes) ├── System Header (可变) └── PES Packets ├── Video PES (H.264/H.265) └── Audio PES (G.711/AAC)5. 常见问题排查指南问题1设备返回488 Not Acceptable Here检查SDP中的artpmap是否匹配设备能力尝试将96 PS/90000改为98 H264/90000问题2能收到RTP包但无法播放用rtpdump工具验证负载类型rtpdump -F payload -f capture.pcap | head -n 20检查RTP时间戳是否连续# Wireshark导出CSV后分析 df pd.read_csv(rtp.csv) df[delta] df[rtp.timestamp].diff() print(df[df[delta] 3600]) # 90000Hz时钟下1秒90000问题3播放控制无响应确认INFO消息的Content-Type正确Content-Type: Application/MANSCDPxml检查XML中的CmdType是否为Playback在完成本次抓包分析后我习惯用tshark统计关键指标作为验收依据tshark -r gb28181.pcapng -qz io,stat,1,\ COUNT(frame) frame,COUNT(rtp.pkt) rtp,COUNT(rtcp) rtcp这能清晰展示信令与媒体流的比例关系对性能调优很有帮助。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2579800.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!