Commit e94b99d11c46246532edc93cd25cbf8c0b88f03f
1 parent
10f77667
实现国标录像级联播放,优化点播流程,加快点播速度
Showing
19 changed files
with
209 additions
and
101 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java
| @@ -71,6 +71,16 @@ public class SendRtpItem { | @@ -71,6 +71,16 @@ public class SendRtpItem { | ||
| 71 | */ | 71 | */ |
| 72 | private String mediaServerId; | 72 | private String mediaServerId; |
| 73 | 73 | ||
| 74 | + /** | ||
| 75 | + * invite的callId | ||
| 76 | + */ | ||
| 77 | + private String CallId; | ||
| 78 | + | ||
| 79 | + /** | ||
| 80 | + * 是否是play, false是playback | ||
| 81 | + */ | ||
| 82 | + private boolean isPlay; | ||
| 83 | + | ||
| 74 | public String getIp() { | 84 | public String getIp() { |
| 75 | return ip; | 85 | return ip; |
| 76 | } | 86 | } |
| @@ -174,4 +184,20 @@ public class SendRtpItem { | @@ -174,4 +184,20 @@ public class SendRtpItem { | ||
| 174 | public void setMediaServerId(String mediaServerId) { | 184 | public void setMediaServerId(String mediaServerId) { |
| 175 | this.mediaServerId = mediaServerId; | 185 | this.mediaServerId = mediaServerId; |
| 176 | } | 186 | } |
| 187 | + | ||
| 188 | + public String getCallId() { | ||
| 189 | + return CallId; | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + public void setCallId(String callId) { | ||
| 193 | + CallId = callId; | ||
| 194 | + } | ||
| 195 | + | ||
| 196 | + public boolean isPlay() { | ||
| 197 | + return isPlay; | ||
| 198 | + } | ||
| 199 | + | ||
| 200 | + public void setPlay(boolean play) { | ||
| 201 | + isPlay = play; | ||
| 202 | + } | ||
| 177 | } | 203 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/session/SsrcConfig.java
| @@ -81,7 +81,6 @@ public class SsrcConfig { | @@ -81,7 +81,6 @@ public class SsrcConfig { | ||
| 81 | isUsed.remove(sn); | 81 | isUsed.remove(sn); |
| 82 | notUsed.add(sn); | 82 | notUsed.add(sn); |
| 83 | }catch (NullPointerException e){ | 83 | }catch (NullPointerException e){ |
| 84 | - System.out.printf("11111"); | ||
| 85 | } | 84 | } |
| 86 | } | 85 | } |
| 87 | 86 |
src/main/java/com/genersoft/iot/vmp/gb28181/task/GPSSubscribeTask.java
| @@ -36,7 +36,6 @@ public class GPSSubscribeTask implements Runnable{ | @@ -36,7 +36,6 @@ public class GPSSubscribeTask implements Runnable{ | ||
| 36 | 36 | ||
| 37 | SubscribeInfo subscribe = redisCatchStorage.getSubscribe(key); | 37 | SubscribeInfo subscribe = redisCatchStorage.getSubscribe(key); |
| 38 | if (subscribe != null) { | 38 | if (subscribe != null) { |
| 39 | - System.out.println("发送GPS消息"); | ||
| 40 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); | 39 | ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(platformId); |
| 41 | if (parentPlatform == null || parentPlatform.isStatus()) { | 40 | if (parentPlatform == null || parentPlatform.isStatus()) { |
| 42 | // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 | 41 | // TODO 暂时只处理视频流的回复,后续增加对国标设备的支持 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorObserver.java
| @@ -141,7 +141,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { | @@ -141,7 +141,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { | ||
| 141 | */ | 141 | */ |
| 142 | @Override | 142 | @Override |
| 143 | public void processTimeout(TimeoutEvent timeoutEvent) { | 143 | public void processTimeout(TimeoutEvent timeoutEvent) { |
| 144 | - System.out.println("processTimeout"); | ||
| 145 | if(timeoutProcessor != null) { | 144 | if(timeoutProcessor != null) { |
| 146 | timeoutProcessor.process(timeoutEvent); | 145 | timeoutProcessor.process(timeoutEvent); |
| 147 | } | 146 | } |
| @@ -173,7 +172,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { | @@ -173,7 +172,6 @@ public class SIPProcessorObserver implements ISIPProcessorObserver { | ||
| 173 | 172 | ||
| 174 | @Override | 173 | @Override |
| 175 | public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { | 174 | public void processDialogTerminated(DialogTerminatedEvent dialogTerminatedEvent) { |
| 176 | - System.out.println("processDialogTerminated"); | ||
| 177 | CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId(); | 175 | CallIdHeader callId = dialogTerminatedEvent.getDialog().getCallId(); |
| 178 | } | 176 | } |
| 179 | 177 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
| @@ -346,8 +346,11 @@ public class SIPCommander implements ISIPCommander { | @@ -346,8 +346,11 @@ public class SIPCommander implements ISIPCommander { | ||
| 346 | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, | 346 | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, |
| 347 | (MediaServerItem mediaServerItemInUse, JSONObject json)->{ | 347 | (MediaServerItem mediaServerItemInUse, JSONObject json)->{ |
| 348 | if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return; | 348 | if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return; |
| 349 | - event.response(mediaServerItemInUse, json); | ||
| 350 | - subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); | 349 | + if (event != null) { |
| 350 | + event.response(mediaServerItemInUse, json); | ||
| 351 | + } | ||
| 352 | + | ||
| 353 | +// subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); | ||
| 351 | }); | 354 | }); |
| 352 | // | 355 | // |
| 353 | StringBuffer content = new StringBuffer(200); | 356 | StringBuffer content = new StringBuffer(200); |
| @@ -452,9 +455,11 @@ public class SIPCommander implements ISIPCommander { | @@ -452,9 +455,11 @@ public class SIPCommander implements ISIPCommander { | ||
| 452 | logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); | 455 | logger.debug("录像回放添加订阅,订阅内容:" + subscribeKey.toString()); |
| 453 | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, | 456 | subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, |
| 454 | (MediaServerItem mediaServerItemInUse, JSONObject json)->{ | 457 | (MediaServerItem mediaServerItemInUse, JSONObject json)->{ |
| 458 | + System.out.println(344444); | ||
| 455 | if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return; | 459 | if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return; |
| 456 | - event.response(mediaServerItemInUse, json); | ||
| 457 | - subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); | 460 | + if (event != null) { |
| 461 | + event.response(mediaServerItemInUse, json); | ||
| 462 | + } | ||
| 458 | }); | 463 | }); |
| 459 | 464 | ||
| 460 | StringBuffer content = new StringBuffer(200); | 465 | StringBuffer content = new StringBuffer(200); |
| @@ -466,8 +471,6 @@ public class SIPCommander implements ISIPCommander { | @@ -466,8 +471,6 @@ public class SIPCommander implements ISIPCommander { | ||
| 466 | content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" " | 471 | content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" " |
| 467 | +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n"); | 472 | +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n"); |
| 468 | 473 | ||
| 469 | - | ||
| 470 | - | ||
| 471 | String streamMode = device.getStreamMode().toUpperCase(); | 474 | String streamMode = device.getStreamMode().toUpperCase(); |
| 472 | 475 | ||
| 473 | if (userSetup.isSeniorSdp()) { | 476 | if (userSetup.isSeniorSdp()) { |
| @@ -1202,7 +1205,6 @@ public class SIPCommander implements ISIPCommander { | @@ -1202,7 +1205,6 @@ public class SIPCommander implements ISIPCommander { | ||
| 1202 | if (type == null) { | 1205 | if (type == null) { |
| 1203 | type = "all"; | 1206 | type = "all"; |
| 1204 | } | 1207 | } |
| 1205 | - | ||
| 1206 | try { | 1208 | try { |
| 1207 | StringBuffer recordInfoXml = new StringBuffer(200); | 1209 | StringBuffer recordInfoXml = new StringBuffer(200); |
| 1208 | recordInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); | 1210 | recordInfoXml.append("<?xml version=\"1.0\" encoding=\"GB2312\"?>\r\n"); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java
| @@ -508,9 +508,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | @@ -508,9 +508,6 @@ public class SIPCommanderFroPlatform implements ISIPCommanderForPlatform { | ||
| 508 | // callid | 508 | // callid |
| 509 | CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() | 509 | CallIdHeader callIdHeader = parentPlatform.getTransport().equals("TCP") ? tcpSipProvider.getNewCallId() |
| 510 | : udpSipProvider.getNewCallId(); | 510 | : udpSipProvider.getNewCallId(); |
| 511 | - System.out.println( | ||
| 512 | - recordXml.toString() | ||
| 513 | - ); | ||
| 514 | Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, callIdHeader); | 511 | Request request = headerProviderPlarformProvider.createMessageRequest(parentPlatform, recordXml.toString(), fromTag, callIdHeader); |
| 515 | transmitRequest(parentPlatform, request); | 512 | transmitRequest(parentPlatform, request); |
| 516 | 513 |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | ||
| 3 | +import com.alibaba.fastjson.JSON; | ||
| 4 | +import com.alibaba.fastjson.JSONObject; | ||
| 3 | import com.genersoft.iot.vmp.common.StreamInfo; | 5 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | 6 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| 5 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 7 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 6 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; | 8 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 7 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 9 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 10 | +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; | ||
| 8 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 11 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 9 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 12 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 10 | import com.genersoft.iot.vmp.service.IMediaServerService; | 13 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| @@ -24,6 +27,8 @@ import javax.sip.header.HeaderAddress; | @@ -24,6 +27,8 @@ import javax.sip.header.HeaderAddress; | ||
| 24 | import javax.sip.header.ToHeader; | 27 | import javax.sip.header.ToHeader; |
| 25 | import java.util.HashMap; | 28 | import java.util.HashMap; |
| 26 | import java.util.Map; | 29 | import java.util.Map; |
| 30 | +import java.util.Timer; | ||
| 31 | +import java.util.TimerTask; | ||
| 27 | 32 | ||
| 28 | /** | 33 | /** |
| 29 | * SIP命令类型: ACK请求 | 34 | * SIP命令类型: ACK请求 |
| @@ -52,6 +57,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -52,6 +57,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 52 | @Autowired | 57 | @Autowired |
| 53 | private IMediaServerService mediaServerService; | 58 | private IMediaServerService mediaServerService; |
| 54 | 59 | ||
| 60 | + @Autowired | ||
| 61 | + private ZLMHttpHookSubscribe subscribe; | ||
| 62 | + | ||
| 55 | 63 | ||
| 56 | /** | 64 | /** |
| 57 | * 处理 ACK请求 | 65 | * 处理 ACK请求 |
| @@ -60,6 +68,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -60,6 +68,7 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 60 | */ | 68 | */ |
| 61 | @Override | 69 | @Override |
| 62 | public void process(RequestEvent evt) { | 70 | public void process(RequestEvent evt) { |
| 71 | + logger.debug("ACK请求: {}", ((System.currentTimeMillis()))); | ||
| 63 | Dialog dialog = evt.getDialog(); | 72 | Dialog dialog = evt.getDialog(); |
| 64 | if (dialog == null) return; | 73 | if (dialog == null) return; |
| 65 | if (dialog.getState()== DialogState.CONFIRMED) { | 74 | if (dialog.getState()== DialogState.CONFIRMED) { |
| @@ -69,16 +78,17 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -69,16 +78,17 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 69 | String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; | 78 | String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; |
| 70 | String deviceId = sendRtpItem.getDeviceId(); | 79 | String deviceId = sendRtpItem.getDeviceId(); |
| 71 | StreamInfo streamInfo = null; | 80 | StreamInfo streamInfo = null; |
| 72 | - if (deviceId == null) { | 81 | + if (sendRtpItem.isPlay()) { |
| 82 | + streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); | ||
| 83 | + }else { | ||
| 84 | + streamInfo = redisCatchStorage.queryPlaybackByDevice(deviceId, channelId); | ||
| 85 | + } | ||
| 86 | + System.out.println(JSON.toJSON(streamInfo)); | ||
| 87 | + if (streamInfo == null) { | ||
| 73 | streamInfo = new StreamInfo(); | 88 | streamInfo = new StreamInfo(); |
| 74 | streamInfo.setApp(sendRtpItem.getApp()); | 89 | streamInfo.setApp(sendRtpItem.getApp()); |
| 75 | streamInfo.setStreamId(sendRtpItem.getStreamId()); | 90 | streamInfo.setStreamId(sendRtpItem.getStreamId()); |
| 76 | - }else { | ||
| 77 | - streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); | ||
| 78 | - sendRtpItem.setStreamId(streamInfo.getStreamId()); | ||
| 79 | - streamInfo.setApp("rtp"); | ||
| 80 | } | 91 | } |
| 81 | - | ||
| 82 | redisCatchStorage.updateSendRTPSever(sendRtpItem); | 92 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 83 | logger.info(platformGbId); | 93 | logger.info(platformGbId); |
| 84 | logger.info(channelId); | 94 | logger.info(channelId); |
| @@ -90,34 +100,42 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -90,34 +100,42 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 90 | param.put("dst_url",sendRtpItem.getIp()); | 100 | param.put("dst_url",sendRtpItem.getIp()); |
| 91 | param.put("dst_port", sendRtpItem.getPort()); | 101 | param.put("dst_port", sendRtpItem.getPort()); |
| 92 | param.put("is_udp", is_Udp); | 102 | param.put("is_udp", is_Udp); |
| 93 | - //param.put ("src_port", sendRtpItem.getLocalPort()); | ||
| 94 | // 设备推流查询,成功后才能转推 | 103 | // 设备推流查询,成功后才能转推 |
| 95 | - boolean rtpPushed = false; | ||
| 96 | - long startTime = System.currentTimeMillis(); | ||
| 97 | - while (!rtpPushed) { | ||
| 98 | - try { | ||
| 99 | - if (System.currentTimeMillis() - startTime < 30 * 1000) { | ||
| 100 | - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | ||
| 101 | - if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { | ||
| 102 | - rtpPushed = true; | ||
| 103 | - logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]", | ||
| 104 | - streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); | ||
| 105 | - zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | ||
| 106 | - } else { | ||
| 107 | - logger.info("等待设备推流[{}/{}].......", | ||
| 108 | - streamInfo.getApp() ,streamInfo.getStreamId()); | ||
| 109 | - Thread.sleep(1000); | ||
| 110 | - continue; | ||
| 111 | - } | ||
| 112 | - } else { | ||
| 113 | - rtpPushed = true; | ||
| 114 | - logger.info("设备推流[{}/{}]超时,终止向上级推流", | ||
| 115 | - streamInfo.getApp() ,streamInfo.getStreamId()); | ||
| 116 | - } | ||
| 117 | - } catch (InterruptedException e) { | ||
| 118 | - e.printStackTrace(); | ||
| 119 | - } | ||
| 120 | - } | 104 | + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 105 | + zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | ||
| 106 | +// if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { | ||
| 107 | +// logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]", | ||
| 108 | +// streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); | ||
| 109 | +// zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | ||
| 110 | +// } else { | ||
| 111 | +// // 对hook进行订阅 | ||
| 112 | +// logger.info("等待设备推流[{}/{}].......", | ||
| 113 | +// streamInfo.getApp(), streamInfo.getStreamId()); | ||
| 114 | +// Timer timer = new Timer(); | ||
| 115 | +// timer.schedule(new TimerTask() { | ||
| 116 | +// @Override | ||
| 117 | +// public void run() { | ||
| 118 | +// logger.info("设备推流[{}/{}]超时,终止向上级推流", | ||
| 119 | +// finalStreamInfo.getApp() , finalStreamInfo.getStreamId()); | ||
| 120 | +// | ||
| 121 | +// } | ||
| 122 | +// }, 30*1000L); | ||
| 123 | +// // 添加订阅 | ||
| 124 | +// JSONObject subscribeKey = new JSONObject(); | ||
| 125 | +// subscribeKey.put("app", "rtp"); | ||
| 126 | +// subscribeKey.put("stream", streamInfo.getStreamId()); | ||
| 127 | +// subscribeKey.put("mediaServerId", streamInfo.getMediaServerId()); | ||
| 128 | +// subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, subscribeKey, | ||
| 129 | +// (MediaServerItem mediaServerItemInUse, JSONObject json) -> { | ||
| 130 | +// logger.info("已获取设备推流[{}/{}],开始向上级推流[{}:{}]", | ||
| 131 | +// finalStreamInfo.getApp(), finalStreamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); | ||
| 132 | +// timer.cancel(); | ||
| 133 | +// zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); | ||
| 134 | +// subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); | ||
| 135 | +// }); | ||
| 136 | +// } | ||
| 137 | + | ||
| 138 | + | ||
| 121 | } | 139 | } |
| 122 | } | 140 | } |
| 123 | } | 141 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
| @@ -87,18 +87,29 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -87,18 +87,29 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 87 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 87 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 88 | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); | 88 | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); |
| 89 | redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); | 89 | redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); |
| 90 | - if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) { | 90 | + int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); |
| 91 | + if (totalReaderCount == 0) { | ||
| 91 | logger.info(streamId + "无其它观看者,通知设备停止推流"); | 92 | logger.info(streamId + "无其它观看者,通知设备停止推流"); |
| 92 | cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); | 93 | cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); |
| 94 | + }else if (totalReaderCount == -1){ | ||
| 95 | + logger.warn(streamId + " 查找其它观看者失败"); | ||
| 93 | } | 96 | } |
| 94 | } | 97 | } |
| 95 | // 可能是设备主动停止 | 98 | // 可能是设备主动停止 |
| 96 | Device device = storager.queryVideoDeviceByChannelId(platformGbId); | 99 | Device device = storager.queryVideoDeviceByChannelId(platformGbId); |
| 97 | if (device != null) { | 100 | if (device != null) { |
| 98 | - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); | ||
| 99 | - if (streamInfo != null) { | ||
| 100 | - redisCatchStorage.stopPlay(streamInfo); | 101 | + if (sendRtpItem.isPlay()) { |
| 102 | + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); | ||
| 103 | + if (streamInfo != null) { | ||
| 104 | + redisCatchStorage.stopPlay(streamInfo); | ||
| 105 | + } | ||
| 106 | + }else { | ||
| 107 | + StreamInfo streamInfo = redisCatchStorage.queryPlaybackByDevice(device.getDeviceId(), channelId); | ||
| 108 | + if (streamInfo != null) { | ||
| 109 | + redisCatchStorage.stopPlayback(streamInfo); | ||
| 110 | + } | ||
| 101 | } | 111 | } |
| 112 | + | ||
| 102 | storager.stopPlay(device.getDeviceId(), channelId); | 113 | storager.stopPlay(device.getDeviceId(), channelId); |
| 103 | mediaServerService.closeRTPServer(device, channelId); | 114 | mediaServerService.closeRTPServer(device, channelId); |
| 104 | } | 115 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java
| 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | 1 | package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; |
| 2 | 2 | ||
| 3 | +import com.alibaba.fastjson.JSON; | ||
| 4 | +import com.alibaba.fastjson.JSONObject; | ||
| 5 | +import com.genersoft.iot.vmp.common.StreamInfo; | ||
| 3 | import com.genersoft.iot.vmp.gb28181.bean.*; | 6 | import com.genersoft.iot.vmp.gb28181.bean.*; |
| 7 | +import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | ||
| 4 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 8 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 9 | +import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; | ||
| 10 | +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | ||
| 5 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; | 11 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; |
| 6 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; | 12 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; |
| 7 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; | 13 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; |
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; | 14 | import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; |
| 15 | +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; | ||
| 9 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | 16 | import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; |
| 10 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 17 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 11 | import com.genersoft.iot.vmp.service.IMediaServerService; | 18 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 12 | import com.genersoft.iot.vmp.service.IPlayService; | 19 | import com.genersoft.iot.vmp.service.IPlayService; |
| 20 | +import com.genersoft.iot.vmp.service.bean.SSRCInfo; | ||
| 13 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 21 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 14 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | 22 | import com.genersoft.iot.vmp.storager.IVideoManagerStorager; |
| 15 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; | 23 | import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; |
| 24 | +import gov.nist.javax.sdp.TimeDescriptionImpl; | ||
| 25 | +import gov.nist.javax.sdp.fields.TimeField; | ||
| 16 | import gov.nist.javax.sip.address.AddressImpl; | 26 | import gov.nist.javax.sip.address.AddressImpl; |
| 17 | import gov.nist.javax.sip.address.SipUri; | 27 | import gov.nist.javax.sip.address.SipUri; |
| 18 | import org.slf4j.Logger; | 28 | import org.slf4j.Logger; |
| @@ -27,10 +37,13 @@ import javax.sip.RequestEvent; | @@ -27,10 +37,13 @@ import javax.sip.RequestEvent; | ||
| 27 | import javax.sip.ServerTransaction; | 37 | import javax.sip.ServerTransaction; |
| 28 | import javax.sip.SipException; | 38 | import javax.sip.SipException; |
| 29 | import javax.sip.address.SipURI; | 39 | import javax.sip.address.SipURI; |
| 40 | +import javax.sip.header.CallIdHeader; | ||
| 30 | import javax.sip.header.FromHeader; | 41 | import javax.sip.header.FromHeader; |
| 31 | import javax.sip.message.Request; | 42 | import javax.sip.message.Request; |
| 32 | import javax.sip.message.Response; | 43 | import javax.sip.message.Response; |
| 33 | import java.text.ParseException; | 44 | import java.text.ParseException; |
| 45 | +import java.text.SimpleDateFormat; | ||
| 46 | +import java.util.Date; | ||
| 34 | import java.util.List; | 47 | import java.util.List; |
| 35 | import java.util.Vector; | 48 | import java.util.Vector; |
| 36 | 49 | ||
| @@ -61,6 +74,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -61,6 +74,9 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 61 | private IPlayService playService; | 74 | private IPlayService playService; |
| 62 | 75 | ||
| 63 | @Autowired | 76 | @Autowired |
| 77 | + private ISIPCommander commander; | ||
| 78 | + | ||
| 79 | + @Autowired | ||
| 64 | private ZLMRTPServerFactory zlmrtpServerFactory; | 80 | private ZLMRTPServerFactory zlmrtpServerFactory; |
| 65 | 81 | ||
| 66 | @Autowired | 82 | @Autowired |
| @@ -69,6 +85,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -69,6 +85,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 69 | @Autowired | 85 | @Autowired |
| 70 | private SIPProcessorObserver sipProcessorObserver; | 86 | private SIPProcessorObserver sipProcessorObserver; |
| 71 | 87 | ||
| 88 | + | ||
| 72 | @Override | 89 | @Override |
| 73 | public void afterPropertiesSet() throws Exception { | 90 | public void afterPropertiesSet() throws Exception { |
| 74 | // 添加消息处理的订阅 | 91 | // 添加消息处理的订阅 |
| @@ -84,6 +101,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -84,6 +101,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 84 | @Override | 101 | @Override |
| 85 | public void process(RequestEvent evt) { | 102 | public void process(RequestEvent evt) { |
| 86 | // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令 | 103 | // Invite Request消息实现,此消息一般为级联消息,上级给下级发送请求视频指令 |
| 104 | + Long startTimeForInvite = System.currentTimeMillis(); | ||
| 87 | try { | 105 | try { |
| 88 | Request request = evt.getRequest(); | 106 | Request request = evt.getRequest(); |
| 89 | SipURI sipURI = (SipURI) request.getRequestURI(); | 107 | SipURI sipURI = (SipURI) request.getRequestURI(); |
| @@ -91,6 +109,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -91,6 +109,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 91 | String requesterId = null; | 109 | String requesterId = null; |
| 92 | 110 | ||
| 93 | FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); | 111 | FromHeader fromHeader = (FromHeader)request.getHeader(FromHeader.NAME); |
| 112 | + CallIdHeader callIdHeader = (CallIdHeader)request.getHeader(CallIdHeader.NAME); | ||
| 94 | AddressImpl address = (AddressImpl) fromHeader.getAddress(); | 113 | AddressImpl address = (AddressImpl) fromHeader.getAddress(); |
| 95 | SipUri uri = (SipUri) address.getURI(); | 114 | SipUri uri = (SipUri) address.getURI(); |
| 96 | requesterId = uri.getUser(); | 115 | requesterId = uri.getUser(); |
| @@ -101,7 +120,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -101,7 +120,7 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 101 | return; | 120 | return; |
| 102 | } | 121 | } |
| 103 | 122 | ||
| 104 | - // 查询请求方是否上级平台 | 123 | + // 查询请求是否来自上级平台\设备 |
| 105 | ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); | 124 | ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); |
| 106 | if (platform != null) { | 125 | if (platform != null) { |
| 107 | // 查询平台下是否有该通道 | 126 | // 查询平台下是否有该通道 |
| @@ -158,7 +177,21 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -158,7 +177,21 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 158 | ssrc = ssrcDefault; | 177 | ssrc = ssrcDefault; |
| 159 | sdp = SdpFactory.getInstance().createSessionDescription(contentString); | 178 | sdp = SdpFactory.getInstance().createSessionDescription(contentString); |
| 160 | } | 179 | } |
| 161 | - | 180 | + String sessionName = sdp.getSessionName().getValue(); |
| 181 | + | ||
| 182 | + Long startTime = null; | ||
| 183 | + Long stopTime = null; | ||
| 184 | + Date start = null; | ||
| 185 | + Date end = null; | ||
| 186 | + if (sdp.getTimeDescriptions(false) != null && sdp.getTimeDescriptions(false).size() > 0) { | ||
| 187 | + TimeDescriptionImpl timeDescription = (TimeDescriptionImpl)(sdp.getTimeDescriptions(false).get(0)); | ||
| 188 | + TimeField startTimeFiled = (TimeField)timeDescription.getTime(); | ||
| 189 | + startTime = startTimeFiled.getStartTime(); | ||
| 190 | + stopTime = startTimeFiled.getStopTime(); | ||
| 191 | + | ||
| 192 | + start = new Date(startTime*1000); | ||
| 193 | + end = new Date(stopTime*1000); | ||
| 194 | + } | ||
| 162 | // 获取支持的格式 | 195 | // 获取支持的格式 |
| 163 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); | 196 | Vector mediaDescriptions = sdp.getMediaDescriptions(true); |
| 164 | // 查看是否支持PS 负载96 | 197 | // 查看是否支持PS 负载96 |
| @@ -228,23 +261,31 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -228,23 +261,31 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 228 | responseAck(evt, Response.BUSY_HERE); | 261 | responseAck(evt, Response.BUSY_HERE); |
| 229 | return; | 262 | return; |
| 230 | } | 263 | } |
| 231 | - | 264 | + sendRtpItem.setCallId(callIdHeader.getCallId()); |
| 265 | + sendRtpItem.setPlay("Play".equals(sessionName)); | ||
| 232 | // 写入redis, 超时时回复 | 266 | // 写入redis, 超时时回复 |
| 233 | redisCatchStorage.updateSendRTPSever(sendRtpItem); | 267 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 234 | - // 通知下级推流, | ||
| 235 | - PlayResult playResult = playService.play(mediaServerItem,device.getDeviceId(), channelId, (mediaServerItemInUSe, responseJSON)->{ | ||
| 236 | - // 收到推流, 回复200OK, 等待ack | 268 | + |
| 269 | + Device finalDevice = device; | ||
| 270 | + MediaServerItem finalMediaServerItem = mediaServerItem; | ||
| 271 | + Long finalStartTime = startTime; | ||
| 272 | + Long finalStopTime = stopTime; | ||
| 273 | + ZLMHttpHookSubscribe.Event hookEvent = (mediaServerItemInUSe, responseJSON)->{ | ||
| 274 | + logger.info("[上级点播]收到下级开始点播订阅, {}/{}", sendRtpItem.getApp(), sendRtpItem.getStreamId()); | ||
| 237 | // if (sendRtpItem == null) return; | 275 | // if (sendRtpItem == null) return; |
| 238 | sendRtpItem.setStatus(1); | 276 | sendRtpItem.setStatus(1); |
| 239 | redisCatchStorage.updateSendRTPSever(sendRtpItem); | 277 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 240 | - // TODO 添加对tcp的支持 | ||
| 241 | 278 | ||
| 242 | StringBuffer content = new StringBuffer(200); | 279 | StringBuffer content = new StringBuffer(200); |
| 243 | content.append("v=0\r\n"); | 280 | content.append("v=0\r\n"); |
| 244 | content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); | 281 | content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); |
| 245 | - content.append("s=Play\r\n"); | 282 | + content.append("s=" + sessionName+"\r\n"); |
| 246 | content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); | 283 | content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); |
| 247 | - content.append("t=0 0\r\n"); | 284 | + if ("Playback".equals(sessionName)) { |
| 285 | + content.append("t=" + finalStartTime + " " + finalStopTime + "\r\n"); | ||
| 286 | + }else { | ||
| 287 | + content.append("t=0 0\r\n"); | ||
| 288 | + } | ||
| 248 | content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); | 289 | content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); |
| 249 | content.append("a=sendonly\r\n"); | 290 | content.append("a=sendonly\r\n"); |
| 250 | content.append("a=rtpmap:96 PS/90000\r\n"); | 291 | content.append("a=rtpmap:96 PS/90000\r\n"); |
| @@ -260,7 +301,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -260,7 +301,11 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 260 | } catch (ParseException e) { | 301 | } catch (ParseException e) { |
| 261 | e.printStackTrace(); | 302 | e.printStackTrace(); |
| 262 | } | 303 | } |
| 263 | - } ,((event) -> { | 304 | + if ("Playback".equals(sessionName) && responseJSON != null) { |
| 305 | + playService.onPublishHandlerForPlayBack(finalMediaServerItem, responseJSON, finalDevice.getDeviceId(), channelId, null); | ||
| 306 | + } | ||
| 307 | + }; | ||
| 308 | + SipSubscribe.Event errorEvent = ((event) -> { | ||
| 264 | // 未知错误。直接转发设备点播的错误 | 309 | // 未知错误。直接转发设备点播的错误 |
| 265 | Response response = null; | 310 | Response response = null; |
| 266 | try { | 311 | try { |
| @@ -271,11 +316,27 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -271,11 +316,27 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 271 | } catch (ParseException | SipException | InvalidArgumentException e) { | 316 | } catch (ParseException | SipException | InvalidArgumentException e) { |
| 272 | e.printStackTrace(); | 317 | e.printStackTrace(); |
| 273 | } | 318 | } |
| 274 | - })); | ||
| 275 | - if (logger.isDebugEnabled()) { | ||
| 276 | - logger.debug(playResult.getResult().toString()); | 319 | + }); |
| 320 | + if ("Playback".equals(sessionName)) { | ||
| 321 | + sendRtpItem.setPlay(false); | ||
| 322 | + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, sendRtpItem.getSsrc(), true); | ||
| 323 | + sendRtpItem.setStreamId(ssrc); | ||
| 324 | + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | ||
| 325 | + commander.playbackStreamCmd(mediaServerItem, ssrcInfo, device, channelId, format.format(start), format.format(end), hookEvent, errorEvent); | ||
| 326 | + }else { | ||
| 327 | + sendRtpItem.setPlay(true); | ||
| 328 | + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); | ||
| 329 | + if (streamInfo == null) { | ||
| 330 | + if (mediaServerItem.isRtpEnable()) { | ||
| 331 | + sendRtpItem.setStreamId(String.format("%s_%s", device.getDeviceId(), channelId)); | ||
| 332 | + } | ||
| 333 | + sendRtpItem.setPlay(false); | ||
| 334 | + playService.play(mediaServerItem,device.getDeviceId(), channelId, hookEvent,errorEvent); | ||
| 335 | + }else { | ||
| 336 | + sendRtpItem.setStreamId(streamInfo.getStreamId()); | ||
| 337 | + hookEvent.response(mediaServerItem, null); | ||
| 338 | + } | ||
| 277 | } | 339 | } |
| 278 | - | ||
| 279 | }else if (gbStream != null) { | 340 | }else if (gbStream != null) { |
| 280 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, | 341 | SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, |
| 281 | gbStream.getApp(), gbStream.getStream(), channelId, | 342 | gbStream.getApp(), gbStream.getStream(), channelId, |
| @@ -295,7 +356,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | @@ -295,7 +356,6 @@ public class InviteRequestProcessor extends SIPRequestProcessorParent implements | ||
| 295 | 356 | ||
| 296 | sendRtpItem.setStatus(1); | 357 | sendRtpItem.setStatus(1); |
| 297 | redisCatchStorage.updateSendRTPSever(sendRtpItem); | 358 | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| 298 | - // TODO 添加对tcp的支持 | ||
| 299 | StringBuffer content = new StringBuffer(200); | 359 | StringBuffer content = new StringBuffer(200); |
| 300 | content.append("v=0\r\n"); | 360 | content.append("v=0\r\n"); |
| 301 | content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); | 361 | content.append("o="+ channelId +" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/response/impl/InviteResponseProcessor.java
| @@ -82,9 +82,6 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { | @@ -82,9 +82,6 @@ public class InviteResponseProcessor extends SIPResponseProcessorAbstract { | ||
| 82 | requestURI.setPort(event.getRemotePort()); | 82 | requestURI.setPort(event.getRemotePort()); |
| 83 | reqAck.setRequestURI(requestURI); | 83 | reqAck.setRequestURI(requestURI); |
| 84 | logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack"); | 84 | logger.info("向 " + event.getRemoteIpAddress() + ":" + event.getRemotePort() + "回复ack"); |
| 85 | - SipURI sipURI = (SipURI)dialog.getRemoteParty().getURI(); | ||
| 86 | - String deviceId = requestURI.getUser(); | ||
| 87 | - String channelId = sipURI.getUser(); | ||
| 88 | 85 | ||
| 89 | dialog.sendAck(reqAck); | 86 | dialog.sendAck(reqAck); |
| 90 | 87 |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| @@ -181,7 +181,7 @@ public class ZLMHttpHookListener { | @@ -181,7 +181,7 @@ public class ZLMHttpHookListener { | ||
| 181 | @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8") | 181 | @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8") |
| 182 | public ResponseEntity<String> onPublish(@RequestBody JSONObject json) { | 182 | public ResponseEntity<String> onPublish(@RequestBody JSONObject json) { |
| 183 | 183 | ||
| 184 | - logger.debug("[ ZLM HOOK ]on_publish API调用,参数:" + json.toString()); | 184 | + logger.info("[ ZLM HOOK ]on_publish API调用,参数:" + json.toString()); |
| 185 | JSONObject ret = new JSONObject(); | 185 | JSONObject ret = new JSONObject(); |
| 186 | ret.put("code", 0); | 186 | ret.put("code", 0); |
| 187 | ret.put("msg", "success"); | 187 | ret.put("msg", "success"); |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java
| @@ -77,21 +77,23 @@ public class ZLMHttpHookSubscribe { | @@ -77,21 +77,23 @@ public class ZLMHttpHookSubscribe { | ||
| 77 | if (eventMap == null) { | 77 | if (eventMap == null) { |
| 78 | return; | 78 | return; |
| 79 | } | 79 | } |
| 80 | - Iterator<Map.Entry<JSONObject, Event>> iterator = eventMap.entrySet().iterator(); | ||
| 81 | - while (iterator.hasNext()){ | ||
| 82 | - Map.Entry<JSONObject, Event> next = iterator.next(); | ||
| 83 | - JSONObject key = next.getKey(); | ||
| 84 | - Boolean result = null; | ||
| 85 | - for (String s : key.keySet()) { | ||
| 86 | - if (result == null) { | ||
| 87 | - result = key.getString(s).equals(hookResponse.getString(s)); | ||
| 88 | - }else { | ||
| 89 | - if (key.getString(s) == null) continue; | ||
| 90 | - result = result && key.getString(s).equals(hookResponse.getString(s)); | 80 | + |
| 81 | + Set<Map.Entry<JSONObject, Event>> entries = eventMap.entrySet(); | ||
| 82 | + if (entries.size() > 0) { | ||
| 83 | + for (Map.Entry<JSONObject, Event> entry : entries) { | ||
| 84 | + JSONObject key = entry.getKey(); | ||
| 85 | + Boolean result = null; | ||
| 86 | + for (String s : key.keySet()) { | ||
| 87 | + if (result == null) { | ||
| 88 | + result = key.getString(s).equals(hookResponse.getString(s)); | ||
| 89 | + }else { | ||
| 90 | + if (key.getString(s) == null) continue; | ||
| 91 | + result = result && key.getString(s).equals(hookResponse.getString(s)); | ||
| 92 | + } | ||
| 93 | + } | ||
| 94 | + if (null != result && result){ | ||
| 95 | + entries.remove(entry); | ||
| 91 | } | 96 | } |
| 92 | - } | ||
| 93 | - if (null != result && result){ | ||
| 94 | - iterator.remove(); | ||
| 95 | } | 97 | } |
| 96 | } | 98 | } |
| 97 | } | 99 | } |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java
| @@ -72,7 +72,6 @@ public class ZLMRESTfulUtils { | @@ -72,7 +72,6 @@ public class ZLMRESTfulUtils { | ||
| 72 | ResponseBody responseBody = response.body(); | 72 | ResponseBody responseBody = response.body(); |
| 73 | if (responseBody != null) { | 73 | if (responseBody != null) { |
| 74 | String responseStr = responseBody.string(); | 74 | String responseStr = responseBody.string(); |
| 75 | - System.out.println(responseStr); | ||
| 76 | responseJSON = JSON.parseObject(responseStr); | 75 | responseJSON = JSON.parseObject(responseStr); |
| 77 | } | 76 | } |
| 78 | }else { | 77 | }else { |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java
| @@ -242,9 +242,18 @@ public class ZLMRTPServerFactory { | @@ -242,9 +242,18 @@ public class ZLMRTPServerFactory { | ||
| 242 | */ | 242 | */ |
| 243 | public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) { | 243 | public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) { |
| 244 | JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); | 244 | JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); |
| 245 | + Integer code = mediaInfo.getInteger("code"); | ||
| 245 | if (mediaInfo == null) { | 246 | if (mediaInfo == null) { |
| 246 | return 0; | 247 | return 0; |
| 247 | } | 248 | } |
| 249 | + if ( code < 0) { | ||
| 250 | + logger.warn("查询流({}/{})是否有其它观看者时得到: {}", app, streamId, mediaInfo.getString("msg")); | ||
| 251 | + return -1; | ||
| 252 | + } | ||
| 253 | + if ( code == 0 && ! mediaInfo.getBoolean("online")) { | ||
| 254 | + logger.warn("查询流({}/{})是否有其它观看者时得到: {}", app, streamId, mediaInfo.getString("msg")); | ||
| 255 | + return -1; | ||
| 256 | + } | ||
| 248 | return mediaInfo.getInteger("totalReaderCount"); | 257 | return mediaInfo.getInteger("totalReaderCount"); |
| 249 | } | 258 | } |
| 250 | 259 |
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
| @@ -122,7 +122,6 @@ public class PlayServiceImpl implements IPlayService { | @@ -122,7 +122,6 @@ public class PlayServiceImpl implements IPlayService { | ||
| 122 | // 点播结束时调用截图接口 | 122 | // 点播结束时调用截图接口 |
| 123 | try { | 123 | try { |
| 124 | String classPath = ResourceUtils.getURL("classpath:").getPath(); | 124 | String classPath = ResourceUtils.getURL("classpath:").getPath(); |
| 125 | - // System.out.println(classPath); | ||
| 126 | // 兼容打包为jar的class路径 | 125 | // 兼容打包为jar的class路径 |
| 127 | if(classPath.contains("jar")) { | 126 | if(classPath.contains("jar")) { |
| 128 | classPath = classPath.substring(0, classPath.lastIndexOf(".")); | 127 | classPath = classPath.substring(0, classPath.lastIndexOf(".")); |
| @@ -238,11 +237,11 @@ public class PlayServiceImpl implements IPlayService { | @@ -238,11 +237,11 @@ public class PlayServiceImpl implements IPlayService { | ||
| 238 | } | 237 | } |
| 239 | 238 | ||
| 240 | @Override | 239 | @Override |
| 241 | - public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { | 240 | + public void onPublishHandlerForPlay(MediaServerItem mediaServerItem, JSONObject response, String deviceId, String channelId, String uuid) { |
| 242 | RequestMessage msg = new RequestMessage(); | 241 | RequestMessage msg = new RequestMessage(); |
| 243 | msg.setId(uuid); | 242 | msg.setId(uuid); |
| 244 | msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId); | 243 | msg.setKey(DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId); |
| 245 | - StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); | 244 | + StreamInfo streamInfo = onPublishHandler(mediaServerItem, response, deviceId, channelId, uuid); |
| 246 | if (streamInfo != null) { | 245 | if (streamInfo != null) { |
| 247 | DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); | 246 | DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); |
| 248 | if (deviceChannel != null) { | 247 | if (deviceChannel != null) { |
src/main/java/com/genersoft/iot/vmp/storager/dao/ParentPlatformMapper.java
| @@ -88,7 +88,7 @@ public interface ParentPlatformMapper { | @@ -88,7 +88,7 @@ public interface ParentPlatformMapper { | ||
| 88 | "</script>"}) | 88 | "</script>"}) |
| 89 | int setDefaultCatalog(String platformId, String catalogId); | 89 | int setDefaultCatalog(String platformId, String catalogId); |
| 90 | 90 | ||
| 91 | - @Select("select 'channel' as name, count(pgc.platformId) count from platform_gb_channel pgc where pgc.platformId=#{platformId} and pgc.channelId =#{gbId} " + | 91 | + @Select("select 'channel' as name, count(pgc.platformId) count from platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId where pgc.platformId=#{platformId} and dc.channelId =#{gbId} " + |
| 92 | "union " + | 92 | "union " + |
| 93 | "select 'stream' as name, count(pgs.platformId) count from platform_gb_stream pgs left join gb_stream gs on pgs.gbStreamId = gs.gbStreamId where pgs.platformId=#{platformId} and gs.gbId = #{gbId}") | 93 | "select 'stream' as name, count(pgs.platformId) count from platform_gb_stream pgs left join gb_stream gs on pgs.gbStreamId = gs.gbStreamId where pgs.platformId=#{platformId} and gs.gbId = #{gbId}") |
| 94 | List<ChannelSourceInfo> getChannelSource(String platformId, String gbId); | 94 | List<ChannelSourceInfo> getChannelSource(String platformId, String gbId); |
src/main/java/com/genersoft/iot/vmp/storager/dao/PlatformChannelMapper.java
| @@ -52,8 +52,8 @@ public interface PlatformChannelMapper { | @@ -52,8 +52,8 @@ public interface PlatformChannelMapper { | ||
| 52 | int cleanChannelForGB(String platformId); | 52 | int cleanChannelForGB(String platformId); |
| 53 | 53 | ||
| 54 | 54 | ||
| 55 | - @Select("SELECT * FROM device_channel WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE " + | ||
| 56 | - "platformId='${platformId}' AND channelId='${channelId}' ) AND channelId='${channelId}'") | 55 | + @Select("SELECT dc.* FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE " + |
| 56 | + "pgc.platformId=#{platformId} AND dc.channelId=#{channelId}") | ||
| 57 | DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); | 57 | DeviceChannel queryChannelInParentPlatform(String platformId, String channelId); |
| 58 | 58 | ||
| 59 | 59 | ||
| @@ -62,7 +62,7 @@ public interface PlatformChannelMapper { | @@ -62,7 +62,7 @@ public interface PlatformChannelMapper { | ||
| 62 | "where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") | 62 | "where pgc.platformId=#{platformId} and pgc.catalogId=#{catalogId}") |
| 63 | List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId); | 63 | List<PlatformCatalog> queryChannelInParentPlatformAndCatalog(String platformId, String catalogId); |
| 64 | 64 | ||
| 65 | - @Select("SELECT * FROM device WHERE deviceId = (SELECT deviceId FROM platform_gb_channel WHERE platformId='${platformId}' AND channelId='${channelId}')") | 65 | + @Select("SELECT * FROM device WHERE deviceId = (SELECT deviceId FROM platform_gb_channel pgc left join device_channel dc on dc.id = pgc.deviceChannelId WHERE pgc.platformId='${platformId}' AND dc.channelId='${channelId}')") |
| 66 | Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId); | 66 | Device queryVideoDeviceByPlatformIdAndChannelId(String platformId, String channelId); |
| 67 | 67 | ||
| 68 | @Delete("<script> "+ | 68 | @Delete("<script> "+ |
| @@ -71,7 +71,7 @@ public interface PlatformChannelMapper { | @@ -71,7 +71,7 @@ public interface PlatformChannelMapper { | ||
| 71 | int delByCatalogId(String id); | 71 | int delByCatalogId(String id); |
| 72 | 72 | ||
| 73 | @Delete("<script> "+ | 73 | @Delete("<script> "+ |
| 74 | - "DELETE FROM platform_gb_channel WHERE catalogId=#{parentId} AND platformId=#{platformId} AND channelId=#{id}" + | 74 | + "DELETE FROM platform_gb_channel WHERE catalogId=#{parentId} AND platformId=#{platformId} AND channelId=#{id}" + |
| 75 | "</script>") | 75 | "</script>") |
| 76 | int delByCatalogIdAndChannelIdAndPlatformId(PlatformCatalog platformCatalog); | 76 | int delByCatalogIdAndChannelIdAndPlatformId(PlatformCatalog platformCatalog); |
| 77 | 77 |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| @@ -139,7 +139,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -139,7 +139,6 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 139 | 139 | ||
| 140 | @Override | 140 | @Override |
| 141 | public StreamInfo queryPlayByDevice(String deviceId, String channelId) { | 141 | public StreamInfo queryPlayByDevice(String deviceId, String channelId) { |
| 142 | -// List<Object> playLeys = redis.keys(String.format("%S_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, | ||
| 143 | List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, | 142 | List<Object> playLeys = redis.scan(String.format("%S_%s_*_%s_%s", VideoManagerConstants.PLAYER_PREFIX, |
| 144 | userSetup.getServerId(), | 143 | userSetup.getServerId(), |
| 145 | deviceId, | 144 | deviceId, |
src/test/java/com/genersoft/iot/vmp/service/impl/DeviceAlarmServiceImplTest.java
| @@ -50,14 +50,7 @@ class DeviceAlarmServiceImplTest { | @@ -50,14 +50,7 @@ class DeviceAlarmServiceImplTest { | ||
| 50 | // System.out.println(deviceAlarmService.getAllAlarm(0, 10000, "11111111111111111111", null, "1", null, | 50 | // System.out.println(deviceAlarmService.getAllAlarm(0, 10000, "11111111111111111111", null, "1", null, |
| 51 | // null, null).getSize()); | 51 | // null, null).getSize()); |
| 52 | 52 | ||
| 53 | - System.out.println(deviceAlarmService.getAllAlarm(0, 10000, "11111111111111111111", null, null, null, | ||
| 54 | - "2021-01-01 00:00:00", null).getSize()); | ||
| 55 | 53 | ||
| 56 | - System.out.println(deviceAlarmService.getAllAlarm(0, 10000, "11111111111111111111", null, null, null, | ||
| 57 | - null, "2021-04-01 09:00:00").getSize()); | ||
| 58 | - | ||
| 59 | - System.out.println(deviceAlarmService.getAllAlarm(0, 10000, "11111111111111111111", null, null, null, | ||
| 60 | - "2021-02-01 01:00:00", "2021-04-01 04:00:00").getSize()); | ||
| 61 | } | 54 | } |
| 62 | 55 | ||
| 63 | 56 |