Commit 2b3b7dbc7973def2342eecd8caf7514f0a367c1b

Authored by panlinlin
1 parent 760f1f4d

使用设备Id+通道Id作为session的识别标识,解决点播异常时无法释放session的问题

src/main/java/com/genersoft/iot/vmp/gb28181/session/VideoStreamSessionManager.java
@@ -16,6 +16,7 @@ public class VideoStreamSessionManager { @@ -16,6 +16,7 @@ public class VideoStreamSessionManager {
16 16
17 private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>(); 17 private ConcurrentHashMap<String, ClientTransaction> sessionMap = new ConcurrentHashMap<>();
18 private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>(); 18 private ConcurrentHashMap<String, String> ssrcMap = new ConcurrentHashMap<>();
  19 + private ConcurrentHashMap<String, String> streamIdMap = new ConcurrentHashMap<>();
19 20
20 public String createPlaySsrc(){ 21 public String createPlaySsrc(){
21 return SsrcUtil.getPlaySsrc(); 22 return SsrcUtil.getPlaySsrc();
@@ -25,18 +26,23 @@ public class VideoStreamSessionManager { @@ -25,18 +26,23 @@ public class VideoStreamSessionManager {
25 return SsrcUtil.getPlayBackSsrc(); 26 return SsrcUtil.getPlayBackSsrc();
26 } 27 }
27 28
28 - public void put(String streamId,String ssrc,ClientTransaction transaction){  
29 - sessionMap.put(streamId, transaction);  
30 - ssrcMap.put(streamId, ssrc); 29 + public void put(String deviceId, String channelId ,String ssrc, String streamId, ClientTransaction transaction){
  30 + sessionMap.put(deviceId + "_" + channelId, transaction);
  31 + ssrcMap.put(deviceId + "_" + channelId, ssrc);
  32 + streamIdMap.put(deviceId + "_" + channelId, streamId);
31 } 33 }
32 34
33 - public ClientTransaction get(String streamId){  
34 - return sessionMap.get(streamId); 35 + public ClientTransaction getTransaction(String deviceId, String channelId){
  36 + return sessionMap.get(deviceId + "_" + channelId);
  37 + }
  38 +
  39 + public String getStreamId(String deviceId, String channelId){
  40 + return streamIdMap.get(deviceId + "_" + channelId);
35 } 41 }
36 42
37 - public void remove(String streamId) {  
38 - sessionMap.remove(streamId);  
39 - SsrcUtil.releaseSsrc(ssrcMap.get(streamId));  
40 - ssrcMap.remove(streamId); 43 + public void remove(String deviceId, String channelId) {
  44 + sessionMap.remove(deviceId + "_" + channelId);
  45 + SsrcUtil.releaseSsrc(ssrcMap.get(deviceId + "_" + channelId));
  46 + ssrcMap.remove(deviceId + "_" + channelId);
41 } 47 }
42 } 48 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
@@ -87,7 +87,6 @@ public interface ISIPCommander { @@ -87,7 +87,6 @@ public interface ISIPCommander {
87 87
88 /** 88 /**
89 * 请求预览视频流 89 * 请求预览视频流
90 - *  
91 * @param device 视频设备 90 * @param device 视频设备
92 * @param channelId 预览通道 91 * @param channelId 预览通道
93 */ 92 */
@@ -108,8 +107,8 @@ public interface ISIPCommander { @@ -108,8 +107,8 @@ public interface ISIPCommander {
108 * 107 *
109 * @param ssrc ssrc 108 * @param ssrc ssrc
110 */ 109 */
111 - void streamByeCmd(String ssrc, SipSubscribe.Event okEvent);  
112 - void streamByeCmd(String ssrc); 110 + void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent);
  111 + void streamByeCmd(String deviceId, String channelId);
113 112
114 /** 113 /**
115 * 语音广播 114 * 语音广播
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -332,17 +332,17 @@ public class SIPCommander implements ISIPCommander { @@ -332,17 +332,17 @@ public class SIPCommander implements ISIPCommander {
332 332
333 /** 333 /**
334 * 请求预览视频流 334 * 请求预览视频流
335 - * @param device 视频设备  
336 - * @param channelId 预览通道  
337 - * @param event hook订阅  
338 - * @param errorEvent sip错误订阅  
339 - */ 335 + * @param device 视频设备
  336 + * @param channelId 预览通道
  337 + * @param event hook订阅
  338 + * @param errorEvent sip错误订阅
  339 + */
340 @Override 340 @Override
341 public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) { 341 public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) {
  342 + String streamId = null;
342 try { 343 try {
343 if (device == null) return; 344 if (device == null) return;
344 String ssrc = streamSession.createPlaySsrc(); 345 String ssrc = streamSession.createPlaySsrc();
345 - String streamId = null;  
346 if (rtpEnable) { 346 if (rtpEnable) {
347 streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId); 347 streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
348 }else { 348 }else {
@@ -444,9 +444,12 @@ public class SIPCommander implements ISIPCommander { @@ -444,9 +444,12 @@ public class SIPCommander implements ISIPCommander {
444 444
445 Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc, callIdHeader); 445 Request request = headerProvider.createInviteRequest(device, channelId, content.toString(), null, "FromInvt" + tm, null, ssrc, callIdHeader);
446 446
447 - ClientTransaction transaction = transmitRequest(device, request, errorEvent);  
448 - streamSession.put(streamId,ssrc, transaction);  
449 - 447 + ClientTransaction transaction = transmitRequest(device, request, (e -> {
  448 + streamSession.remove(device.getDeviceId(), channelId);
  449 + errorEvent.response(e);
  450 + }));
  451 + streamSession.put(device.getDeviceId(), channelId ,ssrc,streamId, transaction);
  452 +
450 } catch ( SipException | ParseException | InvalidArgumentException e) { 453 } catch ( SipException | ParseException | InvalidArgumentException e) {
451 e.printStackTrace(); 454 e.printStackTrace();
452 } 455 }
@@ -552,7 +555,7 @@ public class SIPCommander implements ISIPCommander { @@ -552,7 +555,7 @@ public class SIPCommander implements ISIPCommander {
552 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader); 555 Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), null, "fromplybck" + tm, null, callIdHeader);
553 556
554 ClientTransaction transaction = transmitRequest(device, request, errorEvent); 557 ClientTransaction transaction = transmitRequest(device, request, errorEvent);
555 - streamSession.put(streamId, ssrc, transaction); 558 + streamSession.put(device.getDeviceId(), channelId, ssrc, streamId, transaction);
556 559
557 } catch ( SipException | ParseException | InvalidArgumentException e) { 560 } catch ( SipException | ParseException | InvalidArgumentException e) {
558 e.printStackTrace(); 561 e.printStackTrace();
@@ -566,17 +569,17 @@ public class SIPCommander implements ISIPCommander { @@ -566,17 +569,17 @@ public class SIPCommander implements ISIPCommander {
566 * 569 *
567 */ 570 */
568 @Override 571 @Override
569 - public void streamByeCmd(String ssrc) {  
570 - streamByeCmd(ssrc, null); 572 + public void streamByeCmd(String deviceId, String channelId) {
  573 + streamByeCmd(deviceId, channelId, null);
571 } 574 }
572 @Override 575 @Override
573 - public void streamByeCmd(String streamId, SipSubscribe.Event okEvent) { 576 + public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) {
574 577
575 try { 578 try {
576 - ClientTransaction transaction = streamSession.get(streamId); 579 + ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId);
577 // 服务重启后 580 // 服务重启后
578 if (transaction == null) { 581 if (transaction == null) {
579 - StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); 582 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
580 if (streamInfo != null) { 583 if (streamInfo != null) {
581 584
582 } 585 }
@@ -613,14 +616,9 @@ public class SIPCommander implements ISIPCommander { @@ -613,14 +616,9 @@ public class SIPCommander implements ISIPCommander {
613 } 616 }
614 617
615 dialog.sendRequest(clientTransaction); 618 dialog.sendRequest(clientTransaction);
616 -  
617 - streamSession.remove(streamId);  
618 - zlmrtpServerFactory.closeRTPServer(streamId);  
619 - } catch (TransactionDoesNotExistException e) {  
620 - e.printStackTrace();  
621 - } catch (SipException e) {  
622 - e.printStackTrace();  
623 - } catch (ParseException e) { 619 + zlmrtpServerFactory.closeRTPServer(streamSession.getStreamId(deviceId, channelId));
  620 + streamSession.remove(deviceId, channelId);
  621 + } catch (SipException | ParseException e) {
624 e.printStackTrace(); 622 e.printStackTrace();
625 } 623 }
626 } 624 }
@@ -641,7 +639,6 @@ public class SIPCommander implements ISIPCommander { @@ -641,7 +639,6 @@ public class SIPCommander implements ISIPCommander {
641 * 语音广播 639 * 语音广播
642 * 640 *
643 * @param device 视频设备 641 * @param device 视频设备
644 - * @param channelId 预览通道  
645 */ 642 */
646 @Override 643 @Override
647 public boolean audioBroadcastCmd(Device device) { 644 public boolean audioBroadcastCmd(Device device) {
@@ -1140,7 +1137,7 @@ public class SIPCommander implements ISIPCommander { @@ -1140,7 +1137,7 @@ public class SIPCommander implements ISIPCommander {
1140 * @param device 视频设备 1137 * @param device 视频设备
1141 * @param startPriority 报警起始级别(可选) 1138 * @param startPriority 报警起始级别(可选)
1142 * @param endPriority 报警终止级别(可选) 1139 * @param endPriority 报警终止级别(可选)
1143 - * @param alarmMethods 报警方式条件(可选) 1140 + * @param alarmMethod 报警方式条件(可选)
1144 * @param alarmType 报警类型 1141 * @param alarmType 报警类型
1145 * @param startTime 报警发生起始时间(可选) 1142 * @param startTime 报警发生起始时间(可选)
1146 * @param endTime 报警发生终止时间(可选) 1143 * @param endTime 报警发生终止时间(可选)
@@ -1428,5 +1425,6 @@ public class SIPCommander implements ISIPCommander { @@ -1428,5 +1425,6 @@ public class SIPCommander implements ISIPCommander {
1428 String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId); 1425 String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId);
1429 zlmrtpServerFactory.closeRTPServer(streamId); 1426 zlmrtpServerFactory.closeRTPServer(streamId);
1430 } 1427 }
  1428 + streamSession.remove(device.getDeviceId(), channelId);
1431 } 1429 }
1432 } 1430 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java
@@ -58,7 +58,7 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor { @@ -58,7 +58,7 @@ public class ByeRequestProcessor extends SIPRequestAbstractProcessor {
58 redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); 58 redisCatchStorage.deleteSendRTPServer(platformGbId, channelId);
59 if (zlmrtpServerFactory.totalReaderCount(sendRtpItem.getApp(), streamId) == 0) { 59 if (zlmrtpServerFactory.totalReaderCount(sendRtpItem.getApp(), streamId) == 0) {
60 System.out.println(streamId + "无其它观看者,通知设备停止推流"); 60 System.out.println(streamId + "无其它观看者,通知设备停止推流");
61 - cmder.streamByeCmd(streamId); 61 + cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId);
62 } 62 }
63 } 63 }
64 } catch (SipException e) { 64 } catch (SipException e) {
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java
@@ -922,7 +922,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor { @@ -922,7 +922,7 @@ public class MessageRequestProcessor extends SIPRequestAbstractProcessor {
922 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, "*"); 922 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, "*");
923 if (streamInfo != null) { 923 if (streamInfo != null) {
924 redisCatchStorage.stopPlayback(streamInfo); 924 redisCatchStorage.stopPlayback(streamInfo);
925 - cmder.streamByeCmd(streamInfo.getStreamId()); 925 + cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId());
926 } 926 }
927 } 927 }
928 } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) { 928 } catch (ParseException | SipException | InvalidArgumentException | DocumentException e) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -306,12 +306,12 @@ public class ZLMHttpHookListener { @@ -306,12 +306,12 @@ public class ZLMHttpHookListener {
306 if (redisCatchStorage.isChannelSendingRTP(streamInfo.getChannelId())) { 306 if (redisCatchStorage.isChannelSendingRTP(streamInfo.getChannelId())) {
307 ret.put("close", false); 307 ret.put("close", false);
308 } else { 308 } else {
309 - cmder.streamByeCmd(streamId); 309 + cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId());
310 redisCatchStorage.stopPlay(streamInfo); 310 redisCatchStorage.stopPlay(streamInfo);
311 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 311 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
312 } 312 }
313 }else{ 313 }else{
314 - cmder.streamByeCmd(streamId); 314 + cmder.streamByeCmd(streamInfo.getDeviceID(), streamInfo.getChannelId());
315 streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId); 315 streamInfo = redisCatchStorage.queryPlaybackByStreamId(streamId);
316 redisCatchStorage.stopPlayback(streamInfo); 316 redisCatchStorage.stopPlayback(streamInfo);
317 } 317 }
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -63,7 +63,16 @@ public class PlayServiceImpl implements IPlayService { @@ -63,7 +63,16 @@ public class PlayServiceImpl implements IPlayService {
63 playResult.setResult(result); 63 playResult.setResult(result);
64 // 录像查询以channelId作为deviceId查询 64 // 录像查询以channelId作为deviceId查询
65 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); 65 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
66 - 66 + // 超时处理
  67 + result.onTimeout(()->{
  68 + logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));
  69 + // 释放rtpserver
  70 + cmder.closeRTPServer(playResult.getDevice(), channelId);
  71 + RequestMessage msg = new RequestMessage();
  72 + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());
  73 + msg.setData("Timeout");
  74 + resultHolder.invokeResult(msg);
  75 + });
67 if (streamInfo == null) { 76 if (streamInfo == null) {
68 // 发送点播消息 77 // 发送点播消息
69 cmder.playStreamCmd(device, channelId, (JSONObject response) -> { 78 cmder.playStreamCmd(device, channelId, (JSONObject response) -> {
@@ -76,6 +85,7 @@ public class PlayServiceImpl implements IPlayService { @@ -76,6 +85,7 @@ public class PlayServiceImpl implements IPlayService {
76 RequestMessage msg = new RequestMessage(); 85 RequestMessage msg = new RequestMessage();
77 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); 86 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
78 Response response = event.getResponse(); 87 Response response = event.getResponse();
  88 + cmder.closeRTPServer(playResult.getDevice(), channelId);
79 msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase())); 89 msg.setData(String.format("点播失败, 错误码: %s, %s", response.getStatusCode(), response.getReasonPhrase()));
80 resultHolder.invokeResult(msg); 90 resultHolder.invokeResult(msg);
81 if (errorEvent != null) { 91 if (errorEvent != null) {
@@ -107,6 +117,7 @@ public class PlayServiceImpl implements IPlayService { @@ -107,6 +117,7 @@ public class PlayServiceImpl implements IPlayService {
107 logger.info("收到订阅消息: " + response.toJSONString()); 117 logger.info("收到订阅消息: " + response.toJSONString());
108 onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString()); 118 onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString());
109 }, event -> { 119 }, event -> {
  120 + cmder.closeRTPServer(playResult.getDevice(), channelId);
110 RequestMessage msg = new RequestMessage(); 121 RequestMessage msg = new RequestMessage();
111 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); 122 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
112 Response response = event.getResponse(); 123 Response response = event.getResponse();
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -36,7 +36,7 @@ public interface IRedisCatchStorage { @@ -36,7 +36,7 @@ public interface IRedisCatchStorage {
36 36
37 StreamInfo queryPlaybackByStreamId(String steamId); 37 StreamInfo queryPlaybackByStreamId(String steamId);
38 38
39 - StreamInfo queryPlayByDevice(String deviceId, String code); 39 + StreamInfo queryPlayByDevice(String deviceId, String channelId);
40 40
41 /** 41 /**
42 * 更新流媒体信息 42 * 更新流媒体信息
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -75,11 +75,11 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -75,11 +75,11 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
75 } 75 }
76 76
77 @Override 77 @Override
78 - public StreamInfo queryPlayByDevice(String deviceId, String code) { 78 + public StreamInfo queryPlayByDevice(String deviceId, String channelId) {
79 // List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, 79 // List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
80 List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, 80 List<Object> playLeys = redis.scan(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX,
81 deviceId, 81 deviceId,
82 - code)); 82 + channelId));
83 if (playLeys == null || playLeys.size() == 0) return null; 83 if (playLeys == null || playLeys.size() == 0) return null;
84 return (StreamInfo)redis.get(playLeys.get(0).toString()); 84 return (StreamInfo)redis.get(playLeys.get(0).toString());
85 } 85 }
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java
@@ -75,27 +75,19 @@ public class PlayController { @@ -75,27 +75,19 @@ public class PlayController {
75 75
76 PlayResult playResult = playService.play(deviceId, channelId, null, null); 76 PlayResult playResult = playService.play(deviceId, channelId, null, null);
77 77
78 - // 超时处理  
79 - playResult.getResult().onTimeout(()->{  
80 - logger.warn(String.format("设备点播超时,deviceId:%s ,channelId:%s", deviceId, channelId));  
81 - // 释放rtpserver  
82 - cmder.closeRTPServer(playResult.getDevice(), channelId);  
83 - RequestMessage msg = new RequestMessage();  
84 - msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid());  
85 - msg.setData("Timeout");  
86 - resultHolder.invokeResult(msg);  
87 - }); 78 +
88 return playResult.getResult(); 79 return playResult.getResult();
89 } 80 }
90 81
91 @ApiOperation("停止点播") 82 @ApiOperation("停止点播")
92 @ApiImplicitParams({ 83 @ApiImplicitParams({
93 - @ApiImplicitParam(name = "streamId", value = "视频流ID", dataTypeClass = String.class), 84 + @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
  85 + @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
94 }) 86 })
95 - @GetMapping("/stop/{streamId}")  
96 - public DeferredResult<ResponseEntity<String>> playStop(@PathVariable String streamId) { 87 + @GetMapping("/stop/{deviceId}/{channelId}")
  88 + public DeferredResult<ResponseEntity<String>> playStop(@PathVariable String deviceId, @PathVariable String channelId) {
97 89
98 - logger.debug(String.format("设备预览/回放停止API调用,streamId:%s", streamId)); 90 + logger.debug(String.format("设备预览/回放停止API调用,streamId:%s/$s", deviceId, channelId ));
99 91
100 UUID uuid = UUID.randomUUID(); 92 UUID uuid = UUID.randomUUID();
101 DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(); 93 DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>();
@@ -103,8 +95,8 @@ public class PlayController { @@ -103,8 +95,8 @@ public class PlayController {
103 // 录像查询以channelId作为deviceId查询 95 // 录像查询以channelId作为deviceId查询
104 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_STOP + uuid, result); 96 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_STOP + uuid, result);
105 97
106 - cmder.streamByeCmd(streamId, event -> {  
107 - StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); 98 + cmder.streamByeCmd(deviceId, channelId, event -> {
  99 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId);
108 if (streamInfo == null) { 100 if (streamInfo == null) {
109 RequestMessage msg = new RequestMessage(); 101 RequestMessage msg = new RequestMessage();
110 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); 102 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
@@ -121,9 +113,10 @@ public class PlayController { @@ -121,9 +113,10 @@ public class PlayController {
121 } 113 }
122 }); 114 });
123 115
124 - if (streamId != null) { 116 + if (deviceId != null || channelId != null) {
125 JSONObject json = new JSONObject(); 117 JSONObject json = new JSONObject();
126 - json.put("streamId", streamId); 118 + json.put("deviceId", deviceId);
  119 + json.put("channelId", channelId);
127 RequestMessage msg = new RequestMessage(); 120 RequestMessage msg = new RequestMessage();
128 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); 121 msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid);
129 msg.setData(json.toString()); 122 msg.setData(json.toString());
@@ -138,7 +131,7 @@ public class PlayController { @@ -138,7 +131,7 @@ public class PlayController {
138 131
139 // 超时处理 132 // 超时处理
140 result.onTimeout(()->{ 133 result.onTimeout(()->{
141 - logger.warn(String.format("设备预览/回放停止超时,streamId:%s ", streamId)); 134 + logger.warn(String.format("设备预览/回放停止超时,deviceId/channelId:%s/$s ", deviceId, channelId));
142 RequestMessage msg = new RequestMessage(); 135 RequestMessage msg = new RequestMessage();
143 msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid); 136 msg.setId(DeferredResultHolder.CALLBACK_CMD_STOP + uuid);
144 msg.setData("Timeout"); 137 msg.setData("Timeout");
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
@@ -84,7 +84,7 @@ public class PlaybackController { @@ -84,7 +84,7 @@ public class PlaybackController {
84 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); 84 StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId);
85 if (streamInfo != null) { 85 if (streamInfo != null) {
86 // 停止之前的回放 86 // 停止之前的回放
87 - cmder.streamByeCmd(streamInfo.getStreamId()); 87 + cmder.streamByeCmd(deviceId, channelId);
88 } 88 }
89 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); 89 resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result);
90 cmder.playbackStreamCmd(device, channelId, startTime, endTime, (JSONObject response) -> { 90 cmder.playbackStreamCmd(device, channelId, startTime, endTime, (JSONObject response) -> {
@@ -103,20 +103,22 @@ public class PlaybackController { @@ -103,20 +103,22 @@ public class PlaybackController {
103 103
104 @ApiOperation("停止视频回放") 104 @ApiOperation("停止视频回放")
105 @ApiImplicitParams({ 105 @ApiImplicitParams({
106 - @ApiImplicitParam(name = "ssrc", value = "视频流标识", dataTypeClass = String.class), 106 + @ApiImplicitParam(name = "deviceId", value = "设备ID", dataTypeClass = String.class),
  107 + @ApiImplicitParam(name = "channelId", value = "通道ID", dataTypeClass = String.class),
107 }) 108 })
108 - @GetMapping("/stop/{ssrc}")  
109 - public ResponseEntity<String> playStop(@PathVariable String ssrc) { 109 + @GetMapping("/stop/{deviceId}/{channelId}")
  110 + public ResponseEntity<String> playStop(@PathVariable String deviceId, @PathVariable String channelId) {
110 111
111 - cmder.streamByeCmd(ssrc); 112 + cmder.streamByeCmd(deviceId, channelId);
112 113
113 if (logger.isDebugEnabled()) { 114 if (logger.isDebugEnabled()) {
114 - logger.debug(String.format("设备录像回放停止 API调用,ssrc:%s", ssrc)); 115 + logger.debug(String.format("设备录像回放停止 API调用,deviceId/channelId:%s/%s", deviceId, channelId));
115 } 116 }
116 117
117 - if (ssrc != null) { 118 + if (deviceId != null && channelId != null) {
118 JSONObject json = new JSONObject(); 119 JSONObject json = new JSONObject();
119 - json.put("ssrc", ssrc); 120 + json.put("deviceId", deviceId);
  121 + json.put("channelId", channelId);
120 return new ResponseEntity<String>(json.toString(), HttpStatus.OK); 122 return new ResponseEntity<String>(json.toString(), HttpStatus.OK);
121 } else { 123 } else {
122 logger.warn("设备录像回放停止API调用失败!"); 124 logger.warn("设备录像回放停止API调用失败!");
src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java
@@ -163,7 +163,7 @@ public class ApiStreamController { @@ -163,7 +163,7 @@ public class ApiStreamController {
163 result.put("error","未找到流信息"); 163 result.put("error","未找到流信息");
164 return result; 164 return result;
165 } 165 }
166 - cmder.streamByeCmd(streamInfo.getStreamId()); 166 + cmder.streamByeCmd(serial, code);
167 redisCatchStorage.stopPlay(streamInfo); 167 redisCatchStorage.stopPlay(streamInfo);
168 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); 168 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
169 return null; 169 return null;
src/main/resources/application.yml
1 spring: 1 spring:
2 profiles: 2 profiles:
3 - active: dev  
4 \ No newline at end of file 3 \ No newline at end of file
  4 + active: local
5 \ No newline at end of file 5 \ No newline at end of file
web_src/src/components/channelList.vue
@@ -216,12 +216,12 @@ export default { @@ -216,12 +216,12 @@ export default {
216 var that = this; 216 var that = this;
217 this.$axios({ 217 this.$axios({
218 method: 'get', 218 method: 'get',
219 - url: '/api/play/stop/' + itemData.streamId 219 + url: '/api/play/stop/' + this.deviceId + "/" + itemData.channelId
220 }).then(function (res) { 220 }).then(function (res) {
221 console.log(JSON.stringify(res)); 221 console.log(JSON.stringify(res));
222 that.initData(); 222 that.initData();
223 }).catch(function (error) { 223 }).catch(function (error) {
224 - if (error.response.status == 402) { // 已经停止过 224 + if (error.response.status === 402) { // 已经停止过
225 that.initData(); 225 that.initData();
226 }else { 226 }else {
227 console.log(error) 227 console.log(error)
@@ -253,7 +253,7 @@ export default { @@ -253,7 +253,7 @@ export default {
253 253
254 this.$axios({ 254 this.$axios({
255 method: 'get', 255 method: 'get',
256 - url:`/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`, 256 + url:`/api/device/query/sub_channels/${this.deviceId}/${this.parentChannelId}/channels`,
257 params: { 257 params: {
258 page: that.currentPage, 258 page: that.currentPage,
259 count: that.count, 259 count: that.count,
web_src/src/components/dialog/devicePlayer.vue
@@ -415,7 +415,7 @@ export default { @@ -415,7 +415,7 @@ export default {
415 this.videoUrl = ''; 415 this.videoUrl = '';
416 this.$axios({ 416 this.$axios({
417 method: 'get', 417 method: 'get',
418 - url: '/api/playback/stop/' + this.streamId 418 + url: '/api/playback/stop/' + this.deviceId + "/" + this.channelId
419 }).then(function (res) { 419 }).then(function (res) {
420 if (callback) callback() 420 if (callback) callback()
421 }); 421 });