Commit 14174ff40022a1f7662759d478d06b7b350ccd98

Authored by 648540858
2 parents 1dcdbc37 2eb1ca2d

Merge branch 'wvp-28181-2.0' into wvp-pro-record

# Conflicts:
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
#	src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
#	src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
Showing 38 changed files with 312 additions and 234 deletions
sql/mysql.sql
@@ -415,6 +415,7 @@ DROP TABLE IF EXISTS `stream_proxy`; @@ -415,6 +415,7 @@ DROP TABLE IF EXISTS `stream_proxy`;
415 CREATE TABLE `stream_proxy` ( 415 CREATE TABLE `stream_proxy` (
416 `id` int NOT NULL AUTO_INCREMENT, 416 `id` int NOT NULL AUTO_INCREMENT,
417 `type` varchar(50) COLLATE utf8mb4_general_ci NOT NULL, 417 `type` varchar(50) COLLATE utf8mb4_general_ci NOT NULL,
  418 + `name` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
418 `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL, 419 `app` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
419 `stream` varchar(255) COLLATE utf8mb4_general_ci NOT NULL, 420 `stream` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
420 `url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL, 421 `url` varchar(255) COLLATE utf8mb4_general_ci DEFAULT NULL,
src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
@@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray; @@ -5,7 +5,7 @@ import com.alibaba.fastjson.JSONArray;
5 public class StreamInfo { 5 public class StreamInfo {
6 6
7 private String app; 7 private String app;
8 - private String streamId; 8 + private String stream;
9 private String deviceID; 9 private String deviceID;
10 private String channelId; 10 private String channelId;
11 private String flv; 11 private String flv;
@@ -153,12 +153,12 @@ public class StreamInfo { @@ -153,12 +153,12 @@ public class StreamInfo {
153 this.ws_ts = ws_ts; 153 this.ws_ts = ws_ts;
154 } 154 }
155 155
156 - public String getStreamId() {  
157 - return streamId; 156 + public String getStream() {
  157 + return stream;
158 } 158 }
159 159
160 - public void setStreamId(String streamId) {  
161 - this.streamId = streamId; 160 + public void setStream(String stream) {
  161 + this.stream = stream;
162 } 162 }
163 163
164 public String getRtc() { 164 public String getRtc() {
src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
@@ -29,6 +29,7 @@ public class VideoManagerConstants { @@ -29,6 +29,7 @@ public class VideoManagerConstants {
29 // 此处多了一个_,暂不修改 29 // 此处多了一个_,暂不修改
30 public static final String PLAYER_PREFIX = "VMP_PLAYER_"; 30 public static final String PLAYER_PREFIX = "VMP_PLAYER_";
31 public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_"; 31 public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_";
  32 + public static final String PLAY_INFO_PREFIX = "VMP_PLAY_INFO_";
32 33
33 public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_"; 34 public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_";
34 35
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SsrcTransaction.java
@@ -4,11 +4,12 @@ public class SsrcTransaction { @@ -4,11 +4,12 @@ public class SsrcTransaction {
4 4
5 private String deviceId; 5 private String deviceId;
6 private String channelId; 6 private String channelId;
7 - private String ssrc;  
8 - private String streamId; 7 + private String callId;
  8 + private String stream;
9 private byte[] transaction; 9 private byte[] transaction;
10 private byte[] dialog; 10 private byte[] dialog;
11 private String mediaServerId; 11 private String mediaServerId;
  12 + private String ssrc;
12 13
13 public String getDeviceId() { 14 public String getDeviceId() {
14 return deviceId; 15 return deviceId;
@@ -26,20 +27,20 @@ public class SsrcTransaction { @@ -26,20 +27,20 @@ public class SsrcTransaction {
26 this.channelId = channelId; 27 this.channelId = channelId;
27 } 28 }
28 29
29 - public String getSsrc() {  
30 - return ssrc; 30 + public String getCallId() {
  31 + return callId;
31 } 32 }
32 33
33 - public void setSsrc(String ssrc) {  
34 - this.ssrc = ssrc; 34 + public void setCallId(String callId) {
  35 + this.callId = callId;
35 } 36 }
36 37
37 - public String getStreamId() {  
38 - return streamId; 38 + public String getStream() {
  39 + return stream;
39 } 40 }
40 41
41 - public void setStreamId(String streamId) {  
42 - this.streamId = streamId; 42 + public void setStream(String stream) {
  43 + this.stream = stream;
43 } 44 }
44 45
45 public byte[] getTransaction() { 46 public byte[] getTransaction() {
@@ -65,4 +66,12 @@ public class SsrcTransaction { @@ -65,4 +66,12 @@ public class SsrcTransaction {
65 public void setMediaServerId(String mediaServerId) { 66 public void setMediaServerId(String mediaServerId) {
66 this.mediaServerId = mediaServerId; 67 this.mediaServerId = mediaServerId;
67 } 68 }
  69 +
  70 + public String getSsrc() {
  71 + return ssrc;
  72 + }
  73 +
  74 + public void setSsrc(String ssrc) {
  75 + this.ssrc = ssrc;
  76 + }
68 } 77 }
src/main/java/com/genersoft/iot/vmp/gb28181/event/SipSubscribe.java
@@ -23,24 +23,36 @@ public class SipSubscribe { @@ -23,24 +23,36 @@ public class SipSubscribe {
23 23
24 private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>(); 24 private Map<String, SipSubscribe.Event> okSubscribes = new ConcurrentHashMap<>();
25 25
26 - private Map<String, Date> timeSubscribes = new ConcurrentHashMap<>(); 26 + private Map<String, Date> okTimeSubscribes = new ConcurrentHashMap<>();
  27 + private Map<String, Date> errorTimeSubscribes = new ConcurrentHashMap<>();
27 28
28 -// @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次 29 + // @Scheduled(cron="*/5 * * * * ?") //每五秒执行一次
29 // @Scheduled(fixedRate= 100 * 60 * 60 ) 30 // @Scheduled(fixedRate= 100 * 60 * 60 )
30 - @Scheduled(cron="0 0 * * * ?") //每小时执行一次, 每个整点 31 + @Scheduled(cron="0 0/5 * * * ?") //每5分钟执行一次
31 public void execute(){ 32 public void execute(){
32 logger.info("[定时任务] 清理过期的订阅信息"); 33 logger.info("[定时任务] 清理过期的订阅信息");
33 Calendar calendar = Calendar.getInstance(); 34 Calendar calendar = Calendar.getInstance();
34 calendar.setTime(new Date()); 35 calendar.setTime(new Date());
35 - calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) - 1);  
36 - for (String key : timeSubscribes.keySet()) {  
37 - if (timeSubscribes.get(key).before(calendar.getTime())){  
38 - logger.info("[定时任务] 清理过期的订阅信息: {}", key);  
39 - errorSubscribes.remove(key); 36 + calendar.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) - 5);
  37 +
  38 + for (String key : okTimeSubscribes.keySet()) {
  39 + if (okTimeSubscribes.get(key).before(calendar.getTime())){
  40 +// logger.info("[定时任务] 清理过期的订阅信息: {}", key);
40 okSubscribes.remove(key); 41 okSubscribes.remove(key);
41 - timeSubscribes.remove(key); 42 + okTimeSubscribes.remove(key);
  43 + }
  44 + }
  45 + for (String key : errorTimeSubscribes.keySet()) {
  46 + if (errorTimeSubscribes.get(key).before(calendar.getTime())){
  47 +// logger.info("[定时任务] 清理过期的订阅信息: {}", key);
  48 + errorSubscribes.remove(key);
  49 + errorTimeSubscribes.remove(key);
42 } 50 }
43 } 51 }
  52 + logger.info("okTimeSubscribes.size:{}",okTimeSubscribes.size());
  53 + logger.info("okSubscribes.size:{}",okSubscribes.size());
  54 + logger.info("errorTimeSubscribes.size:{}",errorTimeSubscribes.size());
  55 + logger.info("errorSubscribes.size:{}",errorSubscribes.size());
44 } 56 }
45 57
46 public interface Event { 58 public interface Event {
@@ -105,12 +117,12 @@ public class SipSubscribe { @@ -105,12 +117,12 @@ public class SipSubscribe {
105 117
106 public void addErrorSubscribe(String key, SipSubscribe.Event event) { 118 public void addErrorSubscribe(String key, SipSubscribe.Event event) {
107 errorSubscribes.put(key, event); 119 errorSubscribes.put(key, event);
108 - timeSubscribes.put(key, new Date()); 120 + errorTimeSubscribes.put(key, new Date());
109 } 121 }
110 122
111 public void addOkSubscribe(String key, SipSubscribe.Event event) { 123 public void addOkSubscribe(String key, SipSubscribe.Event event) {
112 okSubscribes.put(key, event); 124 okSubscribes.put(key, event);
113 - timeSubscribes.put(key, new Date()); 125 + okTimeSubscribes.put(key, new Date());
114 } 126 }
115 127
116 public SipSubscribe.Event getErrorSubscribe(String key) { 128 public SipSubscribe.Event getErrorSubscribe(String key) {
@@ -119,7 +131,7 @@ public class SipSubscribe { @@ -119,7 +131,7 @@ public class SipSubscribe {
119 131
120 public void removeErrorSubscribe(String key) { 132 public void removeErrorSubscribe(String key) {
121 errorSubscribes.remove(key); 133 errorSubscribes.remove(key);
122 - timeSubscribes.remove(key); 134 + errorTimeSubscribes.remove(key);
123 } 135 }
124 136
125 public SipSubscribe.Event getOkSubscribe(String key) { 137 public SipSubscribe.Event getOkSubscribe(String key) {
@@ -128,7 +140,7 @@ public class SipSubscribe { @@ -128,7 +140,7 @@ public class SipSubscribe {
128 140
129 public void removeOkSubscribe(String key) { 141 public void removeOkSubscribe(String key) {
130 okSubscribes.remove(key); 142 okSubscribes.remove(key);
131 - timeSubscribes.remove(key); 143 + okTimeSubscribes.remove(key);
132 } 144 }
133 public int getErrorSubscribesSize(){ 145 public int getErrorSubscribesSize(){
134 return errorSubscribes.size(); 146 return errorSubscribes.size();
src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
@@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil; @@ -14,6 +14,7 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
14 import gov.nist.javax.sip.stack.SIPDialog; 14 import gov.nist.javax.sip.stack.SIPDialog;
15 import org.springframework.beans.factory.annotation.Autowired; 15 import org.springframework.beans.factory.annotation.Autowired;
16 import org.springframework.stereotype.Component; 16 import org.springframework.stereotype.Component;
  17 +import org.springframework.util.StringUtils;
17 18
18 /** 19 /**
19 * @description:视频流session管理器,管理视频预览、预览回放的通信句柄 20 * @description:视频流session管理器,管理视频预览、预览回放的通信句柄
@@ -29,39 +30,55 @@ public class VideoStreamSessionManager { @@ -29,39 +30,55 @@ public class VideoStreamSessionManager {
29 @Autowired 30 @Autowired
30 private UserSetup userSetup; 31 private UserSetup userSetup;
31 32
32 - public void put(String deviceId, String channelId ,String ssrc, String streamId, String mediaServerId, ClientTransaction transaction){ 33 + /**
  34 + * 添加一个点播/回放的事务信息
  35 + * 后续可以通过流Id/callID
  36 + * @param deviceId 设备ID
  37 + * @param channelId 通道ID
  38 + * @param callId 一次请求的CallID
  39 + * @param stream 流名称
  40 + * @param mediaServerId 所使用的流媒体ID
  41 + * @param transaction 事务
  42 + */
  43 + public void put(String deviceId, String channelId, String callId, String stream, String ssrc, String mediaServerId, ClientTransaction transaction){
33 SsrcTransaction ssrcTransaction = new SsrcTransaction(); 44 SsrcTransaction ssrcTransaction = new SsrcTransaction();
34 ssrcTransaction.setDeviceId(deviceId); 45 ssrcTransaction.setDeviceId(deviceId);
35 ssrcTransaction.setChannelId(channelId); 46 ssrcTransaction.setChannelId(channelId);
36 - ssrcTransaction.setStreamId(streamId); 47 + ssrcTransaction.setStream(stream);
37 byte[] transactionByteArray = SerializeUtils.serialize(transaction); 48 byte[] transactionByteArray = SerializeUtils.serialize(transaction);
38 ssrcTransaction.setTransaction(transactionByteArray); 49 ssrcTransaction.setTransaction(transactionByteArray);
  50 + ssrcTransaction.setCallId(callId);
39 ssrcTransaction.setSsrc(ssrc); 51 ssrcTransaction.setSsrc(ssrc);
40 ssrcTransaction.setMediaServerId(mediaServerId); 52 ssrcTransaction.setMediaServerId(mediaServerId);
41 53
42 - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId, ssrcTransaction); 54 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  55 + + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
  56 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  57 + + "_" + deviceId + "_" + channelId + "_" + callId + "_" + stream, ssrcTransaction);
43 } 58 }
44 59
45 - public void put(String deviceId, String channelId , Dialog dialog){  
46 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); 60 + public void put(String deviceId, String channelId, String callId, Dialog dialog){
  61 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, callId, null);
47 if (ssrcTransaction != null) { 62 if (ssrcTransaction != null) {
48 byte[] dialogByteArray = SerializeUtils.serialize(dialog); 63 byte[] dialogByteArray = SerializeUtils.serialize(dialog);
49 ssrcTransaction.setDialog(dialogByteArray); 64 ssrcTransaction.setDialog(dialogByteArray);
50 } 65 }
51 - redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId, ssrcTransaction); 66 + redisUtil.set(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId()
  67 + + "_" + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_"
  68 + + ssrcTransaction.getStream(), ssrcTransaction);
52 } 69 }
53 70
54 71
55 - public ClientTransaction getTransaction(String deviceId, String channelId){  
56 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); 72 + public ClientTransaction getTransactionByStream(String deviceId, String channelId, String stream){
  73 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
57 if (ssrcTransaction == null) return null; 74 if (ssrcTransaction == null) return null;
58 byte[] transactionByteArray = ssrcTransaction.getTransaction(); 75 byte[] transactionByteArray = ssrcTransaction.getTransaction();
59 ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray); 76 ClientTransaction clientTransaction = (ClientTransaction)SerializeUtils.deSerialize(transactionByteArray);
60 return clientTransaction; 77 return clientTransaction;
61 } 78 }
62 79
63 - public SIPDialog getDialog(String deviceId, String channelId){  
64 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); 80 + public SIPDialog getDialogByStream(String deviceId, String channelId, String stream){
  81 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
65 if (ssrcTransaction == null) return null; 82 if (ssrcTransaction == null) return null;
66 byte[] dialogByteArray = ssrcTransaction.getDialog(); 83 byte[] dialogByteArray = ssrcTransaction.getDialog();
67 if (dialogByteArray == null) return null; 84 if (dialogByteArray == null) return null;
@@ -69,36 +86,37 @@ public class VideoStreamSessionManager { @@ -69,36 +86,37 @@ public class VideoStreamSessionManager {
69 return dialog; 86 return dialog;
70 } 87 }
71 88
72 - public SsrcTransaction getSsrcTransaction(String deviceId, String channelId){  
73 - SsrcTransaction ssrcTransaction = (SsrcTransaction)redisUtil.get(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId);  
74 - return ssrcTransaction; 89 + public SsrcTransaction getSsrcTransaction(String deviceId, String channelId, String callId, String stream){
  90 + if (StringUtils.isEmpty(callId)) callId ="*";
  91 + if (StringUtils.isEmpty(stream)) stream ="*";
  92 + String key = VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId + "_" + callId+ "_" + stream;
  93 + List<Object> scanResult = redisUtil.scan(key);
  94 + if (scanResult.size() == 0) return null;
  95 + return (SsrcTransaction)redisUtil.get((String) scanResult.get(0));
75 } 96 }
76 97
77 - public String getStreamId(String deviceId, String channelId){  
78 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId);  
79 - if (ssrcTransaction == null) return null;  
80 - return ssrcTransaction.getStreamId();  
81 - }  
82 - public String getMediaServerId(String deviceId, String channelId){  
83 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); 98 + public String getMediaServerId(String deviceId, String channelId, String stream){
  99 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
84 if (ssrcTransaction == null) return null; 100 if (ssrcTransaction == null) return null;
85 return ssrcTransaction.getMediaServerId(); 101 return ssrcTransaction.getMediaServerId();
86 } 102 }
87 103
88 - public String getSSRC(String deviceId, String channelId){  
89 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); 104 + public String getSSRC(String deviceId, String channelId, String stream){
  105 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
90 if (ssrcTransaction == null) return null; 106 if (ssrcTransaction == null) return null;
91 return ssrcTransaction.getSsrc(); 107 return ssrcTransaction.getSsrc();
92 } 108 }
93 109
94 - public void remove(String deviceId, String channelId) {  
95 - SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId); 110 + public void remove(String deviceId, String channelId, String stream) {
  111 + SsrcTransaction ssrcTransaction = getSsrcTransaction(deviceId, channelId, null, stream);
96 if (ssrcTransaction == null) return; 112 if (ssrcTransaction == null) return;
97 - redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_" + deviceId + "_" + channelId); 113 + redisUtil.del(VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX + userSetup.getServerId() + "_"
  114 + + deviceId + "_" + channelId + "_" + ssrcTransaction.getCallId() + "_" + ssrcTransaction.getStream());
98 } 115 }
99 116
  117 +
100 public List<SsrcTransaction> getAllSsrc() { 118 public List<SsrcTransaction> getAllSsrc() {
101 - List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" )); 119 + List<Object> ssrcTransactionKeys = redisUtil.scan(String.format("%s_*_*_*_*", VideoManagerConstants.MEDIA_TRANSACTION_USED_PREFIX+ userSetup.getServerId() + "_" ));
102 List<SsrcTransaction> result= new ArrayList<>(); 120 List<SsrcTransaction> result= new ArrayList<>();
103 for (int i = 0; i < ssrcTransactionKeys.size(); i++) { 121 for (int i = 0; i < ssrcTransactionKeys.size(); i++) {
104 String key = (String)ssrcTransactionKeys.get(i); 122 String key = (String)ssrcTransactionKeys.get(i);
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -119,8 +119,8 @@ public interface ISIPCommander { @@ -119,8 +119,8 @@ public interface ISIPCommander {
119 /** 119 /**
120 * 视频流停止 120 * 视频流停止
121 */ 121 */
122 - void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);  
123 - void streamByeCmd(String deviceId, String channelId); 122 + void streamByeCmd(String deviceId, String channelId, String ssrc, SipSubscribe.Event okEvent);
  123 + void streamByeCmd(String deviceId, String channelId, String ssrc);
124 124
125 /** 125 /**
126 * 回放暂停 126 * 回放暂停
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java
@@ -18,7 +18,7 @@ public interface ISIPCommanderForPlatform { @@ -18,7 +18,7 @@ public interface ISIPCommanderForPlatform {
18 * @return 18 * @return
19 */ 19 */
20 boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); 20 boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent);
21 - boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent); 21 + boolean register(ParentPlatform parentPlatform, String callId, WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain);
22 22
23 /** 23 /**
24 * 向上级平台注销 24 * 向上级平台注销
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
@@ -128,7 +128,15 @@ public class SIPRequestHeaderPlarformProvider { @@ -128,7 +128,15 @@ public class SIPRequestHeaderPlarformProvider {
128 128
129 129
130 Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(Request.REGISTER), fromTag, viaTag, callIdHeader); 130 Request registerRequest = createRegisterRequest(parentPlatform, redisCatchStorage.getCSEQ(Request.REGISTER), fromTag, viaTag, callIdHeader);
131 - 131 + SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());
  132 + if (www == null) {
  133 + AuthorizationHeader authorizationHeader = sipFactory.createHeaderFactory().createAuthorizationHeader("Digest");
  134 + authorizationHeader.setUsername(parentPlatform.getDeviceGBId());
  135 + authorizationHeader.setURI(requestURI);
  136 + authorizationHeader.setAlgorithm("MD5");
  137 + registerRequest.addHeader(authorizationHeader);
  138 + return registerRequest;
  139 + }
132 String realm = www.getRealm(); 140 String realm = www.getRealm();
133 String nonce = www.getNonce(); 141 String nonce = www.getNonce();
134 String scheme = www.getScheme(); 142 String scheme = www.getScheme();
@@ -139,7 +147,6 @@ public class SIPRequestHeaderPlarformProvider { @@ -139,7 +147,6 @@ public class SIPRequestHeaderPlarformProvider {
139 147
140 callIdHeader.setCallId(callId); 148 callIdHeader.setCallId(callId);
141 149
142 - SipURI requestURI = sipFactory.createAddressFactory().createSipURI(parentPlatform.getServerGBId(), parentPlatform.getServerIP() + ":" + parentPlatform.getServerPort());  
143 String cNonce = null; 150 String cNonce = null;
144 String nc = "00000001"; 151 String nc = "00000001";
145 if (qop != null) { 152 if (qop != null) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderProvider.java
@@ -226,7 +226,7 @@ public class SIPRequestHeaderProvider { @@ -226,7 +226,7 @@ public class SIPRequestHeaderProvider {
226 throws PeerUnavailableException, ParseException, InvalidArgumentException { 226 throws PeerUnavailableException, ParseException, InvalidArgumentException {
227 Request request = null; 227 Request request = null;
228 if (streamInfo == null) return null; 228 if (streamInfo == null) return null;
229 - Dialog dialog = streamSession.getDialog(streamInfo.getDeviceID(), streamInfo.getChannelId()); 229 + Dialog dialog = streamSession.getDialogByStream(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
230 230
231 SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(), 231 SipURI requestLine = sipFactory.createAddressFactory().createSipURI(device.getDeviceId(),
232 device.getHostAddress()); 232 device.getHostAddress());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -331,7 +331,7 @@ public class SIPCommander implements ISIPCommander { @@ -331,7 +331,7 @@ public class SIPCommander implements ISIPCommander {
331 */ 331 */
332 @Override 332 @Override
333 public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) { 333 public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
334 - String streamId = ssrcInfo.getStreamId(); 334 + String streamId = ssrcInfo.getStream();
335 try { 335 try {
336 if (device == null) return; 336 if (device == null) return;
337 String streamMode = device.getStreamMode().toUpperCase(); 337 String streamMode = device.getStreamMode().toUpperCase();
@@ -407,6 +407,8 @@ public class SIPCommander implements ISIPCommander { @@ -407,6 +407,8 @@ public class SIPCommander implements ISIPCommander {
407 } 407 }
408 408
409 content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc 409 content.append("y="+ssrcInfo.getSsrc()+"\r\n");//ssrc
  410 + // f字段:f= v/编码格式/分辨率/帧率/码率类型/码率大小a/编码格式/码率大小/采样率
  411 +// content.append("f=v/2/5/25/1/4000a/1/8/1" + "\r\n"); // 未发现支持此特性的设备
410 412
411 String tm = Long.toString(System.currentTimeMillis()); 413 String tm = Long.toString(System.currentTimeMillis());
412 414
@@ -415,14 +417,14 @@ public class SIPCommander implements ISIPCommander { @@ -415,14 +417,14 @@ public class SIPCommander implements ISIPCommander {
415 417
416 Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader); 418 Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrcInfo.getSsrc(), callIdHeader);
417 419
418 - String finalStreamId = streamId;  
419 transmitRequest(device, request, (e -> { 420 transmitRequest(device, request, (e -> {
420 - streamSession.remove(device.getDeviceId(), channelId); 421 + streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream());
421 mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc()); 422 mediaServerService.releaseSsrc(mediaServerItem, ssrcInfo.getSsrc());
422 errorEvent.response(e); 423 errorEvent.response(e);
423 }), e ->{ 424 }), e ->{
424 - streamSession.put(device.getDeviceId(), channelId ,ssrcInfo.getSsrc(), finalStreamId, mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());  
425 - streamSession.put(device.getDeviceId(), channelId , e.dialog); 425 + // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值
  426 + streamSession.put(device.getDeviceId(), channelId ,"play", streamId, ssrcInfo.getSsrc(), mediaServerItem.getId(), ((ResponseEvent)e.event).getClientTransaction());
  427 + streamSession.put(device.getDeviceId(), channelId ,"play", e.dialog);
426 }); 428 });
427 429
428 430
@@ -444,12 +446,12 @@ public class SIPCommander implements ISIPCommander { @@ -444,12 +446,12 @@ public class SIPCommander implements ISIPCommander {
444 , SipSubscribe.Event errorEvent) { 446 , SipSubscribe.Event errorEvent) {
445 try { 447 try {
446 448
447 - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); 449 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
448 450
449 // 添加订阅 451 // 添加订阅
450 JSONObject subscribeKey = new JSONObject(); 452 JSONObject subscribeKey = new JSONObject();
451 subscribeKey.put("app", "rtp"); 453 subscribeKey.put("app", "rtp");
452 - subscribeKey.put("stream", ssrcInfo.getStreamId()); 454 + subscribeKey.put("stream", ssrcInfo.getStream());
453 subscribeKey.put("regist", true); 455 subscribeKey.put("regist", true);
454 subscribeKey.put("mediaServerId", mediaServerItem.getId()); 456 subscribeKey.put("mediaServerId", mediaServerItem.getId());
455 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); 457 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
@@ -530,8 +532,8 @@ public class SIPCommander implements ISIPCommander { @@ -530,8 +532,8 @@ public class SIPCommander implements ISIPCommander {
530 532
531 transmitRequest(device, request, errorEvent, okEvent -> { 533 transmitRequest(device, request, errorEvent, okEvent -> {
532 ResponseEvent responseEvent = (ResponseEvent) okEvent.event; 534 ResponseEvent responseEvent = (ResponseEvent) okEvent.event;
533 - streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), responseEvent.getClientTransaction());  
534 - streamSession.put(device.getDeviceId(), channelId, okEvent.dialog); 535 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), responseEvent.getClientTransaction());
  536 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), okEvent.dialog);
535 }); 537 });
536 } catch ( SipException | ParseException | InvalidArgumentException e) { 538 } catch ( SipException | ParseException | InvalidArgumentException e) {
537 e.printStackTrace(); 539 e.printStackTrace();
@@ -551,12 +553,12 @@ public class SIPCommander implements ISIPCommander { @@ -551,12 +553,12 @@ public class SIPCommander implements ISIPCommander {
551 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event 553 public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, String downloadSpeed, ZLMHttpHookSubscribe.Event event
552 , SipSubscribe.Event errorEvent) { 554 , SipSubscribe.Event errorEvent) {
553 try { 555 try {
554 - logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStreamId(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); 556 + logger.info("{} 分配的ZLM为: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort());
555 557
556 // 添加订阅 558 // 添加订阅
557 JSONObject subscribeKey = new JSONObject(); 559 JSONObject subscribeKey = new JSONObject();
558 subscribeKey.put("app", "rtp"); 560 subscribeKey.put("app", "rtp");
559 - subscribeKey.put("stream", ssrcInfo.getStreamId()); 561 + subscribeKey.put("stream", ssrcInfo.getStream());
560 subscribeKey.put("regist", true); 562 subscribeKey.put("regist", true);
561 subscribeKey.put("mediaServerId", mediaServerItem.getId()); 563 subscribeKey.put("mediaServerId", mediaServerItem.getId());
562 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); 564 logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString());
@@ -637,7 +639,8 @@ public class SIPCommander implements ISIPCommander { @@ -637,7 +639,8 @@ public class SIPCommander implements ISIPCommander {
637 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc()); 639 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader, ssrcInfo.getSsrc());
638 640
639 ClientTransaction transaction = transmitRequest(device, request, errorEvent); 641 ClientTransaction transaction = transmitRequest(device, request, errorEvent);
640 - streamSession.put(device.getDeviceId(), channelId, ssrcInfo.getSsrc(), ssrcInfo.getStreamId(), mediaServerItem.getId(), transaction); 642 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
  643 + streamSession.put(device.getDeviceId(), channelId, callIdHeader.getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), transaction);
641 644
642 } catch ( SipException | ParseException | InvalidArgumentException e) { 645 } catch ( SipException | ParseException | InvalidArgumentException e) {
643 e.printStackTrace(); 646 e.printStackTrace();
@@ -648,17 +651,17 @@ public class SIPCommander implements ISIPCommander { @@ -648,17 +651,17 @@ public class SIPCommander implements ISIPCommander {
648 * 视频流停止, 不使用回调 651 * 视频流停止, 不使用回调
649 */ 652 */
650 @Override 653 @Override
651 - public void streamByeCmd(String deviceId, String channelId) {  
652 - streamByeCmd(deviceId, channelId, null); 654 + public void streamByeCmd(String deviceId, String channelId, String stream) {
  655 + streamByeCmd(deviceId, channelId, stream, null);
653 } 656 }
654 657
655 /** 658 /**
656 * 视频流停止 659 * 视频流停止
657 */ 660 */
658 @Override 661 @Override
659 - public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) { 662 + public void streamByeCmd(String deviceId, String channelId, String stream, SipSubscribe.Event okEvent) {
660 try { 663 try {
661 - ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId); 664 + ClientTransaction transaction = streamSession.getTransactionByStream(deviceId, channelId, stream);
662 if (transaction == null) { 665 if (transaction == null) {
663 logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId); 666 logger.warn("[ {} -> {}]停止视频流的时候发现事务已丢失", deviceId, channelId);
664 SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>(); 667 SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>();
@@ -667,7 +670,7 @@ public class SIPCommander implements ISIPCommander { @@ -667,7 +670,7 @@ public class SIPCommander implements ISIPCommander {
667 } 670 }
668 return; 671 return;
669 } 672 }
670 - SIPDialog dialog = streamSession.getDialog(deviceId, channelId); 673 + SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, stream);
671 if (dialog == null) { 674 if (dialog == null) {
672 logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId); 675 logger.warn("[ {} -> {}]停止视频流的时候发现对话已丢失", deviceId, channelId);
673 return; 676 return;
@@ -711,11 +714,11 @@ public class SIPCommander implements ISIPCommander { @@ -711,11 +714,11 @@ public class SIPCommander implements ISIPCommander {
711 714
712 dialog.sendRequest(clientTransaction); 715 dialog.sendRequest(clientTransaction);
713 716
714 - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId); 717 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(deviceId, channelId, callIdHeader.getCallId(), null);
715 if (ssrcTransaction != null) { 718 if (ssrcTransaction != null) {
716 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId()); 719 MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
717 mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc()); 720 mediaServerService.releaseSsrc(mediaServerItem, ssrcTransaction.getSsrc());
718 - streamSession.remove(deviceId, channelId); 721 + streamSession.remove(deviceId, channelId, ssrcTransaction.getStream());
719 } 722 }
720 } catch (SipException | ParseException e) { 723 } catch (SipException | ParseException e) {
721 e.printStackTrace(); 724 e.printStackTrace();
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
@@ -52,7 +52,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -52,7 +52,7 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
52 52
53 @Override 53 @Override
54 public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { 54 public boolean register(ParentPlatform parentPlatform, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) {
55 - return register(parentPlatform, null, null, errorEvent, okEvent); 55 + return register(parentPlatform, null, null, errorEvent, okEvent, false);
56 } 56 }
57 57
58 @Override 58 @Override
@@ -64,15 +64,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { @@ -64,15 +64,16 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform {
64 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch); 64 redisCatchStorage.updatePlatformCatchInfo(parentPlatformCatch);
65 } 65 }
66 66
67 - return register(parentPlatform, null, null, errorEvent, okEvent); 67 + return register(parentPlatform, null, null, errorEvent, okEvent, false);
68 } 68 }
69 69
70 @Override 70 @Override
71 - public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www, SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent) { 71 + public boolean register(ParentPlatform parentPlatform, @Nullable String callId, @Nullable WWWAuthenticateHeader www,
  72 + SipSubscribe.Event errorEvent , SipSubscribe.Event okEvent, boolean registerAgain) {
72 try { 73 try {
73 Request request = null; 74 Request request = null;
74 String tm = Long.toString(System.currentTimeMillis()); 75 String tm = Long.toString(System.currentTimeMillis());
75 - if (www == null ) { 76 + if (!registerAgain ) {
76 // //callid 77 // //callid
77 CallIdHeader callIdHeader = null; 78 CallIdHeader callIdHeader = null;
78 if(parentPlatform.getTransport().equals("TCP")) { 79 if(parentPlatform.getTransport().equals("TCP")) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
@@ -87,7 +87,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -87,7 +87,11 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
87 if (streamInfo == null) { 87 if (streamInfo == null) {
88 streamInfo = new StreamInfo(); 88 streamInfo = new StreamInfo();
89 streamInfo.setApp(sendRtpItem.getApp()); 89 streamInfo.setApp(sendRtpItem.getApp());
90 - streamInfo.setStreamId(sendRtpItem.getStreamId()); 90 + streamInfo.setStream(sendRtpItem.getStreamId());
  91 + }else {
  92 + streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
  93 + sendRtpItem.setStreamId(streamInfo.getStream());
  94 + streamInfo.setApp("rtp");
91 } 95 }
92 redisCatchStorage.updateSendRTPSever(sendRtpItem); 96 redisCatchStorage.updateSendRTPSever(sendRtpItem);
93 logger.info(platformGbId); 97 logger.info(platformGbId);
@@ -95,7 +99,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In @@ -95,7 +99,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In
95 Map<String, Object> param = new HashMap<>(); 99 Map<String, Object> param = new HashMap<>();
96 param.put("vhost","__defaultVhost__"); 100 param.put("vhost","__defaultVhost__");
97 param.put("app",streamInfo.getApp()); 101 param.put("app",streamInfo.getApp());
98 - param.put("stream",streamInfo.getStreamId()); 102 + param.put("stream",streamInfo.getStream());
99 param.put("ssrc", sendRtpItem.getSsrc()); 103 param.put("ssrc", sendRtpItem.getSsrc());
100 param.put("dst_url",sendRtpItem.getIp()); 104 param.put("dst_url",sendRtpItem.getIp());
101 param.put("dst_port", sendRtpItem.getPort()); 105 param.put("dst_port", sendRtpItem.getPort());
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -111,7 +111,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -111,7 +111,7 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
111 } 111 }
112 112
113 storager.stopPlay(device.getDeviceId(), channelId); 113 storager.stopPlay(device.getDeviceId(), channelId);
114 - mediaServerService.closeRTPServer(device, channelId); 114 + mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream());
115 } 115 }
116 } 116 }
117 } catch (SipException e) { 117 } catch (SipException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/KeepaliveNotifyMessageHandler.java
@@ -68,6 +68,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp @@ -68,6 +68,7 @@ public class KeepaliveNotifyMessageHandler extends SIPRequestProcessorParent imp
68 } 68 }
69 if (device.getPort() != rPort) { 69 if (device.getPort() != rPort) {
70 device.setPort(rPort); 70 device.setPort(rPort);
  71 + device.setHostAddress(received.concat(":").concat(String.valueOf(rPort)));
71 videoManagerStorager.updateDevice(device); 72 videoManagerStorager.updateDevice(device);
72 redisCatchStorage.updateDevice(device); 73 redisCatchStorage.updateDevice(device);
73 } 74 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java
@@ -62,7 +62,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i @@ -62,7 +62,7 @@ public class MediaStatusNotifyMessageHandler extends SIPRequestProcessorParent i
62 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*"); 62 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), "*");
63 if (streamInfo != null) { 63 if (streamInfo != null) {
64 redisCatchStorage.stopPlayback(streamInfo); 64 redisCatchStorage.stopPlayback(streamInfo);
65 - cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId()); 65 + cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId(), streamInfo.getStream());
66 } 66 }
67 } 67 }
68 } 68 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/RegisterResponseProcessor.java
@@ -78,7 +78,7 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract { @@ -78,7 +78,7 @@ public class RegisterResponseProcessor extends SIPResponseProcessorAbstract {
78 78
79 if (response.getStatusCode() == 401) { 79 if (response.getStatusCode() == 401) {
80 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME); 80 WWWAuthenticateHeader www = (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);
81 - sipCommanderForPlatform.register(parentPlatform, callId, www, null, null); 81 + sipCommanderForPlatform.register(parentPlatform, callId, www, null, null, true);
82 }else if (response.getStatusCode() == 200){ 82 }else if (response.getStatusCode() == 200){
83 // 注册/注销成功 83 // 注册/注销成功
84 logger.info(String.format("%s %s成功", platformGBId, action)); 84 logger.info(String.format("%s %s成功", platformGBId, action));
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -360,6 +360,7 @@ public class ZLMHttpHookListener { @@ -360,6 +360,7 @@ public class ZLMHttpHookListener {
360 StreamPushItem streamPushItem = null; 360 StreamPushItem streamPushItem = null;
361 StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks); 361 StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks);
362 item.setStreamInfo(streamInfoByAppAndStream); 362 item.setStreamInfo(streamInfoByAppAndStream);
  363 +
363 redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item); 364 redisCatchStorage.addStream(mediaServerItem, type, app, streamId, item);
364 if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() 365 if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal()
365 || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() 366 || item.getOriginType() == OriginType.RTMP_PUSH.ordinal()
@@ -438,14 +439,16 @@ public class ZLMHttpHookListener { @@ -438,14 +439,16 @@ public class ZLMHttpHookListener {
438 if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) { 439 if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
439 ret.put("close", false); 440 ret.put("close", false);
440 } else { 441 } else {
441 - cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); 442 + cmder.streamByeCmd(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId(),
  443 + streamInfoForPlayCatch.getStream());
442 redisCatchStorage.stopPlay(streamInfoForPlayCatch); 444 redisCatchStorage.stopPlay(streamInfoForPlayCatch);
443 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId()); 445 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
444 } 446 }
445 }else{ 447 }else{
446 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlaybackByStreamId(streamId); 448 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlaybackByStreamId(streamId);
447 if (streamInfoForPlayBackCatch != null) { 449 if (streamInfoForPlayBackCatch != null) {
448 - cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), streamInfoForPlayBackCatch.getChannelId()); 450 + cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(),
  451 + streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream());
449 redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch); 452 redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch);
450 }else { 453 }else {
451 StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId); 454 StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId);
src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java
@@ -46,7 +46,7 @@ public interface IMediaServerService { @@ -46,7 +46,7 @@ public interface IMediaServerService {
46 46
47 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback); 47 SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, boolean isPlayback);
48 48
49 - void closeRTPServer(Device device, String channelId); 49 + void closeRTPServer(Device device, String channelId, String ssrc);
50 50
51 void clearRTPServer(MediaServerItem mediaServerItem); 51 void clearRTPServer(MediaServerItem mediaServerItem);
52 52
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
@@ -5,14 +5,16 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; @@ -5,14 +5,16 @@ import com.genersoft.iot.vmp.gb28181.bean.Device;
5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; 5 import com.genersoft.iot.vmp.gb28181.event.SipSubscribe;
6 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; 6 import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  8 +import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
8 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; 9 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
  10 +import org.springframework.http.ResponseEntity;
  11 +import org.springframework.web.context.request.async.DeferredResult;
9 12
10 /** 13 /**
11 * 点播处理 14 * 点播处理
12 */ 15 */
13 public interface IPlayService { 16 public interface IPlayService {
14 17
15 - void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);  
16 void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid); 18 void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid);
17 19
18 PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); 20 PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
@@ -20,4 +22,6 @@ public interface IPlayService { @@ -20,4 +22,6 @@ public interface IPlayService {
20 MediaServerItem getNewMediaServerItem(Device device); 22 MediaServerItem getNewMediaServerItem(Device device);
21 23
22 void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString); 24 void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString);
  25 +
  26 + DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback errorCallBack);
23 } 27 }
src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackCallback.java 0 → 100644
  1 +package com.genersoft.iot.vmp.service.bean;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  4 +
  5 +public interface PlayBackCallback {
  6 +
  7 + void call(RequestMessage msg);
  8 +
  9 +}
src/main/java/com/genersoft/iot/vmp/service/bean/SSRCInfo.java
@@ -4,12 +4,12 @@ public class SSRCInfo { @@ -4,12 +4,12 @@ public class SSRCInfo {
4 4
5 private int port; 5 private int port;
6 private String ssrc; 6 private String ssrc;
7 - private String StreamId; 7 + private String Stream;
8 8
9 - public SSRCInfo(int port, String ssrc, String streamId) { 9 + public SSRCInfo(int port, String ssrc, String stream) {
10 this.port = port; 10 this.port = port;
11 this.ssrc = ssrc; 11 this.ssrc = ssrc;
12 - StreamId = streamId; 12 + Stream = stream;
13 } 13 }
14 14
15 public int getPort() { 15 public int getPort() {
@@ -28,11 +28,11 @@ public class SSRCInfo { @@ -28,11 +28,11 @@ public class SSRCInfo {
28 this.ssrc = ssrc; 28 this.ssrc = ssrc;
29 } 29 }
30 30
31 - public String getStreamId() {  
32 - return StreamId; 31 + public String getStream() {
  32 + return Stream;
33 } 33 }
34 34
35 - public void setStreamId(String streamId) {  
36 - StreamId = streamId; 35 + public void setStream(String stream) {
  36 + Stream = stream;
37 } 37 }
38 } 38 }
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
@@ -162,15 +162,16 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR @@ -162,15 +162,16 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR
162 } 162 }
163 163
164 @Override 164 @Override
165 - public void closeRTPServer(Device device, String channelId) {  
166 - String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId); 165 + public void closeRTPServer(Device device, String channelId, String stream) {
  166 + String mediaServerId = streamSession.getMediaServerId(device.getDeviceId(), channelId, stream);
  167 + String ssrc = streamSession.getSSRC(device.getDeviceId(), channelId, stream);
167 MediaServerItem mediaServerItem = this.getOne(mediaServerId); 168 MediaServerItem mediaServerItem = this.getOne(mediaServerId);
168 if (mediaServerItem != null) { 169 if (mediaServerItem != null) {
169 String streamId = String.format("%s_%s", device.getDeviceId(), channelId); 170 String streamId = String.format("%s_%s", device.getDeviceId(), channelId);
170 zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId); 171 zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId);
171 - releaseSsrc(mediaServerItem, streamSession.getSSRC(device.getDeviceId(), channelId)); 172 + releaseSsrc(mediaServerItem, ssrc);
172 } 173 }
173 - streamSession.remove(device.getDeviceId(), channelId); 174 + streamSession.remove(device.getDeviceId(), channelId, stream);
174 } 175 }
175 176
176 @Override 177 @Override
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java
@@ -74,7 +74,7 @@ public class MediaServiceImpl implements IMediaService { @@ -74,7 +74,7 @@ public class MediaServiceImpl implements IMediaService {
74 @Override 74 @Override
75 public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) { 75 public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr) {
76 StreamInfo streamInfoResult = new StreamInfo(); 76 StreamInfo streamInfoResult = new StreamInfo();
77 - streamInfoResult.setStreamId(stream); 77 + streamInfoResult.setStream(stream);
78 streamInfoResult.setApp(app); 78 streamInfoResult.setApp(app);
79 if (addr == null) { 79 if (addr == null) {
80 addr = mediaInfo.getStreamIp(); 80 addr = mediaInfo.getStreamIp();
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -16,6 +16,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; @@ -16,6 +16,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe;
16 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; 16 import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils;
17 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 17 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
18 import com.genersoft.iot.vmp.service.IMediaServerService; 18 import com.genersoft.iot.vmp.service.IMediaServerService;
  19 +import com.genersoft.iot.vmp.service.bean.PlayBackCallback;
19 import com.genersoft.iot.vmp.service.bean.SSRCInfo; 20 import com.genersoft.iot.vmp.service.bean.SSRCInfo;
20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 21 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
21 import com.genersoft.iot.vmp.storager.IVideoManagerStorager; 22 import com.genersoft.iot.vmp.storager.IVideoManagerStorager;
@@ -104,19 +105,21 @@ public class PlayServiceImpl implements IPlayService { @@ -104,19 +105,21 @@ public class PlayServiceImpl implements IPlayService {
104 logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId)); 105 logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
105 WVPResult wvpResult = new WVPResult(); 106 WVPResult wvpResult = new WVPResult();
106 wvpResult.setCode(-1); 107 wvpResult.setCode(-1);
107 - SIPDialog dialog = streamSession.getDialog(deviceId, channelId); 108 + SIPDialog dialog = streamSession.getDialogByStream(deviceId, channelId, streamInfo.getStream());
108 if (dialog != null) { 109 if (dialog != null) {
109 wvpResult.setMsg("收流超时,请稍候重试"); 110 wvpResult.setMsg("收流超时,请稍候重试");
110 }else { 111 }else {
111 wvpResult.setMsg("点播超时,请稍候重试"); 112 wvpResult.setMsg("点播超时,请稍候重试");
112 } 113 }
  114 +
113 msg.setData(wvpResult); 115 msg.setData(wvpResult);
114 // 点播超时回复BYE 116 // 点播超时回复BYE
115 - cmder.streamByeCmd(device.getDeviceId(), channelId); 117 + cmder.streamByeCmd(device.getDeviceId(), channelId, streamInfo.getStream());
116 // 释放rtpserver 118 // 释放rtpserver
117 - mediaServerService.closeRTPServer(playResult.getDevice(), channelId); 119 + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, streamInfo.getStream());
118 // 回复之前所有的点播请求 120 // 回复之前所有的点播请求
119 resultHolder.invokeAllResult(msg); 121 resultHolder.invokeAllResult(msg);
  122 + // TODO 释放ssrc
120 }); 123 });
121 result.onCompletion(()->{ 124 result.onCompletion(()->{
122 // 点播结束时调用截图接口 125 // 点播结束时调用截图接口
@@ -153,14 +156,12 @@ public class PlayServiceImpl implements IPlayService { @@ -153,14 +156,12 @@ public class PlayServiceImpl implements IPlayService {
153 } 156 }
154 }); 157 });
155 if (streamInfo == null) { 158 if (streamInfo == null) {
156 - SSRCInfo ssrcInfo;  
157 String streamId = null; 159 String streamId = null;
158 if (mediaServerItem.isRtpEnable()) { 160 if (mediaServerItem.isRtpEnable()) {
159 streamId = String.format("%s_%s", device.getDeviceId(), channelId); 161 streamId = String.format("%s_%s", device.getDeviceId(), channelId);
160 } 162 }
161 163
162 - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);  
163 - 164 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId);
164 // 发送点播消息 165 // 发送点播消息
165 cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> { 166 cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInUse, JSONObject response) -> {
166 logger.info("收到订阅消息: " + response.toJSONString()); 167 logger.info("收到订阅消息: " + response.toJSONString());
@@ -172,7 +173,7 @@ public class PlayServiceImpl implements IPlayService { @@ -172,7 +173,7 @@ public class PlayServiceImpl implements IPlayService {
172 WVPResult wvpResult = new WVPResult(); 173 WVPResult wvpResult = new WVPResult();
173 wvpResult.setCode(-1); 174 wvpResult.setCode(-1);
174 // 点播返回sip错误 175 // 点播返回sip错误
175 - mediaServerService.closeRTPServer(playResult.getDevice(), channelId); 176 + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream());
176 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); 177 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
177 msg.setData(wvpResult); 178 msg.setData(wvpResult);
178 resultHolder.invokeAllResult(msg); 179 resultHolder.invokeAllResult(msg);
@@ -183,7 +184,7 @@ public class PlayServiceImpl implements IPlayService { @@ -183,7 +184,7 @@ public class PlayServiceImpl implements IPlayService {
183 184
184 }); 185 });
185 } else { 186 } else {
186 - String streamId = streamInfo.getStreamId(); 187 + String streamId = streamInfo.getStream();
187 if (streamId == null) { 188 if (streamId == null) {
188 WVPResult wvpResult = new WVPResult(); 189 WVPResult wvpResult = new WVPResult();
189 wvpResult.setCode(-1); 190 wvpResult.setCode(-1);
@@ -212,18 +213,16 @@ public class PlayServiceImpl implements IPlayService { @@ -212,18 +213,16 @@ public class PlayServiceImpl implements IPlayService {
212 // TODO 点播前是否重置状态 213 // TODO 点播前是否重置状态
213 redisCatchStorage.stopPlay(streamInfo); 214 redisCatchStorage.stopPlay(streamInfo);
214 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 215 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
215 - SSRCInfo ssrcInfo;  
216 String streamId2 = null; 216 String streamId2 = null;
217 if (mediaServerItem.isRtpEnable()) { 217 if (mediaServerItem.isRtpEnable()) {
218 streamId2 = String.format("%s_%s", device.getDeviceId(), channelId); 218 streamId2 = String.format("%s_%s", device.getDeviceId(), channelId);
219 } 219 }
220 - ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2);  
221 - 220 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId2);
222 cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> { 221 cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channelId, (MediaServerItem mediaServerItemInuse, JSONObject response) -> {
223 logger.info("收到订阅消息: " + response.toJSONString()); 222 logger.info("收到订阅消息: " + response.toJSONString());
224 onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid); 223 onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid);
225 }, (event) -> { 224 }, (event) -> {
226 - mediaServerService.closeRTPServer(playResult.getDevice(), channelId); 225 + mediaServerService.closeRTPServer(playResult.getDevice(), channelId, ssrcInfo.getStream());
227 WVPResult wvpResult = new WVPResult(); 226 WVPResult wvpResult = new WVPResult();
228 wvpResult.setCode(-1); 227 wvpResult.setCode(-1);
229 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg)); 228 wvpResult.setMsg(String.format("点播失败, 错误码: %s, %s", event.statusCode, event.msg));
@@ -241,12 +240,12 @@ public class PlayServiceImpl implements IPlayService { @@ -241,12 +240,12 @@ public class PlayServiceImpl implements IPlayService {
241 RequestMessage msg = new RequestMessage(); 240 RequestMessage msg = new RequestMessage();
242 msg.setId(uuid); 241 msg.setId(uuid);
243 msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId); 242 msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId);
244 - StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid); 243 + StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId);
245 if (streamInfo != null) { 244 if (streamInfo != null) {
246 DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); 245 DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId);
247 if (deviceChannel != null) { 246 if (deviceChannel != null) {
248 - deviceChannel.setStreamId(streamInfo.getStreamId());  
249 - storager.startPlay(deviceId, channelId, streamInfo.getStreamId()); 247 + deviceChannel.setStreamId(streamInfo.getStream());
  248 + storager.startPlay(deviceId, channelId, streamInfo.getStream());
250 } 249 }
251 redisCatchStorage.startPlay(streamInfo); 250 redisCatchStorage.startPlay(streamInfo);
252 msg.setData(JSON.toJSONString(streamInfo)); 251 msg.setData(JSON.toJSONString(streamInfo));
@@ -283,29 +282,53 @@ public class PlayServiceImpl implements IPlayService { @@ -283,29 +282,53 @@ public class PlayServiceImpl implements IPlayService {
283 282
284 283
285 @Override 284 @Override
286 - public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { 285 + public DeferredResult<ResponseEntity<String>> playBack(String deviceId, String channelId, String startTime, String endTime, PlayBackCallback callback) {
  286 + String uuid = UUID.randomUUID().toString();
  287 + String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
  288 + DeferredResult<ResponseEntity<String>> result = new DeferredResult<>(30000L);
  289 + Device device = storager.queryVideoDevice(deviceId);
  290 + if (device == null) {
  291 + result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));
  292 + return result;
  293 + }
  294 +
  295 + MediaServerItem newMediaServerItem = getNewMediaServerItem(device);
  296 + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true);
  297 + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result);
287 RequestMessage msg = new RequestMessage(); 298 RequestMessage msg = new RequestMessage();
288 - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId);  
289 msg.setId(uuid); 299 msg.setId(uuid);
290 - StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);  
291 - if (streamInfo != null) { 300 + msg.setKey(key);
  301 + result.onTimeout(()->{
  302 + msg.setData("回放超时");
  303 + callback.call(msg);
  304 + });
  305 + cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> {
  306 + logger.info("收到订阅消息: " + response.toJSONString());
  307 + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
  308 + if (streamInfo == null) {
  309 + logger.warn("设备回放API调用失败!");
  310 + msg.setData("设备回放API调用失败!");
  311 + callback.call(msg);
  312 + return;
  313 + }
292 redisCatchStorage.startPlayback(streamInfo); 314 redisCatchStorage.startPlayback(streamInfo);
293 msg.setData(JSON.toJSONString(streamInfo)); 315 msg.setData(JSON.toJSONString(streamInfo));
294 - resultHolder.invokeResult(msg);  
295 - } else {  
296 - logger.warn("设备回放API调用失败!");  
297 - msg.setData("设备回放API调用失败!");  
298 - resultHolder.invokeResult(msg);  
299 - } 316 + callback.call(msg);
  317 + }, event -> {
  318 + msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg));
  319 + callback.call(msg);
  320 + });
  321 + return result;
300 } 322 }
301 323
302 324
  325 +
303 @Override 326 @Override
304 public void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) { 327 public void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) {
305 RequestMessage msg = new RequestMessage(); 328 RequestMessage msg = new RequestMessage();
306 msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId); 329 msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId);
307 msg.setId(uuid); 330 msg.setId(uuid);
308 - StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid); 331 + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId);
309 if (streamInfo != null) { 332 if (streamInfo != null) {
310 redisCatchStorage.startDownload(streamInfo); 333 redisCatchStorage.startDownload(streamInfo);
311 msg.setData(JSON.toJSONString(streamInfo)); 334 msg.setData(JSON.toJSONString(streamInfo));
@@ -318,7 +341,7 @@ public class PlayServiceImpl implements IPlayService { @@ -318,7 +341,7 @@ public class PlayServiceImpl implements IPlayService {
318 } 341 }
319 342
320 343
321 - public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { 344 + public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId) {
322 String streamId = resonse.getString("stream"); 345 String streamId = resonse.getString("stream");
323 JSONArray tracks = resonse.getJSONArray("tracks"); 346 JSONArray tracks = resonse.getJSONArray("tracks");
324 StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks); 347 StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks);
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
@@ -132,7 +132,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService { @@ -132,7 +132,7 @@ public class StreamProxyServiceImpl implements IStreamProxyService {
132 }else { 132 }else {
133 streamLive = true; 133 streamLive = true;
134 StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( 134 StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(
135 - mediaInfo, param.getApp(), param.getStream(), null); 135 + mediaInfo, param.getApp(), param.getStream(), null, null);
136 wvpResult.setData(streamInfo); 136 wvpResult.setData(streamInfo);
137 137
138 } 138 }
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 7 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
8 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; 8 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
9 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 9 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
  10 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
10 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; 11 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
11 12
12 import java.util.List; 13 import java.util.List;
@@ -220,4 +221,5 @@ public interface IRedisCatchStorage { @@ -220,4 +221,5 @@ public interface IRedisCatchStorage {
220 void addMemInfo(double memInfo); 221 void addMemInfo(double memInfo);
221 222
222 void addNetInfo(Map<String, String> networkInterfaces); 223 void addNetInfo(Map<String, String> networkInterfaces);
  224 +
223 } 225 }
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
@@ -10,15 +10,16 @@ import java.util.List; @@ -10,15 +10,16 @@ import java.util.List;
10 @Repository 10 @Repository
11 public interface StreamProxyMapper { 11 public interface StreamProxyMapper {
12 12
13 - @Insert("INSERT INTO stream_proxy (type, app, stream,mediaServerId, url, src_url, dst_url, " + 13 + @Insert("INSERT INTO stream_proxy (type, name, app, stream,mediaServerId, url, src_url, dst_url, " +
14 "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable, status, enable_remove_none_reader, createTime) VALUES" + 14 "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable, status, enable_remove_none_reader, createTime) VALUES" +
15 - "('${type}','${app}', '${stream}', '${mediaServerId}','${url}', '${src_url}', '${dst_url}', " + 15 + "('${type}','${name}', '${app}', '${stream}', '${mediaServerId}','${url}', '${src_url}', '${dst_url}', " +
16 "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable}, ${status}, " + 16 "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable}, ${status}, " +
17 "${enable_remove_none_reader}, '${createTime}' )") 17 "${enable_remove_none_reader}, '${createTime}' )")
18 int add(StreamProxyItem streamProxyDto); 18 int add(StreamProxyItem streamProxyDto);
19 19
20 @Update("UPDATE stream_proxy " + 20 @Update("UPDATE stream_proxy " +
21 "SET type=#{type}, " + 21 "SET type=#{type}, " +
  22 + "name=#{name}," +
22 "app=#{app}," + 23 "app=#{app}," +
23 "stream=#{stream}," + 24 "stream=#{stream}," +
24 "url=#{url}, " + 25 "url=#{url}, " +
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; @@ -10,6 +10,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
11 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; 11 import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
12 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; 12 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
  13 +import com.genersoft.iot.vmp.service.bean.SSRCInfo;
13 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB; 14 import com.genersoft.iot.vmp.service.bean.ThirdPartyGB;
14 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 15 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
15 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; 16 import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper;
@@ -91,7 +92,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -91,7 +92,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
91 */ 92 */
92 @Override 93 @Override
93 public boolean startPlay(StreamInfo stream) { 94 public boolean startPlay(StreamInfo stream) {
94 - return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(), stream.getStreamId(),stream.getDeviceID(), stream.getChannelId()), 95 + return redis.set(String.format("%S_%S_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, userSetup.getServerId(),
  96 + stream.getStream(), stream.getDeviceID(), stream.getChannelId()),
95 stream); 97 stream);
96 } 98 }
97 99
@@ -105,7 +107,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -105,7 +107,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
105 if (streamInfo == null) return false; 107 if (streamInfo == null) return false;
106 return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX, 108 return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
107 userSetup.getServerId(), 109 userSetup.getServerId(),
108 - streamInfo.getStreamId(), 110 + streamInfo.getStream(),
109 streamInfo.getDeviceID(), 111 streamInfo.getDeviceID(),
110 streamInfo.getChannelId())); 112 streamInfo.getChannelId()));
111 } 113 }
@@ -119,7 +121,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -119,7 +121,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
119 return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s", 121 return (StreamInfo)redis.get(String.format("%S_%s_%s_%s_%s",
120 VideoManagerConstants.PLAYER_PREFIX, 122 VideoManagerConstants.PLAYER_PREFIX,
121 userSetup.getServerId(), 123 userSetup.getServerId(),
122 - streamInfo.getStreamId(), 124 + streamInfo.getStream(),
123 streamInfo.getDeviceID(), 125 streamInfo.getDeviceID(),
124 streamInfo.getChannelId())); 126 streamInfo.getChannelId()));
125 } 127 }
@@ -164,14 +166,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -164,14 +166,14 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
164 166
165 @Override 167 @Override
166 public boolean startPlayback(StreamInfo stream) { 168 public boolean startPlayback(StreamInfo stream) {
167 - return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, userSetup.getServerId(),stream.getStreamId(),  
168 - stream.getDeviceID(), stream.getChannelId()), stream); 169 + return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
  170 + userSetup.getServerId(), stream.getStream(), stream.getDeviceID(), stream.getChannelId()), stream);
169 } 171 }
170 172
171 @Override 173 @Override
172 public boolean startDownload(StreamInfo streamInfo) { 174 public boolean startDownload(StreamInfo streamInfo) {
173 - return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),streamInfo.getStreamId(),  
174 - streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo); 175 + return redis.set(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, userSetup.getServerId(),
  176 + streamInfo.getStream(), streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo);
175 } 177 }
176 178
177 @Override 179 @Override
@@ -185,7 +187,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -185,7 +187,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
185 } 187 }
186 return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, 188 return redis.del(String.format("%S_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
187 userSetup.getServerId(), 189 userSetup.getServerId(),
188 - streamInfo.getStreamId(), 190 + streamInfo.getStream(),
189 streamInfo.getDeviceID(), 191 streamInfo.getDeviceID(),
190 streamInfo.getChannelId())); 192 streamInfo.getChannelId()));
191 } 193 }
src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java
1 package com.genersoft.iot.vmp.storager.impl; 1 package com.genersoft.iot.vmp.storager.impl;
2 2
  3 +import com.genersoft.iot.vmp.common.StreamInfo;
3 import com.genersoft.iot.vmp.conf.SipConfig; 4 import com.genersoft.iot.vmp.conf.SipConfig;
4 import com.genersoft.iot.vmp.gb28181.bean.*; 5 import com.genersoft.iot.vmp.gb28181.bean.*;
5 import com.genersoft.iot.vmp.gb28181.event.EventPublisher; 6 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
@@ -157,7 +158,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -157,7 +158,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
157 public synchronized void updateChannel(String deviceId, DeviceChannel channel) { 158 public synchronized void updateChannel(String deviceId, DeviceChannel channel) {
158 String channelId = channel.getChannelId(); 159 String channelId = channel.getChannelId();
159 channel.setDeviceId(deviceId); 160 channel.setDeviceId(deviceId);
160 - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); 161 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
  162 + if (streamInfo != null) {
  163 + channel.setStreamId(streamInfo.getStream());
  164 + }
161 String now = this.format.format(System.currentTimeMillis()); 165 String now = this.format.format(System.currentTimeMillis());
162 channel.setUpdateTime(now); 166 channel.setUpdateTime(now);
163 DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId); 167 DeviceChannel deviceChannel = deviceChannelMapper.queryChannel(deviceId, channelId);
@@ -179,7 +183,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -179,7 +183,10 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
179 if (channelList.size() == 0) { 183 if (channelList.size() == 0) {
180 for (DeviceChannel channel : channels) { 184 for (DeviceChannel channel : channels) {
181 channel.setDeviceId(deviceId); 185 channel.setDeviceId(deviceId);
182 - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); 186 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
  187 + if (streamInfo != null) {
  188 + channel.setStreamId(streamInfo.getStream());
  189 + }
183 String now = this.format.format(System.currentTimeMillis()); 190 String now = this.format.format(System.currentTimeMillis());
184 channel.setUpdateTime(now); 191 channel.setUpdateTime(now);
185 channel.setCreateTime(now); 192 channel.setCreateTime(now);
@@ -190,9 +197,11 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager { @@ -190,9 +197,11 @@ public class VideoManagerStoragerImpl implements IVideoManagerStorager {
190 channelsInStore.put(deviceChannel.getChannelId(), deviceChannel); 197 channelsInStore.put(deviceChannel.getChannelId(), deviceChannel);
191 } 198 }
192 for (DeviceChannel channel : channels) { 199 for (DeviceChannel channel : channels) {
193 - String channelId = channel.getChannelId();  
194 channel.setDeviceId(deviceId); 200 channel.setDeviceId(deviceId);
195 - channel.setStreamId(streamSession.getStreamId(deviceId, channel.getChannelId())); 201 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channel.getChannelId());
  202 + if (streamInfo != null) {
  203 + channel.setStreamId(streamInfo.getStream());
  204 + }
196 String now = this.format.format(System.currentTimeMillis()); 205 String now = this.format.format(System.currentTimeMillis());
197 channel.setUpdateTime(now); 206 channel.setUpdateTime(now);
198 if (channelsInStore.get(channel.getChannelId()) != null) { 207 if (channelsInStore.get(channel.getChannelId()) != null) {
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -110,26 +110,26 @@ public class PlayController { @@ -110,26 +110,26 @@ public class PlayController {
110 String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId; 110 String key = DeferredResultHolder.CALLBACK_CMD_STOP + deviceId + channelId;
111 resultHolder.put(key, uuid, result); 111 resultHolder.put(key, uuid, result);
112 Device device = storager.queryVideoDevice(deviceId); 112 Device device = storager.queryVideoDevice(deviceId);
113 - cmder.streamByeCmd(deviceId, channelId, (event) -> {  
114 - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);  
115 - if (streamInfo == null) {  
116 - RequestMessage msg = new RequestMessage();  
117 - msg.setId(uuid);  
118 - msg.setKey(key);  
119 - msg.setData("点播未找到");  
120 - resultHolder.invokeAllResult(msg);  
121 - storager.stopPlay(deviceId, channelId);  
122 - }else {  
123 - redisCatchStorage.stopPlay(streamInfo);  
124 - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());  
125 - RequestMessage msg = new RequestMessage();  
126 - msg.setId(uuid);  
127 - msg.setKey(key);  
128 - //Response response = event.getResponse();  
129 - msg.setData(String.format("success"));  
130 - resultHolder.invokeAllResult(msg);  
131 - }  
132 - mediaServerService.closeRTPServer(device, channelId); 113 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
  114 + if (streamInfo == null) {
  115 + RequestMessage msg = new RequestMessage();
  116 + msg.setId(uuid);
  117 + msg.setKey(key);
  118 + msg.setData("点播未找到");
  119 + resultHolder.invokeAllResult(msg);
  120 + storager.stopPlay(deviceId, channelId);
  121 + return result;
  122 + }
  123 + cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream(), (event) -> {
  124 + redisCatchStorage.stopPlay(streamInfo);
  125 + storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
  126 + RequestMessage msg = new RequestMessage();
  127 + msg.setId(uuid);
  128 + msg.setKey(key);
  129 + //Response response = event.getResponse();
  130 + msg.setData(String.format("success"));
  131 + resultHolder.invokeAllResult(msg);
  132 + mediaServerService.closeRTPServer(device, channelId, streamInfo.getStream());
133 }); 133 });
134 134
135 if (deviceId != null || channelId != null) { 135 if (deviceId != null || channelId != null) {
@@ -329,7 +329,7 @@ public class PlayController { @@ -329,7 +329,7 @@ public class PlayController {
329 jsonObject.put("deviceId", transaction.getDeviceId()); 329 jsonObject.put("deviceId", transaction.getDeviceId());
330 jsonObject.put("channelId", transaction.getChannelId()); 330 jsonObject.put("channelId", transaction.getChannelId());
331 jsonObject.put("ssrc", transaction.getSsrc()); 331 jsonObject.put("ssrc", transaction.getSsrc());
332 - jsonObject.put("streamId", transaction.getStreamId()); 332 + jsonObject.put("streamId", transaction.getStream());
333 objects.add(jsonObject); 333 objects.add(jsonObject);
334 } 334 }
335 335
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
@@ -96,7 +96,7 @@ public class DownloadController { @@ -96,7 +96,7 @@ public class DownloadController {
96 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); 96 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
97 if (streamInfo != null) { 97 if (streamInfo != null) {
98 // 停止之前的下载 98 // 停止之前的下载
99 - cmder.streamByeCmd(deviceId, channelId); 99 + cmder.streamByeCmd(deviceId, channelId, streamInfo.getStream());
100 } 100 }
101 101
102 MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); 102 MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);
@@ -114,7 +114,7 @@ public class DownloadController { @@ -114,7 +114,7 @@ public class DownloadController {
114 114
115 cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> { 115 cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> {
116 logger.info("收到订阅消息: " + response.toJSONString()); 116 logger.info("收到订阅消息: " + response.toJSONString());
117 - playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid.toString()); 117 + playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid);
118 }, event -> { 118 }, event -> {
119 RequestMessage msg = new RequestMessage(); 119 RequestMessage msg = new RequestMessage();
120 msg.setId(uuid); 120 msg.setId(uuid);
@@ -130,11 +130,12 @@ public class DownloadController { @@ -130,11 +130,12 @@ public class DownloadController {
130 @ApiImplicitParams({ 130 @ApiImplicitParams({
131 @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), 131 @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
132 @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), 132 @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
  133 + @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class),
133 }) 134 })
134 - @GetMapping("/stop/{deviceId}/{channelId}")  
135 - public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) { 135 + @GetMapping("/stop/{deviceId}/{channelId}/{stream}")
  136 + public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId, @PathVariable String stream) {
136 137
137 - cmder.streamByeCmd(deviceId, channelId); 138 + cmder.streamByeCmd(deviceId, channelId, stream);
138 139
139 if (logger.isDebugEnabled()) { 140 if (logger.isDebugEnabled()) {
140 logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId)); 141 logger.debug(String.format("设备历史媒体下载停止 API调用,deviceId/channelId:%s_%s", deviceId, channelId));
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory; @@ -18,6 +18,7 @@ import org.slf4j.LoggerFactory;
18 import org.springframework.beans.factory.annotation.Autowired; 18 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.http.HttpStatus; 19 import org.springframework.http.HttpStatus;
20 import org.springframework.http.ResponseEntity; 20 import org.springframework.http.ResponseEntity;
  21 +import org.springframework.util.StringUtils;
21 import org.springframework.web.bind.annotation.CrossOrigin; 22 import org.springframework.web.bind.annotation.CrossOrigin;
22 import org.springframework.web.bind.annotation.GetMapping; 23 import org.springframework.web.bind.annotation.GetMapping;
23 import org.springframework.web.bind.annotation.PathVariable; 24 import org.springframework.web.bind.annotation.PathVariable;
@@ -75,52 +76,8 @@ public class PlaybackController { @@ -75,52 +76,8 @@ public class PlaybackController {
75 if (logger.isDebugEnabled()) { 76 if (logger.isDebugEnabled()) {
76 logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId)); 77 logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
77 } 78 }
78 - String uuid = UUID.randomUUID().toString();  
79 - String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;  
80 - DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);  
81 - Device device = storager.queryVideoDevice(deviceId);  
82 - if (device == null) {  
83 - result.setResult(new ResponseEntity<>(HttpStatus.BAD_REQUEST));  
84 - return result;  
85 - }  
86 - MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device);  
87 - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, true);  
88 -  
89 - // 超时处理  
90 - result.onTimeout(()->{  
91 - logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));  
92 - RequestMessage msg = new RequestMessage();  
93 - msg.setId(uuid);  
94 - msg.setKey(key);  
95 - msg.setData("Timeout");  
96 - resultHolder.invokeResult(msg);  
97 - });  
98 -  
99 - StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);  
100 - if (streamInfo != null) {  
101 - // 停止之前的回放  
102 - cmder.streamByeCmd(deviceId, channelId);  
103 - }  
104 - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId, uuid, result);  
105 -  
106 - if (newMediaServerItem == null) {  
107 - logger.warn(String.format("设备回放超时,deviceId:%s ,channelId:%s", deviceId, channelId));  
108 - RequestMessage msg = new RequestMessage();  
109 - msg.setId(uuid);  
110 - msg.setKey(key);  
111 - msg.setData("Timeout");  
112 - resultHolder.invokeResult(msg);  
113 - return result;  
114 - }  
115 79
116 - cmder.playbackStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, (MediaServerItem mediaServerItem, JSONObject response) -> {  
117 - logger.info("收到订阅消息: " + response.toJSONString());  
118 - playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());  
119 - }, event -> {  
120 - RequestMessage msg = new RequestMessage();  
121 - msg.setId(uuid);  
122 - msg.setKey(key);  
123 - msg.setData(String.format("回放失败, 错误码: %s, %s", event.statusCode, event.msg)); 80 + DeferredResult<ResponseEntity<String>> result = playService.playBack(deviceId, channelId, startTime, endTime, msg->{
124 resultHolder.invokeResult(msg); 81 resultHolder.invokeResult(msg);
125 }); 82 });
126 83
@@ -131,24 +88,31 @@ public class PlaybackController { @@ -131,24 +88,31 @@ public class PlaybackController {
131 @ApiImplicitParams({ 88 @ApiImplicitParams({
132 @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class), 89 @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
133 @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class), 90 @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
  91 + @ApiImplicitParam(name = "stream", value = "流ID", dataTypeClass = String.class),
134 }) 92 })
135 - @GetMapping("/stop/{deviceId}/{channelId}")  
136 - public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) { 93 + @GetMapping("/stop/{deviceId}/{channelId}/{stream}")
  94 + public ResponseEntity<String> playStop(
  95 + @PathVariable String deviceId,
  96 + @PathVariable String channelId,
  97 + @PathVariable String stream) {
137 98
138 - cmder.streamByeCmd(deviceId, channelId); 99 + cmder.streamByeCmd(deviceId, channelId, stream);
139 100
140 if (logger.isDebugEnabled()) { 101 if (logger.isDebugEnabled()) {
141 logger.debug(String.format("设备录像回放停止 API调用,deviceId/channelId:%s/%s", deviceId, channelId)); 102 logger.debug(String.format("设备录像回放停止 API调用,deviceId/channelId:%s/%s", deviceId, channelId));
142 } 103 }
  104 + if (StringUtils.isEmpty(deviceId) || StringUtils.isEmpty(channelId) || StringUtils.isEmpty(stream)) {
  105 + return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
  106 + }
143 107
144 if (deviceId != null && channelId != null) { 108 if (deviceId != null && channelId != null) {
145 JSONObject json = new JSONObject(); 109 JSONObject json = new JSONObject();
146 json.put("deviceId", deviceId); 110 json.put("deviceId", deviceId);
147 json.put("channelId", channelId); 111 json.put("channelId", channelId);
148 - return new ResponseEntity<String>(json.toString(), HttpStatus.OK); 112 + return new ResponseEntity<>(json.toString(), HttpStatus.OK);
149 } else { 113 } else {
150 logger.warn("设备录像回放停止API调用失败!"); 114 logger.warn("设备录像回放停止API调用失败!");
151 - return new ResponseEntity<String>(HttpStatus.INTERNAL_SERVER_ERROR); 115 + return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
152 } 116 }
153 } 117 }
154 118
src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java
@@ -103,7 +103,7 @@ public class ApiStreamController { @@ -103,7 +103,7 @@ public class ApiStreamController {
103 PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{ 103 PlayResult play = playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{
104 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code); 104 StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code);
105 JSONObject result = new JSONObject(); 105 JSONObject result = new JSONObject();
106 - result.put("StreamID", streamInfo.getStreamId()); 106 + result.put("StreamID", streamInfo.getStream());
107 result.put("DeviceID", device.getDeviceId()); 107 result.put("DeviceID", device.getDeviceId());
108 result.put("ChannelID", code); 108 result.put("ChannelID", code);
109 result.put("ChannelName", deviceChannel.getName()); 109 result.put("ChannelName", deviceChannel.getName());
@@ -177,7 +177,7 @@ public class ApiStreamController { @@ -177,7 +177,7 @@ public class ApiStreamController {
177 result.put("error","未找到流信息"); 177 result.put("error","未找到流信息");
178 return result; 178 return result;
179 } 179 }
180 - cmder.streamByeCmd(serial, code); 180 + cmder.streamByeCmd(serial, code, streamInfo.getStream());
181 redisCatchStorage.stopPlay(streamInfo); 181 redisCatchStorage.stopPlay(streamInfo);
182 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 182 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
183 return null; 183 return null;
src/main/resources/all-application.yml
@@ -186,7 +186,7 @@ user-settings: @@ -186,7 +186,7 @@ user-settings:
186 # 是否将日志存储进数据库 186 # 是否将日志存储进数据库
187 logInDatebase: true 187 logInDatebase: true
188 # 第三方匹配,用于从stream钟获取有效信息 188 # 第三方匹配,用于从stream钟获取有效信息
189 - thirdPartyGBIdReg: [\s\S]* 189 + thirdPartyGBIdReg: "[\\s\\S]*"
190 190
191 # 在线文档: swagger-ui(生产环境建议关闭) 191 # 在线文档: swagger-ui(生产环境建议关闭)
192 swagger-ui: 192 swagger-ui:
src/main/resources/logback-spring-local.xml
@@ -83,7 +83,7 @@ @@ -83,7 +83,7 @@
83 <logger name="com.genersoft.iot.vmp.storager.dao" level="INFO"> 83 <logger name="com.genersoft.iot.vmp.storager.dao" level="INFO">
84 <appender-ref ref="STDOUT"/> 84 <appender-ref ref="STDOUT"/>
85 </logger> 85 </logger>
86 - <logger name="com.genersoft.iot.vmp.gb28181" level="DEBUG"> 86 + <logger name="com.genersoft.iot.vmp.gb28181" level="INFO">
87 <appender-ref ref="STDOUT"/> 87 <appender-ref ref="STDOUT"/>
88 </logger> 88 </logger>
89 89
web_src/src/components/dialog/changePassword.vue
@@ -75,7 +75,10 @@ export default { @@ -75,7 +75,10 @@ export default {
75 isLoging: false, 75 isLoging: false,
76 rules: { 76 rules: {
77 oldPassword: [{ required: true, validator: validatePass0, trigger: "blur" }], 77 oldPassword: [{ required: true, validator: validatePass0, trigger: "blur" }],
78 - newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }], 78 + newPassword: [{ required: true, validator: validatePass1, trigger: "blur" }, {
  79 + pattern: /^(?=.*[a-zA-Z])(?=.*\d)(?=.*[~!@#$%^&*()_+`\-={}:";'<>?,.\/]).{8,20}$/,
  80 + message: "密码长度在8-20位之间,由字母+数字+特殊字符组成",
  81 + },],
79 confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }], 82 confirmPassword: [{ required: true, validator: validatePass2, trigger: "blur" }],
80 }, 83 },
81 }; 84 };
web_src/src/components/dialog/devicePlayer.vue
@@ -307,7 +307,7 @@ export default { @@ -307,7 +307,7 @@ export default {
307 this.isLoging = false; 307 this.isLoging = false;
308 // this.videoUrl = streamInfo.rtc; 308 // this.videoUrl = streamInfo.rtc;
309 this.videoUrl = this.getUrlByStreamInfo(streamInfo); 309 this.videoUrl = this.getUrlByStreamInfo(streamInfo);
310 - this.streamId = streamInfo.streamId; 310 + this.streamId = streamInfo.stream;
311 this.app = streamInfo.app; 311 this.app = streamInfo.app;
312 this.mediaServerId = streamInfo.mediaServerId; 312 this.mediaServerId = streamInfo.mediaServerId;
313 this.playFromStreamInfo(false, streamInfo) 313 this.playFromStreamInfo(false, streamInfo)
@@ -485,8 +485,9 @@ export default { @@ -485,8 +485,9 @@ export default {
485 }).then(function (res) { 485 }).then(function (res) {
486 var streamInfo = res.data; 486 var streamInfo = res.data;
487 that.app = streamInfo.app; 487 that.app = streamInfo.app;
488 - that.streamId = streamInfo.streamId; 488 + that.streamId = streamInfo.stream;
489 that.mediaServerId = streamInfo.mediaServerId; 489 that.mediaServerId = streamInfo.mediaServerId;
  490 + that.ssrc = streamInfo.ssrc;
490 that.videoUrl = that.getUrlByStreamInfo(streamInfo); 491 that.videoUrl = that.getUrlByStreamInfo(streamInfo);
491 that.recordPlay = true; 492 that.recordPlay = true;
492 }); 493 });
@@ -497,7 +498,7 @@ export default { @@ -497,7 +498,7 @@ export default {
497 this.videoUrl = ''; 498 this.videoUrl = '';
498 this.$axios({ 499 this.$axios({
499 method: 'get', 500 method: 'get',
500 - url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId 501 + url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId + "/" + this.streamId
501 }).then(function (res) { 502 }).then(function (res) {
502 if (callback) callback() 503 if (callback) callback()
503 }); 504 });
@@ -517,7 +518,7 @@ export default { @@ -517,7 +518,7 @@ export default {
517 }).then(function (res) { 518 }).then(function (res) {
518 var streamInfo = res.data; 519 var streamInfo = res.data;
519 that.app = streamInfo.app; 520 that.app = streamInfo.app;
520 - that.streamId = streamInfo.streamId; 521 + that.streamId = streamInfo.stream;
521 that.mediaServerId = streamInfo.mediaServerId; 522 that.mediaServerId = streamInfo.mediaServerId;
522 that.videoUrl = that.getUrlByStreamInfo(streamInfo); 523 that.videoUrl = that.getUrlByStreamInfo(streamInfo);
523 that.recordPlay = true; 524 that.recordPlay = true;
@@ -529,7 +530,7 @@ export default { @@ -529,7 +530,7 @@ export default {
529 this.videoUrl = ''; 530 this.videoUrl = '';
530 this.$axios({ 531 this.$axios({
531 method: 'get', 532 method: 'get',
532 - url: '/api/download/stop/' + this.deviceId + "/" + this.channelId 533 + url: '/api/download/stop/' + this.deviceId + "/" + this.channelId+ "/" + this.streamId
533 }).then(function (res) { 534 }).then(function (res) {
534 if (callback) callback() 535 if (callback) callback()
535 }); 536 });
@@ -539,8 +540,6 @@ export default { @@ -539,8 +540,6 @@ export default {
539 let that = this; 540 let that = this;
540 this.$axios({ 541 this.$axios({
541 method: 'post', 542 method: 'post',
542 - // url: '/api/ptz/' + this.deviceId + '/' + this.channelId + '?leftRight=' + leftRight + '&upDown=' + upDown +  
543 - // '&inOut=' + zoom + '&moveSpeed=50&zoomSpeed=50'  
544 url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed 543 url: '/api/ptz/control/' + this.deviceId + '/' + this.channelId + '?command=' + command + '&horizonSpeed=' + this.controSpeed + '&verticalSpeed=' + this.controSpeed + '&zoomSpeed=' + this.controSpeed
545 }).then(function (res) {}); 544 }).then(function (res) {});
546 }, 545 },