Commit 54568adfdd460164eba5c703f15b2d68b7971cd4

Authored by 648540858
1 parent 3bf2e6ee

优化录像下载逻辑以及录像查询逻辑

src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java
... ... @@ -27,6 +27,7 @@ public class VideoManagerConstants {
27 27 public static final String PLAYER_PREFIX = "VMP_PLAYER_";
28 28  
29 29 public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_";
  30 + public static final String DOWNLOAD_PREFIX = "VMP_DOWNLOAD_";
30 31  
31 32 public static final String PLATFORM_KEEPLIVEKEY_PREFIX = "VMP_PLATFORM_KEEPLIVE_";
32 33  
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/bean/RecordInfo.java
... ... @@ -16,6 +16,8 @@ public class RecordInfo {
16 16  
17 17 private String channelId;
18 18  
  19 + private String sn;
  20 +
19 21 private String name;
20 22  
21 23 private int sumNum;
... ... @@ -61,4 +63,12 @@ public class RecordInfo {
61 63 public void setChannelId(String channelId) {
62 64 this.channelId = channelId;
63 65 }
  66 +
  67 + public String getSn() {
  68 + return sn;
  69 + }
  70 +
  71 + public void setSn(String sn) {
  72 + this.sn = sn;
  73 + }
64 74 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/CheckForAllRecordsThread.java
... ... @@ -53,7 +53,7 @@ public class CheckForAllRecordsThread extends Thread {
53 53 // 自然顺序排序, 元素进行升序排列
54 54 this.recordInfo.getRecordList().sort(Comparator.naturalOrder());
55 55 RequestMessage msg = new RequestMessage();
56   - msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getChannelId());
  56 + msg.setKey(DeferredResultHolder.CALLBACK_CMD_RECORDINFO + recordInfo.getDeviceId() + recordInfo.getSn());
57 57 msg.setData(recordInfo);
58 58 deferredResultHolder.invokeAllResult(msg);
59 59 logger.info("处理完成,返回结果");
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/callback/DeferredResultHolder.java
... ... @@ -35,6 +35,10 @@ public class DeferredResultHolder {
35 35  
36 36 public static final String CALLBACK_CMD_PLAY = "CALLBACK_PLAY";
37 37  
  38 + public static final String CALLBACK_CMD_PLAYBACK = "CALLBACK_PLAY";
  39 +
  40 + public static final String CALLBACK_CMD_DOWNLOAD = "CALLBACK_DOWNLOAD";
  41 +
38 42 public static final String CALLBACK_CMD_STOP = "CALLBACK_STOP";
39 43  
40 44 public static final String CALLBACK_CMD_MOBILEPOSITION = "CALLBACK_MOBILEPOSITION";
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java
... ... @@ -256,8 +256,9 @@ public interface ISIPCommander {
256 256 * @param device 视频设备
257 257 * @param startTime 开始时间,格式要求:yyyy-MM-dd HH:mm:ss
258 258 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
  259 + * @param sn
259 260 */
260   - boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, SipSubscribe.Event errorEvent);
  261 + boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, SipSubscribe.Event errorEvent);
261 262  
262 263 /**
263 264 * 查询报警信息
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
... ... @@ -1196,14 +1196,15 @@ public class SIPCommander implements ISIPCommander {
1196 1196 * @param endTime 结束时间,格式要求:yyyy-MM-dd HH:mm:ss
1197 1197 */
1198 1198 @Override
1199   - public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, SipSubscribe.Event errorEvent) {
1200   -
  1199 + public boolean recordInfoQuery(Device device, String channelId, String startTime, String endTime, int sn, SipSubscribe.Event errorEvent) {
  1200 +
  1201 +
1201 1202 try {
1202 1203 StringBuffer recordInfoXml = new StringBuffer(200);
1203 1204 recordInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n");
1204 1205 recordInfoXml.append("<Query>\r\n");
1205 1206 recordInfoXml.append("<CmdType>RecordInfo</CmdType>\r\n");
1206   - recordInfoXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n");
  1207 + recordInfoXml.append("<SN>" + sn + "</SN>\r\n");
1207 1208 recordInfoXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n");
1208 1209 recordInfoXml.append("<StartTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(startTime) + "</StartTime>\r\n");
1209 1210 recordInfoXml.append("<EndTime>" + DateUtil.yyyy_MM_dd_HH_mm_ssToISO8601(endTime) + "</EndTime>\r\n");
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/MessageRequestProcessor1.java
... ... @@ -914,21 +914,20 @@ public class MessageRequestProcessor1 extends SIPRequestProcessorParent implemen
914 914 String uuid = UUID.randomUUID().toString().replace("-", "");
915 915 RecordInfo recordInfo = new RecordInfo();
916 916 Element rootElement = getRootElement(evt);
917   - Element deviceIdElement = rootElement.element("DeviceID");
918   - String channelId = deviceIdElement.getText().toString();
919   - String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId;
  917 + String sn = getText(rootElement, "SN");
  918 + String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
920 919 if (device != null ) {
921 920 rootElement = getRootElement(evt, device.getCharset());
922 921 }
923 922 recordInfo.setDeviceId(deviceId);
924   - recordInfo.setChannelId(channelId);
  923 + recordInfo.setSn(sn);
925 924 recordInfo.setName(getText(rootElement, "Name"));
926 925 if (getText(rootElement, "SumNum")== null || getText(rootElement, "SumNum") =="") {
927 926 recordInfo.setSumNum(0);
928 927 } else {
929 928 recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum")));
930 929 }
931   - String sn = getText(rootElement, "SN");
  930 +
932 931 Element recordListElement = rootElement.element("RecordList");
933 932 if (recordListElement == null || recordInfo.getSumNum() == 0) {
934 933 logger.info("无录像数据");
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/response/cmd/RecordInfoResponseMessageHandler.java
... ... @@ -64,18 +64,16 @@ public class RecordInfoResponseMessageHandler extends SIPRequestProcessorParent
64 64 rootElement = getRootElement(evt, device.getCharset());
65 65 String uuid = UUID.randomUUID().toString().replace("-", "");
66 66 RecordInfo recordInfo = new RecordInfo();
67   - Element deviceIdElement = rootElement.element("DeviceID");
68   - String channelId = deviceIdElement.getText();
69   - String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + device.getDeviceId() + channelId;
  67 + String sn = getText(rootElement, "SN");
  68 + String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + device.getDeviceId() + sn;
70 69 recordInfo.setDeviceId(device.getDeviceId());
71   - recordInfo.setChannelId(channelId);
  70 + recordInfo.setSn(sn);
72 71 recordInfo.setName(getText(rootElement, "Name"));
73 72 if (getText(rootElement, "SumNum") == null || getText(rootElement, "SumNum") == "") {
74 73 recordInfo.setSumNum(0);
75 74 } else {
76 75 recordInfo.setSumNum(Integer.parseInt(getText(rootElement, "SumNum")));
77 76 }
78   - String sn = getText(rootElement, "SN");
79 77 Element recordListElement = rootElement.element("RecordList");
80 78 if (recordListElement == null || recordInfo.getSumNum() == 0) {
81 79 logger.info("无录像数据");
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -358,14 +358,13 @@ public class ZLMHttpHookListener {
358 358 String mediaServerId = json.getString("mediaServerId");
359 359 String streamId = json.getString("stream");
360 360 String app = json.getString("app");
361   -
362   - // TODO 如果在给上级推流,也不停止。
  361 + JSONObject ret = new JSONObject();
  362 + ret.put("code", 0);
363 363 if ("rtp".equals(app)){
364   - JSONObject ret = new JSONObject();
365   - ret.put("code", 0);
366 364 ret.put("close", true);
367 365 StreamInfo streamInfoForPlayCatch = redisCatchStorage.queryPlayByStreamId(streamId);
368 366 if (streamInfoForPlayCatch != null) {
  367 + // 如果在给上级推流,也不停止。
369 368 if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
370 369 ret.put("close", false);
371 370 } else {
... ... @@ -378,6 +377,12 @@ public class ZLMHttpHookListener {
378 377 if (streamInfoForPlayBackCatch != null) {
379 378 cmder.streamByeCmd(streamInfoForPlayBackCatch.getDeviceID(), streamInfoForPlayBackCatch.getChannelId());
380 379 redisCatchStorage.stopPlayback(streamInfoForPlayBackCatch);
  380 + }else {
  381 + StreamInfo streamInfoForDownload = redisCatchStorage.queryDownloadByStreamId(streamId);
  382 + // 进行录像下载时无人观看不断流
  383 + if (streamInfoForDownload != null) {
  384 + ret.put("close", false);
  385 + }
381 386 }
382 387 }
383 388 MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId);
... ... @@ -386,8 +391,6 @@ public class ZLMHttpHookListener {
386 391 }
387 392 return new ResponseEntity<String>(ret.toString(),HttpStatus.OK);
388 393 }else {
389   - JSONObject ret = new JSONObject();
390   - ret.put("code", 0);
391 394 StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, streamId);
392 395 if (streamProxyItem != null && streamProxyItem.isEnable_remove_none_reader()) {
393 396 ret.put("close", true);
... ...
src/main/java/com/genersoft/iot/vmp/service/IPlayService.java
... ... @@ -18,4 +18,6 @@ public interface IPlayService {
18 18 PlayResult play(MediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent);
19 19  
20 20 MediaServerItem getNewMediaServerItem(Device device);
  21 +
  22 + void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String toString);
21 23 }
... ...
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
... ... @@ -34,11 +34,6 @@ import org.springframework.stereotype.Service;
34 34 import org.springframework.util.ResourceUtils;
35 35 import org.springframework.web.context.request.async.DeferredResult;
36 36  
37   -import javax.sip.DialogTerminatedEvent;
38   -import javax.sip.ResponseEvent;
39   -import javax.sip.TimeoutEvent;
40   -import javax.sip.TransactionTerminatedEvent;
41   -import javax.sip.message.Response;
42 37 import java.io.FileNotFoundException;
43 38 import java.util.Objects;
44 39 import java.util.UUID;
... ... @@ -286,10 +281,11 @@ public class PlayServiceImpl implements IPlayService {
286 281 return mediaServerItem;
287 282 }
288 283  
  284 +
289 285 @Override
290 286 public void onPublishHandlerForPlayBack(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
291 287 RequestMessage msg = new RequestMessage();
292   - msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId);
  288 + msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId);
293 289 msg.setId(uuid);
294 290 StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid);
295 291 if (streamInfo != null) {
... ... @@ -297,12 +293,31 @@ public class PlayServiceImpl implements IPlayService {
297 293 msg.setData(JSON.toJSONString(streamInfo));
298 294 resultHolder.invokeResult(msg);
299 295 } else {
  296 + logger.warn("设备回放API调用失败!");
  297 + msg.setData("设备回放API调用失败!");
  298 + resultHolder.invokeResult(msg);
  299 + }
  300 + }
  301 +
  302 +
  303 + @Override
  304 + public void onPublishHandlerForDownload(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) {
  305 + RequestMessage msg = new RequestMessage();
  306 + msg.setKey(DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId);
  307 + msg.setId(uuid);
  308 + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid);
  309 + if (streamInfo != null) {
  310 + redisCatchStorage.startDownload(streamInfo);
  311 + msg.setData(JSON.toJSONString(streamInfo));
  312 + resultHolder.invokeResult(msg);
  313 + } else {
300 314 logger.warn("设备预览API调用失败!");
301 315 msg.setData("设备预览API调用失败!");
302 316 resultHolder.invokeResult(msg);
303 317 }
304 318 }
305 319  
  320 +
306 321 public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) {
307 322 String streamId = resonse.getString("stream");
308 323 JSONArray tracks = resonse.getJSONArray("tracks");
... ...
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
... ... @@ -144,4 +144,12 @@ public interface IRedisCatchStorage {
144 144 * @param streamId
145 145 */
146 146 void removePushStream(MediaServerItem mediaServerItem, String app, String streamId);
  147 +
  148 + /**
  149 + * 开始下载录像时存入
  150 + * @param streamInfo
  151 + */
  152 + boolean startDownload(StreamInfo streamInfo);
  153 +
  154 + StreamInfo queryDownloadByStreamId(String streamId);
147 155 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -64,15 +64,15 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
64 64 streamInfo.getChannelId()));
65 65 }
66 66 @Override
67   - public StreamInfo queryPlayByStreamId(String steamId) {
68   - List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, steamId));
  67 + public StreamInfo queryPlayByStreamId(String streamId) {
  68 + List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAYER_PREFIX, streamId));
69 69 if (playLeys == null || playLeys.size() == 0) return null;
70 70 return (StreamInfo)redis.get(playLeys.get(0).toString());
71 71 }
72 72  
73 73 @Override
74   - public StreamInfo queryPlaybackByStreamId(String steamId) {
75   - List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, steamId));
  74 + public StreamInfo queryPlaybackByStreamId(String streamId) {
  75 + List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.PLAY_BLACK_PREFIX, streamId));
76 76 if (playLeys == null || playLeys.size() == 0) return null;
77 77 return (StreamInfo)redis.get(playLeys.get(0).toString());
78 78 }
... ... @@ -104,10 +104,15 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
104 104  
105 105 @Override
106 106 public boolean startPlayback(StreamInfo stream) {
107   - return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getStreamId(),stream.getDeviceID(), stream.getChannelId()),
108   - stream);
  107 + return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.PLAY_BLACK_PREFIX, stream.getStreamId(),
  108 + stream.getDeviceID(), stream.getChannelId()), stream);
109 109 }
110 110  
  111 + @Override
  112 + public boolean startDownload(StreamInfo streamInfo) {
  113 + return redis.set(String.format("%S_%s_%s_%s", VideoManagerConstants.DOWNLOAD_PREFIX, streamInfo.getStreamId(),
  114 + streamInfo.getDeviceID(), streamInfo.getChannelId()), streamInfo);
  115 + }
111 116  
112 117 @Override
113 118 public boolean stopPlayback(StreamInfo streamInfo) {
... ... @@ -318,4 +323,11 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
318 323 String key = VideoManagerConstants.WVP_SERVER_STREAM_PUSH_PREFIX + app + "_" + streamId + "_" + mediaServerItem.getId();
319 324 redis.del(key);
320 325 }
  326 +
  327 + @Override
  328 + public StreamInfo queryDownloadByStreamId(String streamId) {
  329 + List<Object> playLeys = redis.scan(String.format("%S_%s_*", VideoManagerConstants.DOWNLOAD_PREFIX, streamId));
  330 + if (playLeys == null || playLeys.size() == 0) return null;
  331 + return (StreamInfo)redis.get(playLeys.get(0).toString());
  332 + }
321 333 }
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/DownloadController.java
... ... @@ -76,7 +76,7 @@ public class DownloadController {
76 76 if (logger.isDebugEnabled()) {
77 77 logger.debug(String.format("历史媒体下载 API调用,deviceId:%s,channelId:%s,downloadSpeed:%s", deviceId, channelId, downloadSpeed));
78 78 }
79   - String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
  79 + String key = DeferredResultHolder.CALLBACK_CMD_DOWNLOAD + deviceId + channelId;
80 80 String uuid = UUID.randomUUID().toString();
81 81 DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
82 82 // 超时处理
... ... @@ -114,7 +114,7 @@ public class DownloadController {
114 114  
115 115 cmder.downloadStreamCmd(newMediaServerItem, ssrcInfo, device, channelId, startTime, endTime, downloadSpeed, (MediaServerItem mediaServerItem, JSONObject response) -> {
116 116 logger.info("收到订阅消息: " + response.toJSONString());
117   - playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString());
  117 + playService.onPublishHandlerForDownload(mediaServerItem, response, deviceId, channelId, uuid.toString());
118 118 }, event -> {
119 119 RequestMessage msg = new RequestMessage();
120 120 msg.setId(uuid);
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java
... ... @@ -78,7 +78,7 @@ public class PlaybackController {
78 78 logger.debug(String.format("设备回放 API调用,deviceId:%s ,channelId:%s", deviceId, channelId));
79 79 }
80 80 String uuid = UUID.randomUUID().toString();
81   - String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId;
  81 + String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId;
82 82 DeferredResult<ResponseEntity<String>> result = new DeferredResult<ResponseEntity<String>>(30000L);
83 83 Device device = storager.queryVideoDevice(deviceId);
84 84 if (device == null) {
... ...
src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/record/GBRecordController.java
... ... @@ -59,11 +59,12 @@ public class GBRecordController {
59 59 // 指定超时时间 1分钟30秒
60 60 DeferredResult<ResponseEntity<RecordInfo>> result = new DeferredResult<>(90*1000L);
61 61 String uuid = UUID.randomUUID().toString();
62   - String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + channelId;
  62 + int sn = (int)((Math.random()*9+1)*100000);
  63 + String key = DeferredResultHolder.CALLBACK_CMD_RECORDINFO + deviceId + sn;
63 64 RequestMessage msg = new RequestMessage();
64 65 msg.setId(uuid);
65 66 msg.setKey(key);
66   - cmder.recordInfoQuery(device, channelId, startTime, endTime, (eventResult -> {
  67 + cmder.recordInfoQuery(device, channelId, startTime, endTime, sn, (eventResult -> {
67 68 msg.setData("查询录像失败, status: " + eventResult.statusCode + ", message: " + eventResult.msg );
68 69 resultHolder.invokeResult(msg);
69 70 }));
... ...