Commit a4f48a15223400a580a61df92a17d6e2309406cf

Authored by 648540858
1 parent 386b4819

修复回看控制失效 #619

src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java
... ... @@ -39,6 +39,8 @@ public class StreamInfo {
39 39 private String endTime;
40 40 private double progress;
41 41  
  42 + private boolean pause;
  43 +
42 44 public static class TransactionInfo{
43 45 public String callId;
44 46 public String localTag;
... ... @@ -312,4 +314,12 @@ public class StreamInfo {
312 314 public void setRtcs(String rtcs) {
313 315 this.rtcs = rtcs;
314 316 }
  317 +
  318 + public boolean isPause() {
  319 + return pause;
  320 + }
  321 +
  322 + public void setPause(boolean pause) {
  323 + this.pause = pause;
  324 + }
315 325 }
... ...
src/main/java/com/genersoft/iot/vmp/conf/exception/ServiceException.java 0 → 100644
  1 +package com.genersoft.iot.vmp.conf.exception;
  2 +
  3 +/**
  4 + * @author lin
  5 + */
  6 +public class ServiceException extends Exception{
  7 + private String msg;
  8 +
  9 +
  10 +
  11 + public ServiceException(String msg) {
  12 + this.msg = msg;
  13 + }
  14 +
  15 + public String getMsg() {
  16 + return msg;
  17 + }
  18 +
  19 + public void setMsg(String msg) {
  20 + this.msg = msg;
  21 + }
  22 +
  23 + @Override
  24 + public String getMessage() {
  25 + return msg;
  26 + }
  27 +}
... ...
src/main/java/com/genersoft/iot/vmp/conf/exception/SsrcTransactionNotFoundException.java
... ... @@ -39,12 +39,12 @@ public class SsrcTransactionNotFoundException extends Exception{
39 39 @Override
40 40 public String getMessage() {
41 41 StringBuffer msg = new StringBuffer();
42   - msg.append(StringFormatter.format("缓存事务信息未找到,device:%s channel: %s ", deviceId, channelId));
  42 + msg.append(String.format("缓存事务信息未找到,device:%s channel: %s ", deviceId, channelId));
43 43 if (callId != null) {
44   - msg.append("callId: " + callId);
  44 + msg.append(",callId: " + callId);
45 45 }
46 46 if (stream != null) {
47   - msg.append("stream: " + stream);
  47 + msg.append(",stream: " + stream);
48 48 }
49 49 return msg.toString();
50 50 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -129,6 +129,7 @@ public interface ISIPCommander {
129 129 * 视频流停止
130 130 */
131 131 void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException;
  132 +
132 133 void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException;
133 134  
134 135 /**
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -521,10 +521,15 @@ public class ZLMHttpHookListener {
521 521 if (sendRtpItem.getApp().equals(app)) {
522 522 String platformId = sendRtpItem.getPlatformId();
523 523 ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId);
  524 + Device device = deviceService.queryDevice(platformId);
524 525  
525 526 try {
526   - commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
527   - } catch (SipException | InvalidArgumentException | ParseException e) {
  527 + if (platform != null) {
  528 + commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
  529 + }else {
  530 + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), stream, sendRtpItem.getCallId());
  531 + }
  532 + } catch (SipException | InvalidArgumentException | ParseException | SsrcTransactionNotFoundException e) {
528 533 logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
529 534 }
530 535 }
... ... @@ -587,19 +592,24 @@ public class ZLMHttpHookListener {
587 592 storager.stopPlay(streamInfoForPlayCatch.getDeviceID(), streamInfoForPlayCatch.getChannelId());
588 593 }else{
589 594 StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, streamId, null);
590   - if (streamInfoForPlayBackCatch != null) {
591   - Device device = deviceService.queryDevice(streamInfoForPlayCatch.getDeviceID());
592   - if (device != null) {
593   - try {
594   - cmder.streamByeCmd(device,streamInfoForPlayBackCatch.getChannelId(),
595   - streamInfoForPlayBackCatch.getStream(), null);
596   - } catch (InvalidArgumentException | ParseException | SipException |
597   - SsrcTransactionNotFoundException e) {
598   - logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage());
  595 + if (streamInfoForPlayBackCatch != null ) {
  596 + if (streamInfoForPlayBackCatch.isPause()) {
  597 + ret.put("close", false);
  598 + }else {
  599 + Device device = deviceService.queryDevice(streamInfoForPlayBackCatch.getDeviceID());
  600 + if (device != null) {
  601 + try {
  602 + cmder.streamByeCmd(device,streamInfoForPlayBackCatch.getChannelId(),
  603 + streamInfoForPlayBackCatch.getStream(), null);
  604 + } catch (InvalidArgumentException | ParseException | SipException |
  605 + SsrcTransactionNotFoundException e) {
  606 + logger.error("[无人观看]回放, 发送BYE失败 {}", e.getMessage());
  607 + }
599 608 }
  609 + redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),
  610 + streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
600 611 }
601   - redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch.getDeviceID(),
602   - streamInfoForPlayBackCatch.getChannelId(), streamInfoForPlayBackCatch.getStream(), null);
  612 +
603 613 }else {
604 614 StreamInfo streamInfoForDownload = redisCatchStorage.queryDownload(null, null, streamId, null);
605 615 // 进行录像下载时无人观看不断流
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
... ... @@ -23,6 +23,9 @@ public class ZLMRESTfulUtils {
23 23  
24 24 private final static Logger logger = LoggerFactory.getLogger(ZLMRESTfulUtils.class);
25 25  
  26 +
  27 +
  28 +
26 29 public interface RequestCallback{
27 30 void run(JSONObject response);
28 31 }
... ... @@ -322,10 +325,22 @@ public class ZLMRESTfulUtils {
322 325 }
323 326  
324 327 public void getSnap(MediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) {
325   - Map<String, Object> param = new HashMap<>();
  328 + Map<String, Object> param = new HashMap<>(3);
326 329 param.put("url", flvUrl);
327 330 param.put("timeout_sec", timeout_sec);
328 331 param.put("expire_sec", expire_sec);
329 332 sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName);
330 333 }
  334 +
  335 + public JSONObject pauseRtpCheck(MediaServerItem mediaServerItem, String streamId) {
  336 + Map<String, Object> param = new HashMap<>(1);
  337 + param.put("stream_id", streamId);
  338 + return sendPost(mediaServerItem, "pauseRtpCheck",param, null);
  339 + }
  340 +
  341 + public JSONObject resumeRtpCheck(MediaServerItem mediaServerItem, String streamId) {
  342 + Map<String, Object> param = new HashMap<>(1);
  343 + param.put("stream_id", streamId);
  344 + return sendPost(mediaServerItem, "resumeRtpCheck",param, null);
  345 + }
331 346 }
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
... ... @@ -103,7 +103,6 @@ public class ZLMRTPServerFactory {
103 103 param.put("stream_id", streamId);
104 104 JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(mediaServerItem, param);
105 105 if (jsonObject != null ) {
106   - System.out.println(jsonObject);
107 106 if (jsonObject.getInteger("code") == 0) {
108 107 return createRTPServer(mediaServerItem, streamId, ssrc, port);
109 108 }else {
... ... @@ -150,7 +149,6 @@ public class ZLMRTPServerFactory {
150 149 param.put("stream_id", streamId);
151 150 JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(serverItem, param);
152 151 if (jsonObject != null ) {
153   - System.out.println(jsonObject);
154 152 if (jsonObject.getInteger("code") == 0) {
155 153 result = jsonObject.getInteger("hit") == 1;
156 154 }else {
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
... ... @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service;
2 2  
3 3 import com.alibaba.fastjson.JSONObject;
4 4 import com.genersoft.iot.vmp.common.StreamInfo;
  5 +import com.genersoft.iot.vmp.conf.exception.ServiceException;
5 6 import com.genersoft.iot.vmp.gb28181.bean.Device;
6 7 import com.genersoft.iot.vmp.gb28181.bean.InviteStreamCallback;
7 8 import com.genersoft.iot.vmp.gb28181.bean.InviteStreamInfo;
... ... @@ -15,6 +16,10 @@ import com.genersoft.iot.vmp.vmanager.bean.WVPResult;
15 16 import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult;
16 17 import org.springframework.web.context.request.async.DeferredResult;
17 18  
  19 +import javax.sip.InvalidArgumentException;
  20 +import javax.sip.SipException;
  21 +import java.text.ParseException;
  22 +
18 23 /**
19 24 * 点播处理
20 25 */
... ... @@ -42,4 +47,8 @@ public interface IPlayService {
42 47 StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream);
43 48  
44 49 void zlmServerOnline(String mediaServerId);
  50 +
  51 + void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
  52 +
  53 + void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException;
45 54 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -9,10 +9,13 @@ import javax.sip.InvalidArgumentException;
9 9 import javax.sip.ResponseEvent;
10 10 import javax.sip.SipException;
11 11  
  12 +import com.genersoft.iot.vmp.common.VideoManagerConstants;
12 13 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  14 +import com.genersoft.iot.vmp.conf.exception.ServiceException;
13 15 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
14 16 import com.genersoft.iot.vmp.gb28181.bean.*;
15 17 import com.genersoft.iot.vmp.service.IDeviceService;
  18 +import com.genersoft.iot.vmp.utils.redis.RedisUtil;
16 19 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
17 20 import org.slf4j.Logger;
18 21 import org.slf4j.LoggerFactory;
... ... @@ -822,4 +825,52 @@ public class PlayServiceImpl implements IPlayService {
822 825 // }
823 826 // }));
824 827 }
  828 +
  829 + @Override
  830 + public void pauseRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
  831 + String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null);
  832 + StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
  833 + if (null == streamInfo) {
  834 + logger.warn("streamId不存在!");
  835 + throw new ServiceException("streamId不存在");
  836 + }
  837 + streamInfo.setPause(true);
  838 + RedisUtil.set(key, streamInfo);
  839 + MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId());
  840 + if (null == mediaServerItem) {
  841 + logger.warn("mediaServer 不存在!");
  842 + throw new ServiceException("mediaServer不存在");
  843 + }
  844 + // zlm 暂停RTP超时检查
  845 + JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamId);
  846 + if (jsonObject == null || jsonObject.getInteger("code") != 0) {
  847 + throw new ServiceException("暂停RTP接收失败");
  848 + }
  849 + Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
  850 + cmder.playPauseCmd(device, streamInfo);
  851 + }
  852 +
  853 + @Override
  854 + public void resumeRtp(String streamId) throws ServiceException, InvalidArgumentException, ParseException, SipException {
  855 + String key = redisCatchStorage.queryPlaybackForKey(null, null, streamId, null);
  856 + StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
  857 + if (null == streamInfo) {
  858 + logger.warn("streamId不存在!");
  859 + throw new ServiceException("streamId不存在");
  860 + }
  861 + streamInfo.setPause(false);
  862 + RedisUtil.set(key, streamInfo);
  863 + MediaServerItem mediaServerItem = mediaServerService.getOne(streamInfo.getMediaServerId());
  864 + if (null == mediaServerItem) {
  865 + logger.warn("mediaServer 不存在!");
  866 + throw new ServiceException("mediaServer不存在");
  867 + }
  868 + // zlm 暂停RTP超时检查
  869 + JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamId);
  870 + if (jsonObject == null || jsonObject.getInteger("code") != 0) {
  871 + throw new ServiceException("继续RTP接收失败");
  872 + }
  873 + Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
  874 + cmder.playResumeCmd(device, streamInfo);
  875 + }
825 876 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
... ... @@ -56,6 +56,8 @@ public interface IRedisCatchStorage {
56 56  
57 57 StreamInfo queryPlayback(String deviceId, String channelID, String stream, String callId);
58 58  
  59 + String queryPlaybackForKey(String deviceId, String channelId, String stream, String callId);
  60 +
59 61 void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch);
60 62  
61 63 ParentPlatformCatch queryPlatformCatchInfo(String platformGbId);
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -9,7 +9,6 @@ import com.genersoft.iot.vmp.conf.UserSetting;
9 9 import com.genersoft.iot.vmp.gb28181.bean.*;
10 10 import com.genersoft.iot.vmp.media.zlm.dto.MediaItem;
11 11 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
12   -import com.genersoft.iot.vmp.media.zlm.dto.OnPublishHookParam;
13 12 import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo;
14 13 import com.genersoft.iot.vmp.service.bean.GPSMsgInfo;
15 14 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
... ... @@ -22,7 +21,6 @@ import com.genersoft.iot.vmp.utils.redis.RedisUtil;
22 21 import org.slf4j.Logger;
23 22 import org.slf4j.LoggerFactory;
24 23 import org.springframework.beans.factory.annotation.Autowired;
25   -import org.springframework.context.annotation.DependsOn;
26 24 import org.springframework.stereotype.Component;
27 25  
28 26 import java.util.*;
... ... @@ -127,6 +125,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
127 125 }
128 126 @Override
129 127 public StreamInfo queryPlayByStreamId(String streamId) {
  128 + System.out.println(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), streamId));
130 129 List<Object> playLeys = RedisUtil.scan(String.format("%S_%s_%s_*", VideoManagerConstants.PLAYER_PREFIX, userSetting.getServerId(), streamId));
131 130 if (playLeys == null || playLeys.size() == 0) {
132 131 return null;
... ... @@ -165,6 +164,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
165 164  
166 165 @Override
167 166 public boolean startPlayback(StreamInfo stream, String callId) {
  167 + System.out.println(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
  168 + userSetting.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId));
168 169 return RedisUtil.set(String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
169 170 userSetting.getServerId(), stream.getDeviceID(), stream.getChannelId(), stream.getStream(), callId), stream);
170 171 }
... ... @@ -286,6 +287,34 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
286 287 }
287 288  
288 289 @Override
  290 + public String queryPlaybackForKey(String deviceId, String channelId, String stream, String callId) {
  291 + if (stream == null && callId == null) {
  292 + return null;
  293 + }
  294 + if (deviceId == null) {
  295 + deviceId = "*";
  296 + }
  297 + if (channelId == null) {
  298 + channelId = "*";
  299 + }
  300 + if (stream == null) {
  301 + stream = "*";
  302 + }
  303 + if (callId == null) {
  304 + callId = "*";
  305 + }
  306 + String key = String.format("%S_%s_%s_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX,
  307 + userSetting.getServerId(),
  308 + deviceId,
  309 + channelId,
  310 + stream,
  311 + callId
  312 + );
  313 + List<Object> streamInfoScan = RedisUtil.scan(key);
  314 + return (String) streamInfoScan.get(0);
  315 + }
  316 +
  317 + @Override
289 318 public void updatePlatformCatchInfo(ParentPlatformCatch parentPlatformCatch) {
290 319 String key = VideoManagerConstants.PLATFORM_CATCH_PREFIX + userSetting.getServerId() + "_" + parentPlatformCatch.getId();
291 320 RedisUtil.set(key, parentPlatformCatch);
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
... ... @@ -2,9 +2,11 @@ package com.genersoft.iot.vmp.vmanager.gb28181.playback;
2 2  
3 3 import com.genersoft.iot.vmp.common.StreamInfo;
4 4 import com.genersoft.iot.vmp.conf.exception.ControllerException;
  5 +import com.genersoft.iot.vmp.conf.exception.ServiceException;
5 6 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
6 7 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
7 8 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
  9 +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
8 10 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
9 11 import com.genersoft.iot.vmp.service.IPlayService;
10 12 import com.genersoft.iot.vmp.vmanager.bean.ErrorCode;
... ... @@ -46,6 +48,9 @@ public class PlaybackController {
46 48 private SIPCommander cmder;
47 49  
48 50 @Autowired
  51 + private ZLMRTPServerFactory zlmrtpServerFactory;
  52 +
  53 + @Autowired
49 54 private IVideoManagerStorage storager;
50 55  
51 56 @Autowired
... ... @@ -113,14 +118,11 @@ public class PlaybackController {
113 118 @GetMapping("/pause/{streamId}")
114 119 public void playPause(@PathVariable String streamId) {
115 120 logger.info("playPause: "+streamId);
116   - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
117   - if (null == streamInfo) {
118   - logger.warn("streamId不存在!");
119   - throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
120   - }
121   - Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
  121 +
122 122 try {
123   - cmder.playPauseCmd(device, streamInfo);
  123 + playService.pauseRtp(streamId);
  124 + } catch (ServiceException e) {
  125 + throw new ControllerException(ErrorCode.ERROR400.getCode(), e.getMessage());
124 126 } catch (InvalidArgumentException | ParseException | SipException e) {
125 127 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
126 128 }
... ... @@ -132,14 +134,10 @@ public class PlaybackController {
132 134 @GetMapping("/resume/{streamId}")
133 135 public void playResume(@PathVariable String streamId) {
134 136 logger.info("playResume: "+streamId);
135   - StreamInfo streamInfo = redisCatchStorage.queryPlayback(null, null, streamId, null);
136   - if (null == streamInfo) {
137   - logger.warn("streamId不存在!");
138   - throw new ControllerException(ErrorCode.ERROR400.getCode(), "streamId不存在");
139   - }
140   - Device device = storager.queryVideoDevice(streamInfo.getDeviceID());
141 137 try {
142   - cmder.playResumeCmd(device, streamInfo);
  138 + playService.resumeRtp(streamId);
  139 + } catch (ServiceException e) {
  140 + throw new ControllerException(ErrorCode.ERROR400.getCode(), e.getMessage());
143 141 } catch (InvalidArgumentException | ParseException | SipException e) {
144 142 throw new ControllerException(ErrorCode.ERROR100.getCode(), e.getMessage());
145 143 }
... ...