Commit 6bfd48776d72bdc450aa367b490327710f306304

Authored by 648540858
2 parents e1af52fb c4fc4abf

Merge branch 'wvp-28181-2.0'

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
#	src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
.gitignore
@@ -27,3 +27,4 @@ hs_err_pid* @@ -27,3 +27,4 @@ hs_err_pid*
27 /target/ 27 /target/
28 28
29 /src/main/resources/static/ 29 /src/main/resources/static/
  30 +certificates
sql/mysql.sql
@@ -48,6 +48,7 @@ CREATE TABLE `device` ( @@ -48,6 +48,7 @@ CREATE TABLE `device` (
48 `ssrcCheck` int DEFAULT '0', 48 `ssrcCheck` int DEFAULT '0',
49 `geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 49 `geoCoordSys` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
50 `treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, 50 `treeType` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
  51 + `mediaServerId` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT 'auto',
51 PRIMARY KEY (`id`), 52 PRIMARY KEY (`id`),
52 UNIQUE KEY `device_deviceId_uindex` (`deviceId`) 53 UNIQUE KEY `device_deviceId_uindex` (`deviceId`)
53 ) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci; 54 ) ENGINE=InnoDB AUTO_INCREMENT=36 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -39,6 +39,8 @@ public class StreamInfo { @@ -39,6 +39,8 @@ public class StreamInfo {
39 private String endTime; 39 private String endTime;
40 private double progress; 40 private double progress;
41 41
  42 + private boolean pause;
  43 +
42 public static class TransactionInfo{ 44 public static class TransactionInfo{
43 public String callId; 45 public String callId;
44 public String localTag; 46 public String localTag;
@@ -312,4 +314,12 @@ public class StreamInfo { @@ -312,4 +314,12 @@ public class StreamInfo {
312 public void setRtcs(String rtcs) { 314 public void setRtcs(String rtcs) {
313 this.rtcs = rtcs; 315 this.rtcs = rtcs;
314 } 316 }
  317 +
  318 + public boolean isPause() {
  319 + return pause;
  320 + }
  321 +
  322 + public void setPause(boolean pause) {
  323 + this.pause = pause;
  324 + }
315 } 325 }
src/main/java/com/genersoft/iot/vmp/conf/exception/ServiceException.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.exception;
  2 +
  3 +/**
  4 + * @author lin
  5 + */
  6 +public class ServiceException extends Exception{
  7 + private String msg;
  8 +
  9 +
  10 +
  11 + public ServiceException(String msg) {
  12 + this.msg = msg;
  13 + }
  14 +
  15 + public String getMsg() {
  16 + return msg;
  17 + }
  18 +
  19 + public void setMsg(String msg) {
  20 + this.msg = msg;
  21 + }
  22 +
  23 + @Override
  24 + public String getMessage() {
  25 + return msg;
  26 + }
  27 +}
src/main/java/com/genersoft/iot/vmp/conf/exception/SsrcTransactionNotFoundException.java
1 package com.genersoft.iot.vmp.conf.exception; 1 package com.genersoft.iot.vmp.conf.exception;
2 2
3 -import com.sun.javafx.binding.StringFormatter;  
4 -  
5 /** 3 /**
6 * @author lin 4 * @author lin
7 */ 5 */
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -132,6 +132,7 @@ public interface ISIPCommander { @@ -132,6 +132,7 @@ public interface ISIPCommander {
132 132
133 void talkStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; 133 void talkStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException;
134 134
  135 +
135 void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException; 136 void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
136 137
137 void streamByeCmd(Device device, String channelId, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; 138 void streamByeCmd(Device device, String channelId, SipTransactionInfo sipTransactionInfo, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -729,19 +729,24 @@ public class ZLMHttpHookListener { @@ -729,19 +729,24 @@ public class ZLMHttpHookListener {
729 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); 729 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
730 }else{ 730 }else{
731 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null); 731 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null);
732 - if (streamInfoForPlayBackCatch != null) {  
733 - Device device = deviceService.queryDevice(streamInfoForPlayCatch.getDeviceID());  
734 - if (device != null) {  
735 - try {  
736 - cmder.streamByeCmd(device,streamInfoForPlayBackCatch.getChannelId(),  
737 - streamInfoForPlayBackCatch.getStream(), null);  
738 - } catch (InvalidArgumentException | ParseException | SipException |  
739 - SsrcTransactionNotFoundException e) {  
740 - logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage()); 732 + if (streamInfoForPlayBackCatch != null ) {
  733 + if (streamInfoForPlayBackCatch.isPause()) {
  734 + ret.put("close", false);
  735 + }else {
  736 + Device device = deviceService.queryDevice(streamInfoForPlayBackCatch.getDeviceID());
  737 + if (device != null) {
  738 + try {
  739 + cmder.streamByeCmd(device,streamInfoForPlayBackCatch.getChannelId(),
  740 + streamInfoForPlayBackCatch.getStream(), null);
  741 + } catch (InvalidArgumentException | ParseException | SipException |
  742 + SsrcTransactionNotFoundException e) {
  743 + logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage());
  744 + }
741 } 745 }
  746 + redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),
  747 + streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
742 } 748 }
743 - redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),  
744 - streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null); 749 +
745 }else { 750 }else {
746 StreamInfo streamInfoForDownload = redisCatchStorage.queryDownload(null, null, streamId, null); 751 StreamInfo streamInfoForDownload = redisCatchStorage.queryDownload(null, null, streamId, null);
747 // 进行录像下载时无人观看不断流 752 // 进行录像下载时无人观看不断流
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
@@ -23,6 +23,9 @@ public class ZLMRESTfulUtils { @@ -23,6 +23,9 @@ public class ZLMRESTfulUtils {
23 23
24 private final static Logger logger = LoggerFactory.getLogger(ZLMRESTfulUtils.class); 24 private final static Logger logger = LoggerFactory.getLogger(ZLMRESTfulUtils.class);
25 25
  26 +
  27 +
  28 +
26 public interface RequestCallback{ 29 public interface RequestCallback{
27 void run(JSONObject response); 30 void run(JSONObject response);
28 } 31 }
@@ -326,10 +329,22 @@ public class ZLMRESTfulUtils { @@ -326,10 +329,22 @@ public class ZLMRESTfulUtils {
326 } 329 }
327 330
328 public void getSnap(MediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { 331 public void getSnap(MediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
329 - Map<String, Object> param = new HashMap<>(); 332 + Map<String, Object> param = new HashMap<>(3);
330 param.put("url", flvUrl); 333 param.put("url", flvUrl);
331 param.put("timeout_sec", timeout_sec); 334 param.put("timeout_sec", timeout_sec);
332 param.put("expire_sec", expire_sec); 335 param.put("expire_sec", expire_sec);
333 sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName); 336 sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName);
334 } 337 }
  338 +
  339 + public JSONObject pauseRtpCheck(MediaServerItem mediaServerItem, String streamId) {
  340 + Map<String, Object> param = new HashMap<>(1);
  341 + param.put("stream_id", streamId);
  342 + return sendPost(mediaServerItem, "pauseRtpCheck",param, null);
  343 + }
  344 +
  345 + public JSONObject resumeRtpCheck(MediaServerItem mediaServerItem, String streamId) {
  346 + Map<String, Object> param = new HashMap<>(1);
  347 + param.put("stream_id", streamId);
  348 + return sendPost(mediaServerItem, "resumeRtpCheck",param, null);
  349 + }
335 } 350 }
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
@@ -104,7 +104,6 @@ public class ZLMRTPServerFactory { @@ -104,7 +104,6 @@ public class ZLMRTPServerFactory {
104 param.put("stream_id", streamId); 104 param.put("stream_id", streamId);
105 JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param); 105 JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param);
106 if (jsonObject != null ) { 106 if (jsonObject != null ) {
107 - System.out.println(jsonObject);  
108 if (jsonObject.getInteger("code") == 0) { 107 if (jsonObject.getInteger("code") == 0) {
109 return createRTPServer(mediaServerItem, streamId, ssrc, port); 108 return createRTPServer(mediaServerItem, streamId, ssrc, port);
110 }else { 109 }else {
@@ -151,7 +150,6 @@ public class ZLMRTPServerFactory { @@ -151,7 +150,6 @@ public class ZLMRTPServerFactory {
151 param.put("stream_id", streamId); 150 param.put("stream_id", streamId);
152 JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(serverItem, param); 151 JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(serverItem, param);
153 if (jsonObject != null ) { 152 if (jsonObject != null ) {
154 - System.out.println(jsonObject);  
155 if (jsonObject.getInteger("code") == 0) { 153 if (jsonObject.getInteger("code") == 0) {
156 result = jsonObject.getInteger("hit") == 1; 154 result = jsonObject.getInteger("hit") == 1;
157 }else { 155 }else {
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service; @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service;
2 2
3 import com.alibaba.fastjson.JSONObject; 3 import com.alibaba.fastjson.JSONObject;
4 import com.genersoft.iot.vmp.common.StreamInfo; 4 import com.genersoft.iot.vmp.common.StreamInfo;
  5 +import com.genersoft.iot.vmp.conf.exception.ServiceException;
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.InviteStreamCallback; 7 import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
7 import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo; 8 import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
@@ -57,4 +58,8 @@ public interface IPlayService { @@ -57,4 +58,8 @@ public interface IPlayService {
57 void stopAudioBroadcast(String deviceId, String channelId); 58 void stopAudioBroadcast(String deviceId, String channelId);
58 59
59 void audioBroadcastCmd(Device device, String channelId, int timeout, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException; 60 void audioBroadcastCmd(Device device, String channelId, int timeout, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException;
  61 +
  62 + void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
  63 +
  64 + void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
60 } 65 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -526,7 +526,6 @@ public class MediaServerServiceImpl implements IMediaServerService { @@ -526,7 +526,6 @@ public class MediaServerServiceImpl implements IMediaServerService {
526 526
527 Map<String, Object> param = new HashMap<>(); 527 Map<String, Object> param = new HashMap<>();
528 param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline 528 param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline
529 - param.put("ffmpeg.cmd","%s -fflags nobuffer -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s");  
530 param.put("hook.enable","1"); 529 param.put("hook.enable","1");
531 param.put("hook.on_flow_report",String.format("%s/on_flow_report", hookPrex)); 530 param.put("hook.on_flow_report",String.format("%s/on_flow_report", hookPrex));
532 param.put("hook.on_play",String.format("%s/on_play", hookPrex)); 531 param.put("hook.on_play",String.format("%s/on_play", hookPrex));
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -10,20 +10,26 @@ import javax.sip.ResponseEvent; @@ -10,20 +10,26 @@ import javax.sip.ResponseEvent;
10 import javax.sip.SipException; 10 import javax.sip.SipException;
11 11
12 import com.genersoft.iot.vmp.gb28181.bean.*; 12 import com.genersoft.iot.vmp.gb28181.bean.*;
  13 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
13 import com.genersoft.iot.vmp.conf.exception.ControllerException; 14 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  15 +import com.genersoft.iot.vmp.conf.exception.ServiceException;
14 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; 16 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
15 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; 17 import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
16 import com.genersoft.iot.vmp.gb28181.utils.SipUtils; 18 import com.genersoft.iot.vmp.gb28181.utils.SipUtils;
17 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; 19 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
18 import com.genersoft.iot.vmp.service.IDeviceService; 20 import com.genersoft.iot.vmp.service.IDeviceService;
19 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; 21 import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult;
  22 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
20 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 23 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
21 import org.slf4j.Logger; 24 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory; 25 import org.slf4j.LoggerFactory;
23 import org.springframework.beans.factory.annotation.Autowired; 26 import org.springframework.beans.factory.annotation.Autowired;
24 import org.springframework.beans.factory.annotation.Qualifier; 27 import org.springframework.beans.factory.annotation.Qualifier;
  28 +import org.springframework.beans.factory.annotation.Value;
25 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; 29 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
26 import org.springframework.stereotype.Service; 30 import org.springframework.stereotype.Service;
  31 +import org.springframework.util.ObjectUtils;
  32 +import org.springframework.util.StringUtils;
27 import org.springframework.web.context.request.async.DeferredResult; 33 import org.springframework.web.context.request.async.DeferredResult;
28 34
29 import com.alibaba.fastjson.JSON; 35 import com.alibaba.fastjson.JSON;
@@ -157,6 +163,7 @@ public class PlayServiceImpl implements IPlayService { @@ -157,6 +163,7 @@ public class PlayServiceImpl implements IPlayService {
157 StreamInfo streamInfoForSuccess = (StreamInfo) wvpResult.getData(); 163 StreamInfo streamInfoForSuccess = (StreamInfo) wvpResult.getData();
158 MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); 164 MediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId());
159 String streamUrl = streamInfoForSuccess.getFmp4(); 165 String streamUrl = streamInfoForSuccess.getFmp4();
  166 +
160 // 请求截图 167 // 请求截图
161 logger.info("[请求截图]: " + fileName); 168 logger.info("[请求截图]: " + fileName);
162 zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); 169 zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName);
@@ -441,7 +448,6 @@ public class PlayServiceImpl implements IPlayService { @@ -441,7 +448,6 @@ public class PlayServiceImpl implements IPlayService {
441 448
442 } 449 }
443 450
444 -  
445 @Override 451 @Override
446 public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, 452 public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId,
447 ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, 453 ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent,
@@ -600,12 +606,13 @@ public class PlayServiceImpl implements IPlayService { @@ -600,12 +606,13 @@ public class PlayServiceImpl implements IPlayService {
600 if (device == null) { 606 if (device == null) {
601 return null; 607 return null;
602 } 608 }
603 - String mediaServerId = device.getMediaServerId();  
604 MediaServerItem mediaServerItem; 609 MediaServerItem mediaServerItem;
605 - if (mediaServerId == null) { 610 + if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) {
606 mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(); 611 mediaServerItem = mediaServerService.getMediaServerForMinimumLoad();
607 } else { 612 } else {
608 mediaServerItem = mediaServerService.getOne(mediaServerId); 613 mediaServerItem = mediaServerService.getOne(mediaServerId);
  614 + } else {
  615 + mediaServerItem = mediaServerService.getOne(device.getMediaServerId());
609 } 616 }
610 if (mediaServerItem == null) { 617 if (mediaServerItem == null) {
611 logger.warn("点播时未找到可使用的ZLM..."); 618 logger.warn("点播时未找到可使用的ZLM...");
@@ -960,7 +967,7 @@ public class PlayServiceImpl implements IPlayService { @@ -960,7 +967,7 @@ public class PlayServiceImpl implements IPlayService {
960 cmder.streamByeCmd(device, ssrcTransaction.getChannelId(), 967 cmder.streamByeCmd(device, ssrcTransaction.getChannelId(),
961 ssrcTransaction.getStream(), null); 968 ssrcTransaction.getStream(), null);
962 } catch (InvalidArgumentException | ParseException | SipException | 969 } catch (InvalidArgumentException | ParseException | SipException |
963 - SsrcTransactionNotFoundException e) { 970 + SsrcTransactionNotFoundException e) {
964 logger.error("[zlm离线]为正在使用此zlm的设备, 发送BYE失败 {}", e.getMessage()); 971 logger.error("[zlm离线]为正在使用此zlm的设备, 发送BYE失败 {}", e.getMessage());
965 } 972 }
966 } 973 }
@@ -1116,4 +1123,52 @@ public class PlayServiceImpl implements IPlayService { @@ -1116,4 +1123,52 @@ public class PlayServiceImpl implements IPlayService {
1116 // } 1123 // }
1117 // })); 1124 // }));
1118 } 1125 }
  1126 +
  1127 + @Override
  1128 + public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
  1129 + String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null);
  1130 + StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
  1131 + if (null == streamInfo) {
  1132 + logger.warn("streamId不存在!");
  1133 + throw new ServiceException("streamId不存在");
  1134 + }
  1135 + streamInfo.setPause(true);
  1136 + RedisUtil.set(key, streamInfo);
  1137 + MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId());
  1138 + if (null == mediaServerItem) {
  1139 + logger.warn("mediaServer 不存在!");
  1140 + throw new ServiceException("mediaServer不存在");
  1141 + }
  1142 + // zlm 暂停RTP超时检查
  1143 + JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamId);
  1144 + if (jsonObject == null || jsonObject.getInteger("code") != 0) {
  1145 + throw new ServiceException("暂停RTP接收失败");
  1146 + }
  1147 + Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
  1148 + cmder.playPauseCmd(device, streamInfo);
  1149 + }
  1150 +
  1151 + @Override
  1152 + public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
  1153 + String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null);
  1154 + StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
  1155 + if (null == streamInfo) {
  1156 + logger.warn("streamId不存在!");
  1157 + throw new ServiceException("streamId不存在");
  1158 + }
  1159 + streamInfo.setPause(false);
  1160 + RedisUtil.set(key, streamInfo);
  1161 + MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId());
  1162 + if (null == mediaServerItem) {
  1163 + logger.warn("mediaServer 不存在!");
  1164 + throw new ServiceException("mediaServer不存在");
  1165 + }
  1166 + // zlm 暂停RTP超时检查
  1167 + JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamId);
  1168 + if (jsonObject == null || jsonObject.getInteger("code") != 0) {
  1169 + throw new ServiceException("继续RTP接收失败");
  1170 + }
  1171 + Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
  1172 + cmder.playResumeCmd(device, streamInfo);
  1173 + }
1119 } 1174 }
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -92,7 +92,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -92,7 +92,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
92 @Override 92 @Override
93 public StreamInfo save(StreamProxyItem param) { 93 public StreamInfo save(StreamProxyItem param) {
94 MediaServerItem mediaInfo; 94 MediaServerItem mediaInfo;
95 - if (param.getMediaServerId() == null || "auto".equals(param.getMediaServerId())){ 95 + if (ObjectUtils.isEmpty(param.getMediaServerId()) || "auto".equals(param.getMediaServerId())){
96 mediaInfo = mediaServerService.getMediaServerForMinimumLoad(); 96 mediaInfo = mediaServerService.getMediaServerForMinimumLoad();
97 }else { 97 }else {
98 mediaInfo = mediaServerService.getOne(param.getMediaServerId()); 98 mediaInfo = mediaServerService.getOne(param.getMediaServerId());
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -56,6 +56,8 @@ public interface IRedisCatchStorage { @@ -56,6 +56,8 @@ public interface IRedisCatchStorage {
56 56
57 StreamInfo queryPlayback(String deviceId, String channelID, String stream, String callId); 57 StreamInfo queryPlayback(String deviceId, String channelID, String stream, String callId);
58 58
  59 + String queryPlaybackForKey(String deviceId, String channelId, String stream, String callId);
  60 +
59 void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch); 61 void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch);
60 62
61 ParentPlatformCatch queryPlatformCatchInfo(String platformGbId); 63 ParentPlatformCatch queryPlatformCatchInfo(String platformGbId);
src/main/java/com/genersoft/iot/vmp/storager/dao/DeviceMapper.java
@@ -93,6 +93,7 @@ public interface DeviceMapper { @@ -93,6 +93,7 @@ public interface DeviceMapper {
93 "<if test=\"ssrcCheck != null\">, ssrcCheck=${ssrcCheck}</if>" + 93 "<if test=\"ssrcCheck != null\">, ssrcCheck=${ssrcCheck}</if>" +
94 "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" + 94 "<if test=\"geoCoordSys != null\">, geoCoordSys=#{geoCoordSys}</if>" +
95 "<if test=\"treeType != null\">, treeType=#{treeType}</if>" + 95 "<if test=\"treeType != null\">, treeType=#{treeType}</if>" +
  96 + "<if test=\"mediaServerId != null\">, mediaServerId=#{mediaServerId}</if>" +
96 "WHERE deviceId='${deviceId}'"+ 97 "WHERE deviceId='${deviceId}'"+
97 " </script>"}) 98 " </script>"})
98 int update(Device device); 99 int update(Device device);
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -9,7 +9,6 @@ import com.genersoft.iot.vmp.conf.UserSetting; @@ -9,7 +9,6 @@ import com.genersoft.iot.vmp.conf.UserSetting;
9 import com.genersoft.iot.vmp.gb28181.bean.*; 9 import com.genersoft.iot.vmp.gb28181.bean.*;
10 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12 -import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;  
13 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; 12 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
14 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 13 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
15 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; 14 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
@@ -22,7 +21,6 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; @@ -22,7 +21,6 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
22 import org.slf4j.Logger; 21 import org.slf4j.Logger;
23 import org.slf4j.LoggerFactory; 22 import org.slf4j.LoggerFactory;
24 import org.springframework.beans.factory.annotation.Autowired; 23 import org.springframework.beans.factory.annotation.Autowired;
25 -import org.springframework.context.annotation.DependsOn;  
26 import org.springframework.stereotype.Component; 24 import org.springframework.stereotype.Component;
27 25
28 import java.util.*; 26 import java.util.*;
@@ -127,6 +125,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -127,6 +125,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
127 } 125 }
128 @Override 126 @Override
129 public StreamInfo queryPlayByStreamId(String streamId) { 127 public StreamInfo queryPlayByStreamId(String streamId) {
  128 + System.out.println(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), streamId));
130 List<Object> playLeys = RedisUtil.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), streamId)); 129 List<Object> playLeys = RedisUtil.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), streamId));
131 if (playLeys == null || playLeys.size() == 0) { 130 if (playLeys == null || playLeys.size() == 0) {
132 return null; 131 return null;
@@ -165,6 +164,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -165,6 +164,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
165 164
166 @Override 165 @Override
167 public boolean startPlayback(StreamInfo stream, String callId) { 166 public boolean startPlayback(StreamInfo stream, String callId) {
  167 + System.out.println(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
  168 + userSetting.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId));
168 return RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, 169 return RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
169 userSetting.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream); 170 userSetting.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream);
170 } 171 }
@@ -286,6 +287,34 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -286,6 +287,34 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
286 } 287 }
287 288
288 @Override 289 @Override
  290 + public String queryPlaybackForKey(String deviceId, String channelId, String stream, String callId) {
  291 + if (stream == null && callId == null) {
  292 + return null;
  293 + }
  294 + if (deviceId == null) {
  295 + deviceId = "*";
  296 + }
  297 + if (channelId == null) {
  298 + channelId = "*";
  299 + }
  300 + if (stream == null) {
  301 + stream = "*";
  302 + }
  303 + if (callId == null) {
  304 + callId = "*";
  305 + }
  306 + String key = String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
  307 + userSetting.getServerId(),
  308 + deviceId,
  309 + channelId,
  310 + stream,
  311 + callId
  312 + );
  313 + List<Object> streamInfoScan = RedisUtil.scan(key);
  314 + return (String) streamInfoScan.get(0);
  315 + }
  316 +
  317 + @Override
289 public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) { 318 public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) {
290 String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + parentPlatformCatch.getId(); 319 String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + parentPlatformCatch.getId();
291 RedisUtil.set(key, parentPlatformCatch); 320 RedisUtil.set(key, parentPlatformCatch);
src/main/java/com/genersoft/iot/vmp/utils/CollectionUtil.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.utils;  
2 -  
3 -import java.util.Arrays;  
4 -  
5 -public class CollectionUtil {  
6 -  
7 - public static <T> boolean contains(T[] array, final T element) {  
8 - return array != null && Arrays.stream(array).anyMatch((x) -> {  
9 - return ObjectUtils.nullSafeEquals(x, element);  
10 - });  
11 - }  
12 -}  
src/main/java/com/genersoft/iot/vmp/utils/ObjectUtils.java deleted 100644 → 0
1 -package com.genersoft.iot.vmp.utils;  
2 -  
3 -import java.util.Arrays;  
4 -  
5 -public class ObjectUtils {  
6 - public static boolean nullSafeEquals(Object o1, Object o2) {  
7 - if (o1 == o2) {  
8 - return true;  
9 - } else if (o1 != null && o2 != null) {  
10 - if (o1.equals(o2)) {  
11 - return true;  
12 - } else {  
13 - return o1.getClass().isArray() && o2.getClass().isArray() && arrayEquals(o1, o2);  
14 - }  
15 - } else {  
16 - return false;  
17 - }  
18 - }  
19 -  
20 - private static boolean arrayEquals(Object o1, Object o2) {  
21 - if (o1 instanceof Object[] && o2 instanceof Object[]) {  
22 - return Arrays.equals((Object[])((Object[])o1), (Object[])((Object[])o2));  
23 - } else if (o1 instanceof boolean[] && o2 instanceof boolean[]) {  
24 - return Arrays.equals((boolean[])((boolean[])o1), (boolean[])((boolean[])o2));  
25 - } else if (o1 instanceof byte[] && o2 instanceof byte[]) {  
26 - return Arrays.equals((byte[])((byte[])o1), (byte[])((byte[])o2));  
27 - } else if (o1 instanceof char[] && o2 instanceof char[]) {  
28 - return Arrays.equals((char[])((char[])o1), (char[])((char[])o2));  
29 - } else if (o1 instanceof double[] && o2 instanceof double[]) {  
30 - return Arrays.equals((double[])((double[])o1), (double[])((double[])o2));  
31 - } else if (o1 instanceof float[] && o2 instanceof float[]) {  
32 - return Arrays.equals((float[])((float[])o1), (float[])((float[])o2));  
33 - } else if (o1 instanceof int[] && o2 instanceof int[]) {  
34 - return Arrays.equals((int[])((int[])o1), (int[])((int[])o2));  
35 - } else if (o1 instanceof long[] && o2 instanceof long[]) {  
36 - return Arrays.equals((long[])((long[])o1), (long[])((long[])o2));  
37 - } else {  
38 - return o1 instanceof short[] && o2 instanceof short[] && Arrays.equals((short[]) ((short[]) o1), (short[]) ((short[]) o2));  
39 - }  
40 - }  
41 -}  
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -2,9 +2,11 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback; @@ -2,9 +2,11 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
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.exception.ControllerException; 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.conf.exception.ServiceException;
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.transmit.callback.DeferredResultHolder; 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
7 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; 8 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  9 +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
8 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 import com.genersoft.iot.vmp.service.IPlayService; 11 import com.genersoft.iot.vmp.service.IPlayService;
10 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; 12 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
@@ -46,6 +48,9 @@ public class PlaybackController { @@ -46,6 +48,9 @@ public class PlaybackController {
46 private SIPCommander cmder; 48 private SIPCommander cmder;
47 49
48 @Autowired 50 @Autowired
  51 + private ZLMRTPServerFactory zlmrtpServerFactory;
  52 +
  53 + @Autowired
49 private IVideoManagerStorage storager; 54 private IVideoManagerStorage storager;
50 55
51 @Autowired 56 @Autowired
@@ -113,14 +118,11 @@ public class PlaybackController { @@ -113,14 +118,11 @@ public class PlaybackController {
113 @GetMapping("/pause/{streamId}") 118 @GetMapping("/pause/{streamId}")
114 public void playPause(@PathVariable String streamId) { 119 public void playPause(@PathVariable String streamId) {
115 logger.info("playPause: "+streamId); 120 logger.info("playPause: "+streamId);
116 - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);  
117 - if (null == streamInfo) {  
118 - logger.warn("streamId不存在!");  
119 - throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");  
120 - }  
121 - Device device = storager.queryVideoDevice(streamInfo.getDeviceID()); 121 +
122 try { 122 try {
123 - cmder.playPauseCmd(device, streamInfo); 123 + playService.pauseRtp(streamId);
  124 + } catch (ServiceException e) {
  125 + throw new ControllerException(ErrorCode.ERROR400.getCode(), e.getMessage());
124 } catch (InvalidArgumentException | ParseException | SipException e) { 126 } catch (InvalidArgumentException | ParseException | SipException e) {
125 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage()); 127 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
126 } 128 }
@@ -132,14 +134,10 @@ public class PlaybackController { @@ -132,14 +134,10 @@ public class PlaybackController {
132 @GetMapping("/resume/{streamId}") 134 @GetMapping("/resume/{streamId}")
133 public void playResume(@PathVariable String streamId) { 135 public void playResume(@PathVariable String streamId) {
134 logger.info("playResume: "+streamId); 136 logger.info("playResume: "+streamId);
135 - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);  
136 - if (null == streamInfo) {  
137 - logger.warn("streamId不存在!");  
138 - throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");  
139 - }  
140 - Device device = storager.queryVideoDevice(streamInfo.getDeviceID());  
141 try { 137 try {
142 - cmder.playResumeCmd(device, streamInfo); 138 + playService.resumeRtp(streamId);
  139 + } catch (ServiceException e) {
  140 + throw new ControllerException(ErrorCode.ERROR400.getCode(), e.getMessage());
143 } catch (InvalidArgumentException | ParseException | SipException e) { 141 } catch (InvalidArgumentException | ParseException | SipException e) {
144 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage()); 142 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
145 } 143 }
web_src/src/components/dialog/deviceEdit.vue
@@ -18,17 +18,17 @@ @@ -18,17 +18,17 @@
18 <el-form-item label="设备名称" prop="name"> 18 <el-form-item label="设备名称" prop="name">
19 <el-input v-model="form.name" clearable></el-input> 19 <el-input v-model="form.name" clearable></el-input>
20 </el-form-item> 20 </el-form-item>
21 -<!-- <el-form-item label="流媒体ID" prop="mediaServerId">-->  
22 -<!-- <el-select v-model="form.mediaServerId" style="float: left; width: 100%" >-->  
23 -<!-- <el-option key="auto" label="自动负载最小" value="null"></el-option>-->  
24 -<!-- <el-option-->  
25 -<!-- v-for="item in mediaServerList"-->  
26 -<!-- :key="item.id"-->  
27 -<!-- :label="item.id"-->  
28 -<!-- :value="item.id">-->  
29 -<!-- </el-option>-->  
30 -<!-- </el-select>-->  
31 -<!-- </el-form-item>--> 21 + <el-form-item label="流媒体ID" prop="mediaServerId">
  22 + <el-select v-model="form.mediaServerId" style="float: left; width: 100%" >
  23 + <el-option key="auto" label="自动负载最小" value="auto"></el-option>
  24 + <el-option
  25 + v-for="item in mediaServerList"
  26 + :key="item.id"
  27 + :label="item.id"
  28 + :value="item.id">
  29 + </el-option>
  30 + </el-select>
  31 + </el-form-item>
32 32
33 <el-form-item label="字符集" prop="charset" > 33 <el-form-item label="字符集" prop="charset" >
34 <el-select v-model="form.charset" style="float: left; width: 100%" > 34 <el-select v-model="form.charset" style="float: left; width: 100%" >