Commit b944f8867c78dbe6dd4704115b48beb9f6dc12d9

Authored by 648540858
1 parent 269ad8ce

支持推流和拉流代理通道状态变化发送通知

src/main/java/com/genersoft/iot/vmp/gb28181/event/subscribe/catalog/CatalogEventLister.java
1 1 package com.genersoft.iot.vmp.gb28181.event.subscribe.catalog;
2 2  
3   -import com.genersoft.iot.vmp.common.VideoManagerConstants;
4   -import com.genersoft.iot.vmp.conf.SipConfig;
5 3 import com.genersoft.iot.vmp.conf.UserSetting;
6 4 import com.genersoft.iot.vmp.gb28181.bean.*;
7 5 import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform;
8   -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
9 6 import com.genersoft.iot.vmp.service.IGbStreamService;
10   -import com.genersoft.iot.vmp.service.IMediaServerService;
11   -import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
12 7 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
13 8 import org.slf4j.Logger;
14 9 import org.slf4j.LoggerFactory;
... ... @@ -16,12 +11,14 @@ import org.springframework.beans.factory.annotation.Autowired;
16 11 import org.springframework.context.ApplicationListener;
17 12 import org.springframework.stereotype.Component;
18 13 import org.springframework.util.ObjectUtils;
19   -import org.springframework.util.StringUtils;
20 14  
21 15 import javax.sip.InvalidArgumentException;
22 16 import javax.sip.SipException;
23 17 import java.text.ParseException;
24   -import java.util.*;
  18 +import java.util.ArrayList;
  19 +import java.util.HashMap;
  20 +import java.util.List;
  21 +import java.util.Map;
25 22  
26 23 /**
27 24 * catalog事件
... ... @@ -43,6 +40,9 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
43 40 @Autowired
44 41 private SubscribeHolder subscribeHolder;
45 42  
  43 + @Autowired
  44 + private UserSetting userSetting;
  45 +
46 46 @Override
47 47 public void onApplicationEvent(CatalogEvent event) {
48 48 SubscribeInfo subscribe = null;
... ... @@ -93,6 +93,9 @@ public class CatalogEventLister implements ApplicationListener<CatalogEvent> {
93 93 }
94 94 if (event.getGbStreams() != null && event.getGbStreams().size() > 0){
95 95 for (GbStream gbStream : event.getGbStreams()) {
  96 + if (gbStream.getStreamType().equals("push") && !userSetting.isUsePushingAsStatus()) {
  97 + continue;
  98 + }
96 99 DeviceChannel deviceChannelByStream = gbStreamService.getDeviceChannelListByStream(gbStream, gbStream.getCatalogId(), parentPlatform);
97 100 deviceChannelList.add(deviceChannelByStream);
98 101 }
... ...
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java
... ... @@ -118,6 +118,8 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
118 118 // 离线
119 119 logger.info("[收到通道离线通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
120 120 if (userSetting.getRefuseChannelStatusChannelFormNotify()) {
  121 + logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  122 + }else {
121 123 updateChannelOfflineList.add(channel);
122 124 if (updateChannelOfflineList.size() > 300) {
123 125 executeSaveForOffline();
... ... @@ -126,14 +128,14 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
126 128 // 发送redis消息
127 129 redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false);
128 130 }
129   - }else {
130   - logger.info("[收到通道离线通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
131 131 }
132 132 break;
133 133 case CatalogEvent.VLOST:
134 134 // 视频丢失
135 135 logger.info("[收到通道视频丢失通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
136 136 if (userSetting.getRefuseChannelStatusChannelFormNotify()) {
  137 + logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  138 + }else {
137 139 updateChannelOfflineList.add(channel);
138 140 if (updateChannelOfflineList.size() > 300) {
139 141 executeSaveForOffline();
... ... @@ -142,14 +144,14 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
142 144 // 发送redis消息
143 145 redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false);
144 146 }
145   - }else {
146   - logger.info("[收到通道视频丢失通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
147 147 }
148 148 break;
149 149 case CatalogEvent.DEFECT:
150 150 // 故障
151 151 logger.info("[收到通道视频故障通知] 来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
152 152 if (userSetting.getRefuseChannelStatusChannelFormNotify()) {
  153 + logger.info("[收到通道视频故障通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
  154 + }else {
153 155 updateChannelOfflineList.add(channel);
154 156 if (updateChannelOfflineList.size() > 300) {
155 157 executeSaveForOffline();
... ... @@ -158,8 +160,6 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent
158 160 // 发送redis消息
159 161 redisCatchStorage.sendDeviceOrChannelStatus(device.getDeviceId(), channel.getChannelId(), false);
160 162 }
161   - }else {
162   - logger.info("[收到通道视频故障通知] 但是平台已配置拒绝此消息,来自设备: {}, 通道 {}", device.getDeviceId(), channel.getChannelId());
163 163 }
164 164 break;
165 165 case CatalogEvent.ADD:
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
... ... @@ -7,6 +7,7 @@ import com.genersoft.iot.vmp.conf.UserSetting;
7 7 import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException;
8 8 import com.genersoft.iot.vmp.gb28181.bean.*;
9 9 import com.genersoft.iot.vmp.gb28181.event.EventPublisher;
  10 +import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent;
10 11 import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager;
11 12 import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder;
12 13 import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage;
... ... @@ -292,22 +293,24 @@ public class ZLMHttpHookListener {
292 293 JSONObject json = (JSONObject) JSON.toJSON(param);
293 294 taskExecutor.execute(() -> {
294 295 ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json);
  296 + MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId());
  297 + if (mediaInfo == null) {
  298 + logger.info("[ZLM HOOK] 流变化未找到ZLM, {}", param.getMediaServerId());
  299 + return;
  300 + }
295 301 if (subscribe != null) {
296   - MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId());
297   - if (mediaInfo != null) {
298   - subscribe.response(mediaInfo, json);
299   - }
  302 + subscribe.response(mediaInfo, json);
300 303 }
301 304  
302 305 List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks();
303 306 // TODO 重构此处逻辑
304   -
  307 + boolean isPush = false;
305 308 if (param.isRegist()) {
306 309 // 处理流注册的鉴权信息
307 310 if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
308 311 || param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
309 312 || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
310   -
  313 + isPush = true;
311 314 StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
312 315 if (streamAuthorityInfo == null) {
313 316 streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param);
... ... @@ -329,7 +332,10 @@ public class ZLMHttpHookListener {
329 332 mediaServerService.removeCount(param.getMediaServerId());
330 333 }
331 334 // 设置拉流代理上线/离线
332   - streamProxyService.updateStatus(param.isRegist(), param.getApp(), param.getStream());
  335 + int updateStatusResult = streamProxyService.updateStatus(param.isRegist(), param.getApp(), param.getStream());
  336 + if (updateStatusResult > 0) {
  337 +
  338 + }
333 339  
334 340 if ("rtp".equals(param.getApp()) && !param.isRegist()) {
335 341 StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(param.getStream());
... ... @@ -337,7 +343,8 @@ public class ZLMHttpHookListener {
337 343 redisCatchStorage.stopPlay(streamInfo);
338 344 storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId());
339 345 } else {
340   - streamInfo = redisCatchStorage.queryPlayback(null, null, param.getStream(), null);
  346 + streamInfo = redisCatchStorage.queryPlayback(null, null,
  347 + param.getStream(), null);
341 348 if (streamInfo != null) {
342 349 redisCatchStorage.stopPlayback(streamInfo.getDeviceID(), streamInfo.getChannelId(),
343 350 streamInfo.getStream(), null);
... ... @@ -346,48 +353,50 @@ public class ZLMHttpHookListener {
346 353 } else {
347 354 if (!"rtp".equals(param.getApp())) {
348 355 String type = OriginType.values()[param.getOriginType()].getType();
349   - MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId());
350   -
351   - if (mediaServerItem != null) {
352   - if (param.isRegist()) {
353   - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream());
354   - String callId = null;
355   - if (streamAuthorityInfo != null) {
356   - callId = streamAuthorityInfo.getCallId();
357   - }
358   - StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaServerItem,
359   - param.getApp(), param.getStream(), tracks, callId);
360   - param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));
361   - redisCatchStorage.addStream(mediaServerItem, type, param.getApp(), param.getStream(), param);
362   - if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
363   - || param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
364   - || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
365   - param.setSeverId(userSetting.getServerId());
366   - zlmMediaListManager.addPush(param);
367   - }
368   - } else {
369   - // 兼容流注销时类型从redis记录获取
370   - OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo(param.getApp(), param.getStream(), param.getMediaServerId());
371   - if (onStreamChangedHookParam != null) {
372   - type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType();
373   - redisCatchStorage.removeStream(mediaServerItem.getId(), type, param.getApp(), param.getStream());
374   - }
375   - GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream());
376   - if (gbStream != null) {
377   -// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF);
378   - }
379   - zlmMediaListManager.removeMedia(param.getApp(), param.getStream());
  356 + if (param.isRegist()) {
  357 + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(
  358 + param.getApp(), param.getStream());
  359 + String callId = null;
  360 + if (streamAuthorityInfo != null) {
  361 + callId = streamAuthorityInfo.getCallId();
  362 + }
  363 + StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo,
  364 + param.getApp(), param.getStream(), tracks, callId);
  365 + param.setStreamInfo(new StreamContent(streamInfoByAppAndStream));
  366 + redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param);
  367 + if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal()
  368 + || param.getOriginType() == OriginType.RTMP_PUSH.ordinal()
  369 + || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) {
  370 + param.setSeverId(userSetting.getServerId());
  371 + zlmMediaListManager.addPush(param);
380 372 }
381   - if (type != null) {
382   - // 发送流变化redis消息
383   - JSONObject jsonObject = new JSONObject();
384   - jsonObject.put("serverId", userSetting.getServerId());
385   - jsonObject.put("app", param.getApp());
386   - jsonObject.put("stream", param.getStream());
387   - jsonObject.put("register", param.isRegist());
388   - jsonObject.put("mediaServerId", param.getMediaServerId());
389   - redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
  373 + } else {
  374 + // 兼容流注销时类型从redis记录获取
  375 + OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo(
  376 + param.getApp(), param.getStream(), param.getMediaServerId());
  377 + if (onStreamChangedHookParam != null) {
  378 + type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType();
  379 + redisCatchStorage.removeStream(mediaInfo.getId(), type, param.getApp(), param.getStream());
390 380 }
  381 + GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream());
  382 + if (gbStream != null) {
  383 +// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF);
  384 + }
  385 + zlmMediaListManager.removeMedia(param.getApp(), param.getStream());
  386 + }
  387 + GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream());
  388 + if (gbStream != null) {
  389 + eventPublisher.catalogEventPublishForStream(null, gbStream, param.isRegist()?CatalogEvent.ON:CatalogEvent.OFF);
  390 + }
  391 + if (type != null) {
  392 + // 发送流变化redis消息
  393 + JSONObject jsonObject = new JSONObject();
  394 + jsonObject.put("serverId", userSetting.getServerId());
  395 + jsonObject.put("app", param.getApp());
  396 + jsonObject.put("stream", param.getStream());
  397 + jsonObject.put("register", param.isRegist());
  398 + jsonObject.put("mediaServerId", param.getMediaServerId());
  399 + redisCatchStorage.sendStreamChangeMsg(type, jsonObject);
391 400 }
392 401 }
393 402 }
... ... @@ -403,7 +412,8 @@ public class ZLMHttpHookListener {
403 412 try {
404 413 if (platform != null) {
405 414 commanderFroPlatform.streamByeCmd(platform, sendRtpItem);
406   - redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStreamId());
  415 + redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(),
  416 + sendRtpItem.getCallId(), sendRtpItem.getStreamId());
407 417 } else {
408 418 cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId());
409 419 }
... ... @@ -428,7 +438,8 @@ public class ZLMHttpHookListener {
428 438 @PostMapping(value = "/on_stream_none_reader", produces = "application/json;charset=UTF-8")
429 439 public JSONObject onStreamNoneReader(@RequestBody OnStreamNoneReaderHookParam param) {
430 440  
431   - logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream());
  441 + logger.info("[ZLM HOOK]流无人观看:{]->{}->{}/{}" + param.getMediaServerId(), param.getSchema(),
  442 + param.getApp(), param.getStream());
432 443 JSONObject ret = new JSONObject();
433 444 ret.put("code", 0);
434 445 // 国标类型的流
... ... @@ -440,7 +451,8 @@ public class ZLMHttpHookListener {
440 451 if (streamInfoForPlayCatch != null) {
441 452 // 收到无人观看说明流也没有在往上级推送
442 453 if (redisCatchStorage.isChannelSendingRTP(streamInfoForPlayCatch.getChannelId())) {
443   - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(streamInfoForPlayCatch.getChannelId());
  454 + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(
  455 + streamInfoForPlayCatch.getChannelId());
444 456 if (sendRtpItems.size() > 0) {
445 457 for (SendRtpItem sendRtpItem : sendRtpItems) {
446 458 ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
... ... @@ -470,7 +482,8 @@ public class ZLMHttpHookListener {
470 482 return ret;
471 483 }
472 484 // 录像回放
473   - StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null, param.getStream(), null);
  485 + StreamInfo streamInfoForPlayBackCatch = redisCatchStorage.queryPlayback(null, null,
  486 + param.getStream(), null);
474 487 if (streamInfoForPlayBackCatch != null) {
475 488 if (streamInfoForPlayBackCatch.isPause()) {
476 489 ret.put("close", false);
... ... @@ -491,7 +504,8 @@ public class ZLMHttpHookListener {
491 504 return ret;
492 505 }
493 506 // 录像下载
494   - StreamInfo streamInfoForDownload = redisCatchStorage.queryDownload(null, null, param.getStream(), null);
  507 + StreamInfo streamInfoForDownload = redisCatchStorage.queryDownload(null, null,
  508 + param.getStream(), null);
495 509 // 进行录像下载时无人观看不断流
496 510 if (streamInfoForDownload != null) {
497 511 ret.put("close", false);
... ...
src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java
... ... @@ -18,6 +18,10 @@ public class HookResult {
18 18 return new HookResult(0, "success");
19 19 }
20 20  
  21 + public static HookResult Fail(){
  22 + return new HookResult(-1, "fail");
  23 + }
  24 +
21 25 public int getCode() {
22 26 return code;
23 27 }
... ...
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
... ... @@ -24,6 +24,7 @@ import org.slf4j.Logger;
24 24 import org.slf4j.LoggerFactory;
25 25 import org.springframework.beans.factory.annotation.Autowired;
26 26 import org.springframework.data.redis.core.RedisTemplate;
  27 +import org.springframework.data.redis.core.StringRedisTemplate;
27 28 import org.springframework.stereotype.Component;
28 29  
29 30 import java.util.*;
... ... @@ -43,6 +44,9 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
43 44 @Autowired
44 45 private RedisTemplate<Object, Object> redisTemplate;
45 46  
  47 + @Autowired
  48 + private StringRedisTemplate stringRedisTemplate;
  49 +
46 50 @Override
47 51 public Long getCSEQ() {
48 52 String key = VideoManagerConstants.SIP_CSEQ_PREFIX + userSetting.getServerId();
... ... @@ -913,7 +917,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
913 917 msg.append(":").append(channelId);
914 918 }
915 919 msg.append(" ").append(online? "ON":"OFF");
916   -
917   - redisTemplate.convertAndSend(key, msg.toString());
  920 + // 使用 RedisTemplate<Object, Object> 发送字符串消息会导致发送的消息多带了双引号
  921 + stringRedisTemplate.convertAndSend(key, msg.toString());
918 922 }
919 923 }
... ...