Commit c429a34e5390b0245da276c2c03a6116822167c3

Authored by 648540858
1 parent 490c5538

修复国标视频点播三种级联并发点播和录像下载的问题

Showing 20 changed files with 515 additions and 673 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -4,7 +4,6 @@ import com.genersoft.iot.vmp.common.StreamInfo; @@ -4,7 +4,6 @@ import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 4 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; 6 import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm;
7 -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;  
8 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 7 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
9 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; 8 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 9 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
@@ -109,7 +108,7 @@ public interface ISIPCommander { @@ -109,7 +108,7 @@ public interface ISIPCommander {
109 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss 108 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
110 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss 109 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
111 */ 110 */
112 - void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,InviteStreamCallback inviteStreamCallback, InviteStreamCallback event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; 111 + void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
113 112
114 /** 113 /**
115 * 请求历史媒体下载 114 * 请求历史媒体下载
@@ -121,7 +120,7 @@ public interface ISIPCommander { @@ -121,7 +120,7 @@ public interface ISIPCommander {
121 * @param downloadSpeed 下载倍速参数 120 * @param downloadSpeed 下载倍速参数
122 */ 121 */
123 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 122 void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
124 - String startTime, String endTime, int downloadSpeed, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, 123 + String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent,
125 SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; 124 SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException;
126 125
127 /** 126 /**
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -366,11 +366,11 @@ public class SIPCommander implements ISIPCommander { @@ -366,11 +366,11 @@ public class SIPCommander implements ISIPCommander {
366 */ 366 */
367 @Override 367 @Override
368 public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 368 public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
369 - String startTime, String endTime, InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, 369 + String startTime, String endTime, ZlmHttpHookSubscribe.Event hookEvent,
370 SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { 370 SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException {
371 371
372 372
373 - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort()); 373 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
374 String sdpIp; 374 String sdpIp;
375 if (!ObjectUtils.isEmpty(device.getSdpIp())) { 375 if (!ObjectUtils.isEmpty(device.getSdpIp())) {
376 sdpIp = device.getSdpIp(); 376 sdpIp = device.getSdpIp();
@@ -443,8 +443,7 @@ public class SIPCommander implements ISIPCommander { @@ -443,8 +443,7 @@ public class SIPCommander implements ISIPCommander {
443 // 添加订阅 443 // 添加订阅
444 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { 444 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
445 if (hookEvent != null) { 445 if (hookEvent != null) {
446 - InviteStreamInfo inviteStreamInfo = new InviteStreamInfo(mediaServerItemInUse, json,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream());  
447 - hookEvent.call(inviteStreamInfo); 446 + hookEvent.response(mediaServerItemInUse, json);
448 } 447 }
449 subscribe.removeSubscribe(hookSubscribe); 448 subscribe.removeSubscribe(hookSubscribe);
450 }); 449 });
@@ -456,9 +455,6 @@ public class SIPCommander implements ISIPCommander { @@ -456,9 +455,6 @@ public class SIPCommander implements ISIPCommander {
456 streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAYBACK); 455 streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, InviteSessionType.PLAYBACK);
457 okEvent.response(event); 456 okEvent.response(event);
458 }); 457 });
459 - if (inviteStreamCallback != null) {  
460 - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), "rtp", ssrcInfo.getStream()));  
461 - }  
462 } 458 }
463 459
464 /** 460 /**
@@ -473,10 +469,10 @@ public class SIPCommander implements ISIPCommander { @@ -473,10 +469,10 @@ public class SIPCommander implements ISIPCommander {
473 @Override 469 @Override
474 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 470 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
475 String startTime, String endTime, int downloadSpeed, 471 String startTime, String endTime, int downloadSpeed,
476 - InviteStreamCallback inviteStreamCallback, InviteStreamCallback hookEvent, 472 + ZlmHttpHookSubscribe.Event hookEvent,
477 SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { 473 SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException {
478 474
479 - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getSdpIp(), mediaServerItem.getIp(), ssrcInfo.getPort()); 475 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort());
480 String sdpIp; 476 String sdpIp;
481 if (!ObjectUtils.isEmpty(device.getSdpIp())) { 477 if (!ObjectUtils.isEmpty(device.getSdpIp())) {
482 sdpIp = device.getSdpIp(); 478 sdpIp = device.getSdpIp();
@@ -550,7 +546,7 @@ public class SIPCommander implements ISIPCommander { @@ -550,7 +546,7 @@ public class SIPCommander implements ISIPCommander {
550 String callId= newCallIdHeader.getCallId(); 546 String callId= newCallIdHeader.getCallId();
551 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> { 547 subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject json) -> {
552 logger.debug("sipc 添加订阅===callId {}",callId); 548 logger.debug("sipc 添加订阅===callId {}",callId);
553 - hookEvent.call(new InviteStreamInfo(mediaServerItem, json,callId, "rtp", ssrcInfo.getStream())); 549 + hookEvent.response(mediaServerItemInUse, json);
554 subscribe.removeSubscribe(hookSubscribe); 550 subscribe.removeSubscribe(hookSubscribe);
555 hookSubscribe.getContent().put("regist", false); 551 hookSubscribe.getContent().put("regist", false);
556 hookSubscribe.getContent().put("schema", "rtsp"); 552 hookSubscribe.getContent().put("schema", "rtsp");
@@ -568,9 +564,6 @@ public class SIPCommander implements ISIPCommander { @@ -568,9 +564,6 @@ public class SIPCommander implements ISIPCommander {
568 }); 564 });
569 565
570 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc()); 566 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, SipUtils.getNewFromTag(), null,newCallIdHeader, ssrcInfo.getSsrc());
571 - if (inviteStreamCallback != null) {  
572 - inviteStreamCallback.call(new InviteStreamInfo(mediaServerItem, null,callId, "rtp", ssrcInfo.getStream()));  
573 - }  
574 567
575 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { 568 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
576 ResponseEvent responseEvent = (ResponseEvent) event.event; 569 ResponseEvent responseEvent = (ResponseEvent) event.event;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
@@ -356,7 +356,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -356,7 +356,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
356 }else { 356 }else {
357 streamTypeStr = "UDP"; 357 streamTypeStr = "UDP";
358 } 358 }
359 - logger.info("[上级点播] 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", username, channelId, addressStr, port, streamTypeStr, ssrc); 359 + logger.info("[上级Invite] {}, 平台:{}, 通道:{}, 收流地址:{}:{},收流方式:{}, ssrc:{}", sessionName, username, channelId, addressStr, port, streamTypeStr, ssrc);
360 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, 360 SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId,
361 device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp()); 361 device.getDeviceId(), channelId, mediaTransmissionTCP, platform.isRtcp());
362 362
@@ -380,7 +380,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -380,7 +380,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
380 InviteErrorCallback<Object> hookEvent = (code, msg, data) -> { 380 InviteErrorCallback<Object> hookEvent = (code, msg, data) -> {
381 StreamInfo streamInfo = (StreamInfo)data; 381 StreamInfo streamInfo = (StreamInfo)data;
382 MediaServerItem mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId()); 382 MediaServerItem mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId());
383 - logger.info("[上级点播]下级已经开始推流。 回复200OK(SDP), {}/{}", streamInfo.getApp(), streamInfo.getStream()); 383 + logger.info("[上级Invite]下级已经开始推流。 回复200OK(SDP), {}/{}", streamInfo.getApp(), streamInfo.getStream());
384 // * 0 等待设备推流上来 384 // * 0 等待设备推流上来
385 // * 1 下级已经推流,等待上级平台回复ack 385 // * 1 下级已经推流,等待上级平台回复ack
386 // * 2 推流中 386 // * 2 推流中
@@ -443,22 +443,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -443,22 +443,16 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
443 // 写入redis, 超时时回复 443 // 写入redis, 超时时回复
444 redisCatchStorage.updateSendRTPSever(sendRtpItem); 444 redisCatchStorage.updateSendRTPSever(sendRtpItem);
445 playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), 445 playService.playBack(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start),
446 - DateUtil.formatter.format(end), null, result -> {  
447 - if (result.getCode() != 0) {  
448 - logger.warn("录像回放失败");  
449 - if (result.getEvent() != null) {  
450 -// errorEvent.response(result.getEvent());  
451 - } 446 + DateUtil.formatter.format(end),
  447 + (code, msg, data) -> {
  448 + if (code == InviteErrorCode.SUCCESS.getCode()){
  449 + hookEvent.run(code, msg, data);
  450 + }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){
  451 + logger.info("[录像回放]超时, 用户:{}, 通道:{}", username, channelId);
452 redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); 452 redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
453 - try {  
454 - responseAck(request, Response.REQUEST_TIMEOUT);  
455 - } catch (SipException | InvalidArgumentException | ParseException e) {  
456 - logger.error("[命令发送失败] 国标级联 录像回放 发送REQUEST_TIMEOUT: {}", e.getMessage());  
457 - }  
458 - } else {  
459 - if (result.getMediaServerItem() != null) {  
460 -// hookEvent.response(result.getMediaServerItem(), result.getResponse());  
461 - } 453 + errorEvent.run(code, msg, data);
  454 + }else {
  455 + errorEvent.run(code, msg, data);
462 } 456 }
463 }); 457 });
464 } else { 458 } else {
@@ -477,6 +471,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements @@ -477,6 +471,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements
477 }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){ 471 }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){
478 logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId); 472 logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId);
479 redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); 473 redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null);
  474 + errorEvent.run(code, msg, data);
480 }else { 475 }else {
481 errorEvent.run(code, msg, data); 476 errorEvent.run(code, msg, data);
482 } 477 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/RegisterRequestProcessor.java
@@ -80,7 +80,6 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -80,7 +80,6 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
80 public void process(RequestEvent evt) { 80 public void process(RequestEvent evt) {
81 try { 81 try {
82 RequestEventExt evtExt = (RequestEventExt) evt; 82 RequestEventExt evtExt = (RequestEventExt) evt;
83 - String requestAddress = evtExt.getRemoteIpAddress() + ":" + evtExt.getRemotePort();  
84 83
85 SIPRequest request = (SIPRequest)evt.getRequest(); 84 SIPRequest request = (SIPRequest)evt.getRequest();
86 Response response = null; 85 Response response = null;
@@ -91,12 +90,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen @@ -91,12 +90,13 @@ public class RegisterRequestProcessor extends SIPRequestProcessorParent implemen
91 AddressImpl address = (AddressImpl) fromHeader.getAddress(); 90 AddressImpl address = (AddressImpl) fromHeader.getAddress();
92 SipUri uri = (SipUri) address.getURI(); 91 SipUri uri = (SipUri) address.getURI();
93 String deviceId = uri.getUser(); 92 String deviceId = uri.getUser();
94 - logger.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress); 93 +
95 Device device = deviceService.getDevice(deviceId); 94 Device device = deviceService.getDevice(deviceId);
96 95
97 RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request, 96 RemoteAddressInfo remoteAddressInfo = SipUtils.getRemoteAddressFromRequest(request,
98 userSetting.getSipUseSourceIpAsRemoteAddress()); 97 userSetting.getSipUseSourceIpAsRemoteAddress());
99 - logger.info("[注册请求] 设备:{}, 远程地址为: {}:{}", deviceId, remoteAddressInfo.getIp(), remoteAddressInfo.getPort()); 98 + String requestAddress = remoteAddressInfo.getIp() + ":" + remoteAddressInfo.getPort();
  99 + logger.info("[注册请求] 设备:{}, 开始处理: {}", deviceId, requestAddress);
100 if (device != null && 100 if (device != null &&
101 device.getSipTransactionInfo() != null && 101 device.getSipTransactionInfo() != null &&
102 request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) { 102 request.getCallIdHeader().getCallId().equals(device.getSipTransactionInfo().getCallId())) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/info/InfoRequestProcessor.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.info; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.info;
2 2
3 -import com.genersoft.iot.vmp.common.StreamInfo; 3 +import com.genersoft.iot.vmp.common.InviteInfo;
  4 +import com.genersoft.iot.vmp.common.InviteSessionType;
4 import com.genersoft.iot.vmp.gb28181.bean.*; 5 import com.genersoft.iot.vmp.gb28181.bean.*;
5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 6 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 7 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
@@ -9,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; @@ -9,6 +10,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
9 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; 10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor;
10 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
11 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 12 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
  13 +import com.genersoft.iot.vmp.service.IInviteStreamService;
12 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
13 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
14 import gov.nist.javax.sip.message.SIPRequest; 16 import gov.nist.javax.sip.message.SIPRequest;
@@ -17,10 +19,12 @@ import org.slf4j.LoggerFactory; @@ -17,10 +19,12 @@ import org.slf4j.LoggerFactory;
17 import org.springframework.beans.factory.InitializingBean; 19 import org.springframework.beans.factory.InitializingBean;
18 import org.springframework.beans.factory.annotation.Autowired; 20 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.stereotype.Component; 21 import org.springframework.stereotype.Component;
  22 +
20 import javax.sip.InvalidArgumentException; 23 import javax.sip.InvalidArgumentException;
21 import javax.sip.RequestEvent; 24 import javax.sip.RequestEvent;
22 import javax.sip.SipException; 25 import javax.sip.SipException;
23 -import javax.sip.header.*; 26 +import javax.sip.header.CallIdHeader;
  27 +import javax.sip.header.ContentTypeHeader;
24 import javax.sip.message.Response; 28 import javax.sip.message.Response;
25 import java.text.ParseException; 29 import java.text.ParseException;
26 30
@@ -44,6 +48,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I @@ -44,6 +48,9 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
44 private IRedisCatchStorage redisCatchStorage; 48 private IRedisCatchStorage redisCatchStorage;
45 49
46 @Autowired 50 @Autowired
  51 + private IInviteStreamService inviteStreamService;
  52 +
  53 + @Autowired
47 private IVideoManagerStorage storager; 54 private IVideoManagerStorage storager;
48 55
49 @Autowired 56 @Autowired
@@ -103,27 +110,30 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I @@ -103,27 +110,30 @@ public class InfoRequestProcessor extends SIPRequestProcessorParent implements I
103 if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) { 110 if ("Application".equalsIgnoreCase(contentType) && "MANSRTSP".equalsIgnoreCase(contentSubType)) {
104 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId()); 111 SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId());
105 String streamId = sendRtpItem.getStreamId(); 112 String streamId = sendRtpItem.getStreamId();
106 - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);  
107 - if (null == streamInfo) { 113 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
  114 + if (null == inviteInfo) {
108 responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found"); 115 responseAck(request, Response.NOT_FOUND, "stream " + streamId + " not found");
109 return; 116 return;
110 } 117 }
111 - Device device1 = storager.queryVideoDevice(streamInfo.getDeviceID());  
112 - cmder.playbackControlCmd(device1,streamInfo,new String(evt.getRequest().getRawContent()),eventResult -> {  
113 - // 失败的回复  
114 - try {  
115 - responseAck(request, eventResult.statusCode, eventResult.msg);  
116 - } catch (SipException | InvalidArgumentException | ParseException e) {  
117 - logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());  
118 - }  
119 - }, eventResult -> {  
120 - // 成功的回复  
121 - try {  
122 - responseAck(request, eventResult.statusCode);  
123 - } catch (SipException | InvalidArgumentException | ParseException e) {  
124 - logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());  
125 - }  
126 - }); 118 + Device device1 = storager.queryVideoDevice(inviteInfo.getDeviceId());
  119 + if (inviteInfo.getStreamInfo() != null) {
  120 + cmder.playbackControlCmd(device1,inviteInfo.getStreamInfo(),new String(evt.getRequest().getRawContent()),eventResult -> {
  121 + // 失败的回复
  122 + try {
  123 + responseAck(request, eventResult.statusCode, eventResult.msg);
  124 + } catch (SipException | InvalidArgumentException | ParseException e) {
  125 + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
  126 + }
  127 + }, eventResult -> {
  128 + // 成功的回复
  129 + try {
  130 + responseAck(request, eventResult.statusCode);
  131 + } catch (SipException | InvalidArgumentException | ParseException e) {
  132 + logger.error("[命令发送失败] 国标级联 录像控制: {}", e.getMessage());
  133 + }
  134 + });
  135 + }
  136 +
127 } 137 }
128 } 138 }
129 } catch (SipException e) { 139 } catch (SipException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; 1 package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd;
2 2
3 -import com.genersoft.iot.vmp.common.StreamInfo; 3 +import com.genersoft.iot.vmp.common.InviteInfo;
  4 +import com.genersoft.iot.vmp.common.InviteSessionType;
4 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 5 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; 7 import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
@@ -15,6 +16,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify. @@ -15,6 +16,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.
15 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; 16 import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe;
16 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; 17 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
17 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; 18 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
  19 +import com.genersoft.iot.vmp.service.IInviteStreamService;
18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
19 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 21 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
20 import gov.nist.javax.sip.message.SIPRequest; 22 import gov.nist.javax.sip.message.SIPRequest;
@@ -64,6 +66,12 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i @@ -64,6 +66,12 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
64 @Autowired 66 @Autowired
65 private ZlmHttpHookSubscribe subscribe; 67 private ZlmHttpHookSubscribe subscribe;
66 68
  69 + @Autowired
  70 + private IInviteStreamService inviteStreamService;
  71 +
  72 + @Autowired
  73 + private VideoStreamSessionManager streamSession;
  74 +
67 @Override 75 @Override
68 public void afterPropertiesSet() throws Exception { 76 public void afterPropertiesSet() throws Exception {
69 notifyMessageHandler.addHandler(cmdType, this); 77 notifyMessageHandler.addHandler(cmdType, this);
@@ -82,17 +90,15 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i @@ -82,17 +90,15 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
82 String NotifyType =getText(rootElement, "NotifyType"); 90 String NotifyType =getText(rootElement, "NotifyType");
83 if ("121".equals(NotifyType)){ 91 if ("121".equals(NotifyType)){
84 logger.info("[录像流]推送完毕,收到关流通知"); 92 logger.info("[录像流]推送完毕,收到关流通知");
85 - // 查询是设备  
86 - StreamInfo streamInfo = redisCatchStorage.queryDownload(null, null, null, callIdHeader.getCallId());  
87 - if (streamInfo != null) {  
88 - // 设置进度100%  
89 - streamInfo.setProgress(1);  
90 - redisCatchStorage.startDownload(streamInfo, callIdHeader.getCallId());  
91 - }  
92 93
93 - // 先从会话内查找  
94 - SsrcTransaction ssrcTransaction = sessionManager.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);  
95 - if (ssrcTransaction != null) { // 兼容海康 媒体通知 消息from字段不是设备ID的问题 94 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
  95 + if (ssrcTransaction != null) {
  96 + logger.info("[录像流]推送完毕,关流通知, device: {}, channelId: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
  97 + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId(), ssrcTransaction.getStream());
  98 + if (inviteInfo.getStreamInfo() != null) {
  99 + inviteInfo.getStreamInfo().setProgress(1);
  100 + inviteStreamService.updateInviteInfo(inviteInfo);
  101 + }
96 102
97 try { 103 try {
98 cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId()); 104 cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), null, callIdHeader.getCallId());
@@ -117,6 +123,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i @@ -117,6 +123,8 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
117 logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage()); 123 logger.error("[命令发送失败] 国标级联 录像播放完毕: {}", e.getMessage());
118 } 124 }
119 } 125 }
  126 + }else {
  127 + logger.info("[录像流]推送完毕,关流通知, 但是未找到对应的下载信息");
120 } 128 }
121 } 129 }
122 } 130 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -451,6 +451,11 @@ public class ZLMHttpHookListener { @@ -451,6 +451,11 @@ public class ZLMHttpHookListener {
451 InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); 451 InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream());
452 // 点播 452 // 点播
453 if (inviteInfo != null) { 453 if (inviteInfo != null) {
  454 + // 录像下载
  455 + if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) {
  456 + ret.put("close", false);
  457 + return ret;
  458 + }
454 // 收到无人观看说明流也没有在往上级推送 459 // 收到无人观看说明流也没有在往上级推送
455 if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { 460 if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) {
456 List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId( 461 List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(
@@ -486,36 +491,6 @@ public class ZLMHttpHookListener { @@ -486,36 +491,6 @@ public class ZLMHttpHookListener {
486 storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); 491 storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId());
487 return ret; 492 return ret;
488 } 493 }
489 - // 录像回放  
490 - StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null,  
491 - param.getStream(), null);  
492 - if (streamInfoForPlayBackCatch != null) {  
493 - if (streamInfoForPlayBackCatch.isPause()) {  
494 - ret.put("close", false);  
495 - } else {  
496 - Device device = deviceService.getDevice(streamInfoForPlayBackCatch.getDeviceID());  
497 - if (device != null) {  
498 - try {  
499 - cmder.streamByeCmd(device, streamInfoForPlayBackCatch.getChannelId(),  
500 - streamInfoForPlayBackCatch.getStream(), null);  
501 - } catch (InvalidArgumentException | ParseException | SipException |  
502 - SsrcTransactionNotFoundException e) {  
503 - logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage());  
504 - }  
505 - }  
506 - redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),  
507 - streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);  
508 - }  
509 - return ret;  
510 - }  
511 - // 录像下载  
512 - StreamInfo streamInfoForDownload = redisCatchStorage.queryDownload(null, null,  
513 - param.getStream(), null);  
514 - // 进行录像下载时无人观看不断流  
515 - if (streamInfoForDownload != null) {  
516 - ret.put("close", false);  
517 - return ret;  
518 - }  
519 } else { 494 } else {
520 // 非国标流 推流/拉流代理 495 // 非国标流 推流/拉流代理
521 // 拉流代理 496 // 拉流代理
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -293,11 +293,14 @@ public class ZLMRTPServerFactory { @@ -293,11 +293,14 @@ public class ZLMRTPServerFactory {
293 if (jsonObject.getInteger("code") == 0) { 293 if (jsonObject.getInteger("code") == 0) {
294 localPort = jsonObject.getInteger("port"); 294 localPort = jsonObject.getInteger("port");
295 HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId()); 295 HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(ssrc, null, serverItem.getId());
296 - // 订阅 zlm启动事件, 新的zlm也会从这里进入系统  
297 hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, 296 hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout,
298 (MediaServerItem mediaServerItem, JSONObject response)->{ 297 (MediaServerItem mediaServerItem, JSONObject response)->{
299 logger.info("[上级点播] {}->监听端口到期继续保持监听", ssrc); 298 logger.info("[上级点播] {}->监听端口到期继续保持监听", ssrc);
300 - keepPort(serverItem, ssrc); 299 + int port = keepPort(serverItem, ssrc);
  300 + if (port == 0) {
  301 + logger.info("[上级点播] {}->监听端口失败,移除监听", ssrc);
  302 + hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout);
  303 + }
301 }); 304 });
302 logger.info("[上级点播] {}->监听端口: {}", ssrc, localPort); 305 logger.info("[上级点播] {}->监听端口: {}", ssrc, localPort);
303 }else { 306 }else {
src/main/java/com/genersoft/iot/vmp/service/IInviteStreamService.java
@@ -60,4 +60,9 @@ public interface IInviteStreamService { @@ -60,4 +60,9 @@ public interface IInviteStreamService {
60 * 调用一个invite回调 60 * 调用一个invite回调
61 */ 61 */
62 void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data); 62 void call(InviteSessionType type, String deviceId, String channelId, String stream, int code, String msg, Object data);
  63 +
  64 + /**
  65 + * 清空一个设备的所有invite信息
  66 + */
  67 + void clearInviteInfo(String deviceId);
63 } 68 }
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -3,10 +3,8 @@ package com.genersoft.iot.vmp.service; @@ -3,10 +3,8 @@ package com.genersoft.iot.vmp.service;
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.conf.exception.ServiceException; 4 import com.genersoft.iot.vmp.conf.exception.ServiceException;
5 import com.genersoft.iot.vmp.gb28181.bean.Device; 5 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;  
7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 6 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 import com.genersoft.iot.vmp.service.bean.InviteErrorCallback; 7 import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
9 -import com.genersoft.iot.vmp.service.bean.PlayBackCallback;  
10 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 8 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
11 9
12 import javax.sip.InvalidArgumentException; 10 import javax.sip.InvalidArgumentException;
@@ -29,13 +27,13 @@ public interface IPlayService { @@ -29,13 +27,13 @@ public interface IPlayService {
29 */ 27 */
30 MediaServerItem getNewMediaServerItemHasAssist(Device device); 28 MediaServerItem getNewMediaServerItemHasAssist(Device device);
31 29
32 - void playBack(String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback);  
33 - void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); 30 + void playBack(String deviceId, String channelId, String startTime, String endTime, InviteErrorCallback<Object> callback);
  31 + void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, InviteErrorCallback<Object> callback);
34 32
35 void zlmServerOffline(String mediaServerId); 33 void zlmServerOffline(String mediaServerId);
36 34
37 - void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback);  
38 - void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack); 35 + void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback);
  36 + void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback);
39 37
40 StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); 38 StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);
41 39
src/main/java/com/genersoft/iot/vmp/service/bean/InviteErrorCode.java
@@ -5,7 +5,7 @@ package com.genersoft.iot.vmp.service.bean; @@ -5,7 +5,7 @@ package com.genersoft.iot.vmp.service.bean;
5 */ 5 */
6 public enum InviteErrorCode { 6 public enum InviteErrorCode {
7 SUCCESS(0, "成功"), 7 SUCCESS(0, "成功"),
8 - ERROR_FOR_SIGNALLING_TIMEOUT(-1, "点播超时"), 8 + ERROR_FOR_SIGNALLING_TIMEOUT(-1, "信令超时"),
9 ERROR_FOR_STREAM_TIMEOUT(-2, "收流超时"), 9 ERROR_FOR_STREAM_TIMEOUT(-2, "收流超时"),
10 ERROR_FOR_RESOURCE_EXHAUSTION(-3, "资源耗尽"), 10 ERROR_FOR_RESOURCE_EXHAUSTION(-3, "资源耗尽"),
11 ERROR_FOR_CATCH_DATA(-4, "缓存数据异常"), 11 ERROR_FOR_CATCH_DATA(-4, "缓存数据异常"),
@@ -14,7 +14,9 @@ public enum InviteErrorCode { @@ -14,7 +14,9 @@ public enum InviteErrorCode {
14 ERROR_FOR_SDP_PARSING_EXCEPTIONS(-7, "SDP信息解析失败"), 14 ERROR_FOR_SDP_PARSING_EXCEPTIONS(-7, "SDP信息解析失败"),
15 ERROR_FOR_SSRC_UNAVAILABLE(-8, "SSRC不可用"), 15 ERROR_FOR_SSRC_UNAVAILABLE(-8, "SSRC不可用"),
16 ERROR_FOR_RESET_SSRC(-9, "重新设置收流信息失败"), 16 ERROR_FOR_RESET_SSRC(-9, "重新设置收流信息失败"),
17 - ERROR_FOR_SIP_SENDING_FAILED(-10, "命令发送失败"); 17 + ERROR_FOR_SIP_SENDING_FAILED(-10, "命令发送失败"),
  18 + ERROR_FOR_ASSIST_NOT_READY(-11, "没有可用的assist服务"),
  19 + ERROR_FOR_PARAMETER_ERROR(-13, "参数异常");
18 20
19 private final int code; 21 private final int code;
20 private final String msg; 22 private final String msg;
src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java
@@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; @@ -12,6 +12,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander;
12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; 12 import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler;
13 import com.genersoft.iot.vmp.service.IDeviceChannelService; 13 import com.genersoft.iot.vmp.service.IDeviceChannelService;
14 import com.genersoft.iot.vmp.service.IDeviceService; 14 import com.genersoft.iot.vmp.service.IDeviceService;
  15 +import com.genersoft.iot.vmp.service.IInviteStreamService;
15 import com.genersoft.iot.vmp.service.IMediaServerService; 16 import com.genersoft.iot.vmp.service.IMediaServerService;
16 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
17 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; 18 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
@@ -59,6 +60,9 @@ public class DeviceServiceImpl implements IDeviceService { @@ -59,6 +60,9 @@ public class DeviceServiceImpl implements IDeviceService {
59 private IRedisCatchStorage redisCatchStorage; 60 private IRedisCatchStorage redisCatchStorage;
60 61
61 @Autowired 62 @Autowired
  63 + private IInviteStreamService inviteStreamService;
  64 +
  65 + @Autowired
62 private DeviceMapper deviceMapper; 66 private DeviceMapper deviceMapper;
63 67
64 @Autowired 68 @Autowired
@@ -97,7 +101,7 @@ public class DeviceServiceImpl implements IDeviceService { @@ -97,7 +101,7 @@ public class DeviceServiceImpl implements IDeviceService {
97 String now = DateUtil.getNow(); 101 String now = DateUtil.getNow();
98 if (deviceInRedis != null && deviceInDb == null) { 102 if (deviceInRedis != null && deviceInDb == null) {
99 // redis 存在脏数据 103 // redis 存在脏数据
100 - redisCatchStorage.clearCatchByDeviceId(device.getDeviceId()); 104 + inviteStreamService.clearInviteInfo(device.getDeviceId());
101 } 105 }
102 device.setUpdateTime(now); 106 device.setUpdateTime(now);
103 if (device.getKeepaliveIntervalTime() == 0) { 107 if (device.getKeepaliveIntervalTime() == 0) {
src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java
@@ -175,4 +175,8 @@ public class InviteStreamServiceImpl implements IInviteStreamService { @@ -175,4 +175,8 @@ public class InviteStreamServiceImpl implements IInviteStreamService {
175 } 175 }
176 176
177 177
  178 + @Override
  179 + public void clearInviteInfo(String deviceId) {
  180 + removeInviteInfo(null, deviceId, null, null);
  181 + }
178 } 182 }
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
1 package com.genersoft.iot.vmp.service.impl; 1 package com.genersoft.iot.vmp.service.impl;
2 2
3 -import com.alibaba.fastjson2.JSON;  
4 import com.alibaba.fastjson2.JSONArray; 3 import com.alibaba.fastjson2.JSONArray;
5 import com.alibaba.fastjson2.JSONObject; 4 import com.alibaba.fastjson2.JSONObject;
6 import com.genersoft.iot.vmp.common.InviteInfo; 5 import com.genersoft.iot.vmp.common.InviteInfo;
@@ -17,7 +16,6 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; @@ -17,7 +16,6 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
17 import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; 16 import com.genersoft.iot.vmp.gb28181.session.SSRCFactory;
18 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; 17 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
19 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 18 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
20 -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;  
21 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 19 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
22 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; 20 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
23 import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; 21 import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils;
@@ -28,12 +26,13 @@ import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; @@ -28,12 +26,13 @@ import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory;
28 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; 26 import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange;
29 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 27 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
30 import com.genersoft.iot.vmp.service.*; 28 import com.genersoft.iot.vmp.service.*;
31 -import com.genersoft.iot.vmp.service.bean.*; 29 +import com.genersoft.iot.vmp.service.bean.InviteErrorCallback;
  30 +import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
  31 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
32 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 32 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
33 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 33 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
34 import com.genersoft.iot.vmp.utils.DateUtil; 34 import com.genersoft.iot.vmp.utils.DateUtil;
35 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 35 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
36 -import com.genersoft.iot.vmp.vmanager.bean.WVPResult;  
37 import org.slf4j.Logger; 36 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory; 37 import org.slf4j.LoggerFactory;
39 import org.springframework.beans.factory.annotation.Autowired; 38 import org.springframework.beans.factory.annotation.Autowired;
@@ -182,6 +181,12 @@ public class PlayServiceImpl implements IPlayService { @@ -182,6 +181,12 @@ public class PlayServiceImpl implements IPlayService {
182 public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 181 public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
183 InviteErrorCallback<Object> callback) { 182 InviteErrorCallback<Object> callback) {
184 183
  184 + if (mediaServerItem == null || ssrcInfo == null) {
  185 + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
  186 + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
  187 + null);
  188 + return;
  189 + }
185 logger.info("[点播开始] deviceId: {}, channelId: {},收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); 190 logger.info("[点播开始] deviceId: {}, channelId: {},收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
186 191
187 //端口获取失败的ssrcInfo 没有必要发送点播指令 192 //端口获取失败的ssrcInfo 没有必要发送点播指令
@@ -375,11 +380,10 @@ public class PlayServiceImpl implements IPlayService { @@ -375,11 +380,10 @@ public class PlayServiceImpl implements IPlayService {
375 Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse); 380 Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse);
376 if (!result) { 381 if (!result) {
377 try { 382 try {
378 - logger.warn("[停止点播] {}/{}", device.getDeviceId(), channelId); 383 + logger.warn("[点播] 更新ssrc失败,停止点播 {}/{}", device.getDeviceId(), channelId);
379 cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null); 384 cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null);
380 } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) { 385 } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
381 logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage()); 386 logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
382 - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());  
383 } 387 }
384 388
385 dynamicTask.stop(timeOutTaskKey); 389 dynamicTask.stop(timeOutTaskKey);
@@ -459,11 +463,12 @@ public class PlayServiceImpl implements IPlayService { @@ -459,11 +463,12 @@ public class PlayServiceImpl implements IPlayService {
459 463
460 } 464 }
461 465
462 - private void onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, PlayBackCallback playBackCallback) { 466 + private StreamInfo onPublishHandlerForPlayback(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String startTime, String endTime) {
463 467
464 StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId); 468 StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
465 - PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>();  
466 if (streamInfo != null) { 469 if (streamInfo != null) {
  470 + streamInfo.setStartTime(startTime);
  471 + streamInfo.setEndTime(endTime);
467 DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); 472 DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
468 if (deviceChannel != null) { 473 if (deviceChannel != null) {
469 deviceChannel.setStreamId(streamInfo.getStream()); 474 deviceChannel.setStreamId(streamInfo.getStream());
@@ -472,20 +477,13 @@ public class PlayServiceImpl implements IPlayService { @@ -472,20 +477,13 @@ public class PlayServiceImpl implements IPlayService {
472 InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAYBACK, deviceId, channelId); 477 InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAYBACK, deviceId, channelId);
473 if (inviteInfo != null) { 478 if (inviteInfo != null) {
474 inviteInfo.setStatus(InviteSessionStatus.ok); 479 inviteInfo.setStatus(InviteSessionStatus.ok);
  480 +
475 inviteInfo.setStreamInfo(streamInfo); 481 inviteInfo.setStreamInfo(streamInfo);
476 inviteStreamService.updateInviteInfo(inviteInfo); 482 inviteStreamService.updateInviteInfo(inviteInfo);
477 } 483 }
478 484
479 - playBackResult.setCode(ErrorCode.SUCCESS.getCode());  
480 - playBackResult.setMsg(ErrorCode.SUCCESS.getMsg());  
481 - playBackResult.setData(streamInfo);  
482 - playBackCallback.call(playBackResult);  
483 - } else {  
484 - logger.warn("录像回放调用失败!");  
485 - playBackResult.setCode(ErrorCode.ERROR100.getCode());  
486 - playBackResult.setMsg("录像回放调用失败!");  
487 - playBackCallback.call(playBackResult);  
488 } 485 }
  486 + return streamInfo;
489 } 487 }
490 488
491 @Override 489 @Override
@@ -524,23 +522,24 @@ public class PlayServiceImpl implements IPlayService { @@ -524,23 +522,24 @@ public class PlayServiceImpl implements IPlayService {
524 522
525 @Override 523 @Override
526 public void playBack(String deviceId, String channelId, String startTime, 524 public void playBack(String deviceId, String channelId, String startTime,
527 - String endTime, InviteStreamCallback inviteStreamCallback,  
528 - PlayBackCallback callback) { 525 + String endTime, InviteErrorCallback<Object> callback) {
529 Device device = storager.queryVideoDevice(deviceId); 526 Device device = storager.queryVideoDevice(deviceId);
530 if (device == null) { 527 if (device == null) {
531 return; 528 return;
532 } 529 }
533 MediaServerItem newMediaServerItem = getNewMediaServerItem(device); 530 MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
534 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); 531 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
535 - playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, inviteStreamCallback, callback); 532 + playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, callback);
536 } 533 }
537 534
538 @Override 535 @Override
539 public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, 536 public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,
540 String deviceId, String channelId, String startTime, 537 String deviceId, String channelId, String startTime,
541 - String endTime, InviteStreamCallback infoCallBack,  
542 - PlayBackCallback playBackCallback) { 538 + String endTime, InviteErrorCallback<Object> callback) {
543 if (mediaServerItem == null || ssrcInfo == null) { 539 if (mediaServerItem == null || ssrcInfo == null) {
  540 + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
  541 + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
  542 + null);
544 return; 543 return;
545 } 544 }
546 545
@@ -548,133 +547,169 @@ public class PlayServiceImpl implements IPlayService { @@ -548,133 +547,169 @@ public class PlayServiceImpl implements IPlayService {
548 if (device == null) { 547 if (device == null) {
549 throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在"); 548 throw new ControllerException(ErrorCode.ERROR100.getCode(), "设备: " + deviceId + "不存在");
550 } 549 }
551 - logger.info("[回放消息] deviceId: {}, channelId: {},收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());  
552 - PlayBackResult<StreamInfo> playBackResult = new PlayBackResult<>(); 550 + logger.info("[录像回放] deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}, 收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}",
  551 + device.getDeviceId(), channelId, startTime, endTime, ssrcInfo.getPort(), device.getStreamMode(),
  552 + ssrcInfo.getSsrc(), device.isSsrcCheck());
  553 + // 初始化redis中的invite消息状态
  554 + InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo,
  555 + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.PLAYBACK,
  556 + InviteSessionStatus.ready);
  557 + inviteStreamService.updateInviteInfo(inviteInfo);
553 String playBackTimeOutTaskKey = UUID.randomUUID().toString(); 558 String playBackTimeOutTaskKey = UUID.randomUUID().toString();
554 dynamicTask.startDelay(playBackTimeOutTaskKey, () -> { 559 dynamicTask.startDelay(playBackTimeOutTaskKey, () -> {
555 - logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));  
556 - playBackResult.setCode(ErrorCode.ERROR100.getCode());  
557 - playBackResult.setMsg("回放超时"); 560 + logger.warn("[录像回放] 超时,deviceId:{} ,channelId:{}", deviceId, channelId);
  561 + inviteStreamService.removeInviteInfo(inviteInfo);
  562 + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(), InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getMsg(), null);
558 563
559 try { 564 try {
560 cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null); 565 cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null);
561 } catch (InvalidArgumentException | ParseException | SipException e) { 566 } catch (InvalidArgumentException | ParseException | SipException e) {
562 - logger.error("[录像流]回放超时 发送BYE失败 {}", e.getMessage()); 567 + logger.error("[录像回放] 超时 发送BYE失败 {}", e.getMessage());
563 } catch (SsrcTransactionNotFoundException e) { 568 } catch (SsrcTransactionNotFoundException e) {
564 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 569 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
565 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 570 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
566 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); 571 mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
567 streamSession.remove(deviceId, channelId, ssrcInfo.getStream()); 572 streamSession.remove(deviceId, channelId, ssrcInfo.getStream());
568 } 573 }
569 - // 回复之前所有的点播请求  
570 - playBackCallback.call(playBackResult);  
571 }, userSetting.getPlayTimeout()); 574 }, userSetting.getPlayTimeout());
572 575
573 SipSubscribe.Event errorEvent = event -> { 576 SipSubscribe.Event errorEvent = event -> {
  577 + logger.info("[录像回放] 失败,{} {}", event.statusCode, event.msg);
574 dynamicTask.stop(playBackTimeOutTaskKey); 578 dynamicTask.stop(playBackTimeOutTaskKey);
575 - playBackResult.setCode(ErrorCode.ERROR100.getCode());  
576 - playBackResult.setMsg(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));  
577 - playBackResult.setEvent(event);  
578 - playBackCallback.call(playBackResult); 579 + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(),
  580 + String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg), null);
  581 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  582 + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
579 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); 583 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  584 + inviteStreamService.removeInviteInfo(inviteInfo);
580 }; 585 };
581 586
582 - InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> {  
583 - logger.info("收到回放订阅消息: " + inviteStreamInfo.getResponse().toJSONString()); 587 + ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInuse, jsonObject) -> {
  588 + logger.info("收到回放订阅消息: " + jsonObject);
584 dynamicTask.stop(playBackTimeOutTaskKey); 589 dynamicTask.stop(playBackTimeOutTaskKey);
585 - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); 590 + StreamInfo streamInfo = onPublishHandlerForPlayback(mediaServerItemInuse, jsonObject, deviceId, channelId, startTime, endTime);
586 if (streamInfo == null) { 591 if (streamInfo == null) {
587 logger.warn("设备回放API调用失败!"); 592 logger.warn("设备回放API调用失败!");
588 - playBackResult.setCode(ErrorCode.ERROR100.getCode());  
589 - playBackResult.setMsg("设备回放API调用失败!");  
590 - playBackCallback.call(playBackResult); 593 + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
  594 + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
591 return; 595 return;
592 } 596 }
593 - redisCatchStorage.startPlayback(streamInfo, inviteStreamInfo.getCallId());  
594 -  
595 - playBackResult.setCode(ErrorCode.SUCCESS.getCode());  
596 - playBackResult.setMsg(ErrorCode.SUCCESS.getMsg());  
597 - playBackResult.setData(streamInfo);  
598 - playBackResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());  
599 - playBackResult.setResponse(inviteStreamInfo.getResponse());  
600 - playBackCallback.call(playBackResult); 597 + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
  598 + logger.info("[录像回放] 成功 deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}", device.getDeviceId(), channelId, startTime, endTime);
601 }; 599 };
602 600
603 try { 601 try {
604 - cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, infoCallBack, 602 + cmder.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime,
605 hookEvent, eventResult -> { 603 hookEvent, eventResult -> {
606 - if (eventResult.type == SipSubscribe.EventResultType.response) {  
607 - ResponseEvent responseEvent = (ResponseEvent) eventResult.event;  
608 - String contentString = new String(responseEvent.getResponse().getRawContent());  
609 - // 获取ssrc  
610 - int ssrcIndex = contentString.indexOf("y=");  
611 - // 检查是否有y字段  
612 - if (ssrcIndex >= 0) {  
613 - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容  
614 - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);  
615 - // 查询到ssrc不一致且开启了ssrc校验则需要针对处理  
616 - if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {  
617 - return;  
618 - }  
619 - logger.info("[回放消息] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse);  
620 - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {  
621 - logger.info("[回放消息] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);  
622 -  
623 - if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) {  
624 - // ssrc 不可用  
625 - // 释放ssrc 604 + inviteInfo.setStatus(InviteSessionStatus.ok);
  605 + ResponseEvent responseEvent = (ResponseEvent) eventResult.event;
  606 + String contentString = new String(responseEvent.getResponse().getRawContent());
  607 + // 获取ssrc
  608 + int ssrcIndex = contentString.indexOf("y=");
  609 + // 检查是否有y字段
  610 + if (ssrcIndex >= 0) {
  611 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
  612 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  613 + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
  614 + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
  615 + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) {
  616 + String substring = contentString.substring(0, contentString.indexOf("y="));
  617 + try {
  618 + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
  619 + int port = -1;
  620 + Vector mediaDescriptions = sdp.getMediaDescriptions(true);
  621 + for (Object description : mediaDescriptions) {
  622 + MediaDescription mediaDescription = (MediaDescription) description;
  623 + Media media = mediaDescription.getMedia();
  624 +
  625 + Vector mediaFormats = media.getMediaFormats(false);
  626 + if (mediaFormats.contains("96")) {
  627 + port = media.getMediaPort();
  628 + break;
  629 + }
  630 + }
  631 + logger.info("[录像回放-TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
  632 + JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream());
  633 + logger.info("[录像回放-TCP主动连接对方] 结果: {}", jsonObject);
  634 + } catch (SdpException e) {
  635 + logger.error("[录像回放-TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e);
626 dynamicTask.stop(playBackTimeOutTaskKey); 636 dynamicTask.stop(playBackTimeOutTaskKey);
  637 + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
  638 + // 释放ssrc
627 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 639 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  640 +
628 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); 641 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
629 - eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";  
630 - eventResult.statusCode = 400;  
631 - errorEvent.response(eventResult);  
632 - return; 642 +
  643 + callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(),
  644 + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null);
  645 + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
  646 + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(),
  647 + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null);
633 } 648 }
  649 + }
  650 + return;
  651 + }
  652 + logger.info("[录像回放] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse);
  653 + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
  654 + logger.info("[录像回放] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
  655 +
  656 + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) {
  657 + // ssrc 不可用
  658 + logger.info("[录像回放] SSRC修正时发现ssrc不可使用 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
  659 + // 释放ssrc
  660 + dynamicTask.stop(playBackTimeOutTaskKey);
  661 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  662 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  663 + callback.run(InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getCode(),
  664 + InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getMsg(), null);
  665 + return;
  666 + }
  667 +
  668 + // 单端口模式streamId也有变化,需要重新设置监听
  669 + if (!mediaServerItem.isRtpEnable()) {
  670 + // 添加订阅
  671 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
  672 + subscribe.removeSubscribe(hookSubscribe);
  673 + String stream = String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase();
  674 + hookSubscribe.getContent().put("stream", stream);
  675 + inviteInfo.setStream(stream);
  676 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
  677 + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
  678 + dynamicTask.stop(playBackTimeOutTaskKey);
  679 + // hook响应
  680 + hookEvent.response(mediaServerItemInUse, response);
  681 + });
  682 + }
  683 + // 更新ssrc
  684 + Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse);
  685 + if (!result) {
  686 + try {
  687 + logger.warn("[录像回放] 更新ssrc失败,停止录像回放 {}/{}", device.getDeviceId(), channelId);
  688 + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null);
  689 + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
  690 + logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
634 691
635 - // 单端口模式streamId也有变化,需要重新设置监听  
636 - if (!mediaServerItem.isRtpEnable()) {  
637 - // 添加订阅  
638 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());  
639 - subscribe.removeSubscribe(hookSubscribe);  
640 - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());  
641 - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {  
642 - logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());  
643 - dynamicTask.stop(playBackTimeOutTaskKey);  
644 - // hook响应  
645 - onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, playBackCallback);  
646 - hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));  
647 - });  
648 } 692 }
649 693
650 - // 关闭rtp server  
651 - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{  
652 - if (result) {  
653 - // 重新开启ssrc server  
654 - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort(), true, device.getStreamModeForParam());  
655 - }else {  
656 - try {  
657 - logger.warn("[回放消息]停止 {}/{}", device.getDeviceId(), channelId);  
658 - cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null);  
659 - } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {  
660 - logger.error("[命令发送失败] 停止点播 停止, 发送BYE: {}", e.getMessage());  
661 - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());  
662 - } 694 + dynamicTask.stop(playBackTimeOutTaskKey);
  695 + // 释放ssrc
  696 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
663 697
664 - dynamicTask.stop(playBackTimeOutTaskKey);  
665 - // 释放ssrc  
666 - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());  
667 - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());  
668 - errorEvent.response(eventResult);  
669 - eventResult.msg = "下级自定义了ssrc,重新设置收流信息失败";  
670 - eventResult.statusCode = 500;  
671 - errorEvent.response(eventResult);  
672 - }  
673 - }); 698 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  699 +
  700 + callback.run(InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(),
  701 + "下级自定义了ssrc,重新设置收流信息失败", null);
  702 +
  703 + }else {
  704 + ssrcInfo.setSsrc(ssrcInResponse);
  705 + inviteInfo.setSsrcInfo(ssrcInfo);
  706 + inviteInfo.setStream(ssrcInfo.getStream());
674 } 707 }
  708 + }else {
  709 + logger.info("[点播消息] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正");
675 } 710 }
676 } 711 }
677 - 712 + inviteStreamService.updateInviteInfo(inviteInfo);
678 }, errorEvent); 713 }, errorEvent);
679 } catch (InvalidArgumentException | SipException | ParseException e) { 714 } catch (InvalidArgumentException | SipException | ParseException e) {
680 logger.error("[命令发送失败] 回放: {}", e.getMessage()); 715 logger.error("[命令发送失败] 回放: {}", e.getMessage());
@@ -690,42 +725,50 @@ public class PlayServiceImpl implements IPlayService { @@ -690,42 +725,50 @@ public class PlayServiceImpl implements IPlayService {
690 725
691 726
692 @Override 727 @Override
693 - public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback playBackCallback) { 728 + public void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback) {
694 Device device = storager.queryVideoDevice(deviceId); 729 Device device = storager.queryVideoDevice(deviceId);
695 if (device == null) { 730 if (device == null) {
696 return; 731 return;
697 } 732 }
698 MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device); 733 MediaServerItem newMediaServerItem = getNewMediaServerItemHasAssist(device);
699 if (newMediaServerItem == null) { 734 if (newMediaServerItem == null) {
700 - PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>();  
701 - downloadResult.setCode(ErrorCode.ERROR100.getCode());  
702 - downloadResult.setMsg("未找到assist服务");  
703 - playBackCallback.call(downloadResult); 735 + callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(),
  736 + InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getMsg(),
  737 + null);
704 return; 738 return;
705 } 739 }
706 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam()); 740 SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, device.getStreamModeForParam());
707 - download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, infoCallBack, playBackCallback); 741 + download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, callback);
708 } 742 }
709 743
710 744
711 @Override 745 @Override
712 - public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteStreamCallback infoCallBack, PlayBackCallback hookCallBack) { 746 + public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, InviteErrorCallback<Object> callback) {
713 if (mediaServerItem == null || ssrcInfo == null) { 747 if (mediaServerItem == null || ssrcInfo == null) {
  748 + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
  749 + InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(),
  750 + null);
714 return; 751 return;
715 } 752 }
716 -  
717 Device device = storager.queryVideoDevice(deviceId); 753 Device device = storager.queryVideoDevice(deviceId);
718 if (device == null) { 754 if (device == null) {
719 - throw new ControllerException(ErrorCode.ERROR400.getCode(), "设备:" + deviceId + "不存在"); 755 + callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(),
  756 + "设备:" + deviceId + "不存在",
  757 + null);
  758 + return;
720 } 759 }
721 - PlayBackResult<StreamInfo> downloadResult = new PlayBackResult<>();  
722 logger.info("[录像下载] deviceId: {}, channelId: {},收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); 760 logger.info("[录像下载] deviceId: {}, channelId: {},收流端口:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, ssrcInfo.getPort(), device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
  761 + // 初始化redis中的invite消息状态
  762 + InviteInfo inviteInfo = InviteInfo.getinviteInfo(device.getDeviceId(), channelId, ssrcInfo.getStream(), ssrcInfo,
  763 + mediaServerItem.getSdpIp(), ssrcInfo.getPort(), device.getStreamMode(), InviteSessionType.DOWNLOAD,
  764 + InviteSessionStatus.ready);
  765 + inviteStreamService.updateInviteInfo(inviteInfo);
723 String downLoadTimeOutTaskKey = UUID.randomUUID().toString(); 766 String downLoadTimeOutTaskKey = UUID.randomUUID().toString();
724 dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> { 767 dynamicTask.startDelay(downLoadTimeOutTaskKey, () -> {
725 logger.warn(String.format("录像下载请求超时,deviceId:%s ,channelId:%s", deviceId, channelId)); 768 logger.warn(String.format("录像下载请求超时,deviceId:%s ,channelId:%s", deviceId, channelId));
726 - downloadResult.setCode(ErrorCode.ERROR100.getCode());  
727 - downloadResult.setMsg("录像下载请求超时");  
728 - hookCallBack.call(downloadResult); 769 + inviteStreamService.removeInviteInfo(inviteInfo);
  770 + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(),
  771 + InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getMsg(), null);
729 772
730 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源 773 // 点播超时回复BYE 同时释放ssrc以及此次点播的资源
731 try { 774 try {
@@ -741,98 +784,129 @@ public class PlayServiceImpl implements IPlayService { @@ -741,98 +784,129 @@ public class PlayServiceImpl implements IPlayService {
741 784
742 SipSubscribe.Event errorEvent = event -> { 785 SipSubscribe.Event errorEvent = event -> {
743 dynamicTask.stop(downLoadTimeOutTaskKey); 786 dynamicTask.stop(downLoadTimeOutTaskKey);
744 - downloadResult.setCode(ErrorCode.ERROR100.getCode());  
745 - downloadResult.setMsg(String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg));  
746 - downloadResult.setEvent(event);  
747 - hookCallBack.call(downloadResult); 787 + callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode(),
  788 + String.format("录像下载失败, 错误码: %s, %s", event.statusCode, event.msg), null);
748 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); 789 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  790 + inviteStreamService.removeInviteInfo(inviteInfo);
749 }; 791 };
750 - InviteStreamCallback hookEvent = (InviteStreamInfo inviteStreamInfo) -> {  
751 - logger.info("[录像下载]收到订阅消息: " + inviteStreamInfo.getCallId()); 792 + ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInuse, jsonObject) -> {
  793 + logger.info("[录像下载]收到订阅消息: " + jsonObject);
752 dynamicTask.stop(downLoadTimeOutTaskKey); 794 dynamicTask.stop(downLoadTimeOutTaskKey);
753 - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId);  
754 - streamInfo.setStartTime(startTime);  
755 - streamInfo.setEndTime(endTime);  
756 - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());  
757 - downloadResult.setCode(ErrorCode.SUCCESS.getCode());  
758 - downloadResult.setMsg(ErrorCode.SUCCESS.getMsg());  
759 - downloadResult.setData(streamInfo);  
760 - downloadResult.setMediaServerItem(inviteStreamInfo.getMediaServerItem());  
761 - downloadResult.setResponse(inviteStreamInfo.getResponse());  
762 - hookCallBack.call(downloadResult); 795 + StreamInfo streamInfo = onPublishHandlerForDownload(mediaServerItemInuse, jsonObject, deviceId, channelId, startTime, endTime);
  796 + if (streamInfo == null) {
  797 + logger.warn("[录像下载] 获取流地址信息失败");
  798 + callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(),
  799 + InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null);
  800 + return;
  801 + }
  802 + callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo);
  803 + logger.info("[录像下载] 调用成功 deviceId: {}, channelId: {}, 开始时间: {}, 结束时间: {}", device.getDeviceId(), channelId, startTime, endTime);
763 }; 804 };
764 try { 805 try {
765 - cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, infoCallBack,  
766 - hookEvent, errorEvent, eventResult ->  
767 - {  
768 - if (eventResult.type == SipSubscribe.EventResultType.response) {  
769 - ResponseEvent responseEvent = (ResponseEvent) eventResult.event;  
770 - String contentString = new String(responseEvent.getResponse().getRawContent());  
771 - // 获取ssrc  
772 - int ssrcIndex = contentString.indexOf("y=");  
773 - // 检查是否有y字段  
774 - if (ssrcIndex >= 0) {  
775 - //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容  
776 - String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);  
777 - // 查询到ssrc不一致且开启了ssrc校验则需要针对处理  
778 - if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {  
779 - return;  
780 - }  
781 - logger.info("[录像下载] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse);  
782 - if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {  
783 - logger.info("[录像下载] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);  
784 -  
785 - if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) {  
786 - // ssrc 不可用 806 + cmder.downloadStreamCmd(mediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed,
  807 + hookEvent, errorEvent, eventResult ->{
  808 + inviteInfo.setStatus(InviteSessionStatus.ok);
  809 + ResponseEvent responseEvent = (ResponseEvent) eventResult.event;
  810 + String contentString = new String(responseEvent.getResponse().getRawContent());
  811 + // 获取ssrc
  812 + int ssrcIndex = contentString.indexOf("y=");
  813 + // 检查是否有y字段
  814 + if (ssrcIndex >= 0) {
  815 + //ssrc规定长度为10字节,不取余下长度以避免后续还有“f=”字段 TODO 后续对不规范的非10位ssrc兼容
  816 + String ssrcInResponse = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
  817 + // 查询到ssrc不一致且开启了ssrc校验则需要针对处理
  818 + if (ssrcInfo.getSsrc().equals(ssrcInResponse)) {
  819 + if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) {
  820 + String substring = contentString.substring(0, contentString.indexOf("y="));
  821 + try {
  822 + SessionDescription sdp = SdpFactory.getInstance().createSessionDescription(substring);
  823 + int port = -1;
  824 + Vector mediaDescriptions = sdp.getMediaDescriptions(true);
  825 + for (Object description : mediaDescriptions) {
  826 + MediaDescription mediaDescription = (MediaDescription) description;
  827 + Media media = mediaDescription.getMedia();
  828 +
  829 + Vector mediaFormats = media.getMediaFormats(false);
  830 + if (mediaFormats.contains("96")) {
  831 + port = media.getMediaPort();
  832 + break;
  833 + }
  834 + }
  835 + logger.info("[录像下载-TCP主动连接对方] deviceId: {}, channelId: {}, 连接对方的地址:{}:{}, 收流模式:{}, SSRC: {}, SSRC校验:{}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck());
  836 + JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream());
  837 + logger.info("[录像下载-TCP主动连接对方] 结果: {}", jsonObject);
  838 + } catch (SdpException e) {
  839 + logger.error("[录像下载-TCP主动连接对方] deviceId: {}, channelId: {}, 解析200OK的SDP信息失败", device.getDeviceId(), channelId, e);
  840 + dynamicTask.stop(downLoadTimeOutTaskKey);
  841 + mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream());
787 // 释放ssrc 842 // 释放ssrc
788 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 843 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  844 +
789 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); 845 streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
790 - eventResult.msg = "下级自定义了ssrc,但是此ssrc不可用";  
791 - eventResult.statusCode = 400;  
792 - errorEvent.response(eventResult);  
793 - return; 846 +
  847 + callback.run(InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(),
  848 + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null);
  849 + inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null,
  850 + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getCode(),
  851 + InviteErrorCode.ERROR_FOR_SDP_PARSING_EXCEPTIONS.getMsg(), null);
794 } 852 }
  853 + }
  854 + return;
  855 + }
  856 + logger.info("[录像下载] 收到invite 200, 发现下级自定义了ssrc: {}", ssrcInResponse);
  857 + if (!mediaServerItem.isRtpEnable() || device.isSsrcCheck()) {
  858 + logger.info("[录像下载] SSRC修正 {}->{}", ssrcInfo.getSsrc(), ssrcInResponse);
  859 +
  860 + if (!ssrcFactory.checkSsrc(mediaServerItem.getId(),ssrcInResponse)) {
  861 + // ssrc 不可用
  862 + // 释放ssrc
  863 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
  864 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
  865 + callback.run(InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getCode(),
  866 + InviteErrorCode.ERROR_FOR_SSRC_UNAVAILABLE.getMsg(), null);
  867 + return;
  868 + }
  869 +
  870 + // 单端口模式streamId也有变化,需要重新设置监听
  871 + if (!mediaServerItem.isRtpEnable()) {
  872 + // 添加订阅
  873 + HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());
  874 + subscribe.removeSubscribe(hookSubscribe);
  875 + hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());
  876 + subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
  877 + logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());
  878 + dynamicTask.stop(downLoadTimeOutTaskKey);
  879 + hookEvent.response(mediaServerItemInUse, response);
  880 + });
  881 + }
  882 +
  883 + // 更新ssrc
  884 + Boolean result = mediaServerService.updateRtpServerSSRC(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse);
  885 + if (!result) {
  886 + try {
  887 + logger.warn("[录像下载] 更新ssrc失败,停止录像回放 {}/{}", device.getDeviceId(), channelId);
  888 + cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null);
  889 + } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {
  890 + logger.error("[命令发送失败] 停止点播, 发送BYE: {}", e.getMessage());
795 891
796 - // 单端口模式streamId也有变化,需要重新设置监听  
797 - if (!mediaServerItem.isRtpEnable()) {  
798 - // 添加订阅  
799 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId());  
800 - subscribe.removeSubscribe(hookSubscribe);  
801 - hookSubscribe.getContent().put("stream", String.format("%08x", Integer.parseInt(ssrcInResponse)).toUpperCase());  
802 - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {  
803 - logger.info("[ZLM HOOK] ssrc修正后收到订阅消息: " + response.toJSONString());  
804 - dynamicTask.stop(downLoadTimeOutTaskKey);  
805 - // hook响应  
806 - onPublishHandlerForPlayback(mediaServerItemInUse, response, device.getDeviceId(), channelId, hookCallBack);  
807 - hookEvent.call(new InviteStreamInfo(mediaServerItem, null, eventResult.callId, "rtp", ssrcInfo.getStream()));  
808 - });  
809 } 892 }
810 893
811 - // 关闭rtp server  
812 - mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream(), result->{  
813 - if (result) {  
814 - // 重新开启ssrc server  
815 - mediaServerService.openRTPServer(mediaServerItem, ssrcInfo.getStream(), ssrcInResponse, device.isSsrcCheck(), true, ssrcInfo.getPort(), true, device.getStreamModeForParam());  
816 - }else {  
817 - try {  
818 - logger.warn("[录像下载] 停止{}/{}", device.getDeviceId(), channelId);  
819 - cmder.streamByeCmd(device, channelId, ssrcInfo.getStream(), null, null);  
820 - } catch (InvalidArgumentException | SipException | ParseException | SsrcTransactionNotFoundException e) {  
821 - logger.error("[命令发送失败] 录像下载停止, 发送BYE: {}", e.getMessage());  
822 - throw new ControllerException(ErrorCode.ERROR100.getCode(), "命令发送失败: " + e.getMessage());  
823 - } 894 + dynamicTask.stop(downLoadTimeOutTaskKey);
  895 + // 释放ssrc
  896 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
824 897
825 - dynamicTask.stop(downLoadTimeOutTaskKey);  
826 - // 释放ssrc  
827 - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 898 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
828 899
829 - streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());  
830 - eventResult.msg = "下级自定义了ssrc,重新设置收流信息失败";  
831 - eventResult.statusCode = 500;  
832 - errorEvent.response(eventResult);  
833 - }  
834 - }); 900 + callback.run(InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(),
  901 + "下级自定义了ssrc,重新设置收流信息失败", null);
  902 +
  903 + }else {
  904 + ssrcInfo.setSsrc(ssrcInResponse);
  905 + inviteInfo.setSsrcInfo(ssrcInfo);
  906 + inviteInfo.setStream(ssrcInfo.getStream());
835 } 907 }
  908 + }else {
  909 + logger.info("[录像下载] 收到invite 200, 下级自定义了ssrc, 但是当前模式无需修正");
836 } 910 }
837 } 911 }
838 }); 912 });
@@ -849,21 +923,22 @@ public class PlayServiceImpl implements IPlayService { @@ -849,21 +923,22 @@ public class PlayServiceImpl implements IPlayService {
849 923
850 @Override 924 @Override
851 public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) { 925 public StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream) {
852 - StreamInfo streamInfo = redisCatchStorage.queryDownload(deviceId, channelId, stream, null);  
853 - if (streamInfo != null) {  
854 - if (streamInfo.getProgress() == 1) {  
855 - return streamInfo; 926 + InviteInfo inviteInfo = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, stream);
  927 +
  928 + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) {
  929 + if (inviteInfo.getStreamInfo().getProgress() == 1) {
  930 + return inviteInfo.getStreamInfo();
856 } 931 }
857 932
858 // 获取当前已下载时长 933 // 获取当前已下载时长
859 - String mediaServerId = streamInfo.getMediaServerId(); 934 + String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId();
860 MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); 935 MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
861 if (mediaServerItem == null) { 936 if (mediaServerItem == null) {
862 logger.warn("查询录像信息时发现节点已离线"); 937 logger.warn("查询录像信息时发现节点已离线");
863 return null; 938 return null;
864 } 939 }
865 if (mediaServerItem.getRecordAssistPort() > 0) { 940 if (mediaServerItem.getRecordAssistPort() > 0) {
866 - JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, streamInfo.getApp(), streamInfo.getStream(), null); 941 + JSONObject jsonObject = assistRESTfulUtils.fileDuration(mediaServerItem, inviteInfo.getStreamInfo().getApp(), inviteInfo.getStreamInfo().getStream(), null);
867 if (jsonObject == null) { 942 if (jsonObject == null) {
868 throw new ControllerException(ErrorCode.ERROR100.getCode(), "连接Assist服务失败"); 943 throw new ControllerException(ErrorCode.ERROR100.getCode(), "连接Assist服务失败");
869 } 944 }
@@ -871,10 +946,10 @@ public class PlayServiceImpl implements IPlayService { @@ -871,10 +946,10 @@ public class PlayServiceImpl implements IPlayService {
871 long duration = jsonObject.getLong("data"); 946 long duration = jsonObject.getLong("data");
872 947
873 if (duration == 0) { 948 if (duration == 0) {
874 - streamInfo.setProgress(0); 949 + inviteInfo.getStreamInfo().setProgress(0);
875 } else { 950 } else {
876 - String startTime = streamInfo.getStartTime();  
877 - String endTime = streamInfo.getEndTime(); 951 + String startTime = inviteInfo.getStreamInfo().getStartTime();
  952 + String endTime = inviteInfo.getStreamInfo().getEndTime();
878 long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime); 953 long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime);
879 long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime); 954 long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime);
880 955
@@ -882,28 +957,29 @@ public class PlayServiceImpl implements IPlayService { @@ -882,28 +957,29 @@ public class PlayServiceImpl implements IPlayService {
882 BigDecimal totalCount = new BigDecimal(end - start); 957 BigDecimal totalCount = new BigDecimal(end - start);
883 BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP); 958 BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP);
884 double process = divide.doubleValue(); 959 double process = divide.doubleValue();
885 - streamInfo.setProgress(process); 960 + inviteInfo.getStreamInfo().setProgress(process);
886 } 961 }
  962 + inviteStreamService.updateInviteInfo(inviteInfo);
887 } 963 }
888 } 964 }
  965 + return inviteInfo.getStreamInfo();
889 } 966 }
890 - return streamInfo; 967 + return null;
891 } 968 }
892 969
893 - private void onPublishHandlerForDownload(InviteStreamInfo inviteStreamInfo, String deviceId, String channelId, String uuid) {  
894 - RequestMessage msg = new RequestMessage();  
895 - msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId);  
896 - msg.setId(uuid);  
897 - StreamInfo streamInfo = onPublishHandler(inviteStreamInfo.getMediaServerItem(), inviteStreamInfo.getResponse(), deviceId, channelId); 970 + private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, JSONObject response, String deviceId, String channelId, String startTime, String endTime) {
  971 + StreamInfo streamInfo = onPublishHandler(mediaServerItemInuse, response, deviceId, channelId);
898 if (streamInfo != null) { 972 if (streamInfo != null) {
899 - redisCatchStorage.startDownload(streamInfo, inviteStreamInfo.getCallId());  
900 - msg.setData(JSON.toJSONString(streamInfo));  
901 - resultHolder.invokeResult(msg);  
902 - } else {  
903 - logger.warn("设备预览API调用失败!");  
904 - msg.setData(WVPResult.fail(ErrorCode.ERROR100.getCode(), "设备预览API调用失败!"));  
905 - resultHolder.invokeResult(msg); 973 + streamInfo.setStartTime(startTime);
  974 + streamInfo.setEndTime(endTime);
  975 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.DOWNLOAD, deviceId, channelId);
  976 + if (inviteInfo != null) {
  977 + inviteInfo.setStatus(InviteSessionStatus.ok);
  978 + inviteInfo.setStreamInfo(streamInfo);
  979 + inviteStreamService.updateInviteInfo(inviteInfo);
  980 + }
906 } 981 }
  982 + return streamInfo;
907 } 983 }
908 984
909 985
@@ -1007,15 +1083,14 @@ public class PlayServiceImpl implements IPlayService { @@ -1007,15 +1083,14 @@ public class PlayServiceImpl implements IPlayService {
1007 1083
1008 @Override 1084 @Override
1009 public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { 1085 public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
1010 - String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null);  
1011 - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);  
1012 - if (null == streamInfo) { 1086 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
  1087 + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
1013 logger.warn("streamId不存在!"); 1088 logger.warn("streamId不存在!");
1014 throw new ServiceException("streamId不存在"); 1089 throw new ServiceException("streamId不存在");
1015 } 1090 }
1016 - streamInfo.setPause(true);  
1017 - redisTemplate.opsForValue().set(key, streamInfo);  
1018 - MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId()); 1091 + inviteInfo.getStreamInfo().setPause(true);
  1092 + inviteStreamService.updateInviteInfo(inviteInfo);
  1093 + MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
1019 if (null == mediaServerItem) { 1094 if (null == mediaServerItem) {
1020 logger.warn("mediaServer 不存在!"); 1095 logger.warn("mediaServer 不存在!");
1021 throw new ServiceException("mediaServer不存在"); 1096 throw new ServiceException("mediaServer不存在");
@@ -1025,21 +1100,20 @@ public class PlayServiceImpl implements IPlayService { @@ -1025,21 +1100,20 @@ public class PlayServiceImpl implements IPlayService {
1025 if (jsonObject == null || jsonObject.getInteger("code") != 0) { 1100 if (jsonObject == null || jsonObject.getInteger("code") != 0) {
1026 throw new ServiceException("暂停RTP接收失败"); 1101 throw new ServiceException("暂停RTP接收失败");
1027 } 1102 }
1028 - Device device = storager.queryVideoDevice(streamInfo.getDeviceID());  
1029 - cmder.playPauseCmd(device, streamInfo); 1103 + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId());
  1104 + cmder.playPauseCmd(device, inviteInfo.getStreamInfo());
1030 } 1105 }
1031 1106
1032 @Override 1107 @Override
1033 public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException { 1108 public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
1034 - String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null);  
1035 - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);  
1036 - if (null == streamInfo) { 1109 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
  1110 + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
1037 logger.warn("streamId不存在!"); 1111 logger.warn("streamId不存在!");
1038 throw new ServiceException("streamId不存在"); 1112 throw new ServiceException("streamId不存在");
1039 } 1113 }
1040 - streamInfo.setPause(false);  
1041 - redisTemplate.opsForValue().set(key, streamInfo);  
1042 - MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId()); 1114 + inviteInfo.getStreamInfo().setPause(false);
  1115 + inviteStreamService.updateInviteInfo(inviteInfo);
  1116 + MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId());
1043 if (null == mediaServerItem) { 1117 if (null == mediaServerItem) {
1044 logger.warn("mediaServer 不存在!"); 1118 logger.warn("mediaServer 不存在!");
1045 throw new ServiceException("mediaServer不存在"); 1119 throw new ServiceException("mediaServer不存在");
@@ -1049,7 +1123,7 @@ public class PlayServiceImpl implements IPlayService { @@ -1049,7 +1123,7 @@ public class PlayServiceImpl implements IPlayService {
1049 if (jsonObject == null || jsonObject.getInteger("code") != 0) { 1123 if (jsonObject == null || jsonObject.getInteger("code") != 0) {
1050 throw new ServiceException("继续RTP接收失败"); 1124 throw new ServiceException("继续RTP接收失败");
1051 } 1125 }
1052 - Device device = storager.queryVideoDevice(streamInfo.getDeviceID());  
1053 - cmder.playResumeCmd(device, streamInfo); 1126 + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId());
  1127 + cmder.playResumeCmd(device, inviteInfo.getStreamInfo());
1054 } 1128 }
1055 } 1129 }
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
1 package com.genersoft.iot.vmp.storager; 1 package com.genersoft.iot.vmp.storager;
2 2
3 import com.alibaba.fastjson2.JSONObject; 3 import com.alibaba.fastjson2.JSONObject;
4 -import com.genersoft.iot.vmp.common.StreamInfo;  
5 import com.genersoft.iot.vmp.common.SystemAllInfo; 4 import com.genersoft.iot.vmp.common.SystemAllInfo;
6 -import com.genersoft.iot.vmp.gb28181.bean.*;  
7 -import com.genersoft.iot.vmp.media.zlm.dto.*; 5 +import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage;
  6 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  7 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
  8 +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  9 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  10 +import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
8 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; 11 import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
9 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 12 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
10 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; 13 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
11 -import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;  
12 import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; 14 import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
13 15
14 import java.util.List; 16 import java.util.List;
@@ -23,14 +25,6 @@ public interface IRedisCatchStorage { @@ -23,14 +25,6 @@ public interface IRedisCatchStorage {
23 */ 25 */
24 Long getCSEQ(); 26 Long getCSEQ();
25 27
26 - boolean startPlayback(StreamInfo stream, String callId);  
27 -  
28 - boolean stopPlayback(String deviceId, String channelId, String stream, String callId);  
29 -  
30 - StreamInfo queryPlayback(String deviceId, String channelID, String stream, String callId);  
31 -  
32 - String queryPlaybackForKey(String deviceId, String channelId, String stream, String callId);  
33 -  
34 void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch); 28 void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch);
35 29
36 ParentPlatformCatch queryPlatformCatchInfo(String platformGbId); 30 ParentPlatformCatch queryPlatformCatchInfo(String platformGbId);
@@ -47,8 +41,6 @@ public interface IRedisCatchStorage { @@ -47,8 +41,6 @@ public interface IRedisCatchStorage {
47 41
48 void delPlatformRegisterInfo(String callId); 42 void delPlatformRegisterInfo(String callId);
49 43
50 - void cleanPlatformRegisterInfos();  
51 -  
52 void updateSendRTPSever(SendRtpItem sendRtpItem); 44 void updateSendRTPSever(SendRtpItem sendRtpItem);
53 45
54 /** 46 /**
@@ -75,12 +67,6 @@ public interface IRedisCatchStorage { @@ -75,12 +67,6 @@ public interface IRedisCatchStorage {
75 boolean isChannelSendingRTP(String channelId); 67 boolean isChannelSendingRTP(String channelId);
76 68
77 /** 69 /**
78 - * 清空某个设备的所有缓存  
79 - * @param deviceId 设备ID  
80 - */  
81 - void clearCatchByDeviceId(String deviceId);  
82 -  
83 - /**  
84 * 在redis添加wvp的信息 70 * 在redis添加wvp的信息
85 */ 71 */
86 void updateWVPInfo(JSONObject jsonObject, int time); 72 void updateWVPInfo(JSONObject jsonObject, int time);
@@ -120,23 +106,6 @@ public interface IRedisCatchStorage { @@ -120,23 +106,6 @@ public interface IRedisCatchStorage {
120 */ 106 */
121 void removeStream(String mediaServerId, String type); 107 void removeStream(String mediaServerId, String type);
122 108
123 - /**  
124 - * 开始下载录像时存入  
125 - * @param streamInfo  
126 - */  
127 - boolean startDownload(StreamInfo streamInfo, String callId);  
128 -  
129 - StreamInfo queryDownload(String deviceId, String channelId, String stream, String callId);  
130 -  
131 - boolean stopDownload(String deviceId, String channelId, String stream, String callId);  
132 -  
133 - /**  
134 - * 查找第三方系统留下的国标预设值  
135 - * @param queryKey  
136 - * @return  
137 - */  
138 - ThirdPartyGB queryMemberNoGBId(String queryKey);  
139 -  
140 List<OnStreamChangedHookParam> getStreams(String mediaServerId, String pull); 109 List<OnStreamChangedHookParam> getStreams(String mediaServerId, String pull);
141 110
142 /** 111 /**
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -2,17 +2,18 @@ package com.genersoft.iot.vmp.storager.impl; @@ -2,17 +2,18 @@ package com.genersoft.iot.vmp.storager.impl;
2 2
3 import com.alibaba.fastjson2.JSON; 3 import com.alibaba.fastjson2.JSON;
4 import com.alibaba.fastjson2.JSONObject; 4 import com.alibaba.fastjson2.JSONObject;
5 -import com.genersoft.iot.vmp.common.StreamInfo;  
6 import com.genersoft.iot.vmp.common.SystemAllInfo; 5 import com.genersoft.iot.vmp.common.SystemAllInfo;
7 import com.genersoft.iot.vmp.common.VideoManagerConstants; 6 import com.genersoft.iot.vmp.common.VideoManagerConstants;
8 import com.genersoft.iot.vmp.conf.UserSetting; 7 import com.genersoft.iot.vmp.conf.UserSetting;
9 -import com.genersoft.iot.vmp.gb28181.bean.*;  
10 -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; 8 +import com.genersoft.iot.vmp.gb28181.bean.AlarmChannelMessage;
  9 +import com.genersoft.iot.vmp.gb28181.bean.Device;
  10 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch;
  11 +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 12 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; 13 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
  14 +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam;
13 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 15 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
14 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; 16 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
15 -import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;  
16 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
17 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; 18 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
18 import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo; 19 import com.genersoft.iot.vmp.storager.dao.dto.PlatformRegisterInfo;
@@ -92,160 +93,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -92,160 +93,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
92 } 93 }
93 } 94 }
94 95
95 -  
96 - @Override  
97 - public boolean startPlayback(StreamInfo stream, String callId) {  
98 - redisTemplate.opsForValue().set(String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,  
99 - userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream);  
100 - return true;  
101 - }  
102 -  
103 - @Override  
104 - public boolean startDownload(StreamInfo stream, String callId) {  
105 - String key=String.format("%S_%s_%s_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,  
106 - userSetting.getServerId(), stream.getMediaServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId);  
107 - if (stream.getProgress() == 1) {  
108 - logger.debug("添加下载缓存==已完成下载=》{}",key);  
109 - redisTemplate.opsForValue().set(key, stream);  
110 - }else {  
111 - logger.debug("添加下载缓存==未完成下载=》{}",key);  
112 - Duration duration = Duration.ofSeconds(60*60L);  
113 - redisTemplate.opsForValue().set(key, stream, duration);  
114 - }  
115 - return true;  
116 - }  
117 - @Override  
118 - public boolean stopDownload(String deviceId, String channelId, String stream, String callId) {  
119 - DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);  
120 - if (deviceChannel != null) {  
121 - deviceChannel.setStreamId(null);  
122 - deviceChannel.setDeviceId(deviceId);  
123 - deviceChannelMapper.update(deviceChannel);  
124 - }  
125 - if (deviceId == null) {  
126 - deviceId = "*";  
127 - }  
128 - if (channelId == null) {  
129 - channelId = "*";  
130 - }  
131 - if (stream == null) {  
132 - stream = "*";  
133 - }  
134 - if (callId == null) {  
135 - callId = "*";  
136 - }  
137 - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,  
138 - userSetting.getServerId(),  
139 - deviceId,  
140 - channelId,  
141 - stream,  
142 - callId  
143 - );  
144 - List<Object> scan = RedisUtil.scan(redisTemplate, key);  
145 - if (scan.size() > 0) {  
146 - for (Object keyObj : scan) {  
147 - redisTemplate.delete(keyObj);  
148 - }  
149 - }  
150 - return true;  
151 - }  
152 -  
153 - @Override  
154 - public boolean stopPlayback(String deviceId, String channelId, String stream, String callId) {  
155 - DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);  
156 - if (deviceChannel != null) {  
157 - deviceChannel.setStreamId(null);  
158 - deviceChannel.setDeviceId(deviceId);  
159 - deviceChannelMapper.update(deviceChannel);  
160 - }  
161 - if (deviceId == null) {  
162 - deviceId = "*";  
163 - }  
164 - if (channelId == null) {  
165 - channelId = "*";  
166 - }  
167 - if (stream == null) {  
168 - stream = "*";  
169 - }  
170 - if (callId == null) {  
171 - callId = "*";  
172 - }  
173 - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,  
174 - userSetting.getServerId(),  
175 - deviceId,  
176 - channelId,  
177 - stream,  
178 - callId  
179 - );  
180 - List<Object> scan = RedisUtil.scan(redisTemplate, key);  
181 - if (scan.size() > 0) {  
182 - for (Object keyObj : scan) {  
183 - redisTemplate.delete(keyObj);  
184 - }  
185 - }  
186 - return true;  
187 - }  
188 -  
189 - @Override  
190 - public StreamInfo queryPlayback(String deviceId, String channelId, String stream, String callId) {  
191 - if (stream == null && callId == null) {  
192 - return null;  
193 - }  
194 - if (deviceId == null) {  
195 - deviceId = "*";  
196 - }  
197 - if (channelId == null) {  
198 - channelId = "*";  
199 - }  
200 - if (stream == null) {  
201 - stream = "*";  
202 - }  
203 - if (callId == null) {  
204 - callId = "*";  
205 - }  
206 - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,  
207 - userSetting.getServerId(),  
208 - deviceId,  
209 - channelId,  
210 - stream,  
211 - callId  
212 - );  
213 - List<Object> streamInfoScan = RedisUtil.scan(redisTemplate, key);  
214 - if (streamInfoScan.size() > 0) {  
215 - return (StreamInfo) redisTemplate.opsForValue().get(streamInfoScan.get(0));  
216 - }else {  
217 - return null;  
218 - }  
219 - }  
220 -  
221 - @Override  
222 - public String queryPlaybackForKey(String deviceId, String channelId, String stream, String callId) {  
223 - if (stream == null && callId == null) {  
224 - return null;  
225 - }  
226 - if (deviceId == null) {  
227 - deviceId = "*";  
228 - }  
229 - if (channelId == null) {  
230 - channelId = "*";  
231 - }  
232 - if (stream == null) {  
233 - stream = "*";  
234 - }  
235 - if (callId == null) {  
236 - callId = "*";  
237 - }  
238 - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,  
239 - userSetting.getServerId(),  
240 - deviceId,  
241 - channelId,  
242 - stream,  
243 - callId  
244 - );  
245 - List<Object> streamInfoScan = RedisUtil.scan(redisTemplate, key);  
246 - return (String) streamInfoScan.get(0);  
247 - }  
248 -  
249 @Override 96 @Override
250 public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) { 97 public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) {
251 String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + parentPlatformCatch.getId(); 98 String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + parentPlatformCatch.getId();
@@ -292,14 +139,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -292,14 +139,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
292 } 139 }
293 140
294 @Override 141 @Override
295 - public void cleanPlatformRegisterInfos() {  
296 - List regInfos = RedisUtil.scan(redisTemplate, VideoManagerConstants.PLATFORM_REGISTER_INFO_PREFIX + userSetting.getServerId() + "_" + "*");  
297 - for (Object key : regInfos) {  
298 - redisTemplate.delete(key.toString());  
299 - }  
300 - }  
301 -  
302 - @Override  
303 public void updateSendRTPSever(SendRtpItem sendRtpItem) { 142 public void updateSendRTPSever(SendRtpItem sendRtpItem) {
304 143
305 String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + 144 String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX +
@@ -456,36 +295,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -456,36 +295,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
456 } 295 }
457 296
458 @Override 297 @Override
459 - public void clearCatchByDeviceId(String deviceId) {  
460 - List<Object> playLeys = RedisUtil.scan(redisTemplate, String.format("%S_%s_*_%s_*", VideoManagerConstants.PLAYER_PREFIX,  
461 - userSetting.getServerId(),  
462 - deviceId));  
463 - if (playLeys.size() > 0) {  
464 - for (Object key : playLeys) {  
465 - redisTemplate.delete(key.toString());  
466 - }  
467 - }  
468 -  
469 - List<Object> playBackers = RedisUtil.scan(redisTemplate, String.format("%S_%s_*_%s_*_*_*", VideoManagerConstants.PLAY_BLACK_PREFIX,  
470 - userSetting.getServerId(),  
471 - deviceId));  
472 - if (playBackers.size() > 0) {  
473 - for (Object key : playBackers) {  
474 - redisTemplate.delete(key.toString());  
475 - }  
476 - }  
477 -  
478 - List<Object> deviceCache = RedisUtil.scan(redisTemplate, String.format("%S%s_%s", VideoManagerConstants.DEVICE_PREFIX,  
479 - userSetting.getServerId(),  
480 - deviceId));  
481 - if (deviceCache.size() > 0) {  
482 - for (Object key : deviceCache) {  
483 - redisTemplate.delete(key.toString());  
484 - }  
485 - }  
486 - }  
487 -  
488 - @Override  
489 public void updateWVPInfo(JSONObject jsonObject, int time) { 298 public void updateWVPInfo(JSONObject jsonObject, int time) {
490 String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId(); 299 String key = VideoManagerConstants.WVP_SERVER_PREFIX + userSetting.getServerId();
491 Duration duration = Duration.ofSeconds(time); 300 Duration duration = Duration.ofSeconds(time);
@@ -517,44 +326,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -517,44 +326,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
517 } 326 }
518 327
519 @Override 328 @Override
520 - public StreamInfo queryDownload(String deviceId, String channelId, String stream, String callId) {  
521 - if (stream == null && callId == null) {  
522 - return null;  
523 - }  
524 - if (deviceId == null) {  
525 - deviceId = "*";  
526 - }  
527 - if (channelId == null) {  
528 - channelId = "*";  
529 - }  
530 - if (stream == null) {  
531 - stream = "*";  
532 - }  
533 - if (callId == null) {  
534 - callId = "*";  
535 - }  
536 - String key = String.format("%S_%s_*_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX,  
537 - userSetting.getServerId(),  
538 - deviceId,  
539 - channelId,  
540 - stream,  
541 - callId  
542 - );  
543 - List<Object> streamInfoScan = RedisUtil.scan(redisTemplate, key);  
544 - if (streamInfoScan.size() > 0) {  
545 - return (StreamInfo) redisTemplate.opsForValue().get(streamInfoScan.get(0));  
546 - }else {  
547 - return null;  
548 - }  
549 - }  
550 -  
551 - @Override  
552 - public ThirdPartyGB queryMemberNoGBId(String queryKey) {  
553 - String key = VideoManagerConstants.WVP_STREAM_GB_ID_PREFIX + queryKey;  
554 - return JsonUtil.redisJsonToObject(redisTemplate, key, ThirdPartyGB.class);  
555 - }  
556 -  
557 - @Override  
558 public void removeStream(String mediaServerId, String type) { 329 public void removeStream(String mediaServerId, String type) {
559 String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_*_*_" + mediaServerId; 330 String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_*_*_" + mediaServerId;
560 List<Object> streams = RedisUtil.scan(redisTemplate, key); 331 List<Object> streams = RedisUtil.scan(redisTemplate, key);
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceQuery.java
@@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 14 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
15 import com.genersoft.iot.vmp.service.IDeviceChannelService; 15 import com.genersoft.iot.vmp.service.IDeviceChannelService;
16 import com.genersoft.iot.vmp.service.IDeviceService; 16 import com.genersoft.iot.vmp.service.IDeviceService;
  17 +import com.genersoft.iot.vmp.service.IInviteStreamService;
17 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 18 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
18 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 19 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
19 import com.genersoft.iot.vmp.vmanager.bean.BaseTree; 20 import com.genersoft.iot.vmp.vmanager.bean.BaseTree;
@@ -62,6 +63,9 @@ public class DeviceQuery { @@ -62,6 +63,9 @@ public class DeviceQuery {
62 63
63 @Autowired 64 @Autowired
64 private IRedisCatchStorage redisCatchStorage; 65 private IRedisCatchStorage redisCatchStorage;
  66 +
  67 + @Autowired
  68 + private IInviteStreamService inviteStreamService;
65 69
66 @Autowired 70 @Autowired
67 private SIPCommander cmder; 71 private SIPCommander cmder;
@@ -184,7 +188,7 @@ public class DeviceQuery { @@ -184,7 +188,7 @@ public class DeviceQuery {
184 // 清除redis记录 188 // 清除redis记录
185 boolean isSuccess = deviceService.delete(deviceId); 189 boolean isSuccess = deviceService.delete(deviceId);
186 if (isSuccess) { 190 if (isSuccess) {
187 - redisCatchStorage.clearCatchByDeviceId(deviceId); 191 + inviteStreamService.clearInviteInfo(deviceId);
188 // 停止此设备的订阅更新 192 // 停止此设备的订阅更新
189 Set<String> allKeys = dynamicTask.getAllKeys(); 193 Set<String> allKeys = dynamicTask.getAllKeys();
190 for (String key : allKeys) { 194 for (String key : allKeys) {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.play; 1 package com.genersoft.iot.vmp.vmanager.gb28181.play;
2 2
3 -import com.alibaba.fastjson2.JSON;  
4 import com.alibaba.fastjson2.JSONArray; 3 import com.alibaba.fastjson2.JSONArray;
5 import com.alibaba.fastjson2.JSONObject; 4 import com.alibaba.fastjson2.JSONObject;
6 import com.genersoft.iot.vmp.common.InviteInfo; 5 import com.genersoft.iot.vmp.common.InviteInfo;
@@ -116,7 +115,7 @@ public class PlayController { @@ -116,7 +115,7 @@ public class PlayController {
116 // 录像查询以channelId作为deviceId查询 115 // 录像查询以channelId作为deviceId查询
117 resultHolder.put(key, uuid, result); 116 resultHolder.put(key, uuid, result);
118 117
119 - playService.play(newMediaServerItem, deviceId, channelId, ((code, msg, data) -> { 118 + playService.play(newMediaServerItem, deviceId, channelId, (code, msg, data) -> {
120 WVPResult<StreamContent> wvpResult = new WVPResult<>(); 119 WVPResult<StreamContent> wvpResult = new WVPResult<>();
121 if (code == InviteErrorCode.SUCCESS.getCode()) { 120 if (code == InviteErrorCode.SUCCESS.getCode()) {
122 wvpResult.setCode(ErrorCode.SUCCESS.getCode()); 121 wvpResult.setCode(ErrorCode.SUCCESS.getCode());
@@ -133,10 +132,9 @@ public class PlayController { @@ -133,10 +132,9 @@ public class PlayController {
133 wvpResult.setCode(code); 132 wvpResult.setCode(code);
134 wvpResult.setMsg(msg); 133 wvpResult.setMsg(msg);
135 } 134 }
136 - System.out.println(JSON.toJSONString(wvpResult));  
137 requestMessage.setData(wvpResult); 135 requestMessage.setData(wvpResult);
138 resultHolder.invokeResult(requestMessage); 136 resultHolder.invokeResult(requestMessage);
139 - })); 137 + });
140 return result; 138 return result;
141 } 139 }
142 140
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.playback; 1 package com.genersoft.iot.vmp.vmanager.gb28181.playback;
2 2
  3 +import com.genersoft.iot.vmp.common.InviteInfo;
  4 +import com.genersoft.iot.vmp.common.InviteSessionType;
3 import com.genersoft.iot.vmp.common.StreamInfo; 5 import com.genersoft.iot.vmp.common.StreamInfo;
4 import com.genersoft.iot.vmp.conf.UserSetting; 6 import com.genersoft.iot.vmp.conf.UserSetting;
5 import com.genersoft.iot.vmp.conf.exception.ControllerException; 7 import com.genersoft.iot.vmp.conf.exception.ControllerException;
6 import com.genersoft.iot.vmp.conf.exception.ServiceException; 8 import com.genersoft.iot.vmp.conf.exception.ServiceException;
7 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 9 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
  10 +import com.genersoft.iot.vmp.gb28181.bean.Device;
8 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; 11 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
9 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 12 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  13 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
10 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 14 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
11 -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 +import com.genersoft.iot.vmp.service.IInviteStreamService;
12 import com.genersoft.iot.vmp.service.IPlayService; 16 import com.genersoft.iot.vmp.service.IPlayService;
  17 +import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
  18 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  19 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
13 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 20 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
14 import com.genersoft.iot.vmp.vmanager.bean.StreamContent; 21 import com.genersoft.iot.vmp.vmanager.bean.StreamContent;
15 import com.genersoft.iot.vmp.vmanager.bean.WVPResult; 22 import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
@@ -20,17 +27,13 @@ import org.slf4j.Logger; @@ -20,17 +27,13 @@ import org.slf4j.Logger;
20 import org.slf4j.LoggerFactory; 27 import org.slf4j.LoggerFactory;
21 import org.springframework.beans.factory.annotation.Autowired; 28 import org.springframework.beans.factory.annotation.Autowired;
22 import org.springframework.util.ObjectUtils; 29 import org.springframework.util.ObjectUtils;
23 -import org.springframework.web.bind.annotation.CrossOrigin;  
24 import org.springframework.web.bind.annotation.GetMapping; 30 import org.springframework.web.bind.annotation.GetMapping;
25 import org.springframework.web.bind.annotation.PathVariable; 31 import org.springframework.web.bind.annotation.PathVariable;
26 import org.springframework.web.bind.annotation.RequestMapping; 32 import org.springframework.web.bind.annotation.RequestMapping;
27 import org.springframework.web.bind.annotation.RestController; 33 import org.springframework.web.bind.annotation.RestController;
28 -  
29 -import com.genersoft.iot.vmp.gb28181.bean.Device;  
30 -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;  
31 -import com.genersoft.iot.vmp.storager.IVideoManagerStorage;  
32 import org.springframework.web.context.request.async.DeferredResult; 34 import org.springframework.web.context.request.async.DeferredResult;
33 35
  36 +import javax.servlet.http.HttpServletRequest;
34 import javax.sip.InvalidArgumentException; 37 import javax.sip.InvalidArgumentException;
35 import javax.sip.SipException; 38 import javax.sip.SipException;
36 import java.text.ParseException; 39 import java.text.ParseException;
@@ -60,6 +63,9 @@ public class PlaybackController { @@ -60,6 +63,9 @@ public class PlaybackController {
60 private IRedisCatchStorage redisCatchStorage; 63 private IRedisCatchStorage redisCatchStorage;
61 64
62 @Autowired 65 @Autowired
  66 + private IInviteStreamService inviteStreamService;
  67 +
  68 + @Autowired
63 private IPlayService playService; 69 private IPlayService playService;
64 70
65 @Autowired 71 @Autowired
@@ -74,8 +80,8 @@ public class PlaybackController { @@ -74,8 +80,8 @@ public class PlaybackController {
74 @Parameter(name = "startTime", description = "开始时间", required = true) 80 @Parameter(name = "startTime", description = "开始时间", required = true)
75 @Parameter(name = "endTime", description = "结束时间", required = true) 81 @Parameter(name = "endTime", description = "结束时间", required = true)
76 @GetMapping("/start/{deviceId}/{channelId}") 82 @GetMapping("/start/{deviceId}/{channelId}")
77 - public DeferredResult<WVPResult<StreamContent>> start(@PathVariable String deviceId, @PathVariable String channelId,  
78 - String startTime, String endTime) { 83 + public DeferredResult<WVPResult<StreamContent>> start(HttpServletRequest request, @PathVariable String deviceId, @PathVariable String channelId,
  84 + String startTime, String endTime) {
79 85
80 if (logger.isDebugEnabled()) { 86 if (logger.isDebugEnabled()) {
81 logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId)); 87 logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
@@ -86,22 +92,31 @@ public class PlaybackController { @@ -86,22 +92,31 @@ public class PlaybackController {
86 DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); 92 DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue());
87 resultHolder.put(key, uuid, result); 93 resultHolder.put(key, uuid, result);
88 94
89 - WVPResult<StreamContent> wvpResult = new WVPResult<>();  
90 -  
91 - RequestMessage msg = new RequestMessage();  
92 - msg.setKey(key);  
93 - msg.setId(uuid);  
94 -  
95 - playService.playBack(deviceId, channelId, startTime, endTime, null,  
96 - playBackResult->{  
97 - wvpResult.setCode(playBackResult.getCode());  
98 - wvpResult.setMsg(playBackResult.getMsg());  
99 - if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) {  
100 - StreamInfo streamInfo = (StreamInfo)playBackResult.getData();  
101 - wvpResult.setData(new StreamContent(streamInfo)); 95 + RequestMessage requestMessage = new RequestMessage();
  96 + requestMessage.setKey(key);
  97 + requestMessage.setId(uuid);
  98 +
  99 + playService.playBack(deviceId, channelId, startTime, endTime,
  100 + (code, msg, data)->{
  101 +
  102 + WVPResult<StreamContent> wvpResult = new WVPResult<>();
  103 + if (code == InviteErrorCode.SUCCESS.getCode()) {
  104 + wvpResult.setCode(ErrorCode.SUCCESS.getCode());
  105 + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
  106 +
  107 + if (data != null) {
  108 + StreamInfo streamInfo = (StreamInfo)data;
  109 + if (userSetting.getUseSourceIpAsStreamIp()) {
  110 + streamInfo.channgeStreamIp(request.getLocalName());
  111 + }
  112 + wvpResult.setData(new StreamContent(streamInfo));
  113 + }
  114 + }else {
  115 + wvpResult.setCode(code);
  116 + wvpResult.setMsg(msg);
102 } 117 }
103 - msg.setData(wvpResult);  
104 - resultHolder.invokeResult(msg); 118 + requestMessage.setData(wvpResult);
  119 + resultHolder.invokeResult(requestMessage);
105 }); 120 });
106 121
107 return result; 122 return result;
@@ -169,14 +184,15 @@ public class PlaybackController { @@ -169,14 +184,15 @@ public class PlaybackController {
169 @GetMapping("/seek/{streamId}/{seekTime}") 184 @GetMapping("/seek/{streamId}/{seekTime}")
170 public void playSeek(@PathVariable String streamId, @PathVariable long seekTime) { 185 public void playSeek(@PathVariable String streamId, @PathVariable long seekTime) {
171 logger.info("playSeek: "+streamId+", "+seekTime); 186 logger.info("playSeek: "+streamId+", "+seekTime);
172 - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);  
173 - if (null == streamInfo) { 187 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
  188 +
  189 + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
174 logger.warn("streamId不存在!"); 190 logger.warn("streamId不存在!");
175 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); 191 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
176 } 192 }
177 - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); 193 + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId());
178 try { 194 try {
179 - cmder.playSeekCmd(device, streamInfo, seekTime); 195 + cmder.playSeekCmd(device, inviteInfo.getStreamInfo(), seekTime);
180 } catch (InvalidArgumentException | ParseException | SipException e) { 196 } catch (InvalidArgumentException | ParseException | SipException e) {
181 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage()); 197 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
182 } 198 }
@@ -188,8 +204,9 @@ public class PlaybackController { @@ -188,8 +204,9 @@ public class PlaybackController {
188 @GetMapping("/speed/{streamId}/{speed}") 204 @GetMapping("/speed/{streamId}/{speed}")
189 public void playSpeed(@PathVariable String streamId, @PathVariable Double speed) { 205 public void playSpeed(@PathVariable String streamId, @PathVariable Double speed) {
190 logger.info("playSpeed: "+streamId+", "+speed); 206 logger.info("playSpeed: "+streamId+", "+speed);
191 - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);  
192 - if (null == streamInfo) { 207 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, streamId);
  208 +
  209 + if (null == inviteInfo || inviteInfo.getStreamInfo() == null) {
193 logger.warn("streamId不存在!"); 210 logger.warn("streamId不存在!");
194 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在"); 211 throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
195 } 212 }
@@ -197,9 +214,9 @@ public class PlaybackController { @@ -197,9 +214,9 @@ public class PlaybackController {
197 logger.warn("不支持的speed: " + speed); 214 logger.warn("不支持的speed: " + speed);
198 throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)"); 215 throw new ControllerException(ErrorCode.ERROR100.getCode(), "不支持的speed(0.25 0.5 1、2、4)");
199 } 216 }
200 - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); 217 + Device device = storager.queryVideoDevice(inviteInfo.getDeviceId());
201 try { 218 try {
202 - cmder.playSpeedCmd(device, streamInfo, speed); 219 + cmder.playSpeedCmd(device, inviteInfo.getStreamInfo(), speed);
203 } catch (InvalidArgumentException | ParseException | SipException e) { 220 } catch (InvalidArgumentException | ParseException | SipException e) {
204 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage()); 221 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
205 } 222 }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
1 package com.genersoft.iot.vmp.vmanager.gb28181.record; 1 package com.genersoft.iot.vmp.vmanager.gb28181.record;
2 2
3 import com.genersoft.iot.vmp.common.StreamInfo; 3 import com.genersoft.iot.vmp.common.StreamInfo;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
4 import com.genersoft.iot.vmp.conf.exception.ControllerException; 5 import com.genersoft.iot.vmp.conf.exception.ControllerException;
5 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 6 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
6 import com.genersoft.iot.vmp.gb28181.bean.Device; 7 import com.genersoft.iot.vmp.gb28181.bean.Device;
@@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; @@ -10,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
10 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; 11 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander;
11 import com.genersoft.iot.vmp.service.IDeviceService; 12 import com.genersoft.iot.vmp.service.IDeviceService;
12 import com.genersoft.iot.vmp.service.IPlayService; 13 import com.genersoft.iot.vmp.service.IPlayService;
  14 +import com.genersoft.iot.vmp.service.bean.InviteErrorCode;
13 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 15 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
14 import com.genersoft.iot.vmp.utils.DateUtil; 16 import com.genersoft.iot.vmp.utils.DateUtil;
15 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 17 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
@@ -27,6 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping; @@ -27,6 +29,7 @@ import org.springframework.web.bind.annotation.RequestMapping;
27 import org.springframework.web.bind.annotation.RestController; 29 import org.springframework.web.bind.annotation.RestController;
28 import org.springframework.web.context.request.async.DeferredResult; 30 import org.springframework.web.context.request.async.DeferredResult;
29 31
  32 +import javax.servlet.http.HttpServletRequest;
30 import javax.sip.InvalidArgumentException; 33 import javax.sip.InvalidArgumentException;
31 import javax.sip.SipException; 34 import javax.sip.SipException;
32 import java.text.ParseException; 35 import java.text.ParseException;
@@ -55,8 +58,8 @@ public class GBRecordController { @@ -55,8 +58,8 @@ public class GBRecordController {
55 @Autowired 58 @Autowired
56 private IDeviceService deviceService; 59 private IDeviceService deviceService;
57 60
58 -  
59 - 61 + @Autowired
  62 + private UserSetting userSetting;
60 63
61 @Operation(summary = "录像查询") 64 @Operation(summary = "录像查询")
62 @Parameter(name = "deviceId", description = "设备国标编号", required = true) 65 @Parameter(name = "deviceId", description = "设备国标编号", required = true)
@@ -119,8 +122,8 @@ public class GBRecordController { @@ -119,8 +122,8 @@ public class GBRecordController {
119 @Parameter(name = "endTime", description = "结束时间", required = true) 122 @Parameter(name = "endTime", description = "结束时间", required = true)
120 @Parameter(name = "downloadSpeed", description = "下载倍速", required = true) 123 @Parameter(name = "downloadSpeed", description = "下载倍速", required = true)
121 @GetMapping("/download/start/{deviceId}/{channelId}") 124 @GetMapping("/download/start/{deviceId}/{channelId}")
122 - public DeferredResult<WVPResult<StreamContent>> download(@PathVariable String deviceId, @PathVariable String channelId,  
123 - String startTime, String endTime, String downloadSpeed) { 125 + public DeferredResult<WVPResult<StreamContent>> download(HttpServletRequest request, @PathVariable String deviceId, @PathVariable String channelId,
  126 + String startTime, String endTime, String downloadSpeed) {
124 127
125 if (logger.isDebugEnabled()) { 128 if (logger.isDebugEnabled()) {
126 logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed)); 129 logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed));
@@ -130,22 +133,32 @@ public class GBRecordController { @@ -130,22 +133,32 @@ public class GBRecordController {
130 String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId; 133 String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
131 DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(30000L); 134 DeferredResult<WVPResult<StreamContent>> result = new DeferredResult<>(30000L);
132 resultHolder.put(key, uuid, result); 135 resultHolder.put(key, uuid, result);
133 - RequestMessage msg = new RequestMessage();  
134 - msg.setId(uuid);  
135 - msg.setKey(key);  
136 -  
137 - WVPResult<StreamContent> wvpResult = new WVPResult<>();  
138 -  
139 - playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed), null, playBackResult->{  
140 -  
141 - wvpResult.setCode(playBackResult.getCode());  
142 - wvpResult.setMsg(playBackResult.getMsg());  
143 - if (playBackResult.getCode() == ErrorCode.SUCCESS.getCode()) {  
144 - StreamInfo streamInfo = (StreamInfo)playBackResult.getData();  
145 - wvpResult.setData(new StreamContent(streamInfo)); 136 + RequestMessage requestMessage = new RequestMessage();
  137 + requestMessage.setId(uuid);
  138 + requestMessage.setKey(key);
  139 +
  140 +
  141 + playService.download(deviceId, channelId, startTime, endTime, Integer.parseInt(downloadSpeed),
  142 + (code, msg, data)->{
  143 +
  144 + WVPResult<StreamContent> wvpResult = new WVPResult<>();
  145 + if (code == InviteErrorCode.SUCCESS.getCode()) {
  146 + wvpResult.setCode(ErrorCode.SUCCESS.getCode());
  147 + wvpResult.setMsg(ErrorCode.SUCCESS.getMsg());
  148 +
  149 + if (data != null) {
  150 + StreamInfo streamInfo = (StreamInfo)data;
  151 + if (userSetting.getUseSourceIpAsStreamIp()) {
  152 + streamInfo.channgeStreamIp(request.getLocalName());
  153 + }
  154 + wvpResult.setData(new StreamContent(streamInfo));
  155 + }
  156 + }else {
  157 + wvpResult.setCode(code);
  158 + wvpResult.setMsg(msg);
146 } 159 }
147 - msg.setData(wvpResult);  
148 - resultHolder.invokeResult(msg); 160 + requestMessage.setData(wvpResult);
  161 + resultHolder.invokeResult(requestMessage);
149 }); 162 });
150 163
151 return result; 164 return result;