Commit 3291c4b2e67d510186ca5fbfac8ec5af1a9d4f16

Authored by 648540858
1 parent 912c83df

修复多平台推流无人观看redis通知

src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -15,8 +15,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor @@ -15,8 +15,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor
15 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 15 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
16 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; 16 import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory;
17 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 17 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  18 +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
18 import com.genersoft.iot.vmp.service.*; 19 import com.genersoft.iot.vmp.service.*;
19 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; 20 import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
  21 +import com.genersoft.iot.vmp.service.bean.RequestStopPushStreamMsg;
  22 +import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener;
20 import com.genersoft.iot.vmp.storager.IRedisCatchStorage; 23 import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
21 import com.genersoft.iot.vmp.storager.IVideoManagerStorage; 24 import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
22 import gov.nist.javax.sip.message.SIPRequest; 25 import gov.nist.javax.sip.message.SIPRequest;
@@ -92,6 +95,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -92,6 +95,12 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
92 @Autowired 95 @Autowired
93 private UserSetting userSetting; 96 private UserSetting userSetting;
94 97
  98 + @Autowired
  99 + private IStreamPushService pushService;
  100 +
  101 + @Autowired
  102 + private RedisGbPlayMsgListener redisGbPlayMsgListener;
  103 +
95 @Override 104 @Override
96 public void afterPropertiesSet() throws Exception { 105 public void afterPropertiesSet() throws Exception {
97 // 添加消息处理的订阅 106 // 添加消息处理的订阅
@@ -124,58 +133,81 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -124,58 +133,81 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
124 param.put("stream",streamId); 133 param.put("stream",streamId);
125 param.put("ssrc",sendRtpItem.getSsrc()); 134 param.put("ssrc",sendRtpItem.getSsrc());
126 logger.info("[收到bye] 停止推流:{}, 媒体节点: {}", streamId, sendRtpItem.getMediaServerId()); 135 logger.info("[收到bye] 停止推流:{}, 媒体节点: {}", streamId, sendRtpItem.getMediaServerId());
127 - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());  
128 - redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(),  
129 - callIdHeader.getCallId(), null);  
130 - zlmServerFactory.stopSendRtpStream(mediaInfo, param);  
131 - if (userSetting.getUseCustomSsrcForParentInvite()) {  
132 - mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc());  
133 - } 136 +
134 if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) { 137 if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
135 - ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());  
136 - if (platform != null) {  
137 - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,  
138 - sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(),  
139 - sendRtpItem.getPlatformId(), platform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId());  
140 - messageForPushChannel.setPlatFormIndex(platform.getId());  
141 - redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); 138 + // 查询这路流是否是本平台的
  139 + StreamPushItem push = pushService.getPush(sendRtpItem.getApp(), sendRtpItem.getStream());
  140 + if (push!= null && !push.isSelf()) {
  141 + // 不是本平台的就发送redis消息让其他wvp停止发流
  142 + ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
  143 + if (platform != null) {
  144 + RequestStopPushStreamMsg streamMsg = RequestStopPushStreamMsg.getInstance(sendRtpItem, platform.getName(), platform.getId());
  145 + redisGbPlayMsgListener.sendMsgForStopSendRtpStream(sendRtpItem.getServerId(), streamMsg);
  146 + }
142 }else { 147 }else {
143 - logger.info("[上级平台停止观看] 未找到平台{}的信息,发送redis消息失败", sendRtpItem.getPlatformId());  
144 - }  
145 - } 148 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  149 + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(),
  150 + callIdHeader.getCallId(), null);
  151 + zlmServerFactory.stopSendRtpStream(mediaInfo, param);
  152 + if (userSetting.getUseCustomSsrcForParentInvite()) {
  153 + mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc());
  154 + }
146 155
147 - AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());  
148 - if (audioBroadcastCatch != null && audioBroadcastCatch.getSipTransactionInfo().getCallId().equals(callIdHeader.getCallId())) {  
149 - // 来自上级平台的停止对讲  
150 - logger.info("[停止对讲] 来自上级,平台:{}, 通道:{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());  
151 - audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); 156 + ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
  157 + if (platform != null) {
  158 + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
  159 + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(),
  160 + sendRtpItem.getPlatformId(), platform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId());
  161 + messageForPushChannel.setPlatFormIndex(platform.getId());
  162 + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel);
  163 + }else {
  164 + logger.info("[上级平台停止观看] 未找到平台{}的信息,发送redis消息失败", sendRtpItem.getPlatformId());
  165 + }
  166 + }
  167 + }else {
  168 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  169 + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(),
  170 + callIdHeader.getCallId(), null);
  171 + zlmServerFactory.stopSendRtpStream(mediaInfo, param);
  172 + if (userSetting.getUseCustomSsrcForParentInvite()) {
  173 + mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc());
  174 + }
152 } 175 }
  176 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  177 + if (mediaInfo != null) {
  178 + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
  179 + if (audioBroadcastCatch != null && audioBroadcastCatch.getSipTransactionInfo().getCallId().equals(callIdHeader.getCallId())) {
  180 + // 来自上级平台的停止对讲
  181 + logger.info("[停止对讲] 来自上级,平台:{}, 通道:{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
  182 + audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
  183 + }
153 184
154 - int totalReaderCount = zlmServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);  
155 - if (totalReaderCount <= 0) {  
156 - logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);  
157 - if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {  
158 - Device device = deviceService.getDevice(sendRtpItem.getDeviceId());  
159 - if (device == null) {  
160 - logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);  
161 - }  
162 - try {  
163 - logger.info("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());  
164 - cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null);  
165 - } catch (InvalidArgumentException | ParseException | SipException |  
166 - SsrcTransactionNotFoundException e) {  
167 - logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage()); 185 + int totalReaderCount = zlmServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
  186 + if (totalReaderCount <= 0) {
  187 + logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
  188 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
  189 + Device device = deviceService.getDevice(sendRtpItem.getDeviceId());
  190 + if (device == null) {
  191 + logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);
  192 + }
  193 + try {
  194 + logger.info("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
  195 + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null);
  196 + } catch (InvalidArgumentException | ParseException | SipException |
  197 + SsrcTransactionNotFoundException e) {
  198 + logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());
  199 + }
168 } 200 }
169 } 201 }
170 } 202 }
171 } 203 }
172 204
173 - // 可能是设备发送的停止  
174 - SsrcTransaction ssrcTransaction = streamSession.getSsrcTransactionByCallId(callIdHeader.getCallId());  
175 - if (ssrcTransaction == null) {  
176 - return;  
177 - }  
178 - logger.info("[收到bye] 来自设备:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId()); 205 + // 可能是设备发送的停止
  206 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransactionByCallId(callIdHeader.getCallId());
  207 + if (ssrcTransaction == null) {
  208 + return;
  209 + }
  210 + logger.info("[收到bye] 来自设备:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
179 211
180 ParentPlatform platform = platformService.queryPlatformByServerGBId(ssrcTransaction.getDeviceId()); 212 ParentPlatform platform = platformService.queryPlatformByServerGBId(ssrcTransaction.getDeviceId());
181 if (platform != null ) { 213 if (platform != null ) {
src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java
@@ -579,7 +579,7 @@ public class ZLMHttpHookListener { @@ -579,7 +579,7 @@ public class ZLMHttpHookListener {
579 } 579 }
580 // 收到无人观看说明流也没有在往上级推送 580 // 收到无人观看说明流也没有在往上级推送
581 if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { 581 if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) {
582 - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId( 582 + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChannelId(
583 inviteInfo.getChannelId()); 583 inviteInfo.getChannelId());
584 if (!sendRtpItems.isEmpty()) { 584 if (!sendRtpItems.isEmpty()) {
585 for (SendRtpItem sendRtpItem : sendRtpItems) { 585 for (SendRtpItem sendRtpItem : sendRtpItems) {
src/main/java/com/genersoft/iot/vmp/service/bean/RequestStopPushStreamMsg.java 0 → 100755
  1 +package com.genersoft.iot.vmp.service.bean;
  2 +
  3 +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  4 +
  5 +
  6 +public class RequestStopPushStreamMsg {
  7 +
  8 +
  9 + private SendRtpItem sendRtpItem;
  10 +
  11 +
  12 + private String platformName;
  13 +
  14 +
  15 + private int platFormIndex;
  16 +
  17 + public SendRtpItem getSendRtpItem() {
  18 + return sendRtpItem;
  19 + }
  20 +
  21 + public void setSendRtpItem(SendRtpItem sendRtpItem) {
  22 + this.sendRtpItem = sendRtpItem;
  23 + }
  24 +
  25 + public String getPlatformName() {
  26 + return platformName;
  27 + }
  28 +
  29 + public void setPlatformName(String platformName) {
  30 + this.platformName = platformName;
  31 + }
  32 +
  33 +
  34 + public int getPlatFormIndex() {
  35 + return platFormIndex;
  36 + }
  37 +
  38 + public void setPlatFormIndex(int platFormIndex) {
  39 + this.platFormIndex = platFormIndex;
  40 + }
  41 +
  42 + public static RequestStopPushStreamMsg getInstance(SendRtpItem sendRtpItem, String platformName, int platFormIndex) {
  43 + RequestStopPushStreamMsg streamMsg = new RequestStopPushStreamMsg();
  44 + streamMsg.setSendRtpItem(sendRtpItem);
  45 + streamMsg.setPlatformName(platformName);
  46 + streamMsg.setPlatFormIndex(platFormIndex);
  47 + return streamMsg;
  48 + }
  49 +}
src/main/java/com/genersoft/iot/vmp/service/bean/WvpRedisMsgCmd.java
@@ -6,7 +6,17 @@ package com.genersoft.iot.vmp.service.bean; @@ -6,7 +6,17 @@ package com.genersoft.iot.vmp.service.bean;
6 6
7 public class WvpRedisMsgCmd { 7 public class WvpRedisMsgCmd {
8 8
  9 + /**
  10 + * 请求获取推流信息
  11 + */
9 public static final String GET_SEND_ITEM = "GetSendItem"; 12 public static final String GET_SEND_ITEM = "GetSendItem";
  13 + /**
  14 + * 请求推流的请求
  15 + */
10 public static final String REQUEST_PUSH_STREAM = "RequestPushStream"; 16 public static final String REQUEST_PUSH_STREAM = "RequestPushStream";
  17 + /**
  18 + * 停止推流的请求
  19 + */
  20 + public static final String REQUEST_STOP_PUSH_STREAM = "RequestStopPushStream";
11 21
12 } 22 }
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java
@@ -133,7 +133,10 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -133,7 +133,10 @@ public class RedisGbPlayMsgListener implements MessageListener {
133 case WvpRedisMsgCmd.REQUEST_PUSH_STREAM: 133 case WvpRedisMsgCmd.REQUEST_PUSH_STREAM:
134 RequestPushStreamMsg param = JSON.to(RequestPushStreamMsg.class, wvpRedisMsg.getContent()); 134 RequestPushStreamMsg param = JSON.to(RequestPushStreamMsg.class, wvpRedisMsg.getContent());
135 requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial()); 135 requestPushStreamMsgHand(param, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
136 - 136 + break;
  137 + case WvpRedisMsgCmd.REQUEST_STOP_PUSH_STREAM:
  138 + RequestStopPushStreamMsg streamMsg = JSON.to(RequestStopPushStreamMsg.class, wvpRedisMsg.getContent());
  139 + requestStopPushStreamMsgHand(streamMsg, wvpRedisMsg.getFromId(), wvpRedisMsg.getSerial());
137 break; 140 break;
138 default: 141 default:
139 break; 142 break;
@@ -397,6 +400,19 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -397,6 +400,19 @@ public class RedisGbPlayMsgListener implements MessageListener {
397 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject); 400 redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
398 } 401 }
399 402
  403 + /**
  404 + * 发送请求推流的消息
  405 + */
  406 + public void sendMsgForStopSendRtpStream(String serverId, RequestStopPushStreamMsg streamMsg) {
  407 + String key = UUID.randomUUID().toString();
  408 + WvpRedisMsg redisMsg = WvpRedisMsg.getRequestInstance(userSetting.getServerId(), serverId,
  409 + WvpRedisMsgCmd.REQUEST_STOP_PUSH_STREAM, key, JSON.toJSONString(streamMsg));
  410 +
  411 + JSONObject jsonObject = (JSONObject)JSON.toJSON(redisMsg);
  412 + logger.info("[REDIS 请求其他平台停止推流] {}: {}", serverId, jsonObject);
  413 + redisTemplate.convertAndSend(WVP_PUSH_STREAM_KEY, jsonObject);
  414 + }
  415 +
400 private SendRtpItem querySendRTPServer(String platformGbId, String channelId, String streamId, String callId) { 416 private SendRtpItem querySendRTPServer(String platformGbId, String channelId, String streamId, String callId) {
401 if (platformGbId == null) { 417 if (platformGbId == null) {
402 platformGbId = "*"; 418 platformGbId = "*";
@@ -423,4 +439,36 @@ public class RedisGbPlayMsgListener implements MessageListener { @@ -423,4 +439,36 @@ public class RedisGbPlayMsgListener implements MessageListener {
423 return null; 439 return null;
424 } 440 }
425 } 441 }
  442 +
  443 + /**
  444 + * 处理收到的请求推流的请求
  445 + */
  446 + private void requestStopPushStreamMsgHand(RequestStopPushStreamMsg streamMsg, String fromId, String serial) {
  447 + SendRtpItem sendRtpItem = streamMsg.getSendRtpItem();
  448 + if (sendRtpItem == null) {
  449 + logger.info("[REDIS 执行其他平台的请求停止推流] 失败: sendRtpItem为NULL");
  450 + return;
  451 + }
  452 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  453 + if (mediaInfo == null) {
  454 + // TODO 回复错误
  455 + return;
  456 + }
  457 + Map<String, Object> param = new HashMap<>();
  458 + param.put("vhost","__defaultVhost__");
  459 + param.put("app",sendRtpItem.getApp());
  460 + param.put("stream",sendRtpItem.getStream());
  461 + param.put("ssrc", sendRtpItem.getSsrc());
  462 +
  463 + if (zlmServerFactory.stopSendRtpStream(mediaInfo, param)) {
  464 + logger.info("[REDIS 执行其他平台的请求停止推流] 成功: {}/{}", sendRtpItem.getApp(), sendRtpItem.getStream());
  465 + // 发送redis消息
  466 + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
  467 + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(),
  468 + sendRtpItem.getPlatformId(), streamMsg.getPlatformName(), userSetting.getServerId(), sendRtpItem.getMediaServerId());
  469 + messageForPushChannel.setPlatFormIndex(streamMsg.getPlatFormIndex());
  470 + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel);
  471 + }
  472 +
  473 + }
426 } 474 }
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java
@@ -73,7 +73,7 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { @@ -73,7 +73,7 @@ public class RedisPushStreamCloseResponseListener implements MessageListener {
73 MessageForPushChannel pushChannel = JSON.parseObject(message.getBody(), MessageForPushChannel.class); 73 MessageForPushChannel pushChannel = JSON.parseObject(message.getBody(), MessageForPushChannel.class);
74 StreamPushItem push = streamPushService.getPush(pushChannel.getApp(), pushChannel.getStream()); 74 StreamPushItem push = streamPushService.getPush(pushChannel.getApp(), pushChannel.getStream());
75 if (push != null) { 75 if (push != null) {
76 - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId( 76 + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChannelId(
77 push.getGbId()); 77 push.getGbId());
78 if (!sendRtpItems.isEmpty()) { 78 if (!sendRtpItems.isEmpty()) {
79 for (SendRtpItem sendRtpItem : sendRtpItems) { 79 for (SendRtpItem sendRtpItem : sendRtpItems) {
src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java
@@ -181,7 +181,7 @@ public interface IRedisCatchStorage { @@ -181,7 +181,7 @@ public interface IRedisCatchStorage {
181 */ 181 */
182 void sendStreamPushRequestedMsgForStatus(); 182 void sendStreamPushRequestedMsgForStatus();
183 183
184 - List<SendRtpItem> querySendRTPServerByChnnelId(String channelId); 184 + List<SendRtpItem> querySendRTPServerByChannelId(String channelId);
185 185
186 List<SendRtpItem> querySendRTPServerByStream(String stream); 186 List<SendRtpItem> querySendRTPServerByStream(String stream);
187 187
src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java
@@ -184,7 +184,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage { @@ -184,7 +184,7 @@ public class RedisCatchStorageImpl implements IRedisCatchStorage {
184 } 184 }
185 185
186 @Override 186 @Override
187 - public List<SendRtpItem> querySendRTPServerByChnnelId(String channelId) { 187 + public List<SendRtpItem> querySendRTPServerByChannelId(String channelId) {
188 if (channelId == null) { 188 if (channelId == null) {
189 return null; 189 return null;
190 } 190 }