Commit ab81136765f1b641223b982b2baef13e06307fe4
1 parent
9b1af8ef
优化适配zlm的hook保活
Showing
20 changed files
with
440 additions
and
78 deletions
src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java
| 1 | 1 | package com.genersoft.iot.vmp.gb28181; |
| 2 | 2 | |
| 3 | 3 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 4 | -import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; | |
| 5 | 4 | import com.genersoft.iot.vmp.gb28181.transmit.ISIPProcessorObserver; |
| 6 | -import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | |
| 7 | 5 | import gov.nist.javax.sip.SipProviderImpl; |
| 8 | 6 | import gov.nist.javax.sip.SipStackImpl; |
| 9 | 7 | import org.slf4j.Logger; | ... | ... |
src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java
| ... | ... | @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.event.offline.OfflineEvent; |
| 5 | 5 | import com.genersoft.iot.vmp.gb28181.event.platformKeepaliveExpire.PlatformKeepaliveExpireEvent; |
| 6 | 6 | import com.genersoft.iot.vmp.gb28181.event.platformNotRegister.PlatformNotRegisterEvent; |
| 7 | 7 | import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent; |
| 8 | +import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent; | |
| 8 | 9 | import org.springframework.beans.factory.annotation.Autowired; |
| 9 | 10 | import org.springframework.context.ApplicationEventPublisher; |
| 10 | 11 | import org.springframework.stereotype.Component; |
| ... | ... | @@ -73,5 +74,10 @@ public class EventPublisher { |
| 73 | 74 | outEvent.setMediaServerId(mediaServerId); |
| 74 | 75 | applicationEventPublisher.publishEvent(outEvent); |
| 75 | 76 | } |
| 76 | - | |
| 77 | + | |
| 78 | + public void zlmOnlineEventPublish(String mediaServerId) { | |
| 79 | + ZLMOnlineEvent outEvent = new ZLMOnlineEvent(this); | |
| 80 | + outEvent.setMediaServerId(mediaServerId); | |
| 81 | + applicationEventPublisher.publishEvent(outEvent); | |
| 82 | + } | |
| 77 | 83 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| ... | ... | @@ -179,29 +179,33 @@ public class ZLMHttpHookListener { |
| 179 | 179 | public ResponseEntity<String> onPublish(@RequestBody JSONObject json) { |
| 180 | 180 | |
| 181 | 181 | logger.debug("[ ZLM HOOK ]on_publish API调用,参数:" + json.toString()); |
| 182 | - | |
| 182 | + JSONObject ret = new JSONObject(); | |
| 183 | + ret.put("code", 0); | |
| 184 | + ret.put("msg", "success"); | |
| 185 | + ret.put("enableHls", true); | |
| 186 | + ret.put("enableMP4", userSetup.isRecordPushLive()); | |
| 183 | 187 | String mediaServerId = json.getString("mediaServerId"); |
| 184 | 188 | ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json); |
| 185 | 189 | if (subscribe != null) { |
| 186 | 190 | MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); |
| 187 | 191 | if (mediaInfo != null) { |
| 188 | 192 | subscribe.response(mediaInfo, json); |
| 193 | + }else { | |
| 194 | + ret.put("code", 1); | |
| 195 | + ret.put("msg", "zlm not register"); | |
| 189 | 196 | } |
| 190 | 197 | } |
| 191 | 198 | String app = json.getString("app"); |
| 192 | 199 | String stream = json.getString("stream"); |
| 193 | 200 | StreamInfo streamInfo = redisCatchStorage.queryPlaybackByStreamId(stream); |
| 194 | - JSONObject ret = new JSONObject(); | |
| 201 | + | |
| 195 | 202 | // 录像回放时不进行录像下载 |
| 196 | 203 | if (streamInfo != null) { |
| 197 | 204 | ret.put("enableMP4", false); |
| 198 | 205 | }else { |
| 199 | 206 | ret.put("enableMP4", userSetup.isRecordPushLive()); |
| 200 | 207 | } |
| 201 | - ret.put("code", 0); | |
| 202 | - ret.put("msg", "success"); | |
| 203 | - ret.put("enableHls", true); | |
| 204 | - ret.put("enableMP4", userSetup.isRecordPushLive()); | |
| 208 | + | |
| 205 | 209 | return new ResponseEntity<String>(ret.toString(), HttpStatus.OK); |
| 206 | 210 | } |
| 207 | 211 | |
| ... | ... | @@ -340,37 +344,38 @@ public class ZLMHttpHookListener { |
| 340 | 344 | if (!"rtp".equals(app)){ |
| 341 | 345 | String type = OriginType.values()[item.getOriginType()].getType(); |
| 342 | 346 | MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); |
| 343 | - if (regist) { | |
| 344 | - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks); | |
| 345 | - redisCatchStorage.addStream(mediaServerItem, type, app, streamId, streamInfo); | |
| 346 | - if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() | |
| 347 | - || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() | |
| 348 | - || item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) { | |
| 349 | - zlmMediaListManager.addPush(item); | |
| 350 | - } | |
| 351 | - }else { | |
| 352 | - // 兼容流注销时类型错误的问题,等zlm更新后删除 | |
| 353 | - StreamPushItem streamPushItem = streamPushService.getPush(app, streamId); | |
| 354 | - if (streamPushItem != null) { | |
| 355 | - type = "PUSH"; | |
| 347 | + if (mediaServerItem != null){ | |
| 348 | + if (regist) { | |
| 349 | + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, streamId, tracks); | |
| 350 | + redisCatchStorage.addStream(mediaServerItem, type, app, streamId, streamInfo); | |
| 351 | + if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() | |
| 352 | + || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() | |
| 353 | + || item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) { | |
| 354 | + zlmMediaListManager.addPush(item); | |
| 355 | + } | |
| 356 | 356 | }else { |
| 357 | - StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(app, streamId); | |
| 358 | - if (streamProxyByAppAndStream != null) { | |
| 359 | - type = "PULL"; | |
| 357 | + // 兼容流注销时类型错误的问题,等zlm更新后删除 | |
| 358 | + StreamPushItem streamPushItem = streamPushService.getPush(app, streamId); | |
| 359 | + if (streamPushItem != null) { | |
| 360 | + type = "PUSH"; | |
| 361 | + }else { | |
| 362 | + StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(app, streamId); | |
| 363 | + if (streamProxyByAppAndStream != null) { | |
| 364 | + type = "PULL"; | |
| 365 | + } | |
| 360 | 366 | } |
| 367 | + zlmMediaListManager.removeMedia(app, streamId); | |
| 368 | + redisCatchStorage.removeStream(mediaServerItem.getId(), type, app, streamId); | |
| 361 | 369 | } |
| 362 | - zlmMediaListManager.removeMedia(app, streamId); | |
| 363 | - redisCatchStorage.removeStream(mediaServerItem, type, app, streamId); | |
| 370 | + // 发送流变化redis消息 | |
| 371 | + JSONObject jsonObject = new JSONObject(); | |
| 372 | + jsonObject.put("serverId", userSetup.getServerId()); | |
| 373 | + jsonObject.put("app", app); | |
| 374 | + jsonObject.put("stream", streamId); | |
| 375 | + jsonObject.put("register", regist); | |
| 376 | + jsonObject.put("mediaServerId", mediaServerId); | |
| 377 | + redisCatchStorage.sendStreamChangeMsg(type, jsonObject); | |
| 364 | 378 | } |
| 365 | - | |
| 366 | - // 发送流变化redis消息 | |
| 367 | - JSONObject jsonObject = new JSONObject(); | |
| 368 | - jsonObject.put("serverId", userSetup.getServerId()); | |
| 369 | - jsonObject.put("app", app); | |
| 370 | - jsonObject.put("stream", streamId); | |
| 371 | - jsonObject.put("register", regist); | |
| 372 | - jsonObject.put("mediaServerId", mediaServerId); | |
| 373 | - redisCatchStorage.sendStreamChangeMsg(type, jsonObject); | |
| 374 | 379 | } |
| 375 | 380 | } |
| 376 | 381 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java
| ... | ... | @@ -4,6 +4,7 @@ import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONArray; |
| 5 | 5 | import com.alibaba.fastjson.JSONObject; |
| 6 | 6 | import com.genersoft.iot.vmp.conf.MediaConfig; |
| 7 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 7 | 8 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 8 | 9 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 9 | 10 | import com.genersoft.iot.vmp.service.IStreamProxyService; |
| ... | ... | @@ -17,6 +18,7 @@ import org.springframework.core.annotation.Order; |
| 17 | 18 | import org.springframework.scheduling.annotation.Async; |
| 18 | 19 | import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; |
| 19 | 20 | import org.springframework.stereotype.Component; |
| 21 | +import org.springframework.util.StringUtils; | |
| 20 | 22 | |
| 21 | 23 | import java.util.*; |
| 22 | 24 | |
| ... | ... | @@ -38,6 +40,9 @@ public class ZLMRunner implements CommandLineRunner { |
| 38 | 40 | private IStreamProxyService streamProxyService; |
| 39 | 41 | |
| 40 | 42 | @Autowired |
| 43 | + private EventPublisher publisher; | |
| 44 | + | |
| 45 | + @Autowired | |
| 41 | 46 | private IMediaServerService mediaServerService; |
| 42 | 47 | |
| 43 | 48 | @Autowired |
| ... | ... | @@ -117,7 +122,7 @@ public class ZLMRunner implements CommandLineRunner { |
| 117 | 122 | |
| 118 | 123 | @Async |
| 119 | 124 | public void connectZlmServer(MediaServerItem mediaServerItem){ |
| 120 | - ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem); | |
| 125 | + ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem, 1); | |
| 121 | 126 | if (zlmServerConfig != null) { |
| 122 | 127 | zlmServerConfig.setIp(mediaServerItem.getIp()); |
| 123 | 128 | zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort()); |
| ... | ... | @@ -126,7 +131,7 @@ public class ZLMRunner implements CommandLineRunner { |
| 126 | 131 | } |
| 127 | 132 | } |
| 128 | 133 | |
| 129 | - public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) { | |
| 134 | + public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem, int index) { | |
| 130 | 135 | if (startGetMedia == null) { return null;} |
| 131 | 136 | if (!mediaServerItem.isDefaultServer() && mediaServerService.getOne(mediaServerItem.getId()) == null) { |
| 132 | 137 | return null; |
| ... | ... | @@ -143,14 +148,19 @@ public class ZLMRunner implements CommandLineRunner { |
| 143 | 148 | ZLMServerConfig.setIp(mediaServerItem.getIp()); |
| 144 | 149 | } |
| 145 | 150 | } else { |
| 146 | - logger.error("[ {} ]-[ {}:{} ]主动连接失败失败, 2s后重试", | |
| 147 | - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); | |
| 151 | + logger.error("[ {} ]-[ {}:{} ]第{}次主动连接失败, 2s后重试", | |
| 152 | + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), index); | |
| 153 | + if (index == 1 && !StringUtils.isEmpty(mediaServerItem.getId())) { | |
| 154 | + logger.info("[ {} ]-[ {}:{} ]第{}次主动连接失败, 开始清理相关资源", | |
| 155 | + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort(), index); | |
| 156 | + publisher.zlmOfflineEventPublish(mediaServerItem.getId()); | |
| 157 | + } | |
| 148 | 158 | try { |
| 149 | 159 | Thread.sleep(2000); |
| 150 | 160 | } catch (InterruptedException e) { |
| 151 | 161 | e.printStackTrace(); |
| 152 | 162 | } |
| 153 | - ZLMServerConfig = getMediaServerConfig(mediaServerItem); | |
| 163 | + ZLMServerConfig = getMediaServerConfig(mediaServerItem, index += 1); | |
| 154 | 164 | } |
| 155 | 165 | return ZLMServerConfig; |
| 156 | 166 | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMKeepliveTimeoutListener.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.media.zlm.event; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.common.VideoManagerConstants; | |
| 4 | +import com.genersoft.iot.vmp.conf.UserSetup; | |
| 5 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 6 | +import org.slf4j.Logger; | |
| 7 | +import org.slf4j.LoggerFactory; | |
| 8 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 9 | +import org.springframework.data.redis.connection.Message; | |
| 10 | +import org.springframework.data.redis.listener.KeyExpirationEventMessageListener; | |
| 11 | +import org.springframework.data.redis.listener.RedisMessageListenerContainer; | |
| 12 | +import org.springframework.stereotype.Component; | |
| 13 | + | |
| 14 | +/** | |
| 15 | + * @description:设备心跳超时监听,借助redis过期特性,进行监听,监听到说明设备心跳超时,发送离线事件 | |
| 16 | + * @author: swwheihei | |
| 17 | + * @date: 2020年5月6日 上午11:35:46 | |
| 18 | + */ | |
| 19 | +@Component | |
| 20 | +public class ZLMKeepliveTimeoutListener extends KeyExpirationEventMessageListener { | |
| 21 | + | |
| 22 | + private Logger logger = LoggerFactory.getLogger(ZLMKeepliveTimeoutListener.class); | |
| 23 | + | |
| 24 | + @Autowired | |
| 25 | + private EventPublisher publisher; | |
| 26 | + | |
| 27 | + @Autowired | |
| 28 | + private UserSetup userSetup; | |
| 29 | + | |
| 30 | + public ZLMKeepliveTimeoutListener(RedisMessageListenerContainer listenerContainer) { | |
| 31 | + super(listenerContainer); | |
| 32 | + } | |
| 33 | + | |
| 34 | + /** | |
| 35 | + * 监听失效的key,key格式为keeplive_deviceId | |
| 36 | + * @param message | |
| 37 | + * @param pattern | |
| 38 | + */ | |
| 39 | + @Override | |
| 40 | + public void onMessage(Message message, byte[] pattern) { | |
| 41 | + // 获取失效的key | |
| 42 | + String expiredKey = message.toString(); | |
| 43 | + String KEEPLIVEKEY_PREFIX = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetup.getServerId() + "_"; | |
| 44 | + if(!expiredKey.startsWith(KEEPLIVEKEY_PREFIX)){ | |
| 45 | + return; | |
| 46 | + } | |
| 47 | + | |
| 48 | + String mediaServerId = expiredKey.substring(KEEPLIVEKEY_PREFIX.length(),expiredKey.length()); | |
| 49 | + | |
| 50 | + publisher.zlmOfflineEventPublish(mediaServerId); | |
| 51 | + } | |
| 52 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOfflineEvent.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOfflineEventListener.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.media.zlm.event; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.conf.UserSetup; | |
| 4 | +import com.genersoft.iot.vmp.service.IMediaServerService; | |
| 5 | +import com.genersoft.iot.vmp.service.IStreamProxyService; | |
| 6 | +import com.genersoft.iot.vmp.service.IStreamPushService; | |
| 7 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 8 | +import com.genersoft.iot.vmp.utils.redis.RedisUtil; | |
| 9 | +import org.slf4j.Logger; | |
| 10 | +import org.slf4j.LoggerFactory; | |
| 11 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 12 | +import org.springframework.context.ApplicationListener; | |
| 13 | +import org.springframework.stereotype.Component; | |
| 14 | + | |
| 15 | +/** | |
| 16 | + * | |
| 17 | + */ | |
| 18 | +@Component | |
| 19 | +public class ZLMOfflineEventListener implements ApplicationListener<ZLMOfflineEvent> { | |
| 20 | + | |
| 21 | + private final static Logger logger = LoggerFactory.getLogger(ZLMOfflineEventListener.class); | |
| 22 | + | |
| 23 | + @Autowired | |
| 24 | + private IMediaServerService mediaServerService; | |
| 25 | + | |
| 26 | + @Autowired | |
| 27 | + private IStreamPushService streamPushService; | |
| 28 | + | |
| 29 | + @Autowired | |
| 30 | + private IStreamProxyService streamProxyService; | |
| 31 | + | |
| 32 | + @Override | |
| 33 | + public void onApplicationEvent(ZLMOfflineEvent event) { | |
| 34 | + | |
| 35 | + if (logger.isDebugEnabled()) { | |
| 36 | + logger.debug("ZLM离线事件触发,ID:" + event.getMediaServerId()); | |
| 37 | + } | |
| 38 | + // 处理ZLM离线 | |
| 39 | + mediaServerService.zlmServerOffline(event.getMediaServerId()); | |
| 40 | + streamProxyService.zlmServerOffline(event.getMediaServerId()); | |
| 41 | + streamPushService.zlmServerOffline(event.getMediaServerId()); | |
| 42 | + // TODO 处理对国标的影响 | |
| 43 | + } | |
| 44 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOnlineEvent.java
0 → 100644
src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOnlineEventListener.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.media.zlm.event; | |
| 2 | + | |
| 3 | +import com.genersoft.iot.vmp.conf.SipConfig; | |
| 4 | +import com.genersoft.iot.vmp.conf.UserSetup; | |
| 5 | +import com.genersoft.iot.vmp.service.IMediaServerService; | |
| 6 | +import com.genersoft.iot.vmp.service.IStreamProxyService; | |
| 7 | +import com.genersoft.iot.vmp.service.IStreamPushService; | |
| 8 | +import com.genersoft.iot.vmp.storager.IVideoManagerStorager; | |
| 9 | +import com.genersoft.iot.vmp.utils.redis.RedisUtil; | |
| 10 | +import org.slf4j.Logger; | |
| 11 | +import org.slf4j.LoggerFactory; | |
| 12 | +import org.springframework.beans.factory.annotation.Autowired; | |
| 13 | +import org.springframework.context.ApplicationListener; | |
| 14 | +import org.springframework.stereotype.Component; | |
| 15 | + | |
| 16 | +import java.text.SimpleDateFormat; | |
| 17 | + | |
| 18 | +/** | |
| 19 | + * @description: 在线事件监听器,监听到离线后,修改设备离在线状态。 设备在线有两个来源: | |
| 20 | + * 1、设备主动注销,发送注销指令 | |
| 21 | + * 2、设备未知原因离线,心跳超时 | |
| 22 | + * @author: swwheihei | |
| 23 | + * @date: 2020年5月6日 下午1:51:23 | |
| 24 | + */ | |
| 25 | +@Component | |
| 26 | +public class ZLMOnlineEventListener implements ApplicationListener<ZLMOnlineEvent> { | |
| 27 | + | |
| 28 | + private final static Logger logger = LoggerFactory.getLogger(ZLMOnlineEventListener.class); | |
| 29 | + | |
| 30 | + @Autowired | |
| 31 | + private IVideoManagerStorager storager; | |
| 32 | + | |
| 33 | + @Autowired | |
| 34 | + private RedisUtil redis; | |
| 35 | + | |
| 36 | + @Autowired | |
| 37 | + private SipConfig sipConfig; | |
| 38 | + | |
| 39 | + @Autowired | |
| 40 | + private UserSetup userSetup; | |
| 41 | + | |
| 42 | + @Autowired | |
| 43 | + private IMediaServerService mediaServerService; | |
| 44 | + | |
| 45 | + @Autowired | |
| 46 | + private IStreamPushService streamPushService; | |
| 47 | + | |
| 48 | + @Autowired | |
| 49 | + private IStreamProxyService streamProxyService; | |
| 50 | + | |
| 51 | + private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); | |
| 52 | + | |
| 53 | + @Override | |
| 54 | + public void onApplicationEvent(ZLMOnlineEvent event) { | |
| 55 | + | |
| 56 | + if (logger.isDebugEnabled()) { | |
| 57 | + logger.debug("ZLM上线事件触发,ID:" + event.getMediaServerId()); | |
| 58 | + } | |
| 59 | + streamPushService.zlmServerOnline(event.getMediaServerId()); | |
| 60 | + streamProxyService.zlmServerOnline(event.getMediaServerId()); | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + } | |
| 65 | +} | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java
| ... | ... | @@ -78,10 +78,10 @@ public interface IStreamProxyService { |
| 78 | 78 | |
| 79 | 79 | /** |
| 80 | 80 | * 新的节点加入 |
| 81 | - * @param zlmServerConfig | |
| 81 | + * @param mediaServerId | |
| 82 | 82 | * @return |
| 83 | 83 | */ |
| 84 | - void zlmServerOnline(ZLMServerConfig zlmServerConfig); | |
| 84 | + void zlmServerOnline(String mediaServerId); | |
| 85 | 85 | |
| 86 | 86 | /** |
| 87 | 87 | * 节点离线 |
| ... | ... | @@ -89,4 +89,6 @@ public interface IStreamProxyService { |
| 89 | 89 | * @return |
| 90 | 90 | */ |
| 91 | 91 | void zlmServerOffline(String mediaServerId); |
| 92 | + | |
| 93 | + void clean(); | |
| 92 | 94 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java
| ... | ... | @@ -34,6 +34,7 @@ public interface IStreamPushService { |
| 34 | 34 | * @return |
| 35 | 35 | */ |
| 36 | 36 | PageInfo<StreamPushItem> getPushList(Integer page, Integer count); |
| 37 | + List<StreamPushItem> getPushList(String mediaSererId); | |
| 37 | 38 | |
| 38 | 39 | StreamPushItem transform(MediaItem item); |
| 39 | 40 | |
| ... | ... | @@ -49,10 +50,10 @@ public interface IStreamPushService { |
| 49 | 50 | |
| 50 | 51 | /** |
| 51 | 52 | * 新的节点加入 |
| 52 | - * @param zlmServerConfig | |
| 53 | + * @param mediaServerId | |
| 53 | 54 | * @return |
| 54 | 55 | */ |
| 55 | - void zlmServerOnline(ZLMServerConfig zlmServerConfig); | |
| 56 | + void zlmServerOnline(String mediaServerId); | |
| 56 | 57 | |
| 57 | 58 | /** |
| 58 | 59 | * 节点离线 |
| ... | ... | @@ -61,4 +62,5 @@ public interface IStreamPushService { |
| 61 | 62 | */ |
| 62 | 63 | void zlmServerOffline(String mediaServerId); |
| 63 | 64 | |
| 65 | + void clean(); | |
| 64 | 66 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java
| ... | ... | @@ -4,10 +4,10 @@ import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONArray; |
| 5 | 5 | import com.alibaba.fastjson.JSONObject; |
| 6 | 6 | import com.genersoft.iot.vmp.common.VideoManagerConstants; |
| 7 | -import com.genersoft.iot.vmp.conf.MediaConfig; | |
| 8 | 7 | import com.genersoft.iot.vmp.conf.SipConfig; |
| 9 | 8 | import com.genersoft.iot.vmp.conf.UserSetup; |
| 10 | 9 | import com.genersoft.iot.vmp.gb28181.bean.Device; |
| 10 | +import com.genersoft.iot.vmp.gb28181.event.EventPublisher; | |
| 11 | 11 | import com.genersoft.iot.vmp.gb28181.session.SsrcConfig; |
| 12 | 12 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 13 | 13 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| ... | ... | @@ -71,6 +71,9 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 71 | 71 | private RedisUtil redisUtil; |
| 72 | 72 | |
| 73 | 73 | @Autowired |
| 74 | + private EventPublisher publisher; | |
| 75 | + | |
| 76 | + @Autowired | |
| 74 | 77 | JedisUtil jedisUtil; |
| 75 | 78 | |
| 76 | 79 | private final SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); |
| ... | ... | @@ -312,8 +315,6 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 312 | 315 | return mediaServerMapper.update(mediaSerItem); |
| 313 | 316 | } |
| 314 | 317 | |
| 315 | - | |
| 316 | - | |
| 317 | 318 | /** |
| 318 | 319 | * 处理zlm上线 |
| 319 | 320 | * @param zlmServerConfig zlm上线携带的参数 |
| ... | ... | @@ -353,28 +354,31 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 353 | 354 | if (serverItem.getRtpProxyPort() == 0) { |
| 354 | 355 | serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); |
| 355 | 356 | } |
| 356 | - if (StringUtils.isEmpty(serverItem.getId())) { | |
| 357 | - serverItem.setId(zlmServerConfig.getGeneralMediaServerId()); | |
| 358 | - } | |
| 359 | 357 | serverItem.setStatus(true); |
| 358 | + | |
| 360 | 359 | if (StringUtils.isEmpty(serverItem.getId())) { |
| 361 | 360 | serverItem.setId(zlmServerConfig.getGeneralMediaServerId()); |
| 362 | 361 | mediaServerMapper.updateByHostAndPort(serverItem); |
| 363 | 362 | }else { |
| 364 | 363 | mediaServerMapper.update(serverItem); |
| 365 | 364 | } |
| 366 | - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + serverItem.getId(); | |
| 365 | + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetup.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); | |
| 367 | 366 | if (redisUtil.get(key) == null) { |
| 368 | - SsrcConfig ssrcConfig = new SsrcConfig(serverItem.getId(), null, sipConfig.getDomain()); | |
| 367 | + SsrcConfig ssrcConfig = new SsrcConfig(zlmServerConfig.getGeneralMediaServerId(), null, sipConfig.getDomain()); | |
| 369 | 368 | serverItem.setSsrcConfig(ssrcConfig); |
| 370 | - redisUtil.set(key, serverItem); | |
| 369 | + }else { | |
| 370 | + MediaServerItem mediaServerItemInRedis = (MediaServerItem)redisUtil.get(key); | |
| 371 | + serverItem.setSsrcConfig(mediaServerItemInRedis.getSsrcConfig()); | |
| 371 | 372 | } |
| 372 | - | |
| 373 | + redisUtil.set(key, serverItem); | |
| 373 | 374 | resetOnlineServerItem(serverItem); |
| 374 | 375 | updateMediaServerKeepalive(serverItem.getId(), null); |
| 375 | 376 | setZLMConfig(serverItem); |
| 377 | + publisher.zlmOnlineEventPublish(serverItem.getId()); | |
| 378 | + | |
| 376 | 379 | } |
| 377 | 380 | |
| 381 | + | |
| 378 | 382 | @Override |
| 379 | 383 | public void zlmServerOffline(String mediaServerId) { |
| 380 | 384 | delete(mediaServerId); |
| ... | ... | @@ -567,6 +571,10 @@ public class MediaServerServiceImpl implements IMediaServerService, CommandLineR |
| 567 | 571 | @Override |
| 568 | 572 | public void updateMediaServerKeepalive(String mediaServerId, JSONObject data) { |
| 569 | 573 | MediaServerItem mediaServerItem = getOne(mediaServerId); |
| 574 | + if (mediaServerItem == null) { | |
| 575 | + logger.warn("[更新ZLM 保活信息]失败,未找到流媒体信息"); | |
| 576 | + return; | |
| 577 | + } | |
| 570 | 578 | String key = VideoManagerConstants.MEDIA_SERVER_KEEPALIVE_PREFIX + userSetup.getServerId() + "_" + mediaServerId; |
| 571 | 579 | int hookAliveInterval = mediaServerItem.getHookAliveInterval() + 2; |
| 572 | 580 | redisUtil.set(key, data, hookAliveInterval); | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java
| ... | ... | @@ -2,6 +2,7 @@ package com.genersoft.iot.vmp.service.impl; |
| 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.UserSetup; | |
| 5 | 6 | import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
| 6 | 7 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 7 | 8 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| ... | ... | @@ -28,8 +29,7 @@ import org.springframework.beans.factory.annotation.Autowired; |
| 28 | 29 | import org.springframework.stereotype.Service; |
| 29 | 30 | import org.springframework.util.StringUtils; |
| 30 | 31 | |
| 31 | -import java.util.ArrayList; | |
| 32 | -import java.util.List; | |
| 32 | +import java.util.*; | |
| 33 | 33 | |
| 34 | 34 | /** |
| 35 | 35 | * 视频代理业务 |
| ... | ... | @@ -55,6 +55,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService { |
| 55 | 55 | private IRedisCatchStorage redisCatchStorage; |
| 56 | 56 | |
| 57 | 57 | @Autowired |
| 58 | + private UserSetup userSetup; | |
| 59 | + | |
| 60 | + @Autowired | |
| 58 | 61 | private GbStreamMapper gbStreamMapper; |
| 59 | 62 | |
| 60 | 63 | @Autowired |
| ... | ... | @@ -160,6 +163,9 @@ public class StreamProxyServiceImpl implements IStreamProxyService { |
| 160 | 163 | }else { |
| 161 | 164 | mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); |
| 162 | 165 | } |
| 166 | + if (mediaServerItem == null) { | |
| 167 | + return null; | |
| 168 | + } | |
| 163 | 169 | if ("default".equals(param.getType())){ |
| 164 | 170 | result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl(), |
| 165 | 171 | param.isEnable_hls(), param.isEnable_mp4(), param.getRtp_type()); |
| ... | ... | @@ -244,7 +250,6 @@ public class StreamProxyServiceImpl implements IStreamProxyService { |
| 244 | 250 | } |
| 245 | 251 | } |
| 246 | 252 | } |
| 247 | - | |
| 248 | 253 | return result; |
| 249 | 254 | } |
| 250 | 255 | |
| ... | ... | @@ -255,18 +260,41 @@ public class StreamProxyServiceImpl implements IStreamProxyService { |
| 255 | 260 | } |
| 256 | 261 | |
| 257 | 262 | @Override |
| 258 | - public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { | |
| 259 | - | |
| 263 | + public void zlmServerOnline(String mediaServerId) { | |
| 264 | + zlmServerOffline(mediaServerId); | |
| 260 | 265 | } |
| 261 | 266 | |
| 262 | 267 | @Override |
| 263 | 268 | public void zlmServerOffline(String mediaServerId) { |
| 264 | 269 | // 移除开启了无人观看自动移除的流 |
| 270 | + List<StreamProxyItem> streamProxyItemList = streamProxyMapper.selecAutoRemoveItemByMediaServerId(mediaServerId); | |
| 271 | + if (streamProxyItemList.size() > 0) { | |
| 272 | + gbStreamMapper.batchDel(streamProxyItemList); | |
| 273 | + } | |
| 265 | 274 | streamProxyMapper.deleteAutoRemoveItemByMediaServerId(mediaServerId); |
| 266 | 275 | // 其他的流设置未启用 |
| 267 | 276 | streamProxyMapper.updateStatus(false, mediaServerId); |
| 268 | - // 移除redis内流的信息 | |
| 269 | - redisCatchStorage.removeStream(mediaServerId, "PULL"); | |
| 277 | + String type = "PULL"; | |
| 278 | + | |
| 279 | + // 发送redis消息 | |
| 280 | + List<StreamInfo> streamInfoList = redisCatchStorage.getStreams(mediaServerId, type); | |
| 281 | + if (streamInfoList.size() > 0) { | |
| 282 | + for (StreamInfo streamInfo : streamInfoList) { | |
| 283 | + JSONObject jsonObject = new JSONObject(); | |
| 284 | + jsonObject.put("serverId", userSetup.getServerId()); | |
| 285 | + jsonObject.put("app", streamInfo.getApp()); | |
| 286 | + jsonObject.put("stream", streamInfo.getStreamId()); | |
| 287 | + jsonObject.put("register", false); | |
| 288 | + jsonObject.put("mediaServerId", mediaServerId); | |
| 289 | + redisCatchStorage.sendStreamChangeMsg(type, jsonObject); | |
| 290 | + // 移除redis内流的信息 | |
| 291 | + redisCatchStorage.removeStream(mediaServerId, type, streamInfo.getApp(), streamInfo.getStreamId()); | |
| 292 | + } | |
| 293 | + } | |
| 294 | + } | |
| 295 | + | |
| 296 | + @Override | |
| 297 | + public void clean() { | |
| 270 | 298 | |
| 271 | 299 | } |
| 272 | 300 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java
| ... | ... | @@ -3,11 +3,15 @@ package com.genersoft.iot.vmp.service.impl; |
| 3 | 3 | import com.alibaba.fastjson.JSON; |
| 4 | 4 | import com.alibaba.fastjson.JSONObject; |
| 5 | 5 | import com.alibaba.fastjson.TypeReference; |
| 6 | +import com.genersoft.iot.vmp.common.StreamInfo; | |
| 7 | +import com.genersoft.iot.vmp.conf.UserSetup; | |
| 6 | 8 | import com.genersoft.iot.vmp.gb28181.bean.GbStream; |
| 9 | +import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; | |
| 7 | 10 | import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; |
| 8 | 11 | import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; |
| 9 | 12 | import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; |
| 10 | 13 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 14 | +import com.genersoft.iot.vmp.media.zlm.dto.OriginType; | |
| 11 | 15 | import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| 12 | 16 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 13 | 17 | import com.genersoft.iot.vmp.service.IStreamPushService; |
| ... | ... | @@ -20,10 +24,7 @@ import com.github.pagehelper.PageInfo; |
| 20 | 24 | import org.springframework.beans.factory.annotation.Autowired; |
| 21 | 25 | import org.springframework.stereotype.Service; |
| 22 | 26 | |
| 23 | -import java.util.ArrayList; | |
| 24 | -import java.util.HashMap; | |
| 25 | -import java.util.List; | |
| 26 | -import java.util.Map; | |
| 27 | +import java.util.*; | |
| 27 | 28 | |
| 28 | 29 | @Service |
| 29 | 30 | public class StreamPushServiceImpl implements IStreamPushService { |
| ... | ... | @@ -44,6 +45,9 @@ public class StreamPushServiceImpl implements IStreamPushService { |
| 44 | 45 | private IRedisCatchStorage redisCatchStorage; |
| 45 | 46 | |
| 46 | 47 | @Autowired |
| 48 | + private UserSetup userSetup; | |
| 49 | + | |
| 50 | + @Autowired | |
| 47 | 51 | private IMediaServerService mediaServerService; |
| 48 | 52 | |
| 49 | 53 | @Override |
| ... | ... | @@ -56,7 +60,9 @@ public class StreamPushServiceImpl implements IStreamPushService { |
| 56 | 60 | for (MediaItem item : mediaItems) { |
| 57 | 61 | |
| 58 | 62 | // 不保存国标推理以及拉流代理的流 |
| 59 | - if (item.getOriginType() == 1 || item.getOriginType() == 2 || item.getOriginType() == 8) { | |
| 63 | + if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() | |
| 64 | + || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() | |
| 65 | + || item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) { | |
| 60 | 66 | String key = item.getApp() + "_" + item.getStream(); |
| 61 | 67 | StreamPushItem streamPushItem = result.get(key); |
| 62 | 68 | if (streamPushItem == null) { |
| ... | ... | @@ -98,6 +104,11 @@ public class StreamPushServiceImpl implements IStreamPushService { |
| 98 | 104 | } |
| 99 | 105 | |
| 100 | 106 | @Override |
| 107 | + public List<StreamPushItem> getPushList(String mediaServerId) { | |
| 108 | + return streamPushMapper.selectAllByMediaServerId(mediaServerId); | |
| 109 | + } | |
| 110 | + | |
| 111 | + @Override | |
| 101 | 112 | public boolean saveToGB(GbStream stream) { |
| 102 | 113 | stream.setStreamType("push"); |
| 103 | 114 | stream.setStatus(true); |
| ... | ... | @@ -137,17 +148,84 @@ public class StreamPushServiceImpl implements IStreamPushService { |
| 137 | 148 | } |
| 138 | 149 | |
| 139 | 150 | @Override |
| 140 | - public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { | |
| 141 | - // 似乎没啥需要做的 | |
| 151 | + public void zlmServerOnline(String mediaServerId) { | |
| 152 | + // 同步zlm推流信息 | |
| 153 | + MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); | |
| 154 | + if (mediaServerItem == null) { | |
| 155 | + return; | |
| 156 | + } | |
| 157 | + List<StreamPushItem> pushList = getPushList(mediaServerId); | |
| 158 | + if (pushList.size() > 0) { | |
| 159 | + Map<String, StreamPushItem> pushItemMap = new HashMap<>(); | |
| 160 | + for (StreamPushItem streamPushItem : pushList) { | |
| 161 | + pushItemMap.put(streamPushItem.getApp() + streamPushItem.getStream(), streamPushItem); | |
| 162 | + } | |
| 163 | + zlmresTfulUtils.getMediaList(mediaServerItem, (mediaList ->{ | |
| 164 | + if (mediaList == null) return; | |
| 165 | + String dataStr = mediaList.getString("data"); | |
| 166 | + | |
| 167 | + Integer code = mediaList.getInteger("code"); | |
| 168 | + List<StreamPushItem> streamPushItems = null; | |
| 169 | + if (code == 0 ) { | |
| 170 | + if (dataStr != null) { | |
| 171 | + streamPushItems = handleJSON(dataStr, mediaServerItem); | |
| 172 | + } | |
| 173 | + } | |
| 174 | + | |
| 175 | + if (streamPushItems != null) { | |
| 176 | + for (StreamPushItem streamPushItem : streamPushItems) { | |
| 177 | + pushItemMap.remove(streamPushItem.getApp() + streamPushItem.getStream()); | |
| 178 | + } | |
| 179 | + } | |
| 180 | + Collection<StreamPushItem> offlinePushItems = pushItemMap.values(); | |
| 181 | + if (offlinePushItems.size() > 0) { | |
| 182 | + String type = "PUSH"; | |
| 183 | + streamPushMapper.delAll(new ArrayList<>(offlinePushItems)); | |
| 184 | + for (StreamPushItem offlinePushItem : offlinePushItems) { | |
| 185 | + JSONObject jsonObject = new JSONObject(); | |
| 186 | + jsonObject.put("serverId", userSetup.getServerId()); | |
| 187 | + jsonObject.put("app", offlinePushItem.getApp()); | |
| 188 | + jsonObject.put("stream", offlinePushItem.getStream()); | |
| 189 | + jsonObject.put("register", false); | |
| 190 | + jsonObject.put("mediaServerId", mediaServerId); | |
| 191 | + redisCatchStorage.sendStreamChangeMsg(type, jsonObject); | |
| 192 | + // 移除redis内流的信息 | |
| 193 | + redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlinePushItem.getApp(), offlinePushItem.getStream()); | |
| 194 | + } | |
| 195 | + } | |
| 196 | + })); | |
| 197 | + } | |
| 142 | 198 | } |
| 143 | 199 | |
| 144 | 200 | @Override |
| 145 | 201 | public void zlmServerOffline(String mediaServerId) { |
| 146 | - // 移除没有serverId的推流 | |
| 202 | + List<StreamPushItem> streamPushItems = streamPushMapper.selectAllByMediaServerId(mediaServerId); | |
| 203 | + // 移除没有GBId的推流 | |
| 147 | 204 | streamPushMapper.deleteWithoutGBId(mediaServerId); |
| 205 | + gbStreamMapper.deleteWithoutGBId("push", mediaServerId); | |
| 148 | 206 | // 其他的流设置未启用 |
| 149 | 207 | gbStreamMapper.updateStatusByMediaServerId(mediaServerId, false); |
| 150 | - // 移除redis内流的信息 | |
| 151 | - redisCatchStorage.removeStream(mediaServerId, "PUSH"); | |
| 208 | + // 发送流停止消息 | |
| 209 | + String type = "PUSH"; | |
| 210 | + // 发送redis消息 | |
| 211 | + List<StreamInfo> streamInfoList = redisCatchStorage.getStreams(mediaServerId, type); | |
| 212 | + if (streamInfoList.size() > 0) { | |
| 213 | + for (StreamInfo streamInfo : streamInfoList) { | |
| 214 | + JSONObject jsonObject = new JSONObject(); | |
| 215 | + jsonObject.put("serverId", userSetup.getServerId()); | |
| 216 | + jsonObject.put("app", streamInfo.getApp()); | |
| 217 | + jsonObject.put("stream", streamInfo.getStreamId()); | |
| 218 | + jsonObject.put("register", false); | |
| 219 | + jsonObject.put("mediaServerId", mediaServerId); | |
| 220 | + redisCatchStorage.sendStreamChangeMsg(type, jsonObject); | |
| 221 | + // 移除redis内流的信息 | |
| 222 | + redisCatchStorage.removeStream(mediaServerId, type, streamInfo.getApp(), streamInfo.getStreamId()); | |
| 223 | + } | |
| 224 | + } | |
| 225 | + } | |
| 226 | + | |
| 227 | + @Override | |
| 228 | + public void clean() { | |
| 229 | + | |
| 152 | 230 | } |
| 153 | 231 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
| ... | ... | @@ -140,11 +140,11 @@ public interface IRedisCatchStorage { |
| 140 | 140 | |
| 141 | 141 | /** |
| 142 | 142 | * 移除流信息从redis |
| 143 | - * @param mediaServerItem | |
| 143 | + * @param mediaServerId | |
| 144 | 144 | * @param app |
| 145 | 145 | * @param streamId |
| 146 | 146 | */ |
| 147 | - void removeStream(MediaServerItem mediaServerItem, String type, String app, String streamId); | |
| 147 | + void removeStream(String mediaServerId, String type, String app, String streamId); | |
| 148 | 148 | |
| 149 | 149 | |
| 150 | 150 | /** |
| ... | ... | @@ -167,4 +167,6 @@ public interface IRedisCatchStorage { |
| 167 | 167 | * @return |
| 168 | 168 | */ |
| 169 | 169 | ThirdPartyGB queryMemberNoGBId(String queryKey); |
| 170 | + | |
| 171 | + List<StreamInfo> getStreams(String mediaServerId, String pull); | |
| 170 | 172 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java
| ... | ... | @@ -65,4 +65,18 @@ public interface GbStreamMapper { |
| 65 | 65 | "SET status=${status} " + |
| 66 | 66 | "WHERE mediaServerId=#{mediaServerId} ") |
| 67 | 67 | void updateStatusByMediaServerId(String mediaServerId, boolean status); |
| 68 | + | |
| 69 | + @Select("SELECT * FROM gb_stream WHERE mediaServerId=#{mediaServerId}") | |
| 70 | + void delByMediaServerId(String mediaServerId); | |
| 71 | + | |
| 72 | + @Delete("DELETE FROM gb_stream WHERE streamType=#{type} AND gbId=NULL AND mediaServerId=#{mediaServerId}") | |
| 73 | + void deleteWithoutGBId(String type, String mediaServerId); | |
| 74 | + | |
| 75 | + @Delete("<script> "+ | |
| 76 | + "DELETE FROM gb_stream where " + | |
| 77 | + "<foreach collection='streamProxyItemList' item='item' separator='or'>" + | |
| 78 | + "(app=#{item.app} and stream=#{item.stream}) " + | |
| 79 | + "</foreach>" + | |
| 80 | + "</script>") | |
| 81 | + void batchDel(List<StreamProxyItem> streamProxyItemList); | |
| 68 | 82 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java
| ... | ... | @@ -62,6 +62,9 @@ public interface StreamProxyMapper { |
| 62 | 62 | "WHERE mediaServerId=#{mediaServerId}") |
| 63 | 63 | void updateStatus(boolean status, String mediaServerId); |
| 64 | 64 | |
| 65 | - @Delete("DELETE FROM stream_proxy WHERE mediaServerId=#{mediaServerId}") | |
| 65 | + @Delete("DELETE FROM stream_proxy WHERE enable_remove_none_reader=true AND mediaServerId=#{mediaServerId}") | |
| 66 | 66 | void deleteAutoRemoveItemByMediaServerId(String mediaServerId); |
| 67 | + | |
| 68 | + @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.enable_remove_none_reader=true AND st.mediaServerId=#{mediaServerId} order by st.createTime desc") | |
| 69 | + List<StreamProxyItem> selecAutoRemoveItemByMediaServerId(String mediaServerId); | |
| 67 | 70 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java
| ... | ... | @@ -4,6 +4,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; |
| 4 | 4 | import org.apache.ibatis.annotations.*; |
| 5 | 5 | import org.springframework.stereotype.Repository; |
| 6 | 6 | |
| 7 | +import java.util.Collection; | |
| 7 | 8 | import java.util.List; |
| 8 | 9 | |
| 9 | 10 | @Mapper |
| ... | ... | @@ -31,6 +32,14 @@ public interface StreamPushMapper { |
| 31 | 32 | @Delete("DELETE FROM stream_push WHERE app=#{app} AND stream=#{stream}") |
| 32 | 33 | int del(String app, String stream); |
| 33 | 34 | |
| 35 | + @Delete("<script> "+ | |
| 36 | + "DELETE FROM stream_push where " + | |
| 37 | + "<foreach collection='streamPushItems' item='item' separator='or'>" + | |
| 38 | + "(app=#{item.app} and stream=#{item.stream}) " + | |
| 39 | + "</foreach>" + | |
| 40 | + "</script>") | |
| 41 | + int delAll(List<StreamPushItem> streamPushItems); | |
| 42 | + | |
| 34 | 43 | @Select("SELECT st.*, pgs.gbId, pgs.status, pgs.name, pgs.longitude, pgs.latitude FROM stream_push st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream") |
| 35 | 44 | List<StreamPushItem> selectAll(); |
| 36 | 45 | |
| ... | ... | @@ -56,4 +65,7 @@ public interface StreamPushMapper { |
| 56 | 65 | @Delete("DELETE FROM stream_push WHERE mediaServerId=#{mediaServerId}") |
| 57 | 66 | void deleteWithoutGBId(String mediaServerId); |
| 58 | 67 | |
| 68 | + @Select("SELECT * FROM stream_push WHERE mediaServerId=#{mediaServerId}") | |
| 69 | + List<StreamPushItem> selectAllByMediaServerId(String mediaServerId); | |
| 70 | + | |
| 59 | 71 | } | ... | ... |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| ... | ... | @@ -338,8 +338,8 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { |
| 338 | 338 | } |
| 339 | 339 | |
| 340 | 340 | @Override |
| 341 | - public void removeStream(MediaServerItem mediaServerItem, String type, String app, String streamId) { | |
| 342 | - String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId(); | |
| 341 | + public void removeStream(String mediaServerId, String type, String app, String streamId) { | |
| 342 | + String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerId; | |
| 343 | 343 | redis.del(key); |
| 344 | 344 | } |
| 345 | 345 | |
| ... | ... | @@ -365,4 +365,16 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { |
| 365 | 365 | redis.del((String) stream); |
| 366 | 366 | } |
| 367 | 367 | } |
| 368 | + | |
| 369 | + @Override | |
| 370 | + public List<StreamInfo> getStreams(String mediaServerId, String type) { | |
| 371 | + List<StreamInfo> result = new ArrayList<>(); | |
| 372 | + String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetup.getServerId() + "_" + type + "_*_*_" + mediaServerId; | |
| 373 | + List<Object> streams = redis.scan(key); | |
| 374 | + for (Object stream : streams) { | |
| 375 | + StreamInfo streamInfo = (StreamInfo)redis.get((String) stream); | |
| 376 | + result.add(streamInfo); | |
| 377 | + } | |
| 378 | + return result; | |
| 379 | + } | |
| 368 | 380 | } | ... | ... |