GB28181学习(十)——视音频文件下载

要求

  • SIP服务器接收到媒体接收者发送的视音频文件下载请求后向媒体流发送者发送媒体文件下载命令,媒体流发送者采用RTP将视频流传输给媒体流接收者,媒体流接收者直接将视频流保存为媒体文件;
  • 媒体流接收者或SIP服务器可通过配置查询等方式获取媒体流发送者支持的下载发送倍速,并在请求的SDP消息体中携带下载倍速;
  • 视音频文件下载宜支持媒体流保活机制;

流程

录像下载的流程与录像点播、录像回放类似,主要区别为INVITE请求时xml格式有差异:

  • 实时点播

关于实时点播可查看:

实时点播(信令处理):https://blog.csdn.net/www_dong/article/details/132950064

实时点播(数据处理):https://blog.csdn.net/www_dong/article/details/133581370

注意:

  • "t=0 0"中开始时间和结束时间均为0表示实时点播
  • "s=Play"
c++ 复制代码
static std::string CreateRealStreamSDP(const GB28181MediaContext& mediaContext)
{
    char str[500] = { 0 };
    pj_ansi_snprintf(str, 500,
                     "v=0\n"
                     "o=%s 0 0 IN IP4 %s\n"
                     "s=Play\n"
                     "c=IN IP4 %s\n"
                     "t=0 0\n"
                     "m=video %d RTP/AVP 96 98 97\n"
                     "a=recvonly\n"
                     "a=rtpmap:96 PS/90000\n"
                     "a=rtpmap:98 H264/90000\n"
                     "a=rtpmap:97 MPEG4/90000\n"
                     "y=001\n",
                     mediaContext.GetDeviceId().c_str(),
                     mediaContext.GetRecvAddress().c_str(),
                     mediaContext.GetRecvAddress().c_str(),
                     mediaContext.GetRecvPort()
                    );
    return str;
}
  • 录像回放

历史视音频回放:https://blog.csdn.net/www_dong/article/details/133826739

注意:

  • "t=%lld %lld"中开始时间和结束时间为点播的开始时间和结束时间
  • "s=Playback"
c++ 复制代码
static std::string CreatePlayBackSDP(const GB28181MediaContext& mediaContext)
{
    char str[500] = { 0 };
    pj_ansi_snprintf(str, 500,
                     "v=0\n"
                     "o=%s 0 0 IN IP4 %s\n"
                     "s=Playback\n"
                     "c=IN IP4 %s\n"
                     "t=%lld %lld\n"
                     "m=video %d RTP/AVP 96 98 97\n"
                     "a=recvonly\n"
                     "a=rtpmap:96 PS/90000\n"
                     "a=rtpmap:98 H264/90000\n"
                     "a=rtpmap:97 MPEG4/90000\n"
                     "y=001\n",
                     mediaContext.GetDeviceId().c_str(),
                     mediaContext.GetRecvAddress().c_str(),
                     mediaContext.GetRecvAddress().c_str(),
                     mediaContext.GetPBStartTime(),
                     mediaContext.GetPBEndTime(),
                     mediaContext.GetRecvPort()
                    );
    return str;
}
  • 录像下载

注意:

  • "t=%lld %lld"中开始时间和结束时间为需要下载文件的开始时间和结束时间
  • "s=Download"
  • "a=downloadspeed:8"表示8倍速下载
c++ 复制代码
static std::string CreateSDPForDownload(const GB28181MediaContext& mediaContext)
	{
		char str[500] = { 0 };
		pj_ansi_snprintf(str, 500,
			"v=0\n"
			"o=%s 0 0 IN IP4 %s\n"
			"s=Download\n"
			"c=IN IP4 %s\n"
			"t=%lld %lld\n"
			"m=video %d RTP/AVP 96 98 97\n"
			"a=recvonly\n"
			"a=rtpmap:96 PS/90000\n"
			"a=rtpmap:98 H264/90000\n"
			"a=rtpmap:97 MPEG4/90000\n"
			"a=downloadspeed:%d\n"
			"y=0100000001\n",
			mediaContext.GetDeviceId().c_str(),
			mediaContext.GetRecvAddress().c_str(),
			mediaContext.GetRecvAddress().c_str(),
			mediaContext.GetDownloadStartTime(),
			mediaContext.GetDownloadEndTime(),
			mediaContext.GetRecvPort(),
			mediaContext.GetDownloadSpeed()
		);
		return str;
	}

抓包

  1. 查询历史视音频文件,查询结果如图所示:
  1. 选中一条文件记录,右键选择录像下载,弹出如下界面:
  1. 选择8倍速,点击开始下载,向设备发送下载请求:
bash 复制代码
INVITE sip:[email protected]:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.107:5060;rport;branch=xxx
Max-Forwards: 70
From: sip:[email protected];tag=xxx
To: sip:[email protected]
Contact: <sip:[email protected]:5060>
Call-ID: xxx
CSeq: 15724 INVITE
Allow: SUBSCRIBE, NOTIFY, INVITE, ACK, BYE, CANCEL, UPDATE
Supported: 
Subject: xxx:xx,xxx:xx
Content-Type: application/sdp
Content-Length:   251

v=0
o=xxx 0 0 IN IP4 192.168.0.107
s=Download
c=IN IP4 192.168.0.107
t=1697955233 1697958114      # 下载的文件开始时间和结束时间
m=video 36000 RTP/AVP 96 98 97
a=recvonly
a=rtpmap:96 PS/90000
a=rtpmap:98 H264/90000
a=rtpmap:97 MPEG4/90000
a=downloadspeed:8            # 8倍速下载
y=001
  1. 设备返回下载请求结果:
bash 复制代码
# 100 Trying
SIP/2.0 100 Trying
Via: SIP/2.0/UDP 192.168.0.107:5060;rport=5060;branch=xxx
From: <sip:[email protected]>;tag=xxx
To: <sip:[email protected]>
Call-ID: xxx
CSeq: 15724 INVITE
User-Agent: IP Camera
Content-Length: 0

# 200 OK
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.0.107:5060;rport=5060;branch=xxx
From: <sip:[email protected]>;tag=xxx
To: <sip:[email protected]>;tag=904233038
Call-ID: xxx
CSeq: 15724 INVITE
Contact: <sip:[email protected]:5060>
Content-Type: application/sdp
User-Agent: IP Camera
Content-Length:   198

v=0
o=xxx 2131 2131 IN IP4 192.168.0.111
s=Download
c=IN IP4 192.168.0.111
t=0 0
m=video 15060 RTP/AVP 96
a=sendonly
a=rtpmap:96 PS/90000
a=filesize:62224924          # 请求的文件大小
y=001
  1. 接收数据

  2. 文件下载结束通知

当接收到MediaStatus命令且NotifyType为121是表示历史媒体文件发送结束。

抓包如下所示:

bash 复制代码
MESSAGE sip:[email protected]:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.0.111:5060;rport;branch=xxx
From: <sip:[email protected]>;tag=xxx
To: <sip:[email protected]>;tag=xxx
Call-ID: xxx
CSeq: 2 MESSAGE
Contact: <sip:[email protected]:5060>
Content-Type: Application/MANSCDP+xml
Max-Forwards: 70
User-Agent: IP Camera
Content-Length:   174

<?xml version="1.0" encoding="GB2312"?>
<Notify>
<CmdType>MediaStatus</CmdType>
<SN>151</SN>
<DeviceID>xxx</DeviceID>
<NotifyType>121</NotifyType>
</Notify>

下载的文件如下:

相关推荐
C++ 老炮儿的技术栈19 分钟前
UDP 与 TCP 的区别是什么?
开发语言·c++·windows·算法·visual studio
mochensage2 小时前
CSP信奥赛C++常用系统函数汇总
c++·信奥
mochensage2 小时前
C++信息学竞赛中常用函数的一般用法
java·c++·算法
fpcc2 小时前
跟我学c++中级篇——多线程中的文件处理
c++
5:003 小时前
云备份项目
linux·开发语言·c++
乄夜4 小时前
嵌入式面试高频(5)!!!C++语言(嵌入式八股文,嵌入式面经)
c语言·c++·单片机·嵌入式硬件·物联网·面试·职场和发展
YYDS3144 小时前
C++动态规划-01背包
开发语言·c++·动态规划
wydaicls4 小时前
十一.C++ 类 -- 面向对象思想
开发语言·c++
姜君竹5 小时前
QT的工程文件.pro文件
开发语言·c++·qt·系统架构
思捻如枫5 小时前
C++数据结构和算法代码模板总结——算法部分
数据结构·c++