Commit 6afcd5176b89e213fed5d5904279c4095bfada9a
1 parent
2d2832db
请求历史媒体下载增加回复事件处理ssrc与下级不一致情况
Showing
3 changed files
with
152 additions
and
92 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
| ... | ... | @@ -15,26 +15,26 @@ import javax.sip.InvalidArgumentException; |
| 15 | 15 | import javax.sip.SipException; |
| 16 | 16 | import java.text.ParseException; |
| 17 | 17 | |
| 18 | -/** | |
| 19 | - * @description:设备能力接口,用于定义设备的控制、查询能力 | |
| 18 | +/** | |
| 19 | + * @description:设备能力接口,用于定义设备的控制、查询能力 | |
| 20 | 20 | * @author: swwheihei |
| 21 | - * @date: 2020年5月3日 下午9:16:34 | |
| 21 | + * @date: 2020年5月3日 下午9:16:34 | |
| 22 | 22 | */ |
| 23 | 23 | public interface ISIPCommander { |
| 24 | 24 | |
| 25 | 25 | /** |
| 26 | 26 | * 云台方向放控制,使用配置文件中的默认镜头移动速度 |
| 27 | - * | |
| 27 | + * | |
| 28 | 28 | * @param device 控制设备 |
| 29 | 29 | * @param channelId 预览通道 |
| 30 | 30 | * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 |
| 31 | 31 | * @param upDown 镜头上移下移 0:停止 1:上移 2:下移 |
| 32 | 32 | */ |
| 33 | 33 | void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown) throws InvalidArgumentException, ParseException, SipException; |
| 34 | - | |
| 34 | + | |
| 35 | 35 | /** |
| 36 | 36 | * 云台方向放控制 |
| 37 | - * | |
| 37 | + * | |
| 38 | 38 | * @param device 控制设备 |
| 39 | 39 | * @param channelId 预览通道 |
| 40 | 40 | * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 |
| ... | ... | @@ -42,28 +42,28 @@ public interface ISIPCommander { |
| 42 | 42 | * @param moveSpeed 镜头移动速度 |
| 43 | 43 | */ |
| 44 | 44 | void ptzdirectCmd(Device device,String channelId,int leftRight, int upDown, int moveSpeed) throws InvalidArgumentException, ParseException, SipException; |
| 45 | - | |
| 45 | + | |
| 46 | 46 | /** |
| 47 | 47 | * 云台缩放控制,使用配置文件中的默认镜头缩放速度 |
| 48 | - * | |
| 48 | + * | |
| 49 | 49 | * @param device 控制设备 |
| 50 | 50 | * @param channelId 预览通道 |
| 51 | 51 | * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 |
| 52 | 52 | */ |
| 53 | 53 | void ptzZoomCmd(Device device,String channelId,int inOut) throws InvalidArgumentException, ParseException, SipException; |
| 54 | - | |
| 54 | + | |
| 55 | 55 | /** |
| 56 | 56 | * 云台缩放控制 |
| 57 | - * | |
| 57 | + * | |
| 58 | 58 | * @param device 控制设备 |
| 59 | 59 | * @param channelId 预览通道 |
| 60 | 60 | * @param inOut 镜头放大缩小 0:停止 1:缩小 2:放大 |
| 61 | 61 | */ |
| 62 | 62 | void ptzZoomCmd(Device device,String channelId,int inOut, int moveSpeed) throws InvalidArgumentException, ParseException, SipException; |
| 63 | - | |
| 63 | + | |
| 64 | 64 | /** |
| 65 | 65 | * 云台控制,支持方向与缩放控制 |
| 66 | - * | |
| 66 | + * | |
| 67 | 67 | * @param device 控制设备 |
| 68 | 68 | * @param channelId 预览通道 |
| 69 | 69 | * @param leftRight 镜头左移右移 0:停止 1:左移 2:右移 |
| ... | ... | @@ -73,10 +73,10 @@ public interface ISIPCommander { |
| 73 | 73 | * @param zoomSpeed 镜头缩放速度 |
| 74 | 74 | */ |
| 75 | 75 | void ptzCmd(Device device,String channelId,int leftRight, int upDown, int inOut, int moveSpeed, int zoomSpeed) throws InvalidArgumentException, SipException, ParseException; |
| 76 | - | |
| 76 | + | |
| 77 | 77 | /** |
| 78 | 78 | * 前端控制,包括PTZ指令、FI指令、预置位指令、巡航指令、扫描指令和辅助开关指令 |
| 79 | - * | |
| 79 | + * | |
| 80 | 80 | * @param device 控制设备 |
| 81 | 81 | * @param channelId 预览通道 |
| 82 | 82 | * @param cmdCode 指令码 |
| ... | ... | @@ -85,7 +85,7 @@ public interface ISIPCommander { |
| 85 | 85 | * @param combineCode2 组合码2 |
| 86 | 86 | */ |
| 87 | 87 | void frontEndCmd(Device device, String channelId, int cmdCode, int parameter1, int parameter2, int combineCode2) throws SipException, InvalidArgumentException, ParseException; |
| 88 | - | |
| 88 | + | |
| 89 | 89 | /** |
| 90 | 90 | * 前端控制指令(用于转发上级指令) |
| 91 | 91 | * @param device 控制设备 |
| ... | ... | @@ -103,7 +103,7 @@ public interface ISIPCommander { |
| 103 | 103 | |
| 104 | 104 | /** |
| 105 | 105 | * 请求回放视频流 |
| 106 | - * | |
| 106 | + * | |
| 107 | 107 | * @param device 视频设备 |
| 108 | 108 | * @param channelId 预览通道 |
| 109 | 109 | * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss |
| ... | ... | @@ -113,16 +113,16 @@ public interface ISIPCommander { |
| 113 | 113 | |
| 114 | 114 | /** |
| 115 | 115 | * 请求历史媒体下载 |
| 116 | - * | |
| 116 | + * | |
| 117 | 117 | * @param device 视频设备 |
| 118 | 118 | * @param channelId 预览通道 |
| 119 | 119 | * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss |
| 120 | 120 | * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss |
| 121 | 121 | * @param downloadSpeed 下载倍速参数 |
| 122 | - */ | |
| 122 | + */ | |
| 123 | 123 | void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 124 | 124 | String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, |
| 125 | - SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; | |
| 125 | + SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; | |
| 126 | 126 | |
| 127 | 127 | /** |
| 128 | 128 | * 视频流停止 |
| ... | ... | @@ -150,7 +150,7 @@ public interface ISIPCommander { |
| 150 | 150 | * 回放倍速播放 |
| 151 | 151 | */ |
| 152 | 152 | void playSpeedCmd(Device device, StreamInfo streamInfo, Double speed) throws InvalidArgumentException, ParseException, SipException; |
| 153 | - | |
| 153 | + | |
| 154 | 154 | /** |
| 155 | 155 | * 回放控制 |
| 156 | 156 | * @param device |
| ... | ... | @@ -162,55 +162,55 @@ public interface ISIPCommander { |
| 162 | 162 | |
| 163 | 163 | /** |
| 164 | 164 | * 语音广播 |
| 165 | - * | |
| 165 | + * | |
| 166 | 166 | * @param device 视频设备 |
| 167 | 167 | * @param channelId 预览通道 |
| 168 | 168 | */ |
| 169 | 169 | void audioBroadcastCmd(Device device,String channelId); |
| 170 | - | |
| 170 | + | |
| 171 | 171 | /** |
| 172 | 172 | * 语音广播 |
| 173 | - * | |
| 173 | + * | |
| 174 | 174 | * @param device 视频设备 |
| 175 | 175 | */ |
| 176 | 176 | void audioBroadcastCmd(Device device, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; |
| 177 | 177 | void audioBroadcastCmd(Device device) throws InvalidArgumentException, SipException, ParseException; |
| 178 | - | |
| 178 | + | |
| 179 | 179 | /** |
| 180 | 180 | * 音视频录像控制 |
| 181 | - * | |
| 181 | + * | |
| 182 | 182 | * @param device 视频设备 |
| 183 | 183 | * @param channelId 预览通道 |
| 184 | 184 | * @param recordCmdStr 录像命令:Record / StopRecord |
| 185 | 185 | */ |
| 186 | 186 | void recordCmd(Device device, String channelId, String recordCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; |
| 187 | - | |
| 187 | + | |
| 188 | 188 | /** |
| 189 | 189 | * 远程启动控制命令 |
| 190 | - * | |
| 190 | + * | |
| 191 | 191 | * @param device 视频设备 |
| 192 | 192 | */ |
| 193 | 193 | void teleBootCmd(Device device) throws InvalidArgumentException, SipException, ParseException; |
| 194 | 194 | |
| 195 | 195 | /** |
| 196 | 196 | * 报警布防/撤防命令 |
| 197 | - * | |
| 197 | + * | |
| 198 | 198 | * @param device 视频设备 |
| 199 | 199 | */ |
| 200 | 200 | void guardCmd(Device device, String guardCmdStr, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; |
| 201 | - | |
| 201 | + | |
| 202 | 202 | /** |
| 203 | 203 | * 报警复位命令 |
| 204 | - * | |
| 204 | + * | |
| 205 | 205 | * @param device 视频设备 |
| 206 | 206 | * @param alarmMethod 报警方式(可选) |
| 207 | 207 | * @param alarmType 报警类型(可选) |
| 208 | 208 | */ |
| 209 | 209 | void alarmCmd(Device device, String alarmMethod, String alarmType, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; |
| 210 | - | |
| 210 | + | |
| 211 | 211 | /** |
| 212 | 212 | * 强制关键帧命令,设备收到此命令应立刻发送一个IDR帧 |
| 213 | - * | |
| 213 | + * | |
| 214 | 214 | * @param device 视频设备 |
| 215 | 215 | * @param channelId 预览通道 |
| 216 | 216 | */ |
| ... | ... | @@ -230,58 +230,58 @@ public interface ISIPCommander { |
| 230 | 230 | |
| 231 | 231 | /** |
| 232 | 232 | * 设备配置命令 |
| 233 | - * | |
| 233 | + * | |
| 234 | 234 | * @param device 视频设备 |
| 235 | 235 | */ |
| 236 | 236 | void deviceConfigCmd(Device device); |
| 237 | - | |
| 237 | + | |
| 238 | 238 | /** |
| 239 | 239 | * 设备配置命令:basicParam |
| 240 | - * | |
| 240 | + * | |
| 241 | 241 | * @param device 视频设备 |
| 242 | 242 | * @param channelId 通道编码(可选) |
| 243 | 243 | * @param name 设备/通道名称(可选) |
| 244 | 244 | * @param expiration 注册过期时间(可选) |
| 245 | 245 | * @param heartBeatInterval 心跳间隔时间(可选) |
| 246 | 246 | * @param heartBeatCount 心跳超时次数(可选) |
| 247 | - */ | |
| 247 | + */ | |
| 248 | 248 | void deviceBasicConfigCmd(Device device, String channelId, String name, String expiration, String heartBeatInterval, String heartBeatCount, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 249 | 249 | |
| 250 | 250 | /** |
| 251 | 251 | * 查询设备状态 |
| 252 | - * | |
| 252 | + * | |
| 253 | 253 | * @param device 视频设备 |
| 254 | 254 | */ |
| 255 | 255 | void deviceStatusQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 256 | - | |
| 256 | + | |
| 257 | 257 | /** |
| 258 | 258 | * 查询设备信息 |
| 259 | - * | |
| 259 | + * | |
| 260 | 260 | * @param device 视频设备 |
| 261 | - * @return | |
| 261 | + * @return | |
| 262 | 262 | */ |
| 263 | 263 | void deviceInfoQuery(Device device) throws InvalidArgumentException, SipException, ParseException; |
| 264 | - | |
| 264 | + | |
| 265 | 265 | /** |
| 266 | 266 | * 查询目录列表 |
| 267 | - * | |
| 267 | + * | |
| 268 | 268 | * @param device 视频设备 |
| 269 | 269 | */ |
| 270 | 270 | void catalogQuery(Device device, int sn, SipSubscribe.Event errorEvent) throws SipException, InvalidArgumentException, ParseException; |
| 271 | - | |
| 271 | + | |
| 272 | 272 | /** |
| 273 | 273 | * 查询录像信息 |
| 274 | - * | |
| 274 | + * | |
| 275 | 275 | * @param device 视频设备 |
| 276 | 276 | * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss |
| 277 | 277 | * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss |
| 278 | 278 | * @param sn |
| 279 | 279 | */ |
| 280 | 280 | void recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, Integer Secrecy, String type, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 281 | - | |
| 281 | + | |
| 282 | 282 | /** |
| 283 | 283 | * 查询报警信息 |
| 284 | - * | |
| 284 | + * | |
| 285 | 285 | * @param device 视频设备 |
| 286 | 286 | * @param startPriority 报警起始级别(可选) |
| 287 | 287 | * @param endPriority 报警终止级别(可选) |
| ... | ... | @@ -293,33 +293,33 @@ public interface ISIPCommander { |
| 293 | 293 | */ |
| 294 | 294 | void alarmInfoQuery(Device device, String startPriority, String endPriority, String alarmMethod, |
| 295 | 295 | String alarmType, String startTime, String endTime, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 296 | - | |
| 296 | + | |
| 297 | 297 | /** |
| 298 | 298 | * 查询设备配置 |
| 299 | - * | |
| 299 | + * | |
| 300 | 300 | * @param device 视频设备 |
| 301 | 301 | * @param channelId 通道编码(可选) |
| 302 | 302 | * @param configType 配置类型: |
| 303 | 303 | */ |
| 304 | 304 | void deviceConfigQuery(Device device, String channelId, String configType, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 305 | - | |
| 305 | + | |
| 306 | 306 | /** |
| 307 | 307 | * 查询设备预置位置 |
| 308 | - * | |
| 308 | + * | |
| 309 | 309 | * @param device 视频设备 |
| 310 | 310 | */ |
| 311 | 311 | void presetQuery(Device device, String channelId, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 312 | - | |
| 312 | + | |
| 313 | 313 | /** |
| 314 | 314 | * 查询移动设备位置数据 |
| 315 | - * | |
| 315 | + * | |
| 316 | 316 | * @param device 视频设备 |
| 317 | 317 | */ |
| 318 | 318 | void mobilePostitionQuery(Device device, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; |
| 319 | 319 | |
| 320 | 320 | /** |
| 321 | 321 | * 订阅、取消订阅移动位置 |
| 322 | - * | |
| 322 | + * | |
| 323 | 323 | * @param device 视频设备 |
| 324 | 324 | * @return true = 命令发送成功 |
| 325 | 325 | */ | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| ... | ... | @@ -29,7 +29,6 @@ import org.springframework.beans.factory.annotation.Autowired; |
| 29 | 29 | import org.springframework.context.annotation.DependsOn; |
| 30 | 30 | import org.springframework.stereotype.Component; |
| 31 | 31 | import org.springframework.util.ObjectUtils; |
| 32 | -import org.springframework.util.StringUtils; | |
| 33 | 32 | |
| 34 | 33 | import javax.sip.InvalidArgumentException; |
| 35 | 34 | import javax.sip.ResponseEvent; |
| ... | ... | @@ -57,7 +56,7 @@ public class SIPCommander implements ISIPCommander { |
| 57 | 56 | |
| 58 | 57 | @Autowired |
| 59 | 58 | private SIPSender sipSender; |
| 60 | - | |
| 59 | + | |
| 61 | 60 | @Autowired |
| 62 | 61 | private SIPRequestHeaderProvider headerProvider; |
| 63 | 62 | |
| ... | ... | @@ -181,7 +180,7 @@ public class SIPCommander implements ISIPCommander { |
| 181 | 180 | ptzXml.append("<ControlPriority>5</ControlPriority>\r\n"); |
| 182 | 181 | ptzXml.append("</Info>\r\n"); |
| 183 | 182 | ptzXml.append("</Control>\r\n"); |
| 184 | - | |
| 183 | + | |
| 185 | 184 | Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null, sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 186 | 185 | |
| 187 | 186 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); |
| ... | ... | @@ -244,8 +243,8 @@ public class SIPCommander implements ISIPCommander { |
| 244 | 243 | ptzXml.append("<ControlPriority>5</ControlPriority>\r\n"); |
| 245 | 244 | ptzXml.append("</Info>\r\n"); |
| 246 | 245 | ptzXml.append("</Control>\r\n"); |
| 247 | - | |
| 248 | - | |
| 246 | + | |
| 247 | + | |
| 249 | 248 | Request request = headerProvider.createMessageRequest(device, ptzXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 250 | 249 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request, errorEvent, okEvent); |
| 251 | 250 | |
| ... | ... | @@ -365,7 +364,8 @@ public class SIPCommander implements ISIPCommander { |
| 365 | 364 | */ |
| 366 | 365 | @Override |
| 367 | 366 | public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 368 | - String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | |
| 367 | + String startTime, String endTime, | |
| 368 | + InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | |
| 369 | 369 | SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { |
| 370 | 370 | |
| 371 | 371 | |
| ... | ... | @@ -411,7 +411,8 @@ public class SIPCommander implements ISIPCommander { |
| 411 | 411 | content.append("a=setup:active\r\n"); |
| 412 | 412 | content.append("a=connection:new\r\n"); |
| 413 | 413 | } |
| 414 | - } else { | |
| 414 | + } else | |
| 415 | + { | |
| 415 | 416 | if ("TCP-PASSIVE".equalsIgnoreCase(streamMode)) { |
| 416 | 417 | content.append("m=video " + ssrcInfo.getPort() + " TCP/RTP/AVP 96 97 98 99\r\n"); |
| 417 | 418 | } else if ("TCP-ACTIVE".equalsIgnoreCase(streamMode)) { |
| ... | ... | @@ -471,8 +472,9 @@ public class SIPCommander implements ISIPCommander { |
| 471 | 472 | */ |
| 472 | 473 | @Override |
| 473 | 474 | public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, |
| 474 | - String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | |
| 475 | - SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 475 | + String startTime, String endTime, int downloadSpeed, | |
| 476 | + InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, | |
| 477 | + SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { | |
| 476 | 478 | |
| 477 | 479 | logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); |
| 478 | 480 | String sdpIp; |
| ... | ... | @@ -541,10 +543,11 @@ public class SIPCommander implements ISIPCommander { |
| 541 | 543 | content.append("a=downloadspeed:" + downloadSpeed + "\r\n"); |
| 542 | 544 | |
| 543 | 545 | content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc |
| 544 | - | |
| 546 | + | |
| 545 | 547 | HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, null, mediaServerItem.getId()); |
| 546 | 548 | // 添加订阅 |
| 547 | - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { | |
| 549 | + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> | |
| 550 | + { | |
| 548 | 551 | hookEvent.call(new InviteStreamInfo(mediaServerItem, json,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); |
| 549 | 552 | subscribe.removeSubscribe(hookSubscribe); |
| 550 | 553 | hookSubscribe.getContent().put("regist", false); |
| ... | ... | @@ -567,10 +570,11 @@ public class SIPCommander implements ISIPCommander { |
| 567 | 570 | inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream())); |
| 568 | 571 | } |
| 569 | 572 | |
| 570 | - sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, okEvent -> { | |
| 571 | - ResponseEvent responseEvent = (ResponseEvent) okEvent.event; | |
| 573 | + sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { | |
| 574 | + ResponseEvent responseEvent = (ResponseEvent) event.event; | |
| 572 | 575 | SIPResponse response = (SIPResponse) responseEvent.getResponse(); |
| 573 | 576 | streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download); |
| 577 | + okEvent.response(event); | |
| 574 | 578 | }); |
| 575 | 579 | } |
| 576 | 580 | |
| ... | ... | @@ -628,7 +632,7 @@ public class SIPCommander implements ISIPCommander { |
| 628 | 632 | broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n"); |
| 629 | 633 | broadcastXml.append("</Notify>\r\n"); |
| 630 | 634 | |
| 631 | - | |
| 635 | + | |
| 632 | 636 | |
| 633 | 637 | Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 634 | 638 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); |
| ... | ... | @@ -648,7 +652,7 @@ public class SIPCommander implements ISIPCommander { |
| 648 | 652 | broadcastXml.append("<TargetID>" + device.getDeviceId() + "</TargetID>\r\n"); |
| 649 | 653 | broadcastXml.append("</Notify>\r\n"); |
| 650 | 654 | |
| 651 | - | |
| 655 | + | |
| 652 | 656 | |
| 653 | 657 | Request request = headerProvider.createMessageRequest(device, broadcastXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 654 | 658 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); |
| ... | ... | @@ -679,7 +683,7 @@ public class SIPCommander implements ISIPCommander { |
| 679 | 683 | cmdXml.append("<RecordCmd>" + recordCmdStr + "</RecordCmd>\r\n"); |
| 680 | 684 | cmdXml.append("</Control>\r\n"); |
| 681 | 685 | |
| 682 | - | |
| 686 | + | |
| 683 | 687 | |
| 684 | 688 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 685 | 689 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); |
| ... | ... | @@ -703,7 +707,7 @@ public class SIPCommander implements ISIPCommander { |
| 703 | 707 | cmdXml.append("<TeleBoot>Boot</TeleBoot>\r\n"); |
| 704 | 708 | cmdXml.append("</Control>\r\n"); |
| 705 | 709 | |
| 706 | - | |
| 710 | + | |
| 707 | 711 | |
| 708 | 712 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 709 | 713 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); |
| ... | ... | @@ -762,7 +766,7 @@ public class SIPCommander implements ISIPCommander { |
| 762 | 766 | } |
| 763 | 767 | cmdXml.append("</Control>\r\n"); |
| 764 | 768 | |
| 765 | - | |
| 769 | + | |
| 766 | 770 | |
| 767 | 771 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 768 | 772 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); |
| ... | ... | @@ -791,7 +795,7 @@ public class SIPCommander implements ISIPCommander { |
| 791 | 795 | cmdXml.append("<IFameCmd>Send</IFameCmd>\r\n"); |
| 792 | 796 | cmdXml.append("</Control>\r\n"); |
| 793 | 797 | |
| 794 | - | |
| 798 | + | |
| 795 | 799 | |
| 796 | 800 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 797 | 801 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); |
| ... | ... | @@ -802,7 +806,6 @@ public class SIPCommander implements ISIPCommander { |
| 802 | 806 | * |
| 803 | 807 | * @param device 视频设备 |
| 804 | 808 | * @param channelId 通道id,非通道则是设备本身 |
| 805 | - * @param frontCmd 上级平台的指令,如果存在则直接下发 | |
| 806 | 809 | * @param enabled 看守位使能:1 = 开启,0 = 关闭 |
| 807 | 810 | * @param resetTime 自动归位时间间隔,开启看守位时使用,单位:秒(s) |
| 808 | 811 | * @param presetIndex 调用预置位编号,开启看守位时使用,取值范围0~255 |
| ... | ... | @@ -840,7 +843,7 @@ public class SIPCommander implements ISIPCommander { |
| 840 | 843 | cmdXml.append("</HomePosition>\r\n"); |
| 841 | 844 | cmdXml.append("</Control>\r\n"); |
| 842 | 845 | |
| 843 | - | |
| 846 | + | |
| 844 | 847 | |
| 845 | 848 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 846 | 849 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent,okEvent); |
| ... | ... | @@ -903,7 +906,7 @@ public class SIPCommander implements ISIPCommander { |
| 903 | 906 | cmdXml.append("</BasicParam>\r\n"); |
| 904 | 907 | cmdXml.append("</Control>\r\n"); |
| 905 | 908 | |
| 906 | - | |
| 909 | + | |
| 907 | 910 | |
| 908 | 911 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 909 | 912 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); |
| ... | ... | @@ -926,7 +929,7 @@ public class SIPCommander implements ISIPCommander { |
| 926 | 929 | catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); |
| 927 | 930 | catalogXml.append("</Query>\r\n"); |
| 928 | 931 | |
| 929 | - | |
| 932 | + | |
| 930 | 933 | |
| 931 | 934 | Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 932 | 935 | |
| ... | ... | @@ -950,7 +953,7 @@ public class SIPCommander implements ISIPCommander { |
| 950 | 953 | catalogXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); |
| 951 | 954 | catalogXml.append("</Query>\r\n"); |
| 952 | 955 | |
| 953 | - | |
| 956 | + | |
| 954 | 957 | |
| 955 | 958 | Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 956 | 959 | |
| ... | ... | @@ -975,7 +978,7 @@ public class SIPCommander implements ISIPCommander { |
| 975 | 978 | catalogXml.append(" <DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); |
| 976 | 979 | catalogXml.append("</Query>\r\n"); |
| 977 | 980 | |
| 978 | - | |
| 981 | + | |
| 979 | 982 | |
| 980 | 983 | Request request = headerProvider.createMessageRequest(device, catalogXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 981 | 984 | |
| ... | ... | @@ -1020,7 +1023,7 @@ public class SIPCommander implements ISIPCommander { |
| 1020 | 1023 | } |
| 1021 | 1024 | recordInfoXml.append("</Query>\r\n"); |
| 1022 | 1025 | |
| 1023 | - | |
| 1026 | + | |
| 1024 | 1027 | |
| 1025 | 1028 | Request request = headerProvider.createMessageRequest(device, recordInfoXml.toString(), |
| 1026 | 1029 | SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| ... | ... | @@ -1071,7 +1074,7 @@ public class SIPCommander implements ISIPCommander { |
| 1071 | 1074 | } |
| 1072 | 1075 | cmdXml.append("</Query>\r\n"); |
| 1073 | 1076 | |
| 1074 | - | |
| 1077 | + | |
| 1075 | 1078 | |
| 1076 | 1079 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1077 | 1080 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); |
| ... | ... | @@ -1101,7 +1104,7 @@ public class SIPCommander implements ISIPCommander { |
| 1101 | 1104 | cmdXml.append("<ConfigType>" + configType + "</ConfigType>\r\n"); |
| 1102 | 1105 | cmdXml.append("</Query>\r\n"); |
| 1103 | 1106 | |
| 1104 | - | |
| 1107 | + | |
| 1105 | 1108 | |
| 1106 | 1109 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1107 | 1110 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); |
| ... | ... | @@ -1128,7 +1131,7 @@ public class SIPCommander implements ISIPCommander { |
| 1128 | 1131 | } |
| 1129 | 1132 | cmdXml.append("</Query>\r\n"); |
| 1130 | 1133 | |
| 1131 | - | |
| 1134 | + | |
| 1132 | 1135 | |
| 1133 | 1136 | Request request = headerProvider.createMessageRequest(device, cmdXml.toString(), null, SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1134 | 1137 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent); |
| ... | ... | @@ -1152,7 +1155,7 @@ public class SIPCommander implements ISIPCommander { |
| 1152 | 1155 | mobilePostitionXml.append("<Interval>60</Interval>\r\n"); |
| 1153 | 1156 | mobilePostitionXml.append("</Query>\r\n"); |
| 1154 | 1157 | |
| 1155 | - | |
| 1158 | + | |
| 1156 | 1159 | |
| 1157 | 1160 | Request request = headerProvider.createMessageRequest(device, mobilePostitionXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1158 | 1161 | |
| ... | ... | @@ -1237,7 +1240,7 @@ public class SIPCommander implements ISIPCommander { |
| 1237 | 1240 | } |
| 1238 | 1241 | cmdXml.append("</Query>\r\n"); |
| 1239 | 1242 | |
| 1240 | - | |
| 1243 | + | |
| 1241 | 1244 | |
| 1242 | 1245 | Request request = headerProvider.createSubscribeRequest(device, cmdXml.toString(), null, expires, "presence",sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1243 | 1246 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request); |
| ... | ... | @@ -1287,14 +1290,14 @@ public class SIPCommander implements ISIPCommander { |
| 1287 | 1290 | } |
| 1288 | 1291 | dragXml.append(cmdString); |
| 1289 | 1292 | dragXml.append("</Control>\r\n"); |
| 1290 | - | |
| 1293 | + | |
| 1291 | 1294 | Request request = headerProvider.createMessageRequest(device, dragXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1292 | 1295 | logger.debug("拉框信令: " + request.toString()); |
| 1293 | 1296 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); |
| 1294 | 1297 | } |
| 1295 | 1298 | |
| 1296 | 1299 | |
| 1297 | - | |
| 1300 | + | |
| 1298 | 1301 | |
| 1299 | 1302 | |
| 1300 | 1303 | /** |
| ... | ... | @@ -1398,7 +1401,7 @@ public class SIPCommander implements ISIPCommander { |
| 1398 | 1401 | deviceStatusXml.append("</info>\r\n"); |
| 1399 | 1402 | deviceStatusXml.append("</Notify>\r\n"); |
| 1400 | 1403 | |
| 1401 | - | |
| 1404 | + | |
| 1402 | 1405 | Request request = headerProvider.createMessageRequest(device, deviceStatusXml.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport())); |
| 1403 | 1406 | sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()),request); |
| 1404 | 1407 | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| ... | ... | @@ -258,7 +258,8 @@ public class PlayServiceImpl implements IPlayService { |
| 258 | 258 | return; |
| 259 | 259 | } |
| 260 | 260 | try { |
| 261 | - cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { | |
| 261 | + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> | |
| 262 | + { | |
| 262 | 263 | logger.info("收到订阅消息: " + response.toJSONString()); |
| 263 | 264 | dynamicTask.stop(timeOutTaskKey); |
| 264 | 265 | |
| ... | ... | @@ -273,7 +274,8 @@ public class PlayServiceImpl implements IPlayService { |
| 273 | 274 | logger.info("[请求截图]: " + fileName); |
| 274 | 275 | zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); |
| 275 | 276 | |
| 276 | - }, (event) -> { | |
| 277 | + }, (event) -> | |
| 278 | + { | |
| 277 | 279 | ResponseEvent responseEvent = (ResponseEvent) event.event; |
| 278 | 280 | String contentString = new String(responseEvent.getResponse().getRawContent()); |
| 279 | 281 | // 获取ssrc |
| ... | ... | @@ -322,7 +324,8 @@ public class PlayServiceImpl implements IPlayService { |
| 322 | 324 | |
| 323 | 325 | } |
| 324 | 326 | } |
| 325 | - }, (event) -> { | |
| 327 | + }, (event) -> | |
| 328 | + { | |
| 326 | 329 | dynamicTask.stop(timeOutTaskKey); |
| 327 | 330 | mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); |
| 328 | 331 | // 释放ssrc |
| ... | ... | @@ -513,7 +516,8 @@ public class PlayServiceImpl implements IPlayService { |
| 513 | 516 | |
| 514 | 517 | try { |
| 515 | 518 | cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack, |
| 516 | - hookEvent, eventResult -> { | |
| 519 | + hookEvent, eventResult -> | |
| 520 | + { | |
| 517 | 521 | if (eventResult.type == SipSubscribe.EventResultType.response) { |
| 518 | 522 | ResponseEvent responseEvent = (ResponseEvent) eventResult.event; |
| 519 | 523 | String contentString = new String(responseEvent.getResponse().getRawContent()); |
| ... | ... | @@ -582,6 +586,7 @@ public class PlayServiceImpl implements IPlayService { |
| 582 | 586 | if (device == null) { |
| 583 | 587 | return; |
| 584 | 588 | } |
| 589 | + //获取录像下载的服务,配置文件中的record-assist-port不为0 | |
| 585 | 590 | MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device); |
| 586 | 591 | if (newMediaServerItem == null) { |
| 587 | 592 | PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>(); |
| ... | ... | @@ -651,7 +656,59 @@ public class PlayServiceImpl implements IPlayService { |
| 651 | 656 | downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem()); |
| 652 | 657 | downloadResult.setResponse(inviteStreamInfo.getResponse()); |
| 653 | 658 | hookCallBack.call(downloadResult); |
| 654 | - }, errorEvent); | |
| 659 | + }, errorEvent, eventResult -> | |
| 660 | + { | |
| 661 | + if (eventResult.type == SipSubscribe.EventResultType.response) { | |
| 662 | + ResponseEvent responseEvent = (ResponseEvent) eventResult.event; | |
| 663 | + String contentString = new String(responseEvent.getResponse().getRawContent()); | |
| 664 | + // 获取ssrc | |
| 665 | + int ssrcIndex = contentString.indexOf("y="); | |
| 666 | + // 检查是否有y字段 | |
| 667 | + if (ssrcIndex >= 0) { | |
| 668 | + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容 | |
| 669 | + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); | |
| 670 | + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理 | |
| 671 | + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) { | |
| 672 | + return; | |
| 673 | + } | |
| 674 | + logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse); | |
| 675 | + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) { | |
| 676 | + logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse); | |
| 677 | + | |
| 678 | + if (!mediaServerItem.getSsrcConfig().checkSsrc(ssrcInResponse)) { | |
| 679 | + // ssrc 不可用 | |
| 680 | + // 释放ssrc | |
| 681 | + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); | |
| 682 | + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); | |
| 683 | + eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用"; | |
| 684 | + eventResult.statusCode = 400; | |
| 685 | + errorEvent.response(eventResult); | |
| 686 | + return; | |
| 687 | + } | |
| 688 | + | |
| 689 | + // 单端口模式streamId也有变化,需要重新设置监听 | |
| 690 | + if (!mediaServerItem.isRtpEnable()) { | |
| 691 | + // 添加订阅 | |
| 692 | + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); | |
| 693 | + subscribe.removeSubscribe(hookSubscribe); | |
| 694 | + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase()); | |
| 695 | + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { | |
| 696 | + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString()); | |
| 697 | + dynamicTask.stop(downLoadTimeOutTaskKey); | |
| 698 | + // hook响应,TODO 此处待处理 | |
| 699 | +// onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, playBackCallback); | |
| 700 | +// hookCallBack.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream())); | |
| 701 | + }); | |
| 702 | + } | |
| 703 | + // 关闭rtp server | |
| 704 | + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); | |
| 705 | + // 重新开启ssrc server | |
| 706 | + mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort()); | |
| 707 | + } | |
| 708 | + } | |
| 709 | + } | |
| 710 | + | |
| 711 | + }); | |
| 655 | 712 | } catch (InvalidArgumentException | SipException | ParseException e) { |
| 656 | 713 | logger.error("[命令发送失败] 录像下载: {}", e.getMessage()); |
| 657 | 714 | ... | ... |