| | |
| | | import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.*; |
| | | import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; |
| | | import com.genersoft.iot.vmp.service.IMediaServerService; |
| | | import com.genersoft.iot.vmp.service.IPlayService; |
| | | import com.genersoft.iot.vmp.service.IStreamProxyService; |
| | | import com.genersoft.iot.vmp.service.IStreamPushService; |
| | | import com.genersoft.iot.vmp.service.*; |
| | | import com.genersoft.iot.vmp.service.bean.ErrorCallback; |
| | | import com.genersoft.iot.vmp.service.bean.InviteErrorCode; |
| | | import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; |
| | |
| | | |
| | | @Autowired |
| | | private IRedisCatchStorage redisCatchStorage; |
| | | |
| | | @Autowired |
| | | private IInviteStreamService inviteStreamService; |
| | | |
| | | @Autowired |
| | | private SSRCFactory ssrcFactory; |
| | |
| | | String requesterId = SipUtils.getUserIdFromFromHeader(request); |
| | | CallIdHeader callIdHeader = (CallIdHeader) request.getHeader(CallIdHeader.NAME); |
| | | if (requesterId == null || channelId == null) { |
| | | logger.info("无法从FromHeader的Address中获取到平台id,返回400"); |
| | | logger.info("无法从请求中获取到平台id,返回400"); |
| | | // 参数不全, 发400,请求错误 |
| | | try { |
| | | responseAck(request, Response.BAD_REQUEST); |
| | |
| | | return; |
| | | } |
| | | |
| | | logger.info("[INVITE] requesterId: {}, callId: {}, 来自:{}:{}", |
| | | requesterId, callIdHeader.getCallId(), request.getRemoteAddress(), request.getRemotePort()); |
| | | |
| | | // 查询请求是否来自上级平台\设备 |
| | | ParentPlatform platform = storager.queryParentPlatByServerGBId(requesterId); |
| | |
| | | // 非严格模式端口不统一, 增加兼容性,修改为一个不为0的端口 |
| | | localPort = new Random().nextInt(65535) + 1; |
| | | } |
| | | content.append("m=video " + localPort + " RTP/AVP 96\r\n"); |
| | | if (sendRtpItem.isTcp()) { |
| | | content.append("m=video " + localPort + " TCP/RTP/AVP 96\r\n"); |
| | | if (!sendRtpItem.isTcpActive()) { |
| | | content.append("a=setup:active\r\n"); |
| | | } else { |
| | | content.append("a=setup:passive\r\n"); |
| | | } |
| | | }else { |
| | | content.append("m=video " + localPort + " RTP/AVP 96\r\n"); |
| | | } |
| | | content.append("a=sendonly\r\n"); |
| | | content.append("a=rtpmap:96 PS/90000\r\n"); |
| | | content.append("y=" + sendRtpItem.getSsrc() + "\r\n"); |
| | |
| | | errorEvent.run(code, msg, data); |
| | | } |
| | | }); |
| | | }else if ("Download".equalsIgnoreCase(sessionName)) { |
| | | } else if ("Download".equalsIgnoreCase(sessionName)) { |
| | | // 获取指定的下载速度 |
| | | Vector sdpMediaDescriptions = sdp.getMediaDescriptions(true); |
| | | MediaDescription mediaDescription = null; |
| | | String downloadSpeed = "1"; |
| | | if (sdpMediaDescriptions.size() > 0) { |
| | | mediaDescription = (MediaDescription)sdpMediaDescriptions.get(0); |
| | | mediaDescription = (MediaDescription) sdpMediaDescriptions.get(0); |
| | | } |
| | | if (mediaDescription != null) { |
| | | downloadSpeed = mediaDescription.getAttribute("downloadspeed"); |
| | |
| | | playService.download(mediaServerItem, ssrcInfo, device.getDeviceId(), channelId, DateUtil.formatter.format(start), |
| | | DateUtil.formatter.format(end), Integer.parseInt(downloadSpeed), |
| | | (code, msg, data) -> { |
| | | if (code == InviteErrorCode.SUCCESS.getCode()){ |
| | | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| | | hookEvent.run(code, msg, data); |
| | | }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){ |
| | | } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) { |
| | | logger.info("[录像下载]超时, 用户:{}, 通道:{}", username, channelId); |
| | | redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); |
| | | errorEvent.run(code, msg, data); |
| | | }else { |
| | | } else { |
| | | errorEvent.run(code, msg, data); |
| | | } |
| | | }); |
| | | }else { |
| | | |
| | | SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, ((code, msg, data) -> { |
| | | if (code == InviteErrorCode.SUCCESS.getCode()){ |
| | | hookEvent.run(code, msg, data); |
| | | }else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()){ |
| | | logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId); |
| | | redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); |
| | | errorEvent.run(code, msg, data); |
| | | }else { |
| | | errorEvent.run(code, msg, data); |
| | | } |
| | | })); |
| | | } else { |
| | | sendRtpItem.setPlayType(InviteStreamType.PLAY); |
| | | String streamId = String.format("%s_%s", device.getDeviceId(), channelId); |
| | | sendRtpItem.setStreamId(streamId); |
| | | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| | | SSRCInfo ssrcInfo = playService.play(mediaServerItem, device.getDeviceId(), channelId, ssrc, ((code, msg, data) -> { |
| | | if (code == InviteErrorCode.SUCCESS.getCode()) { |
| | | hookEvent.run(code, msg, data); |
| | | } else if (code == InviteErrorCode.ERROR_FOR_SIGNALLING_TIMEOUT.getCode() || code == InviteErrorCode.ERROR_FOR_STREAM_TIMEOUT.getCode()) { |
| | | logger.info("[上级点播]超时, 用户:{}, 通道:{}", username, channelId); |
| | | redisCatchStorage.deleteSendRTPServer(platform.getServerGBId(), channelId, callIdHeader.getCallId(), null); |
| | | errorEvent.run(code, msg, data); |
| | | } else { |
| | | errorEvent.run(code, msg, data); |
| | | } |
| | | })); |
| | | sendRtpItem.setSsrc(ssrcInfo.getSsrc()); |
| | | redisCatchStorage.updateSendRTPSever(sendRtpItem); |
| | | |
| | |
| | | zlmHttpHookSubscribe.removeSubscribe(hookSubscribe); |
| | | dynamicTask.stop(callIdHeader.getCallId()); |
| | | } |
| | | |
| | | |
| | | |
| | | } else if ("push".equals(gbStream.getStreamType())) { |
| | | if (!platform.isStartOfflinePush()) { |
| | | // 平台设置中关闭了拉起离线的推流则直接回复 |
| | |
| | | dynamicTask.startDelay(callIdHeader.getCallId(), () -> { |
| | | logger.info("[ app={}, stream={} ] 等待设备开始推流超时", gbStream.getApp(), gbStream.getStream()); |
| | | try { |
| | | redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream()); |
| | | mediaListManager.removedChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream()); |
| | | responseAck(request, Response.REQUEST_TIMEOUT); // 超时 |
| | | } catch (SipException e) { |
| | | logger.error("未处理的异常 ", e); |
| | | } catch (InvalidArgumentException e) { |
| | | logger.error("未处理的异常 ", e); |
| | | } catch (ParseException e) { |
| | | } catch (SipException | InvalidArgumentException | ParseException e) { |
| | | logger.error("未处理的异常 ", e); |
| | | } |
| | | }, userSetting.getPlatformPlayTimeout()); |
| | |
| | | // 添加在本机上线的通知 |
| | | mediaListManager.addChannelOnlineEventLister(gbStream.getApp(), gbStream.getStream(), (app, stream, serverId) -> { |
| | | dynamicTask.stop(callIdHeader.getCallId()); |
| | | redisPushStreamResponseListener.removeEvent(gbStream.getApp(), gbStream.getStream()); |
| | | if (serverId.equals(userSetting.getServerId())) { |
| | | SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, finalPort, ssrc, requesterId, |
| | | app, stream, channelId, mediaTransmissionTCP, platform.isRtcp()); |