Commit def56793ba7c636fbbcabad38e3ac113a3764087
1 parent
a77628e8
增加上级推流和停止推流的通知
Showing
9 changed files
with
151 additions
and
14 deletions
src/main/java/com/genersoft/iot/vmp/conf/redis/RedisMsgListenConfig.java
| @@ -63,6 +63,7 @@ public class RedisMsgListenConfig { | @@ -63,6 +63,7 @@ public class RedisMsgListenConfig { | ||
| 63 | container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE)); | 63 | container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE)); |
| 64 | container.addMessageListener(redisPushStreamListMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_LIST_CHANGE)); | 64 | container.addMessageListener(redisPushStreamListMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_LIST_CHANGE)); |
| 65 | container.addMessageListener(redisPushStreamResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_RESPONSE)); | 65 | container.addMessageListener(redisPushStreamResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_RESPONSE)); |
| 66 | +// container.addMessageListener(, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE_REQUESTED)); | ||
| 66 | return container; | 67 | return container; |
| 67 | } | 68 | } |
| 68 | } | 69 | } |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java
| @@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | @@ -3,6 +3,8 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl; | ||
| 3 | import com.alibaba.fastjson2.JSON; | 3 | import com.alibaba.fastjson2.JSON; |
| 4 | import com.alibaba.fastjson2.JSONObject; | 4 | import com.alibaba.fastjson2.JSONObject; |
| 5 | import com.genersoft.iot.vmp.conf.DynamicTask; | 5 | import com.genersoft.iot.vmp.conf.DynamicTask; |
| 6 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 7 | +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType; | ||
| 6 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; | 8 | import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; |
| 7 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | 9 | import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; |
| 8 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| @@ -14,6 +16,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | @@ -14,6 +16,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | ||
| 14 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; | 16 | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| 15 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 17 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 16 | import com.genersoft.iot.vmp.service.IMediaServerService; | 18 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 19 | +import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | ||
| 17 | import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; | 20 | import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; |
| 18 | import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; | 21 | import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; |
| 19 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 22 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| @@ -58,6 +61,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -58,6 +61,9 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 58 | private IRedisCatchStorage redisCatchStorage; | 61 | private IRedisCatchStorage redisCatchStorage; |
| 59 | 62 | ||
| 60 | @Autowired | 63 | @Autowired |
| 64 | + private UserSetting userSetting; | ||
| 65 | + | ||
| 66 | + @Autowired | ||
| 61 | private IVideoManagerStorage storager; | 67 | private IVideoManagerStorage storager; |
| 62 | 68 | ||
| 63 | @Autowired | 69 | @Autowired |
| @@ -155,6 +161,13 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | @@ -155,6 +161,13 @@ public class AckRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 155 | } else if (jsonObject.getInteger("code") == 0) { | 161 | } else if (jsonObject.getInteger("code") == 0) { |
| 156 | logger.info("调用ZLM推流接口, 结果: {}", jsonObject); | 162 | logger.info("调用ZLM推流接口, 结果: {}", jsonObject); |
| 157 | logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); | 163 | logger.info("RTP推流成功[ {}/{} ],{}->{}:{}, " ,param.get("app"), param.get("stream"), jsonObject.getString("local_port"), param.get("dst_url"), param.get("dst_port")); |
| 164 | + if (sendRtpItem.getPlayType() == InviteStreamType.PUSH) { | ||
| 165 | + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, sendRtpItem.getApp(), sendRtpItem.getStreamId(), | ||
| 166 | + sendRtpItem.getChannelId(), parentPlatform.getServerGBId(), parentPlatform.getName(), userSetting.getServerId(), | ||
| 167 | + sendRtpItem.getMediaServerId()); | ||
| 168 | + messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); | ||
| 169 | + redisCatchStorage.sendPlatformStartPlayMsg(messageForPushChannel); | ||
| 170 | + } | ||
| 158 | } else { | 171 | } else { |
| 159 | logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"), JSON.toJSONString(param)); | 172 | logger.error("RTP推流失败: {}, 参数:{}",jsonObject.getString("msg"), JSON.toJSONString(param)); |
| 160 | if (sendRtpItem.isOnlyAudio()) { | 173 | if (sendRtpItem.isOnlyAudio()) { |
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.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.genersoft.iot.vmp.common.StreamInfo; | 3 | import com.genersoft.iot.vmp.common.StreamInfo; |
| 4 | +import com.genersoft.iot.vmp.conf.UserSetting; | ||
| 4 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; | 5 | import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; |
| 5 | -import com.genersoft.iot.vmp.gb28181.bean.Device; | ||
| 6 | -import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType; | ||
| 7 | -import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; | ||
| 8 | -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; | 6 | +import com.genersoft.iot.vmp.gb28181.bean.*; |
| 9 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; | 7 | import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; |
| 10 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; | 8 | import com.genersoft.iot.vmp.gb28181.transmit.SIPProcessorObserver; |
| 11 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; | 9 | import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; |
| @@ -15,6 +13,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | @@ -15,6 +13,7 @@ import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; | ||
| 15 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; | 13 | import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; |
| 16 | import com.genersoft.iot.vmp.service.IDeviceService; | 14 | import com.genersoft.iot.vmp.service.IDeviceService; |
| 17 | import com.genersoft.iot.vmp.service.IMediaServerService; | 15 | import com.genersoft.iot.vmp.service.IMediaServerService; |
| 16 | +import com.genersoft.iot.vmp.service.IPlatformService; | ||
| 18 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | 17 | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| 19 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 18 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 20 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 19 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| @@ -25,7 +24,9 @@ import org.springframework.beans.factory.InitializingBean; | @@ -25,7 +24,9 @@ import org.springframework.beans.factory.InitializingBean; | ||
| 25 | import org.springframework.beans.factory.annotation.Autowired; | 24 | import org.springframework.beans.factory.annotation.Autowired; |
| 26 | import org.springframework.stereotype.Component; | 25 | import org.springframework.stereotype.Component; |
| 27 | 26 | ||
| 28 | -import javax.sip.*; | 27 | +import javax.sip.InvalidArgumentException; |
| 28 | +import javax.sip.RequestEvent; | ||
| 29 | +import javax.sip.SipException; | ||
| 29 | import javax.sip.address.SipURI; | 30 | import javax.sip.address.SipURI; |
| 30 | import javax.sip.header.CallIdHeader; | 31 | import javax.sip.header.CallIdHeader; |
| 31 | import javax.sip.header.FromHeader; | 32 | import javax.sip.header.FromHeader; |
| @@ -52,6 +53,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -52,6 +53,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 52 | private IRedisCatchStorage redisCatchStorage; | 53 | private IRedisCatchStorage redisCatchStorage; |
| 53 | 54 | ||
| 54 | @Autowired | 55 | @Autowired |
| 56 | + private IPlatformService platformService; | ||
| 57 | + | ||
| 58 | + @Autowired | ||
| 55 | private IDeviceService deviceService; | 59 | private IDeviceService deviceService; |
| 56 | 60 | ||
| 57 | @Autowired | 61 | @Autowired |
| @@ -69,6 +73,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -69,6 +73,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 69 | @Autowired | 73 | @Autowired |
| 70 | private VideoStreamSessionManager streamSession; | 74 | private VideoStreamSessionManager streamSession; |
| 71 | 75 | ||
| 76 | + @Autowired | ||
| 77 | + private UserSetting userSetting; | ||
| 78 | + | ||
| 72 | @Override | 79 | @Override |
| 73 | public void afterPropertiesSet() throws Exception { | 80 | public void afterPropertiesSet() throws Exception { |
| 74 | // 添加消息处理的订阅 | 81 | // 添加消息处理的订阅 |
| @@ -103,6 +110,19 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -103,6 +110,19 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 103 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); | 110 | MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); |
| 104 | redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null); | 111 | redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null); |
| 105 | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); | 112 | zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); |
| 113 | + if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { | ||
| 114 | + ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); | ||
| 115 | + if (platform != null) { | ||
| 116 | + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | ||
| 117 | + sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), | ||
| 118 | + sendRtpItem.getPlatformId(), platform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); | ||
| 119 | + messageForPushChannel.setPlatFormIndex(platform.getId()); | ||
| 120 | + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); | ||
| 121 | + }else { | ||
| 122 | + logger.info("[上级平台停止观看] 未找到平台{}的信息,发送redis消息失败", sendRtpItem.getPlatformId()); | ||
| 123 | + } | ||
| 124 | + } | ||
| 125 | + | ||
| 106 | int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); | 126 | int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId); |
| 107 | if (totalReaderCount <= 0) { | 127 | if (totalReaderCount <= 0) { |
| 108 | logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); | 128 | logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId); |
| @@ -119,12 +139,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | @@ -119,12 +139,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In | ||
| 119 | logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); | 139 | logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); |
| 120 | } | 140 | } |
| 121 | } | 141 | } |
| 122 | - if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { | ||
| 123 | - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | ||
| 124 | - sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), | ||
| 125 | - sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); | ||
| 126 | - redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); | ||
| 127 | - } | 142 | +// if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { |
| 143 | +// MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | ||
| 144 | +// sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), | ||
| 145 | +// sendRtpItem.getPlatformId(), null, null, sendRtpItem.getMediaServerId()); | ||
| 146 | +// redisCatchStorage.sendStreamPushRequestedMsg(messageForPushChannel); | ||
| 147 | +// } | ||
| 128 | } | 148 | } |
| 129 | } | 149 | } |
| 130 | // 可能是设备主动停止 | 150 | // 可能是设备主动停止 |
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
| @@ -19,6 +19,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; | @@ -19,6 +19,7 @@ import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; | ||
| 19 | import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; | 19 | import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; |
| 20 | import com.genersoft.iot.vmp.media.zlm.dto.hook.*; | 20 | import com.genersoft.iot.vmp.media.zlm.dto.hook.*; |
| 21 | import com.genersoft.iot.vmp.service.*; | 21 | import com.genersoft.iot.vmp.service.*; |
| 22 | +import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; | ||
| 22 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; | 23 | import com.genersoft.iot.vmp.storager.IRedisCatchStorage; |
| 23 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; | 24 | import com.genersoft.iot.vmp.storager.IVideoManagerStorage; |
| 24 | import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; | 25 | import com.genersoft.iot.vmp.vmanager.bean.DeferredResultEx; |
| @@ -463,6 +464,13 @@ public class ZLMHttpHookListener { | @@ -463,6 +464,13 @@ public class ZLMHttpHookListener { | ||
| 463 | } | 464 | } |
| 464 | redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), | 465 | redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), |
| 465 | sendRtpItem.getCallId(), sendRtpItem.getStreamId()); | 466 | sendRtpItem.getCallId(), sendRtpItem.getStreamId()); |
| 467 | + if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) { | ||
| 468 | + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, | ||
| 469 | + sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(), | ||
| 470 | + sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); | ||
| 471 | + messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); | ||
| 472 | + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); | ||
| 473 | + } | ||
| 466 | } | 474 | } |
| 467 | } | 475 | } |
| 468 | } | 476 | } |
src/main/java/com/genersoft/iot/vmp/service/bean/MessageForPushChannel.java
| @@ -34,7 +34,7 @@ public class MessageForPushChannel { | @@ -34,7 +34,7 @@ public class MessageForPushChannel { | ||
| 34 | /** | 34 | /** |
| 35 | * 请求的平台自增ID | 35 | * 请求的平台自增ID |
| 36 | */ | 36 | */ |
| 37 | - private String platFormIndex; | 37 | + private int platFormIndex; |
| 38 | 38 | ||
| 39 | /** | 39 | /** |
| 40 | * 请求平台名称 | 40 | * 请求平台名称 |
| @@ -132,11 +132,11 @@ public class MessageForPushChannel { | @@ -132,11 +132,11 @@ public class MessageForPushChannel { | ||
| 132 | this.mediaServerId = mediaServerId; | 132 | this.mediaServerId = mediaServerId; |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | - public String getPlatFormIndex() { | 135 | + public int getPlatFormIndex() { |
| 136 | return platFormIndex; | 136 | return platFormIndex; |
| 137 | } | 137 | } |
| 138 | 138 | ||
| 139 | - public void setPlatFormIndex(String platFormIndex) { | 139 | + public void setPlatFormIndex(int platFormIndex) { |
| 140 | this.platFormIndex = platFormIndex; | 140 | this.platFormIndex = platFormIndex; |
| 141 | } | 141 | } |
| 142 | } | 142 | } |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
| @@ -129,6 +129,7 @@ public class RedisGbPlayMsgListener implements MessageListener { | @@ -129,6 +129,7 @@ public class RedisGbPlayMsgListener implements MessageListener { | ||
| 129 | case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: | 129 | case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: |
| 130 | RequestPushStreamMsg param = JSON.to(RequestPushStreamMsg.class, wvpRedisMsg.getContent()); | 130 | RequestPushStreamMsg param = JSON.to(RequestPushStreamMsg.class, wvpRedisMsg.getContent()); |
| 131 | requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); | 131 | requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); |
| 132 | + | ||
| 132 | break; | 133 | break; |
| 133 | default: | 134 | default: |
| 134 | break; | 135 | break; |
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java
0 → 100644
| 1 | +package com.genersoft.iot.vmp.service.redisMsg; | ||
| 2 | + | ||
| 3 | +import com.alibaba.fastjson2.JSON; | ||
| 4 | +import com.genersoft.iot.vmp.service.bean.MessageForPushChannelResponse; | ||
| 5 | +import org.slf4j.Logger; | ||
| 6 | +import org.slf4j.LoggerFactory; | ||
| 7 | +import org.springframework.beans.factory.annotation.Autowired; | ||
| 8 | +import org.springframework.beans.factory.annotation.Qualifier; | ||
| 9 | +import org.springframework.data.redis.connection.Message; | ||
| 10 | +import org.springframework.data.redis.connection.MessageListener; | ||
| 11 | +import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; | ||
| 12 | +import org.springframework.stereotype.Component; | ||
| 13 | +import org.springframework.util.ObjectUtils; | ||
| 14 | + | ||
| 15 | +import java.util.Map; | ||
| 16 | +import java.util.concurrent.ConcurrentHashMap; | ||
| 17 | +import java.util.concurrent.ConcurrentLinkedQueue; | ||
| 18 | + | ||
| 19 | +/** | ||
| 20 | + * 接收redis发送的结束推流请求 | ||
| 21 | + * @author lin | ||
| 22 | + */ | ||
| 23 | +@Component | ||
| 24 | +public class RedisPushStreamCloseResponseListener implements MessageListener { | ||
| 25 | + | ||
| 26 | + private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamCloseResponseListener.class); | ||
| 27 | + | ||
| 28 | + private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); | ||
| 29 | + | ||
| 30 | + @Qualifier("taskExecutor") | ||
| 31 | + @Autowired | ||
| 32 | + private ThreadPoolTaskExecutor taskExecutor; | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + private Map<String, PushStreamResponseEvent> responseEvents = new ConcurrentHashMap<>(); | ||
| 36 | + | ||
| 37 | + public interface PushStreamResponseEvent{ | ||
| 38 | + void run(MessageForPushChannelResponse response); | ||
| 39 | + } | ||
| 40 | + | ||
| 41 | + @Override | ||
| 42 | + public void onMessage(Message message, byte[] bytes) { | ||
| 43 | + logger.info("[REDIS消息-请求推流结果]: {}", new String(message.getBody())); | ||
| 44 | + boolean isEmpty = taskQueue.isEmpty(); | ||
| 45 | + taskQueue.offer(message); | ||
| 46 | + if (isEmpty) { | ||
| 47 | + taskExecutor.execute(() -> { | ||
| 48 | + while (!taskQueue.isEmpty()) { | ||
| 49 | + Message msg = taskQueue.poll(); | ||
| 50 | + try { | ||
| 51 | + MessageForPushChannelResponse response = JSON.parseObject(new String(msg.getBody()), MessageForPushChannelResponse.class); | ||
| 52 | + if (response == null || ObjectUtils.isEmpty(response.getApp()) || ObjectUtils.isEmpty(response.getStream())){ | ||
| 53 | + logger.info("[REDIS消息-请求推流结果]:参数不全"); | ||
| 54 | + continue; | ||
| 55 | + } | ||
| 56 | + // 查看正在等待的invite消息 | ||
| 57 | + if (responseEvents.get(response.getApp() + response.getStream()) != null) { | ||
| 58 | + responseEvents.get(response.getApp() + response.getStream()).run(response); | ||
| 59 | + } | ||
| 60 | + }catch (Exception e) { | ||
| 61 | + logger.warn("[REDIS消息-请求推流结果] 发现未处理的异常, \r\n{}", JSON.toJSONString(message)); | ||
| 62 | + logger.error("[REDIS消息-请求推流结果] 异常内容: ", e); | ||
| 63 | + } | ||
| 64 | + } | ||
| 65 | + }); | ||
| 66 | + } | ||
| 67 | + } | ||
| 68 | + | ||
| 69 | + public void addEvent(String app, String stream, PushStreamResponseEvent callback) { | ||
| 70 | + responseEvents.put(app + stream, callback); | ||
| 71 | + } | ||
| 72 | + | ||
| 73 | + public void removeEvent(String app, String stream) { | ||
| 74 | + responseEvents.remove(app + stream); | ||
| 75 | + } | ||
| 76 | +} |
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
| @@ -263,4 +263,8 @@ public interface IRedisCatchStorage { | @@ -263,4 +263,8 @@ public interface IRedisCatchStorage { | ||
| 263 | void removeAllDevice(); | 263 | void removeAllDevice(); |
| 264 | 264 | ||
| 265 | void sendDeviceOrChannelStatus(String deviceId, String channelId, boolean online); | 265 | void sendDeviceOrChannelStatus(String deviceId, String channelId, boolean online); |
| 266 | + | ||
| 267 | + void sendPlatformStartPlayMsg(MessageForPushChannel messageForPushChannel); | ||
| 268 | + | ||
| 269 | + void sendPlatformStopPlayMsg(MessageForPushChannel messageForPushChannel); | ||
| 266 | } | 270 | } |
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
| @@ -925,4 +925,18 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | @@ -925,4 +925,18 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { | ||
| 925 | // 使用 RedisTemplate<Object, Object> 发送字符串消息会导致发送的消息多带了双引号 | 925 | // 使用 RedisTemplate<Object, Object> 发送字符串消息会导致发送的消息多带了双引号 |
| 926 | stringRedisTemplate.convertAndSend(key, msg.toString()); | 926 | stringRedisTemplate.convertAndSend(key, msg.toString()); |
| 927 | } | 927 | } |
| 928 | + | ||
| 929 | + @Override | ||
| 930 | + public void sendPlatformStartPlayMsg(MessageForPushChannel msg) { | ||
| 931 | + String key = VideoManagerConstants.VM_MSG_STREAM_START_PLAY_NOTIFY; | ||
| 932 | + logger.info("[redis发送通知] 推流被上级平台观看 {}: {}/{}->{}", key, msg.getApp(), msg.getStream(), msg.getPlatFormId()); | ||
| 933 | + redisTemplate.convertAndSend(key, JSON.toJSON(msg)); | ||
| 934 | + } | ||
| 935 | + | ||
| 936 | + @Override | ||
| 937 | + public void sendPlatformStopPlayMsg(MessageForPushChannel msg) { | ||
| 938 | + String key = VideoManagerConstants.VM_MSG_STREAM_STOP_PLAY_NOTIFY; | ||
| 939 | + logger.info("[redis发送通知] 上级平台停止观看 {}: {}/{}->{}", key, msg.getApp(), msg.getStream(), msg.getPlatFormId()); | ||
| 940 | + redisTemplate.convertAndSend(key, JSON.toJSON(msg)); | ||
| 941 | + } | ||
| 928 | } | 942 | } |