Commit bfae9780f75db7495f53511f3116bb6c0470a0b0

Authored by 648540858
1 parent def56793

增加流关闭时的处理

src/main/java/com/genersoft/iot/vmp/conf/redis/RedisMsgListenConfig.java
@@ -43,6 +43,9 @@ public class RedisMsgListenConfig { @@ -43,6 +43,9 @@ public class RedisMsgListenConfig {
43 @Autowired 43 @Autowired
44 private RedisPushStreamResponseListener redisPushStreamResponseListener; 44 private RedisPushStreamResponseListener redisPushStreamResponseListener;
45 45
  46 + @Autowired
  47 + private RedisPushStreamCloseResponseListener redisPushStreamCloseResponseListener;
  48 +
46 49
47 /** 50 /**
48 * redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器 51 * redis消息监听器容器 可以添加多个监听不同话题的redis监听器,只需要把消息监听器和相应的消息订阅处理器绑定,该消息监听器
@@ -63,7 +66,7 @@ public class RedisMsgListenConfig { @@ -63,7 +66,7 @@ public class RedisMsgListenConfig {
63 container.addMessageListener(redisPushStreamStatusMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_STATUS_CHANGE)); 66 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)); 67 container.addMessageListener(redisPushStreamListMsgListener, new PatternTopic(VideoManagerConstants.VM_MSG_PUSH_STREAM_LIST_CHANGE));
65 container.addMessageListener(redisPushStreamResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_RESPONSE)); 68 container.addMessageListener(redisPushStreamResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_RESPONSE));
66 -// container.addMessageListener(, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE_REQUESTED)); 69 + container.addMessageListener(redisPushStreamCloseResponseListener, new PatternTopic(VideoManagerConstants.VM_MSG_STREAM_PUSH_CLOSE_REQUESTED));
67 return container; 70 return container;
68 } 71 }
69 } 72 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/SIPRequestHeaderPlarformProvider.java
@@ -283,7 +283,7 @@ public class SIPRequestHeaderPlarformProvider { @@ -283,7 +283,7 @@ public class SIPRequestHeaderPlarformProvider {
283 viaHeader.setRPort(); 283 viaHeader.setRPort();
284 viaHeaders.add(viaHeader); 284 viaHeaders.add(viaHeader);
285 // from 285 // from
286 - SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(platform.getDeviceGBId(), 286 + SipURI fromSipURI = SipFactory.getInstance().createAddressFactory().createSipURI(sendRtpItem.getChannelId(),
287 platform.getDeviceIp() + ":" + platform.getDevicePort()); 287 platform.getDeviceIp() + ":" + platform.getDevicePort());
288 Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI); 288 Address fromAddress = SipFactory.getInstance().createAddressFactory().createAddress(fromSipURI);
289 FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag()); 289 FromHeader fromHeader = SipFactory.getInstance().createHeaderFactory().createFromHeader(fromAddress, sendRtpItem.getToTag());
@@ -296,13 +296,10 @@ public class SIPRequestHeaderPlarformProvider { @@ -296,13 +296,10 @@ public class SIPRequestHeaderPlarformProvider {
296 MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70); 296 MaxForwardsHeader maxForwards = SipFactory.getInstance().createHeaderFactory().createMaxForwardsHeader(70);
297 // ceq 297 // ceq
298 CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE); 298 CSeqHeader cSeqHeader = SipFactory.getInstance().createHeaderFactory().createCSeqHeader(redisCatchStorage.getCSEQ(), Request.BYE);
299 - MessageFactoryImpl messageFactory = (MessageFactoryImpl) SipFactory.getInstance().createMessageFactory();  
300 - // 设置编码, 防止中文乱码  
301 - messageFactory.setDefaultContentEncodingCharset("gb2312");  
302 299
303 CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId()); 300 CallIdHeader callIdHeader = SipFactory.getInstance().createHeaderFactory().createCallIdHeader(sendRtpItem.getCallId());
304 301
305 - request = (SIPRequest) messageFactory.createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader, 302 + request = (SIPRequest) SipFactory.getInstance().createMessageFactory().createRequest(requestURI, Request.BYE, callIdHeader, cSeqHeader, fromHeader,
306 toHeader, viaHeaders, maxForwards); 303 toHeader, viaHeaders, maxForwards);
307 304
308 request.addHeader(SipUtils.createUserAgentHeader(gitUtil)); 305 request.addHeader(SipUtils.createUserAgentHeader(gitUtil));
@@ -310,6 +307,7 @@ public class SIPRequestHeaderPlarformProvider { @@ -310,6 +307,7 @@ public class SIPRequestHeaderPlarformProvider {
310 String sipAddress = platform.getDeviceIp() + ":" + platform.getDevicePort(); 307 String sipAddress = platform.getDeviceIp() + ":" + platform.getDevicePort();
311 Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory() 308 Address concatAddress = SipFactory.getInstance().createAddressFactory().createAddress(SipFactory.getInstance().createAddressFactory()
312 .createSipURI(platform.getDeviceGBId(), sipAddress)); 309 .createSipURI(platform.getDeviceGBId(), sipAddress));
  310 +
313 request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress)); 311 request.addHeader(SipFactory.getInstance().createHeaderFactory().createContactHeader(concatAddress));
314 312
315 return request; 313 return request;
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java
@@ -347,10 +347,9 @@ public class SIPCommander implements ISIPCommander { @@ -347,10 +347,9 @@ public class SIPCommander implements ISIPCommander {
347 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); 347 mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc());
348 errorEvent.response(e); 348 errorEvent.response(e);
349 }), e -> { 349 }), e -> {
350 - // 这里为例避免一个通道的点播只有一个callID这个参数使用一个固定值  
351 ResponseEvent responseEvent = (ResponseEvent) e.event; 350 ResponseEvent responseEvent = (ResponseEvent) e.event;
352 SIPResponse response = (SIPResponse) responseEvent.getResponse(); 351 SIPResponse response = (SIPResponse) responseEvent.getResponse();
353 - streamSession.put(device.getDeviceId(), channelId, "play", stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.play); 352 + streamSession.put(device.getDeviceId(), channelId, e.callId, stream, ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.play);
354 okEvent.response(e); 353 okEvent.response(e);
355 }); 354 });
356 } 355 }
@@ -452,7 +451,7 @@ public class SIPCommander implements ISIPCommander { @@ -452,7 +451,7 @@ public class SIPCommander implements ISIPCommander {
452 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> { 451 sipSender.transmitRequest(sipLayer.getLocalIp(device.getLocalIp()), request, errorEvent, event -> {
453 ResponseEvent responseEvent = (ResponseEvent) event.event; 452 ResponseEvent responseEvent = (ResponseEvent) event.event;
454 SIPResponse response = (SIPResponse) responseEvent.getResponse(); 453 SIPResponse response = (SIPResponse) responseEvent.getResponse();
455 - streamSession.put(device.getDeviceId(), channelId,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()).getCallId(), ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.playback); 454 + streamSession.put(device.getDeviceId(), channelId, event.callId, ssrcInfo.getStream(), ssrcInfo.getSsrc(), mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.playback);
456 okEvent.response(event); 455 okEvent.response(event);
457 }); 456 });
458 if (inviteStreamCallback != null) { 457 if (inviteStreamCallback != null) {
@@ -580,7 +579,7 @@ public class SIPCommander implements ISIPCommander { @@ -580,7 +579,7 @@ public class SIPCommander implements ISIPCommander {
580 if (ssrcIndex >= 0) { 579 if (ssrcIndex >= 0) {
581 ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12); 580 ssrc = contentString.substring(ssrcIndex + 2, ssrcIndex + 12);
582 } 581 }
583 - streamSession.put(device.getDeviceId(), channelId, response.getCallIdHeader().getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download); 582 + streamSession.put(device.getDeviceId(), channelId, newCallIdHeader.getCallId(), ssrcInfo.getStream(), ssrc, mediaServerItem.getId(), response, VideoStreamSessionManager.SessionType.download);
584 okEvent.response(event); 583 okEvent.response(event);
585 }); 584 });
586 } 585 }
src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java
@@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor @@ -11,6 +11,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor
11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; 11 import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent;
12 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; 12 import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
13 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; 13 import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  14 +import com.genersoft.iot.vmp.service.IDeviceChannelService;
14 import com.genersoft.iot.vmp.service.IDeviceService; 15 import com.genersoft.iot.vmp.service.IDeviceService;
15 import com.genersoft.iot.vmp.service.IMediaServerService; 16 import com.genersoft.iot.vmp.service.IMediaServerService;
16 import com.genersoft.iot.vmp.service.IPlatformService; 17 import com.genersoft.iot.vmp.service.IPlatformService;
@@ -27,11 +28,7 @@ import org.springframework.stereotype.Component; @@ -27,11 +28,7 @@ import org.springframework.stereotype.Component;
27 import javax.sip.InvalidArgumentException; 28 import javax.sip.InvalidArgumentException;
28 import javax.sip.RequestEvent; 29 import javax.sip.RequestEvent;
29 import javax.sip.SipException; 30 import javax.sip.SipException;
30 -import javax.sip.address.SipURI;  
31 import javax.sip.header.CallIdHeader; 31 import javax.sip.header.CallIdHeader;
32 -import javax.sip.header.FromHeader;  
33 -import javax.sip.header.HeaderAddress;  
34 -import javax.sip.header.ToHeader;  
35 import javax.sip.message.Response; 32 import javax.sip.message.Response;
36 import java.text.ParseException; 33 import java.text.ParseException;
37 import java.util.HashMap; 34 import java.util.HashMap;
@@ -59,6 +56,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -59,6 +56,9 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
59 private IDeviceService deviceService; 56 private IDeviceService deviceService;
60 57
61 @Autowired 58 @Autowired
  59 + private IDeviceChannelService channelService;
  60 +
  61 + @Autowired
62 private IVideoManagerStorage storager; 62 private IVideoManagerStorage storager;
63 63
64 @Autowired 64 @Autowired
@@ -88,95 +88,91 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In @@ -88,95 +88,91 @@ public class ByeRequestProcessor extends SIPRequestProcessorParent implements In
88 */ 88 */
89 @Override 89 @Override
90 public void process(RequestEvent evt) { 90 public void process(RequestEvent evt) {
91 - 91 + SIPRequest request = (SIPRequest) evt.getRequest();
92 try { 92 try {
93 - responseAck((SIPRequest) evt.getRequest(), Response.OK); 93 + responseAck(request, Response.OK);
94 } catch (SipException | InvalidArgumentException | ParseException e) { 94 } catch (SipException | InvalidArgumentException | ParseException e) {
95 logger.error("[回复BYE信息失败],{}", e.getMessage()); 95 logger.error("[回复BYE信息失败],{}", e.getMessage());
96 } 96 }
97 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME); 97 CallIdHeader callIdHeader = (CallIdHeader)evt.getRequest().getHeader(CallIdHeader.NAME);
98 - String platformGbId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser();  
99 - String channelId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser();  
100 - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(platformGbId, channelId, null, callIdHeader.getCallId());  
101 - logger.info("[收到bye] {}/{}", platformGbId, channelId);  
102 - if (sendRtpItem != null){  
103 - String streamId = sendRtpItem.getStreamId();  
104 - Map<String, Object> param = new HashMap<>();  
105 - param.put("vhost","__defaultVhost__");  
106 - param.put("app",sendRtpItem.getApp());  
107 - param.put("stream",streamId);  
108 - param.put("ssrc",sendRtpItem.getSsrc());  
109 - logger.info("[收到bye] 停止向上级推流:{}", streamId);  
110 - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());  
111 - redisCatchStorage.deleteSendRTPServer(platformGbId, channelId, callIdHeader.getCallId(), null);  
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 98
126 - int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);  
127 - if (totalReaderCount <= 0) {  
128 - logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);  
129 - if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {  
130 - Device device = deviceService.getDevice(sendRtpItem.getDeviceId());  
131 - if (device == null) {  
132 - logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);  
133 - }  
134 - try {  
135 - logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), channelId);  
136 - cmder.streamByeCmd(device, channelId, streamId, null);  
137 - } catch (InvalidArgumentException | ParseException | SipException |  
138 - SsrcTransactionNotFoundException e) {  
139 - logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());  
140 - }  
141 - }  
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 -// } 99 + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, null, callIdHeader.getCallId());
  100 +
  101 + if (sendRtpItem != null){
  102 + logger.info("[收到bye] 来自平台{}, 停止通道:{}", sendRtpItem.getPlatformId(), sendRtpItem.getChannelId());
  103 + String streamId = sendRtpItem.getStreamId();
  104 + Map<String, Object> param = new HashMap<>();
  105 + param.put("vhost","__defaultVhost__");
  106 + param.put("app",sendRtpItem.getApp());
  107 + param.put("stream",streamId);
  108 + param.put("ssrc",sendRtpItem.getSsrc());
  109 + logger.info("[收到bye] 停止向上级推流:{}", streamId);
  110 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  111 + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(),
  112 + callIdHeader.getCallId(), null);
  113 + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
  114 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PUSH)) {
  115 + ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId());
  116 + if (platform != null) {
  117 + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
  118 + sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
  119 + sendRtpItem.getPlatformId(), platform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId());
  120 + messageForPushChannel.setPlatFormIndex(platform.getId());
  121 + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel);
  122 + }else {
  123 + logger.info("[上级平台停止观看] 未找到平台{}的信息,发送redis消息失败", sendRtpItem.getPlatformId());
148 } 124 }
149 } 125 }
150 - // 可能是设备主动停止  
151 - Device device = storager.queryVideoDeviceByChannelId(platformGbId);  
152 - if (device != null) {  
153 - storager.stopPlay(device.getDeviceId(), channelId);  
154 - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId);  
155 - if (streamInfo != null) {  
156 - redisCatchStorage.stopPlay(streamInfo);  
157 - mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());  
158 - }  
159 - SsrcTransaction ssrcTransactionForPlay = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, "play", null);  
160 - if (ssrcTransactionForPlay != null){  
161 - if (ssrcTransactionForPlay.getCallId().equals(callIdHeader.getCallId())){  
162 - // 释放ssrc  
163 - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlay.getMediaServerId());  
164 - if (mediaServerItem != null) {  
165 - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlay.getSsrc());  
166 - }  
167 - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlay.getStream()); 126 +
  127 + int totalReaderCount = zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId);
  128 + if (totalReaderCount <= 0) {
  129 + logger.info("[收到bye] {} 无其它观看者,通知设备停止推流", streamId);
  130 + if (sendRtpItem.getPlayType().equals(InviteStreamType.PLAY)) {
  131 + Device device = deviceService.getDevice(sendRtpItem.getDeviceId());
  132 + if (device == null) {
  133 + logger.info("[收到bye] {} 通知设备停止推流时未找到设备信息", streamId);
168 } 134 }
169 - }  
170 - SsrcTransaction ssrcTransactionForPlayBack = streamSession.getSsrcTransaction(device.getDeviceId(), channelId, callIdHeader.getCallId(), null);  
171 - if (ssrcTransactionForPlayBack != null) {  
172 - // 释放ssrc  
173 - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransactionForPlayBack.getMediaServerId());  
174 - if (mediaServerItem != null) {  
175 - mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransactionForPlayBack.getSsrc()); 135 + try {
  136 + logger.warn("[停止点播] {}/{}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId());
  137 + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), streamId, null);
  138 + } catch (InvalidArgumentException | ParseException | SipException |
  139 + SsrcTransactionNotFoundException e) {
  140 + logger.error("[收到bye] {} 无其它观看者,通知设备停止推流, 发送BYE失败 {}",streamId, e.getMessage());
176 } 141 }
177 - streamSession.remove(device.getDeviceId(), channelId, ssrcTransactionForPlayBack.getStream());  
178 } 142 }
179 } 143 }
  144 + }else {
  145 + // 可能是设备发送的停止
  146 + SsrcTransaction ssrcTransaction = streamSession.getSsrcTransaction(null, null, callIdHeader.getCallId(), null);
  147 + if (ssrcTransaction == null) {
  148 + logger.info("[收到bye] 但是无法获取推流信息和发流信息,忽略此请求");
  149 + logger.info(request.toString());
  150 + return;
  151 + }
  152 + logger.info("[收到bye] 来自设备:{}, 通道已停止推流: {}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
180 153
  154 + Device device = deviceService.getDevice(ssrcTransaction.getDeviceId());
  155 + if (device == null) {
  156 + logger.info("[收到bye] 未找到设备:{} ", ssrcTransaction.getDeviceId());
  157 + return;
  158 + }
  159 + DeviceChannel channel = channelService.getOne(ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
  160 + if (channel == null) {
  161 + logger.info("[收到bye] 未找到通道,设备:{}, 通道:{}", ssrcTransaction.getDeviceId(), ssrcTransaction.getChannelId());
  162 + return;
  163 + }
  164 + storager.stopPlay(device.getDeviceId(), channel.getChannelId());
  165 + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channel.getChannelId());
  166 + if (streamInfo != null) {
  167 + redisCatchStorage.stopPlay(streamInfo);
  168 + mediaServerService.closeRTPServer(streamInfo.getMediaServerId(), streamInfo.getStream());
  169 + }
  170 + // 释放ssrc
  171 + MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId());
  172 + if (mediaServerItem != null) {
  173 + mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc());
  174 + }
  175 + streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcTransaction.getStream());
  176 + }
181 } 177 }
182 } 178 }
src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java
@@ -143,7 +143,7 @@ public class PlayServiceImpl implements IPlayService { @@ -143,7 +143,7 @@ public class PlayServiceImpl implements IPlayService {
143 if (rtpInfo.getBoolean("exist")) { 143 if (rtpInfo.getBoolean("exist")) {
144 int localPort = rtpInfo.getInteger("local_port"); 144 int localPort = rtpInfo.getInteger("local_port");
145 if (localPort == 0) { 145 if (localPort == 0) {
146 - logger.warn("[点播],点播时发现rtpServerC存在,但是尚未开始推流"); 146 + logger.warn("[点播],点播时发现rtpServer存在,但是尚未开始推流");
147 // 此时说明rtpServer已经创建但是流还没有推上来 147 // 此时说明rtpServer已经创建但是流还没有推上来
148 WVPResult wvpResult = new WVPResult(); 148 WVPResult wvpResult = new WVPResult();
149 wvpResult.setCode(ErrorCode.ERROR100.getCode()); 149 wvpResult.setCode(ErrorCode.ERROR100.getCode());
src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java
1 package com.genersoft.iot.vmp.service.redisMsg; 1 package com.genersoft.iot.vmp.service.redisMsg;
2 2
3 import com.alibaba.fastjson2.JSON; 3 import com.alibaba.fastjson2.JSON;
  4 +import com.genersoft.iot.vmp.conf.UserSetting;
  5 +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType;
  6 +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform;
  7 +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem;
  8 +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform;
  9 +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory;
  10 +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem;
  11 +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem;
  12 +import com.genersoft.iot.vmp.service.IMediaServerService;
  13 +import com.genersoft.iot.vmp.service.IStreamPushService;
  14 +import com.genersoft.iot.vmp.service.bean.MessageForPushChannel;
4 import com.genersoft.iot.vmp.service.bean.MessageForPushChannelResponse; 15 import com.genersoft.iot.vmp.service.bean.MessageForPushChannelResponse;
  16 +import com.genersoft.iot.vmp.storager.IRedisCatchStorage;
  17 +import com.genersoft.iot.vmp.storager.IVideoManagerStorage;
5 import org.slf4j.Logger; 18 import org.slf4j.Logger;
6 import org.slf4j.LoggerFactory; 19 import org.slf4j.LoggerFactory;
7 import org.springframework.beans.factory.annotation.Autowired; 20 import org.springframework.beans.factory.annotation.Autowired;
8 -import org.springframework.beans.factory.annotation.Qualifier;  
9 import org.springframework.data.redis.connection.Message; 21 import org.springframework.data.redis.connection.Message;
10 import org.springframework.data.redis.connection.MessageListener; 22 import org.springframework.data.redis.connection.MessageListener;
11 -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;  
12 import org.springframework.stereotype.Component; 23 import org.springframework.stereotype.Component;
13 -import org.springframework.util.ObjectUtils;  
14 24
  25 +import javax.sip.InvalidArgumentException;
  26 +import javax.sip.SipException;
  27 +import java.text.ParseException;
  28 +import java.util.HashMap;
  29 +import java.util.List;
15 import java.util.Map; 30 import java.util.Map;
16 import java.util.concurrent.ConcurrentHashMap; 31 import java.util.concurrent.ConcurrentHashMap;
17 -import java.util.concurrent.ConcurrentLinkedQueue;  
18 32
19 /** 33 /**
20 * 接收redis发送的结束推流请求 34 * 接收redis发送的结束推流请求
@@ -25,11 +39,26 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { @@ -25,11 +39,26 @@ public class RedisPushStreamCloseResponseListener implements MessageListener {
25 39
26 private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamCloseResponseListener.class); 40 private final static Logger logger = LoggerFactory.getLogger(RedisPushStreamCloseResponseListener.class);
27 41
28 - private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); 42 + @Autowired
  43 + private IStreamPushService streamPushService;
  44 +
  45 + @Autowired
  46 + private IRedisCatchStorage redisCatchStorage;
29 47
30 - @Qualifier("taskExecutor")  
31 @Autowired 48 @Autowired
32 - private ThreadPoolTaskExecutor taskExecutor; 49 + private IVideoManagerStorage storager;
  50 +
  51 + @Autowired
  52 + private ISIPCommanderForPlatform commanderFroPlatform;
  53 +
  54 + @Autowired
  55 + private UserSetting userSetting;
  56 +
  57 + @Autowired
  58 + private IMediaServerService mediaServerService;
  59 +
  60 + @Autowired
  61 + private ZLMRTPServerFactory zlmrtpServerFactory;
33 62
34 63
35 private Map<String, PushStreamResponseEvent> responseEvents = new ConcurrentHashMap<>(); 64 private Map<String, PushStreamResponseEvent> responseEvents = new ConcurrentHashMap<>();
@@ -40,30 +69,45 @@ public class RedisPushStreamCloseResponseListener implements MessageListener { @@ -40,30 +69,45 @@ public class RedisPushStreamCloseResponseListener implements MessageListener {
40 69
41 @Override 70 @Override
42 public void onMessage(Message message, byte[] bytes) { 71 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; 72 + logger.info("[REDIS消息-推流结束]: {}", new String(message.getBody()));
  73 + MessageForPushChannel pushChannel = JSON.parseObject(message.getBody(), MessageForPushChannel.class);
  74 + StreamPushItem push = streamPushService.getPush(pushChannel.getApp(), pushChannel.getStream());
  75 + if (push != null) {
  76 + if (redisCatchStorage.isChannelSendingRTP(push.getGbId())) {
  77 + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChnnelId(
  78 + push.getGbId());
  79 + if (sendRtpItems.size() > 0) {
  80 + for (SendRtpItem sendRtpItem : sendRtpItems) {
  81 + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId());
  82 + // 停止向上级推流
  83 + String streamId = sendRtpItem.getStreamId();
  84 + Map<String, Object> param = new HashMap<>();
  85 + param.put("vhost","__defaultVhost__");
  86 + param.put("app",sendRtpItem.getApp());
  87 + param.put("stream",streamId);
  88 + param.put("ssrc",sendRtpItem.getSsrc());
  89 + logger.info("[REDIS消息-推流结束] 停止向上级推流:{}", streamId);
  90 + MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId());
  91 + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStreamId());
  92 + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param);
  93 +
  94 + try {
  95 + commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem);
  96 + } catch (SipException | InvalidArgumentException | ParseException e) {
  97 + logger.error("[命令发送失败] 国标级联 发送BYE: {}", e.getMessage());
55 } 98 }
56 - // 查看正在等待的invite消息  
57 - if (responseEvents.get(response.getApp() + response.getStream()) != null) {  
58 - responseEvents.get(response.getApp() + response.getStream()).run(response); 99 + if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) {
  100 + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0,
  101 + sendRtpItem.getApp(), sendRtpItem.getStreamId(), sendRtpItem.getChannelId(),
  102 + sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId());
  103 + messageForPushChannel.setPlatFormIndex(parentPlatform.getId());
  104 + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel);
59 } 105 }
60 - }catch (Exception e) {  
61 - logger.warn("[REDIS消息-请求推流结果] 发现未处理的异常, \r\n{}", JSON.toJSONString(message));  
62 - logger.error("[REDIS消息-请求推流结果] 异常内容: ", e);  
63 } 106 }
64 } 107 }
65 - }); 108 + }
66 } 109 }
  110 +
67 } 111 }
68 112
69 public void addEvent(String app, String stream, PushStreamResponseEvent callback) { 113 public void addEvent(String app, String stream, PushStreamResponseEvent callback) {