From 89a9ab4534f10a224f70e546db838423e84a1965 Mon Sep 17 00:00:00 2001 From: 64850858 <648540858@qq.com> Date: 星期五, 16 七月 2021 16:34:51 +0800 Subject: [PATCH] 添加zlm集群支持 --- src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java | 13 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java | 6 web_src/src/components/service/MediaServer.js | 32 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java | 76 src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java | 9 src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java | 9 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java | 14 sql/mysql.sql | 27 src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java | 23 src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java | 2 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java | 340 ++++++ web_src/src/components/dialog/StreamProxyEdit.vue | 75 src/main/java/com/genersoft/iot/vmp/service/IPlayService.java | 11 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java | 14 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java | 76 + src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java | 13 web_src/src/components/StreamProxyList.vue | 15 src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java | 4 src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java | 25 src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java | 27 src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java | 24 src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java | 26 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java | 7 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java | 57 src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java | 20 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java | 7 src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java | 91 + src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java | 85 src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java | 9 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java | 10 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java | 12 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMRunInfo.java | 33 src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java | 3 src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java | 16 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java | 15 src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java | 13 src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java | 13 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 213 +-- src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java | 20 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java | 95 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java | 92 + web_src/src/components/PushVideoList.vue | 9 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java | 27 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java | 53 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java | 254 ++++ web_src/src/components/CloudRecord.vue | 36 pom.xml | 10 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java | 4 src/main/java/com/genersoft/iot/vmp/web/ApiController.java | 2 src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java | 25 web_src/src/components/dialog/devicePlayer.vue | 15 src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java | 204 +++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/SIPRequestAbstractProcessor.java | 8 src/main/java/com/genersoft/iot/vmp/service/IMediaService.java | 37 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java | 196 +- src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java | 14 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java | 60 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java | 17 src/main/resources/wvp.sqlite | 0 src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java | 44 src/main/resources/all-application.yml | 4 src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java | 27 src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java | 10 src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java | 2 /dev/null | 45 src/main/java/com/genersoft/iot/vmp/vmanager/record/RecoderProxyController.java | 11 src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java | 39 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 92 + src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java | 99 + src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java | 9 web_src/src/components/control.vue | 124 + src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java | 74 src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java | 2 src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java | 66 74 files changed, 2,431 insertions(+), 860 deletions(-) diff --git a/pom.xml b/pom.xml index 074f9fe..6223945 100644 --- a/pom.xml +++ b/pom.xml @@ -196,6 +196,16 @@ <version>1.12</version> </dependency> +<!-- <!– 妫�娴嬫枃浠剁紪鐮� –>--> +<!-- <!– https://mvnrepository.com/artifact/cpdetector/cpdetector –>--> +<!-- <dependency>--> +<!-- <groupId>cpdetector</groupId>--> +<!-- <artifactId>cpdetector</artifactId>--> +<!-- <version>1.0.8</version>--> +<!-- </dependency>--> + + + <!-- onvif鍗忚鏍� --> <dependency> <groupId>be.teletask</groupId> diff --git a/sql/mysql.sql b/sql/mysql.sql index 21d7a52..0bb4c03 100644 --- a/sql/mysql.sql +++ b/sql/mysql.sql @@ -138,6 +138,7 @@ timeout_ms int null, ffmpeg_cmd_key varchar(255) null, rtp_type varchar(50) null, + mediaServerId varchar(50) null, enable_hls bit(1) null, enable_mp4 bit(1) null, enable bit(1) not null, @@ -166,4 +167,28 @@ create_time varchar(50) not null ); -insert into user (username, password, roleId, create_time) values ('admin', '21232f297a57a5a743894a0e4a801fc3', '0', '2021-04-13 14:14:57'); \ No newline at end of file +insert into user (username, password, roleId, create_time) values ('admin', '21232f297a57a5a743894a0e4a801fc3', '0', '2021-04-13 14:14:57'); + +create table media_server ( + id varchar(255) + primary key, + ip varchar(50) NOT NULL, + hookIp varchar(50) NOT NULL, + sdpIp varchar(50) NOT NULL, + streamIp varchar(50) NOT NULL, + httpPort int NOT NULL, + httpSSlPort int NOT NULL, + rtmpPort int NOT NULL, + rtmpSSlPort int NOT NULL, + rtpProxyPort int NOT NULL, + rtspPort int NOT NULL, + rtspSSLPort int NOT NULL, + autoConfig int NOT NULL, + secret varchar(50) NOT NULL, + streamNoneReaderDelayMS int NOT NULL, + rtpEnable int NOT NULL, + rtpPortRange varchar(50) NOT NULL, + recordAssistPort int NOT NULL, + createTime varchar(50) not null, + updateTime varchar(50) not null +); \ No newline at end of file diff --git a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java index 1336d05..771838d 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java @@ -19,6 +19,7 @@ private String rtmp; private String rtsp; private String rtc; + private String mediaServerId; private JSONArray tracks; public static class TransactionInfo{ @@ -165,4 +166,12 @@ public void setTransactionInfo(TransactionInfo transactionInfo) { this.transactionInfo = transactionInfo; } + + public String getMediaServerId() { + return mediaServerId; + } + + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java index f4e895f..5749314 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -10,33 +10,31 @@ public static final String WVP_SERVER_PREFIX = "VMP_wvp_server"; - public static final String MEDIA_SERVER_PREFIX = "VMP_media_server"; + public static final String MEDIA_SERVER_PREFIX = "VMP_MEDIA_SERVER_"; - public static final String MEDIA_STREAM_PREFIX = "VMP_media_stream"; + public static final String MEDIA_STREAM_PREFIX = "VMP_MEDIA_STREAM"; - public static final String DEVICE_PREFIX = "VMP_device_"; + public static final String DEVICE_PREFIX = "VMP_DEVICE_"; - public static final String CACHEKEY_PREFIX = "VMP_channel_"; + public static final String CACHEKEY_PREFIX = "VMP_CHANNEL_"; public static final String KEEPLIVEKEY_PREFIX = "VMP_keeplive_"; - public static final String PLAYER_PREFIX = "VMP_player_"; + public static final String PLAYER_PREFIX = "VMP_PLAYER_"; - public static final String PLAY_BLACK_PREFIX = "VMP_playback_"; + public static final String PLAY_BLACK_PREFIX = "VMP_PLAYBACK_"; - public static final String PLATFORM_PREFIX = "VMP_platform"; + public static final String PLATFORM_KEEPLIVEKEY_PREFIX = "VMP_PLATFORM_KEEPLIVE_"; - public static final String PLATFORM_KEEPLIVEKEY_PREFIX = "VMP_platform_keeplive_"; + public static final String PLATFORM_CATCH_PREFIX = "VMP_PLATFORM_CATCH_"; - public static final String PLATFORM_CATCH_PREFIX = "VMP_platform_catch_"; + public static final String PLATFORM_REGISTER_PREFIX = "VMP_PLATFORM_REGISTER_"; - public static final String PLATFORM_REGISTER_PREFIX = "VMP_platform_register_"; + public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_PLATFORM_REGISTER_INFO_"; - public static final String PLATFORM_REGISTER_INFO_PREFIX = "VMP_platform_register_info_"; + public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_PLATFORM_SEND_RTP_INFO_"; - public static final String PLATFORM_SEND_RTP_INFO_PREFIX = "VMP_platform_send_rtp_info_"; - - public static final String Pattern_Topic = "VMP_keeplive_platform_"; + public static final String Pattern_Topic = "VMP_KEEPLIVE_PLATFORM_"; public static final String EVENT_ONLINE_REGISTER = "1"; diff --git a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java index 52292a5..88e8a64 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -1,11 +1,16 @@ package com.genersoft.iot.vmp.conf; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.util.StringUtils; @Configuration("mediaConfig") -public class MediaConfig { +public class MediaConfig implements IMediaServerItem { + + @Value("${media.id:}") + private String id; @Value("${media.ip}") private String ip; @@ -25,22 +30,22 @@ @Value("${media.http-port}") private Integer httpPort; - @Value("${media.http-ssl-port:}") + @Value("${media.http-ssl-port:0}") private Integer httpSSlPort; - @Value("${media.rtmp-port:}") + @Value("${media.rtmp-port:0}") private Integer rtmpPort; - @Value("${media.rtmp-ssl-port:}") + @Value("${media.rtmp-ssl-port:0}") private Integer rtmpSSlPort; - @Value("${media.rtp-proxy-port:}") + @Value("${media.rtp-proxy-port:0}") private Integer rtpProxyPort; - @Value("${media.rtsp-port:}") + @Value("${media.rtsp-port:0}") private Integer rtspPort; - @Value("${media.rtsp-ssl-port:}") + @Value("${media.rtsp-ssl-port:0}") private Integer rtspSSLPort; @Value("${media.auto-config:true}") @@ -61,6 +66,23 @@ @Value("${media.record-assist-port:0}") private Integer recordAssistPort; + private String updateTime; + + private String createTime; + + private boolean docker = false; + + private int count; + + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + public String getIp() { return ip; } @@ -82,80 +104,112 @@ this.hookIp = hookIp; } - public String getSdpIp() { - if (StringUtils.isEmpty(sdpIp)){ - return ip; - }else { - return sdpIp; - } + public String getSipIp() { + return sipIp; + } + + public void setSipIp(String sipIp) { + this.sipIp = sipIp; } public void setSdpIp(String sdpIp) { this.sdpIp = sdpIp; } - public String getStreamIp() { - if (StringUtils.isEmpty(streamIp)){ - return ip; - }else { - return streamIp; - } - } - public void setStreamIp(String streamIp) { this.streamIp = streamIp; } - public Integer getHttpPort() { + public int getHttpPort() { return httpPort; + } + + @Override + public void setHttpPort(int httpPort) { + } public void setHttpPort(Integer httpPort) { this.httpPort = httpPort; } - public Integer getHttpSSlPort() { + public int getHttpSSlPort() { return httpSSlPort; + } + + @Override + public void setHttpSSlPort(int httpSSlPort) { + } public void setHttpSSlPort(Integer httpSSlPort) { this.httpSSlPort = httpSSlPort; } - public Integer getRtmpPort() { + public int getRtmpPort() { return rtmpPort; + } + + @Override + public void setRtmpPort(int rtmpPort) { + } public void setRtmpPort(Integer rtmpPort) { this.rtmpPort = rtmpPort; } - public Integer getRtmpSSlPort() { + public int getRtmpSSlPort() { return rtmpSSlPort; + } + + @Override + public void setRtmpSSlPort(int rtmpSSlPort) { + } public void setRtmpSSlPort(Integer rtmpSSlPort) { this.rtmpSSlPort = rtmpSSlPort; } - public Integer getRtpProxyPort() { - return rtpProxyPort; + public int getRtpProxyPort() { + if (rtpProxyPort == null) { + return 0; + }else { + return rtpProxyPort; + } + + } + + @Override + public void setRtpProxyPort(int rtpProxyPort) { + } public void setRtpProxyPort(Integer rtpProxyPort) { this.rtpProxyPort = rtpProxyPort; } - public Integer getRtspPort() { + public int getRtspPort() { return rtspPort; + } + + @Override + public void setRtspPort(int rtspPort) { + } public void setRtspPort(Integer rtspPort) { this.rtspPort = rtspPort; } - public Integer getRtspSSLPort() { + public int getRtspSSLPort() { return rtspSSLPort; + } + + @Override + public void setRtspSSLPort(int rtspSSLPort) { + } public void setRtspSSLPort(Integer rtspSSLPort) { @@ -202,11 +256,101 @@ this.rtpPortRange = rtpPortRange; } - public Integer getRecordAssistPort() { + public int getRecordAssistPort() { return recordAssistPort; + } + + @Override + public void setRecordAssistPort(int recordAssistPort) { + } public void setRecordAssistPort(Integer recordAssistPort) { this.recordAssistPort = recordAssistPort; } + + @Override + public boolean isDocker() { + return docker; + } + + @Override + public void setDocker(boolean docker) { + this.docker = docker; + } + + public String getSdpIp() { + if (StringUtils.isEmpty(sdpIp)){ + return ip; + }else { + return sdpIp; + } + } + + public String getStreamIp() { + if (StringUtils.isEmpty(streamIp)){ + return ip; + }else { + return streamIp; + } + } + + + + public MediaServerItem getMediaSerItem(){ + MediaServerItem mediaServerItem = new MediaServerItem(); + mediaServerItem.setId(id); + mediaServerItem.setIp(ip); + mediaServerItem.setDocker(true); + mediaServerItem.setHookIp(hookIp); + mediaServerItem.setSdpIp(sdpIp); + mediaServerItem.setStreamIp(streamIp); + mediaServerItem.setHttpPort(httpPort); + mediaServerItem.setHttpSSlPort(httpSSlPort); + mediaServerItem.setRtmpPort(rtmpPort); + mediaServerItem.setRtmpSSlPort(rtmpSSlPort); + mediaServerItem.setRtpProxyPort(rtpProxyPort); + mediaServerItem.setRtspPort(rtspPort); + mediaServerItem.setRtspSSLPort(rtspSSLPort); + mediaServerItem.setAutoConfig(autoConfig); + mediaServerItem.setSecret(secret); + mediaServerItem.setStreamNoneReaderDelayMS(streamNoneReaderDelayMS); + mediaServerItem.setRtpEnable(rtpEnable); + mediaServerItem.setRtpPortRange(rtpPortRange); + mediaServerItem.setRecordAssistPort(recordAssistPort); + mediaServerItem.setCreateTime(createTime); + mediaServerItem.setUpdateTime(updateTime); + mediaServerItem.setCount(count); + return mediaServerItem; + } + + @Override + public String getUpdateTime() { + return updateTime; + } + + @Override + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + + @Override + public String getCreateTime() { + return createTime; + } + + @Override + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + @Override + public int getCount() { + return count; + } + + @Override + public void setCount(int count) { + this.count = count; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java index 3c4ea17..c543e6e 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java @@ -1,12 +1,16 @@ package com.genersoft.iot.vmp.conf; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; +import org.apache.catalina.connector.ClientAbortException; +import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; -import org.apache.catalina.connector.ClientAbortException; import org.mitre.dsmiley.httpproxy.ProxyServlet; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.web.servlet.ServletRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -24,13 +28,16 @@ private final static Logger logger = LoggerFactory.getLogger(ProxyServletConfig.class); @Autowired - private MediaConfig mediaConfig; + private IMediaServerService mediaServerService; + + @Value("${server.port}") + private int serverPort; @Bean public ServletRegistrationBean zlmServletRegistrationBean(){ ServletRegistrationBean servletRegistrationBean = new ServletRegistrationBean(new ZLMProxySerlet(),"/zlm/*"); servletRegistrationBean.setName("zlm_Proxy"); - servletRegistrationBean.addInitParameter("targetUri", String.format("http://%s:%s", mediaConfig.getIp(), mediaConfig.getHttpPort())); + servletRegistrationBean.addInitParameter("targetUri", "http://127.0.0.1:6080"); servletRegistrationBean.addUrlMappings(); if (logger.isDebugEnabled()) { servletRegistrationBean.addInitParameter("log", "true"); @@ -38,24 +45,26 @@ return servletRegistrationBean; } - class ZLMProxySerlet extends ProxyServlet{ - - - + class ZLMProxySerlet extends ProxyServlet{ @Override protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) { String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString); - if (!StringUtils.isEmpty(queryStr)) { - queryStr += "&secret=" + mediaConfig.getSecret(); - }else { - queryStr = "secret=" + mediaConfig.getSecret(); + IMediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); + if (mediaInfo != null) { + if (!StringUtils.isEmpty(queryStr)) { + queryStr += "&secret=" + mediaInfo.getSecret(); + }else { + queryStr = "secret=" + mediaInfo.getSecret(); + } } return queryStr; } + /** + * 寮傚父澶勭悊 + */ @Override protected void handleRequestException(HttpRequest proxyRequest, HttpResponse proxyResonse, Exception e){ - //System.out.println(e.getMessage()); try { super.handleRequestException(proxyRequest, proxyResonse, e); } catch (ServletException servletException) { @@ -72,6 +81,64 @@ logger.error("zlm 浠g悊澶辫触锛� ", e); } } + + /** + * 瀵逛簬涓烘寜鐓ф牸寮忚姹傜殑鍙互鐩存帴杩斿洖404 + */ + @Override + protected String getTargetUri(HttpServletRequest servletRequest) { + String requestURI = servletRequest.getRequestURI(); + IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + + String uri = null; + if (mediaInfo != null) { +// String realRequestURI = requestURI.substring(requestURI.indexOf(mediaInfo.getId())+ mediaInfo.getId().length()); + uri = String.format("http://%s:%s", mediaInfo.getIp(), mediaInfo.getHttpPort()); + }else { + uri = "http://127.0.0.1:" + serverPort +"/index/hook/null"; // 鍙槸涓�涓兘杩斿洖404鐨勮姹傝�屽凡锛� 鍏朵粬鐨勪篃鍙互 + } + return uri; + } + + /** + * 鍔ㄦ�佹浛鎹㈣姹傜洰鏍� + */ + @Override + protected HttpHost getTargetHost(HttpServletRequest servletRequest) { + String requestURI = servletRequest.getRequestURI(); + IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + HttpHost host; + if (mediaInfo != null) { + host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort()); + }else { + host = new HttpHost("127.0.0.1", serverPort); + } + return host; + + } + + /** + * 鏍规嵁uri鑾峰彇娴佸獟浣撲俊鎭� + */ + IMediaServerItem getMediaInfoByUri(String uri){ + String[] split = uri.split("/"); + String mediaServerId = split[2]; + return mediaServerService.getOne(mediaServerId); + } + + /** + * 鍘绘帀url涓殑鏍囧織淇℃伅 + */ + @Override + protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) { + String requestURI = servletRequest.getRequestURI(); + IMediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + String url = super.rewriteUrlFromRequest(servletRequest); + if (mediaInfo == null) { + return url; + } + return url.replace(mediaInfo.getId() + "/", ""); + } } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index 0dca4af..0a76f69 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -95,20 +95,43 @@ tcpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "TCP"); tcpSipProvider = sipStack.createSipProvider(tcpListeningPoint); tcpSipProvider.addSipListener(this); - logger.info("Sip Server TCP 鍚姩鎴愬姛 port {" + sipConfig.getSipPort() + "}"); - } catch (TransportNotSupportedException | InvalidArgumentException | TooManyListenersException | ObjectInUseException e) { - logger.error(String.format("鍒涘缓SIP鏈嶅姟澶辫触: %s", e.getMessage())); + logger.info("Sip Server TCP 鍚姩鎴愬姛 port {" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "}"); +// } catch (TransportNotSupportedException | InvalidArgumentException | TooManyListenersException | ObjectInUseException e) { +// logger.error(String.format("鍒涘缓SIP鏈嶅姟澶辫触: %s", e.getMessage())); +// } + } catch (TransportNotSupportedException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + logger.error("鏃犳硶浣跨敤 [ {}:{} ]浣滀负SIP[ TCP ]鏈嶅姟锛屽彲鎺掓煡: 1. sip.monitor-ip 鏄惁涓烘湰鏈虹綉鍗P; 2. sip.port 鏄惁宸茶鍗犵敤" + , sipConfig.getMonitorIp(), sipConfig.getSipPort()); + } catch (TooManyListenersException e) { + e.printStackTrace(); + } catch (ObjectInUseException e) { + e.printStackTrace(); } return tcpSipProvider; } @Bean("udpSipProvider") @DependsOn("sipStack") - private SipProvider startUdpListener() throws Exception { - ListeningPoint udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP"); - SipProvider udpSipProvider = sipStack.createSipProvider(udpListeningPoint); - udpSipProvider.addSipListener(this); - logger.info("Sip Server UDP 鍚姩鎴愬姛 port {" + sipConfig.getSipPort() + "}"); + private SipProvider startUdpListener() { + ListeningPoint udpListeningPoint = null; + SipProvider udpSipProvider = null; + try { + udpListeningPoint = sipStack.createListeningPoint(sipConfig.getMonitorIp(), sipConfig.getSipPort(), "UDP"); + udpSipProvider = sipStack.createSipProvider(udpListeningPoint); + udpSipProvider.addSipListener(this); + } catch (TransportNotSupportedException e) { + e.printStackTrace(); + } catch (InvalidArgumentException e) { + logger.error("鏃犳硶浣跨敤 [ {}:{} ]浣滀负SIP[ UDP ]鏈嶅姟锛屽彲鎺掓煡: 1. sip.monitor-ip 鏄惁涓烘湰鏈虹綉鍗P; 2. sip.port 鏄惁宸茶鍗犵敤" + , sipConfig.getMonitorIp(), sipConfig.getSipPort()); + } catch (TooManyListenersException e) { + e.printStackTrace(); + } catch (ObjectInUseException e) { + e.printStackTrace(); + } + logger.info("Sip Server UDP 鍚姩鎴愬姛 port [" + sipConfig.getMonitorIp() + ":" + sipConfig.getSipPort() + "]"); return udpSipProvider; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java index 6f3d4d7..cf939cf 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/Device.java @@ -94,6 +94,11 @@ */ private String updateTime; + /** + * 璁惧浣跨敤鐨勫獟浣搃d, 榛樿涓簄ull + */ + private String mediaServerId; + public String getDeviceId() { return deviceId; } @@ -229,4 +234,12 @@ public void setUpdateTime(String updateTime) { this.updateTime = updateTime; } + + public String getMediaServerId() { + return mediaServerId; + } + + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java index fd46947..a1ce8ca 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/GbStream.java @@ -9,6 +9,7 @@ private String stream; private String gbId; private String name; + private String mediaServerId; private double longitude; private double latitude; private String streamType; @@ -77,4 +78,12 @@ public void setStatus(boolean status) { this.status = status; } + + public String getMediaServerId() { + return mediaServerId; + } + + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java index 15e6f1e..2c9c494 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/SendRtpItem.java @@ -66,6 +66,11 @@ */ private int localPort; + /** + * 浣跨敤鐨勬祦濯掍綋 + */ + private String mediaServerId; + public String getIp() { return ip; } @@ -161,4 +166,12 @@ public void setTcpActive(boolean tcpActive) { this.tcpActive = tcpActive; } + + public String getMediaServerId() { + return mediaServerId; + } + + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java index a475a1b..aed2100 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/platformNotRegister/PlatformNotRegisterEventLister.java @@ -6,6 +6,9 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import org.slf4j.Logger; @@ -32,6 +35,8 @@ private IVideoManagerStorager storager; @Autowired private IRedisCatchStorage redisCatchStorage; + @Autowired + private IMediaServerService mediaServerService; @Autowired private SIPCommanderFroPlatform sipCommanderFroPlatform; @@ -62,22 +67,24 @@ logger.info("鍋滄[ {} ]鐨勬墍鏈夋帹娴�", event.getPlatformGbID()); StringBuilder app = new StringBuilder(); StringBuilder stream = new StringBuilder(); - for (int i = 0; i < sendRtpItems.size(); i++) { + for (SendRtpItem sendRtpItem : sendRtpItems) { if (app.length() != 0) { app.append(","); } - app.append(sendRtpItems.get(i).getApp()); + app.append(sendRtpItem.getApp()); if (stream.length() != 0) { stream.append(","); } - stream.append(sendRtpItems.get(i).getStreamId()); - redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItems.get(i).getChannelId()); + stream.append(sendRtpItem.getStreamId()); + redisCatchStorage.deleteSendRTPServer(event.getPlatformGbID(), sendRtpItem.getChannelId()); + IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + Map<String, Object> param = new HashMap<>(); + param.put("vhost", "__defaultVhost__"); + param.put("app", app.toString()); + param.put("stream", stream.toString()); + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); } - Map<String, Object> param = new HashMap<>(); - param.put("vhost","__defaultVhost__"); - param.put("app", app.toString()); - param.put("stream", stream.toString()); - zlmrtpServerFactory.stopSendRtpStream(param); + } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java index dcfbf57..e2ff0f4 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/SIPProcessorFactory.java @@ -9,6 +9,7 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.gb28181.transmit.response.impl.*; import com.genersoft.iot.vmp.service.IPlayService; @@ -104,6 +105,9 @@ @Autowired private ZLMRTPServerFactory zlmrtpServerFactory; + @Autowired + private IMediaServerService mediaServerService; + // 娉細杩欓噷浣跨敤娉ㄨВ浼氬鑷村惊鐜緷璧栨敞鍏ワ紝鏆傜敤springBean private SipProvider tcpSipProvider; @@ -128,6 +132,7 @@ processor.setStorager(storager); processor.setRedisCatchStorage(redisCatchStorage); processor.setZlmrtpServerFactory(zlmrtpServerFactory); + processor.setMediaServerService(mediaServerService); return processor; } else if (Request.REGISTER.equals(method)) { RegisterRequestProcessor processor = new RegisterRequestProcessor(); @@ -148,6 +153,7 @@ processor.setRequestEvent(evt); processor.setRedisCatchStorage(redisCatchStorage); processor.setZlmrtpServerFactory(zlmrtpServerFactory); + processor.setMediaServerService(mediaServerService); return processor; } else if (Request.BYE.equals(method)) { ByeRequestProcessor processor = new ByeRequestProcessor(); @@ -155,6 +161,7 @@ processor.setRedisCatchStorage(redisCatchStorage); processor.setZlmrtpServerFactory(zlmrtpServerFactory); processor.setSIPCommander(cmder); + processor.setMediaServerService(mediaServerService); return processor; } else if (Request.CANCEL.equals(method)) { CancelRequestProcessor processor = new CancelRequestProcessor(); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java index 4e111d6..b06fa77 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java @@ -3,6 +3,8 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; /** * @Description:璁惧鑳藉姏鎺ュ彛锛岀敤浜庡畾涔夎澶囩殑鎺у埗銆佹煡璇㈣兘鍔� @@ -90,7 +92,7 @@ * @param device 瑙嗛璁惧 * @param channelId 棰勮閫氶亾 */ - void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); + void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); /** * 璇锋眰鍥炴斁瑙嗛娴� @@ -100,7 +102,7 @@ * @param startTime 寮�濮嬫椂闂�,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss */ - void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); + void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); /** * 瑙嗛娴佸仠姝� @@ -288,12 +290,4 @@ * @return true = 鍛戒护鍙戦�佹垚鍔� */ boolean alarmSubscribe(Device device, int expires, String startPriority, String endPriority, String alarmMethod, String alarmType, String startTime, String endTime); - - - /** - * 閲婃斁rtpserver - * @param device - * @param channelId - */ - void closeRTPServer(Device device, String channelId); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java index 2c9339c..5c2fa32 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java @@ -13,11 +13,10 @@ import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.conf.UserSetup; -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; -import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import gov.nist.javax.sip.message.SIPRequest; @@ -37,6 +36,7 @@ import com.genersoft.iot.vmp.gb28181.utils.DateUtil; import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; import com.genersoft.iot.vmp.gb28181.utils.XmlUtil; +import org.springframework.util.StringUtils; /** * @Description:璁惧鑳藉姏鎺ュ彛锛岀敤浜庡畾涔夎澶囩殑鎺у埗銆佹煡璇㈣兘鍔� @@ -76,12 +76,6 @@ @Autowired private ZLMRTPServerFactory zlmrtpServerFactory; - - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; - - @Autowired - private MediaConfig mediaConfig; @Autowired private UserSetup userSetup; @@ -340,48 +334,45 @@ * @param errorEvent sip閿欒璁㈤槄 */ @Override - public void playStreamCmd(Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) { + public void playStreamCmd(IMediaServerItem mediaServerItem, Device device, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent) { String streamId = null; try { if (device == null) return; + String streamMode = device.getStreamMode().toUpperCase(); + String ssrc = streamSession.createPlaySsrc(); - if (mediaConfig.isRtpEnable()) { + if (mediaServerItem.isRtpEnable()) { streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId); }else { streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); } - String streamMode = device.getStreamMode().toUpperCase(); - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); - if (mediaInfo == null) { - logger.warn("鐐规挱鏃跺彂鐜癦LM灏氭湭杩炴帴..."); - return; - } Integer mediaPort = null; // 浣跨敤鍔ㄦ�乽dp绔彛 - if (mediaConfig.isRtpEnable()) { - mediaPort = zlmrtpServerFactory.createRTPServer(streamId); + if (mediaServerItem.isRtpEnable()) { + mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId); }else { - mediaPort = mediaInfo.getRtpProxyPort(); + mediaPort = mediaServerItem.getRtpProxyPort(); } - + logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort); // 娣诲姞璁㈤槄 JSONObject subscribeKey = new JSONObject(); subscribeKey.put("app", "rtp"); subscribeKey.put("stream", streamId); subscribeKey.put("regist", true); - - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{ + subscribeKey.put("mediaServerId", mediaServerItem.getId()); + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, + (IMediaServerItem mediaServerItemInUse, JSONObject json)->{ if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return; - event.response(json); + event.response(mediaServerItemInUse, json); subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); }); // StringBuffer content = new StringBuffer(200); content.append("v=0\r\n"); // content.append("o=" + sipConfig.getSipId() + " 0 0 IN IP4 "+mediaInfo.getWanIp()+"\r\n"); - content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getSdpIp()+"\r\n"); + content.append("o="+"00000"+" 0 0 IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n"); content.append("s=Play\r\n"); - content.append("c=IN IP4 "+mediaInfo.getSdpIp()+"\r\n"); + content.append("c=IN IP4 "+ mediaServerItem.getSdpIp() +"\r\n"); content.append("t=0 0\r\n"); if (userSetup.isSeniorSdp()) { @@ -459,21 +450,32 @@ * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss */ @Override - public void playbackStreamCmd(Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event + public void playbackStreamCmd(IMediaServerItem mediaServerItem,Device device, String channelId, String startTime, String endTime, ZLMHttpHookSubscribe.Event event , SipSubscribe.Event errorEvent) { try { - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); String ssrc = streamSession.createPlayBackSsrc(); String streamId = String.format("%08x", Integer.parseInt(ssrc)).toUpperCase(); + + Integer mediaPort = null; + // 浣跨敤鍔ㄦ�乽dp绔彛 + if (mediaServerItem.isRtpEnable()) { + mediaPort = zlmrtpServerFactory.createRTPServer(mediaServerItem, streamId); + }else { + mediaPort = mediaServerItem.getRtpProxyPort(); + } + logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", streamId, mediaServerItem.getId(), mediaServerItem.getIp(), mediaPort); + // 娣诲姞璁㈤槄 JSONObject subscribeKey = new JSONObject(); subscribeKey.put("app", "rtp"); subscribeKey.put("stream", streamId); subscribeKey.put("regist", true); + subscribeKey.put("mediaServerId", mediaServerItem.getId()); logger.debug("褰曞儚鍥炴斁娣诲姞璁㈤槄锛岃闃呭唴瀹癸細" + subscribeKey.toString()); - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, json->{ + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey, + (IMediaServerItem mediaServerItemInUse, JSONObject json)->{ if (userSetup.isWaitTrack() && json.getJSONArray("tracks") == null) return; - event.response(json); + event.response(mediaServerItemInUse, json); subscribe.removeSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, subscribeKey); }); @@ -482,16 +484,12 @@ content.append("o="+sipConfig.getSipId()+" 0 0 IN IP4 "+sipConfig.getSipIp()+"\r\n"); content.append("s=Playback\r\n"); content.append("u="+channelId+":0\r\n"); - content.append("c=IN IP4 "+mediaInfo.getSdpIp()+"\r\n"); + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); content.append("t="+DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime)+" " +DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime) +"\r\n"); - Integer mediaPort = null; - // 浣跨敤鍔ㄦ�乽dp绔彛 - if (mediaConfig.isRtpEnable()) { - mediaPort = zlmrtpServerFactory.createRTPServer(streamId); - }else { - mediaPort = mediaInfo.getRtpProxyPort(); - } + + + String streamMode = device.getStreamMode().toUpperCase(); if (userSetup.isSeniorSdp()) { @@ -560,56 +558,63 @@ /** - * 瑙嗛娴佸仠姝� - * + * 瑙嗛娴佸仠姝�, 涓嶄娇鐢ㄥ洖璋� */ @Override public void streamByeCmd(String deviceId, String channelId) { streamByeCmd(deviceId, channelId, null); } + + /** + * 瑙嗛娴佸仠姝� + */ @Override public void streamByeCmd(String deviceId, String channelId, SipSubscribe.Event okEvent) { - + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); try { ClientTransaction transaction = streamSession.getTransaction(deviceId, channelId); // 鏈嶅姟閲嶅惎鍚�, 鏃犳硶鐩存帴鍙戦�乥ye锛� 閫氳繃鎵嬪姩鏋勫缓鍙戦�� +// if (transaction == null) { +// +// if (streamInfo != null) { +// MediaServerItem mediaServerItem = redisCatchStorage.getMediaInfo(streamInfo.getMediaServerId()); +// JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaServerItem,streamInfo.getApp(), streamInfo.getStreamId()); +// if (mediaList != null) { // 浠嶅湪鎺ㄦ祦鎵嶅彂閫� +// if (mediaList.getInteger("code") == 0) { +// JSONArray data = mediaList.getJSONArray("data"); +// if (data != null && data.size() > 0) { +// Device device = storager.queryVideoDevice(deviceId); +// if (device != null) { +// StreamInfo.TransactionInfo transactionInfo = streamInfo.getTransactionInfo(); +// try { +// Request byteRequest = headerProvider.createByteRequest(device, channelId, +// transactionInfo.branch, +// transactionInfo.localTag, +// transactionInfo.remoteTag, +// transactionInfo.callId); +// transmitRequest(device, byteRequest); +// } catch (InvalidArgumentException e) { +// e.printStackTrace(); +// } +// } +// } +// } +// } +// redisCatchStorage.stopPlay(streamInfo); +// } +// +// if (okEvent != null) { +// okEvent.response(null); +// } +// return; +// } if (transaction == null) { - - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); - if (streamInfo != null) { - JSONObject mediaList = zlmresTfulUtils.getMediaList(streamInfo.getApp(), streamInfo.getStreamId()); - if (mediaList != null) { // 浠嶅湪鎺ㄦ祦鎵嶅彂閫� - if (mediaList.getInteger("code") == 0) { - JSONArray data = mediaList.getJSONArray("data"); - if (data != null && data.size() > 0) { - Device device = storager.queryVideoDevice(deviceId); - if (device != null) { - StreamInfo.TransactionInfo transactionInfo = streamInfo.getTransactionInfo(); - try { - Request byteRequest = headerProvider.createByteRequest(device, channelId, - transactionInfo.branch, - transactionInfo.localTag, - transactionInfo.remoteTag, - transactionInfo.callId); - transmitRequest(device, byteRequest); - } catch (InvalidArgumentException e) { - e.printStackTrace(); - } - } - } - } - } - redisCatchStorage.stopPlay(streamInfo); - } - - if (okEvent != null) { - okEvent.response(null); - } + logger.warn("[ {} -> {}]鍋滄瑙嗛娴佺殑鏃跺�欏彂鐜颁簨鍔″凡涓㈠け", deviceId, channelId); return; } - Dialog dialog = transaction.getDialog(); if (dialog == null) { + logger.warn("[ {} -> {}]鍋滄瑙嗛娴佺殑鏃跺�欏彂鐜板璇濆凡涓㈠け", deviceId, channelId); return; } Request byeRequest = dialog.createRequest(Request.BYE); @@ -632,7 +637,7 @@ } dialog.sendRequest(clientTransaction); - zlmrtpServerFactory.closeRTPServer(streamSession.getStreamId(deviceId, channelId)); + streamSession.remove(deviceId, channelId); } catch (SipException | ParseException e) { e.printStackTrace(); @@ -721,7 +726,7 @@ cmdXml.append("<Control>\r\n"); cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); - if (XmlUtil.isEmpty(channelId)) { + if (StringUtils.isEmpty(channelId)) { cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); } else { cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); @@ -821,16 +826,16 @@ cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); cmdXml.append("<AlarmCmd>ResetAlarm</AlarmCmd>\r\n"); - if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { + if (!StringUtils.isEmpty(alarmMethod) || !StringUtils.isEmpty(alarmType)) { cmdXml.append("<Info>\r\n"); } - if (!XmlUtil.isEmpty(alarmMethod)) { + if (!StringUtils.isEmpty(alarmMethod)) { cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); } - if (!XmlUtil.isEmpty(alarmType)) { + if (!StringUtils.isEmpty(alarmType)) { cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); } - if (!XmlUtil.isEmpty(alarmMethod) || !XmlUtil.isEmpty(alarmType)) { + if (!StringUtils.isEmpty(alarmMethod) || !StringUtils.isEmpty(alarmType)) { cmdXml.append("</Info>\r\n"); } cmdXml.append("</Control>\r\n"); @@ -863,7 +868,7 @@ cmdXml.append("<Control>\r\n"); cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); - if (XmlUtil.isEmpty(channelId)) { + if (StringUtils.isEmpty(channelId)) { cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); } else { cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); @@ -901,7 +906,7 @@ cmdXml.append("<Control>\r\n"); cmdXml.append("<CmdType>DeviceControl</CmdType>\r\n"); cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); - if (XmlUtil.isEmpty(channelId)) { + if (StringUtils.isEmpty(channelId)) { cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); } else { cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); @@ -969,13 +974,13 @@ cmdXml.append("<Control>\r\n"); cmdXml.append("<CmdType>DeviceConfig</CmdType>\r\n"); cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); - if (XmlUtil.isEmpty(channelId)) { + if (StringUtils.isEmpty(channelId)) { cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); } else { cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); } cmdXml.append("<BasicParam>\r\n"); - if (!XmlUtil.isEmpty(name)) { + if (!StringUtils.isEmpty(name)) { cmdXml.append("<Name>" + name + "</Name>\r\n"); } if (NumericUtil.isInteger(expiration)) { @@ -1169,22 +1174,22 @@ cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); - if (!XmlUtil.isEmpty(startPriority)) { + if (!StringUtils.isEmpty(startPriority)) { cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); } - if (!XmlUtil.isEmpty(endPriority)) { + if (!StringUtils.isEmpty(endPriority)) { cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n"); } - if (!XmlUtil.isEmpty(alarmMethod)) { + if (!StringUtils.isEmpty(alarmMethod)) { cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); } - if (!XmlUtil.isEmpty(alarmType)) { + if (!StringUtils.isEmpty(alarmType)) { cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); } - if (!XmlUtil.isEmpty(startTime)) { + if (!StringUtils.isEmpty(startTime)) { cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n"); } - if (!XmlUtil.isEmpty(endTime)) { + if (!StringUtils.isEmpty(endTime)) { cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n"); } cmdXml.append("</Query>\r\n"); @@ -1218,7 +1223,7 @@ cmdXml.append("<Query>\r\n"); cmdXml.append("<CmdType>ConfigDownload</CmdType>\r\n"); cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); - if (XmlUtil.isEmpty(channelId)) { + if (StringUtils.isEmpty(channelId)) { cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); } else { cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); @@ -1253,7 +1258,7 @@ cmdXml.append("<Query>\r\n"); cmdXml.append("<CmdType>PresetQuery</CmdType>\r\n"); cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); - if (XmlUtil.isEmpty(channelId)) { + if (StringUtils.isEmpty(channelId)) { cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); } else { cmdXml.append("<DeviceID>" + channelId + "</DeviceID>\r\n"); @@ -1365,22 +1370,22 @@ cmdXml.append("<CmdType>Alarm</CmdType>\r\n"); cmdXml.append("<SN>" + (int)((Math.random()*9+1)*100000) + "</SN>\r\n"); cmdXml.append("<DeviceID>" + device.getDeviceId() + "</DeviceID>\r\n"); - if (!XmlUtil.isEmpty(startPriority)) { + if (!StringUtils.isEmpty(startPriority)) { cmdXml.append("<StartAlarmPriority>" + startPriority + "</StartAlarmPriority>\r\n"); } - if (!XmlUtil.isEmpty(endPriority)) { + if (!StringUtils.isEmpty(endPriority)) { cmdXml.append("<EndAlarmPriority>" + endPriority + "</EndAlarmPriority>\r\n"); } - if (!XmlUtil.isEmpty(alarmMethod)) { + if (!StringUtils.isEmpty(alarmMethod)) { cmdXml.append("<AlarmMethod>" + alarmMethod + "</AlarmMethod>\r\n"); } - if (!XmlUtil.isEmpty(alarmType)) { + if (!StringUtils.isEmpty(alarmType)) { cmdXml.append("<AlarmType>" + alarmType + "</AlarmType>\r\n"); } - if (!XmlUtil.isEmpty(startTime)) { + if (!StringUtils.isEmpty(startTime)) { cmdXml.append("<StartAlarmTime>" + startTime + "</StartAlarmTime>\r\n"); } - if (!XmlUtil.isEmpty(endTime)) { + if (!StringUtils.isEmpty(endTime)) { cmdXml.append("<EndAlarmTime>" + endTime + "</EndAlarmTime>\r\n"); } cmdXml.append("</Query>\r\n"); @@ -1430,17 +1435,5 @@ clientTransaction.sendRequest(); return clientTransaction; - } - - - - - @Override - public void closeRTPServer(Device device, String channelId) { - if (mediaConfig.isRtpEnable()) { - String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId); - zlmrtpServerFactory.closeRTPServer(streamId); - } - streamSession.remove(device.getDeviceId(), channelId); } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/SIPRequestAbstractProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/SIPRequestAbstractProcessor.java index 5410820..12290d2 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/SIPRequestAbstractProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/SIPRequestAbstractProcessor.java @@ -16,6 +16,8 @@ import gov.nist.javax.sip.SipStackImpl; import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.stack.SIPServerTransaction; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @Description:澶勭悊鎺ユ敹IPCamera鍙戞潵鐨凷IP鍗忚璇锋眰娑堟伅 @@ -23,6 +25,8 @@ * @date: 2020骞�5鏈�3鏃� 涓嬪崍4:42:22 */ public abstract class SIPRequestAbstractProcessor implements ISIPRequestProcessor { + + private final static Logger logger = LoggerFactory.getLogger(SIPRequestAbstractProcessor.class); protected RequestEvent evt; @@ -64,9 +68,9 @@ } } } catch (TransactionAlreadyExistsException e) { - e.printStackTrace(); + logger.error(e.getMessage()); } catch (TransactionUnavailableException e) { - e.printStackTrace(); + logger.error(e.getMessage()); } } return serverTransaction; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java index 413f0d1..6f80971 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/AckRequestProcessor.java @@ -13,6 +13,9 @@ import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -29,6 +32,8 @@ private IRedisCatchStorage redisCatchStorage; private ZLMRTPServerFactory zlmrtpServerFactory; + + private IMediaServerService mediaServerService; /** * 澶勭悊 ACK璇锋眰 @@ -76,18 +81,22 @@ while (!rtpPushed) { try { if (System.currentTimeMillis() - startTime < 30 * 1000) { - if (zlmrtpServerFactory.isStreamReady(streamInfo.getApp(), streamInfo.getStreamId())) { + IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + if (zlmrtpServerFactory.isStreamReady(mediaInfo, streamInfo.getApp(), streamInfo.getStreamId())) { rtpPushed = true; - logger.info("宸茶幏鍙栬澶囨帹娴侊紝寮�濮嬪悜涓婄骇鎺ㄦ祦"); - zlmrtpServerFactory.startSendRtpStream(param); + logger.info("宸茶幏鍙栬澶囨帹娴乕{}/{}]锛屽紑濮嬪悜涓婄骇鎺ㄦ祦[{}:{}]", + streamInfo.getApp() ,streamInfo.getStreamId(), sendRtpItem.getIp(), sendRtpItem.getPort()); + zlmrtpServerFactory.startSendRtpStream(mediaInfo, param); } else { - logger.info("绛夊緟璁惧鎺ㄦ祦......."); + logger.info("绛夊緟璁惧鎺ㄦ祦[{}/{}].......", + streamInfo.getApp() ,streamInfo.getStreamId()); Thread.sleep(1000); continue; } } else { rtpPushed = true; - logger.info("璁惧鎺ㄦ祦瓒呮椂锛岀粓姝㈠悜涓婄骇鎺ㄦ祦"); + logger.info("璁惧鎺ㄦ祦[{}/{}]瓒呮椂锛岀粓姝㈠悜涓婄骇鎺ㄦ祦", + streamInfo.getApp() ,streamInfo.getStreamId()); } } catch (InterruptedException e) { e.printStackTrace(); @@ -123,4 +132,12 @@ public void setZlmrtpServerFactory(ZLMRTPServerFactory zlmrtpServerFactory) { this.zlmrtpServerFactory = zlmrtpServerFactory; } + + public IMediaServerService getMediaServerService() { + return mediaServerService; + } + + public void setMediaServerService(IMediaServerService mediaServerService) { + this.mediaServerService = mediaServerService; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java index fdb7c0b..50e8c32 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/ByeRequestProcessor.java @@ -15,6 +15,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -38,6 +41,8 @@ private ZLMRTPServerFactory zlmrtpServerFactory; + private IMediaServerService mediaServerService; + /** * 澶勭悊BYE璇锋眰 * @param evt @@ -60,9 +65,10 @@ param.put("stream",streamId); param.put("ssrc",sendRtpItem.getSsrc()); logger.info("鍋滄鍚戜笂绾ф帹娴侊細" + streamId); - zlmrtpServerFactory.stopSendRtpStream(param); + IMediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + zlmrtpServerFactory.stopSendRtpStream(mediaInfo, param); redisCatchStorage.deleteSendRTPServer(platformGbId, channelId); - if (zlmrtpServerFactory.totalReaderCount(sendRtpItem.getApp(), streamId) == 0) { + if (zlmrtpServerFactory.totalReaderCount(mediaInfo, sendRtpItem.getApp(), streamId) == 0) { logger.info(streamId + "鏃犲叾瀹冭鐪嬭�咃紝閫氱煡璁惧鍋滄鎺ㄦ祦"); cmder.streamByeCmd(sendRtpItem.getDeviceId(), channelId); } @@ -112,4 +118,11 @@ this.cmder = cmder; } + public IMediaServerService getMediaServerService() { + return mediaServerService; + } + + public void setMediaServerService(IMediaServerService mediaServerService) { + this.mediaServerService = mediaServerService; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java index 5f356b0..7219dbb 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/InviteRequestProcessor.java @@ -11,12 +11,16 @@ import javax.sip.message.Request; import javax.sip.message.Response; +import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; import com.genersoft.iot.vmp.gb28181.transmit.request.SIPRequestAbstractProcessor; import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; @@ -50,6 +54,8 @@ private IPlayService playService; private ZLMRTPServerFactory zlmrtpServerFactory; + + private IMediaServerService mediaServerService; public ZLMRTPServerFactory getZlmrtpServerFactory() { return zlmrtpServerFactory; @@ -91,6 +97,7 @@ // 鏌ヨ骞冲彴涓嬫槸鍚︽湁璇ラ�氶亾 DeviceChannel channel = storager.queryChannelInParentPlatform(requesterId, channelId); GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); + IMediaServerItem mediaServerItem = null; // 涓嶆槸閫氶亾鍙兘鏄洿鎾祦 if (channel != null && gbStream == null ) { if (channel.getStatus() == 0) { @@ -100,8 +107,15 @@ } responseAck(evt, Response.CALL_IS_BEING_FORWARDED); // 閫氶亾瀛樺湪锛屽彂181锛屽懠鍙浆鎺ヤ腑 }else if(channel == null && gbStream != null){ - Boolean streamReady = zlmrtpServerFactory.isStreamReady(gbStream.getApp(), gbStream.getStream()); - if (!streamReady) { + String mediaServerId = gbStream.getMediaServerId(); + mediaServerItem = mediaServerService.getOne(mediaServerId); + if (mediaServerItem == null) { + logger.info("[ app={}, stream={} ]zlm鎵句笉鍒帮紝杩斿洖410",gbStream.getApp(), gbStream.getStream()); + responseAck(evt, Response.GONE, "media server not found"); + return; + } + Boolean streamReady = zlmrtpServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); + if (!streamReady ) { logger.info("[ app={}, stream={} ]閫氶亾绂荤嚎锛岃繑鍥�400",gbStream.getApp(), gbStream.getStream()); responseAck(evt, Response.BAD_REQUEST, "channel [" + gbStream.getGbId() + "] offline"); return; @@ -130,8 +144,8 @@ //boolean recvonly = false; boolean mediaTransmissionTCP = false; Boolean tcpActive = null; - for (int i = 0; i < mediaDescriptions.size(); i++) { - MediaDescription mediaDescription = (MediaDescription)mediaDescriptions.get(i); + for (Object description : mediaDescriptions) { + MediaDescription mediaDescription = (MediaDescription) description; Media media = mediaDescription.getMedia(); Vector mediaFormats = media.getMediaFormats(false); @@ -147,7 +161,7 @@ mediaTransmissionTCP = true; if ("active".equals(setup)) { tcpActive = true; - }else if ("passive".equals(setup)) { + } else if ("passive".equals(setup)) { tcpActive = false; } } @@ -174,7 +188,13 @@ responseAck(evt, Response.SERVER_INTERNAL_ERROR); return; } - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId, + mediaServerItem = playService.getNewMediaServerItem(device); + if (mediaServerItem == null) { + logger.warn("鏈壘鍒板彲鐢ㄧ殑zlm"); + responseAck(evt, Response.BUSY_HERE); + return; + } + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, device.getDeviceId(), channelId, mediaTransmissionTCP); if (tcpActive != null) { @@ -189,18 +209,18 @@ // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� redisCatchStorage.updateSendRTPSever(sendRtpItem); // 閫氱煡涓嬬骇鎺ㄦ祦锛� - PlayResult playResult = playService.play(device.getDeviceId(), channelId, (responseJSON)->{ + PlayResult playResult = playService.play(mediaServerItem,device.getDeviceId(), channelId, (mediaServerItemInUSe, responseJSON)->{ // 鏀跺埌鎺ㄦ祦锛� 鍥炲200OK, 绛夊緟ack // if (sendRtpItem == null) return; sendRtpItem.setStatus(1); redisCatchStorage.updateSendRTPSever(sendRtpItem); // TODO 娣诲姞瀵箃cp鐨勬敮鎸� - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + StringBuffer content = new StringBuffer(200); content.append("v=0\r\n"); - content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getSdpIp()+"\r\n"); + content.append("o="+"00000"+" 0 0 IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); content.append("s=Play\r\n"); - content.append("c=IN IP4 "+mediaInfo.getSdpIp()+"\r\n"); + content.append("c=IN IP4 "+mediaServerItemInUSe.getSdpIp()+"\r\n"); content.append("t=0 0\r\n"); content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); content.append("a=sendonly\r\n"); @@ -217,7 +237,7 @@ } catch (ParseException e) { e.printStackTrace(); } - } ,(event -> { + } ,((event) -> { // 鏈煡閿欒銆傜洿鎺ヨ浆鍙戣澶囩偣鎾殑閿欒 Response response = null; try { @@ -232,7 +252,7 @@ } }else if (gbStream != null) { - SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(addressStr, port, ssrc, requesterId, + SendRtpItem sendRtpItem = zlmrtpServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, gbStream.getApp(), gbStream.getStream(), channelId, mediaTransmissionTCP); @@ -251,12 +271,11 @@ sendRtpItem.setStatus(1); redisCatchStorage.updateSendRTPSever(sendRtpItem); // TODO 娣诲姞瀵箃cp鐨勬敮鎸� - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); StringBuffer content = new StringBuffer(200); content.append("v=0\r\n"); - content.append("o="+"00000"+" 0 0 IN IP4 "+mediaInfo.getSdpIp()+"\r\n"); + content.append("o="+"00000"+" 0 0 IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); content.append("s=Play\r\n"); - content.append("c=IN IP4 "+mediaInfo.getSdpIp()+"\r\n"); + content.append("c=IN IP4 "+mediaServerItem.getSdpIp()+"\r\n"); content.append("t=0 0\r\n"); content.append("m=video "+ sendRtpItem.getLocalPort()+" RTP/AVP 96\r\n"); content.append("a=sendonly\r\n"); @@ -444,4 +463,12 @@ public void setRedisCatchStorage(IRedisCatchStorage redisCatchStorage) { this.redisCatchStorage = redisCatchStorage; } + + public IMediaServerService getMediaServerService() { + return mediaServerService; + } + + public void setMediaServerService(IMediaServerService mediaServerService) { + this.mediaServerService = mediaServerService; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java index 9d282c6..70e64a5 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/request/impl/MessageRequestProcessor.java @@ -282,7 +282,7 @@ //String result = XmlUtil.getText(rootElement, "Result"); // 鍥炲200 OK responseAck(evt); - if (rootElement.getName().equals("Response")) {//} !XmlUtil.isEmpty(result)) { + if (rootElement.getName().equals("Response")) {//} !StringUtils.isEmpty(result)) { // 姝ゅ鏄鏈钩鍙板彂鍑篋eviceControl鎸囦护鐨勫簲绛� JSONObject json = new JSONObject(); XmlUtil.node2Json(rootElement, json); @@ -299,7 +299,7 @@ String platformId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(FromHeader.NAME)).getAddress().getURI()).getUser(); String targetGBId = ((SipURI) ((HeaderAddress) evt.getRequest().getHeader(ToHeader.NAME)).getAddress().getURI()).getUser(); // 杩滅▼鍚姩鍔熻兘 - if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) { + if (!StringUtils.isEmpty(XmlUtil.getText(rootElement, "TeleBoot"))) { if (deviceId.equals(targetGBId)) { // 杩滅▼鍚姩鏈钩鍙帮細闇�瑕佸湪閲嶆柊鍚姩绋嬪簭鍚庡厛瀵筍ipStack瑙g粦 logger.info("鎵ц杩滅▼鍚姩鏈钩鍙板懡浠�"); @@ -337,7 +337,7 @@ } } // 浜戝彴/鍓嶇鎺у埗鍛戒护 - if (!XmlUtil.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) { + if (!StringUtils.isEmpty(XmlUtil.getText(rootElement,"PTZCmd")) && !deviceId.equals(targetGBId)) { String cmdString = XmlUtil.getText(rootElement,"PTZCmd"); Device device = storager.queryVideoDeviceByPlatformIdAndChannelId(platformId, deviceId); cmder.fronEndCmd(device, deviceId, cmdString); @@ -421,7 +421,7 @@ String deviceId = XmlUtil.getText(rootElement, "DeviceID"); // 鍥炲200 OK responseAck(evt); - if (rootElement.getName().equals("Response")) {// !XmlUtil.isEmpty(result)) { + if (rootElement.getName().equals("Response")) {// !StringUtils.isEmpty(result)) { // 姝ゅ鏄鏈钩鍙板彂鍑篋eviceControl鎸囦护鐨勫簲绛� JSONObject json = new JSONObject(); XmlUtil.node2Json(rootElement, json); @@ -718,7 +718,7 @@ deviceAlarm.setLatitude(0.00); } - if (!XmlUtil.isEmpty(deviceAlarm.getAlarmMethod())) { + if (!StringUtils.isEmpty(deviceAlarm.getAlarmMethod())) { if ( deviceAlarm.getAlarmMethod().equals("4")) { MobilePosition mobilePosition = new MobilePosition(); mobilePosition.setDeviceId(deviceAlarm.getDeviceId()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java index c82ba60..4220d81 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java @@ -17,6 +17,7 @@ import org.dom4j.io.SAXReader; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.util.StringUtils; /** * 鍩轰簬dom4j鐨勫伐鍏峰寘 @@ -114,12 +115,12 @@ // 濡傛灉鏄睘鎬� for (Object o : element.attributes()) { Attribute attr = (Attribute) o; - if (!isEmpty(attr.getValue())) { + if (!StringUtils.isEmpty(attr.getValue())) { json.put("@" + attr.getName(), attr.getValue()); } } List<Element> chdEl = element.elements(); - if (chdEl.isEmpty() && !isEmpty(element.getText())) {// 濡傛灉娌℃湁瀛愬厓绱�,鍙湁涓�涓�� + if (chdEl.isEmpty() && !StringUtils.isEmpty(element.getText())) {// 濡傛灉娌℃湁瀛愬厓绱�,鍙湁涓�涓�� json.put(element.getName(), element.getText()); } @@ -150,7 +151,7 @@ } else { // 瀛愬厓绱犳病鏈夊瓙鍏冪礌 for (Object o : element.attributes()) { Attribute attr = (Attribute) o; - if (!isEmpty(attr.getValue())) { + if (!StringUtils.isEmpty(attr.getValue())) { json.put("@" + attr.getName(), attr.getValue()); } } @@ -159,12 +160,5 @@ } } } - } - - public static boolean isEmpty(String str) { - if (str == null || str.trim().isEmpty() || "null".equals(str)) { - return true; - } - return false; } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java deleted file mode 100644 index a00bc2a..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHTTPProxyController.java +++ /dev/null @@ -1,54 +0,0 @@ -//package com.genersoft.iot.vmp.media.zlm; -// -//import com.genersoft.iot.vmp.conf.MediaConfig; -//import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -//import org.springframework.beans.factory.annotation.Autowired; -//import org.springframework.beans.factory.annotation.Value; -//import org.springframework.web.bind.annotation.*; -//import org.springframework.web.client.HttpClientErrorException; -//import org.springframework.web.client.RestTemplate; -// -//import javax.servlet.http.HttpServletRequest; -//import javax.servlet.http.HttpServletResponse; -// -//@RestController -//@RequestMapping("/zlm") -//public class ZLMHTTPProxyController { -// -// -// // private final static Logger logger = LoggerFactory.getLogger(ZLMHTTPProxyController.class); -// -// @Autowired -// private IRedisCatchStorage redisCatchStorage; -// -// @Autowired -// private MediaConfig mediaConfig; -// -// @ResponseBody -// @RequestMapping(value = "/**/**/**", produces = "application/json;charset=UTF-8") -// public Object proxy(HttpServletRequest request, HttpServletResponse response){ -// -// if (redisCatchStorage.getMediaInfo() == null) { -// return "鏈帴鍏ユ祦濯掍綋"; -// } -// ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); -// String requestURI = String.format("http://%s:%s%s?%s&%s", -// mediaInfo.getLocalIP(), -// mediaConfig.getHttpPort(), -// request.getRequestURI().replace("/zlm",""), -// mediaInfo.getHookAdminParams(), -// request.getQueryString() -// ); -// // 鍙戦�佽姹� -// RestTemplate restTemplate = new RestTemplate(); -// //灏嗘寚瀹氱殑url杩斿洖鐨勫弬鏁拌嚜鍔ㄥ皝瑁呭埌鑷畾涔夊ソ鐨勫搴旂被瀵硅薄涓� -// Object result = null; -// try { -// result = restTemplate.getForObject(requestURI,Object.class); -// -// }catch (HttpClientErrorException httpClientErrorException) { -// response.setStatus(httpClientErrorException.getStatusCode().value()); -// } -// return result; -// } -//} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java index bd8485d..b7aebf4 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -9,6 +9,9 @@ import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.conf.UserSetup; import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.service.IPlayService; @@ -53,10 +56,10 @@ private IRedisCatchStorage redisCatchStorage; @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; + private IMediaServerService mediaServerService; @Autowired - private ZLMServerManger zlmServerManger; + private ZLMRESTfulUtils zlmresTfulUtils; @Autowired private ZLMMediaListManager zlmMediaListManager; @@ -81,6 +84,7 @@ if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_flow_report API璋冪敤锛屽弬鏁帮細" + json.toString()); } + String mediaServerId = json.getString("mediaServerId"); JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); @@ -98,6 +102,7 @@ if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_http_access API 璋冪敤锛屽弬鏁帮細" + json.toString()); } + String mediaServerId = json.getString("mediaServerId"); JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("err", ""); @@ -117,9 +122,14 @@ if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_play API璋冪敤锛屽弬鏁帮細" + json.toString()); } + String mediaServerId = json.getString("mediaServerId"); ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_play, json); if (subscribe != null ) { - subscribe.response(json); + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + if (mediaInfo != null) { + subscribe.response(mediaInfo, json); + } + } JSONObject ret = new JSONObject(); ret.put("code", 0); @@ -133,20 +143,25 @@ */ @ResponseBody @PostMapping(value = "/on_publish", produces = "application/json;charset=UTF-8") - public ResponseEntity<String> onPublish(@RequestBody JSONObject json){ + public ResponseEntity<String> onPublish(@RequestBody JSONObject json) { logger.debug("ZLM HOOK on_publish API璋冪敤锛屽弬鏁帮細" + json.toString()); + String mediaServerId = json.getString("mediaServerId"); ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_publish, json); - if (subscribe != null) subscribe.response(json); - + if (subscribe != null) { + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + if (mediaInfo != null) { + subscribe.response(mediaInfo, json); + } + } JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); ret.put("enableHls", true); ret.put("enableMP4", userSetup.isRecordPushLive()); ret.put("enableRtxp", true); - return new ResponseEntity<String>(ret.toString(),HttpStatus.OK); + return new ResponseEntity<String>(ret.toString(), HttpStatus.OK); } /** @@ -160,6 +175,7 @@ if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_record_mp4 API璋冪敤锛屽弬鏁帮細" + json.toString()); } + String mediaServerId = json.getString("mediaServerId"); JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); @@ -177,6 +193,7 @@ if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_rtsp_realm API璋冪敤锛屽弬鏁帮細" + json.toString()); } + String mediaServerId = json.getString("mediaServerId"); JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("realm", ""); @@ -195,6 +212,7 @@ if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_rtsp_auth API璋冪敤锛屽弬鏁帮細" + json.toString()); } + String mediaServerId = json.getString("mediaServerId"); JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("encrypted", false); @@ -216,9 +234,15 @@ // TODO 濡傛灉鏄甫鏈塺tpstream鍒欏紑鍚寜闇�鎷夋祦 // String app = json.getString("app"); // String stream = json.getString("stream"); - + String mediaServerId = json.getString("mediaServerId"); ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_shell_login, json); - if (subscribe != null) subscribe.response(json); + if (subscribe != null ) { + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + if (mediaInfo != null) { + subscribe.response(mediaInfo, json); + } + + } JSONObject ret = new JSONObject(); ret.put("code", 0); @@ -237,9 +261,15 @@ if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_stream_changed API璋冪敤锛屽弬鏁帮細" + json.toString()); } - + String mediaServerId = json.getString("mediaServerId"); ZLMHttpHookSubscribe.Event subscribe = this.subscribe.getSubscribe(ZLMHttpHookSubscribe.HookType.on_stream_changed, json); - if (subscribe != null) subscribe.response(json); + if (subscribe != null ) { + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + if (mediaInfo != null) { + subscribe.response(mediaInfo, json); + } + + } // 娴佹秷澶辩Щ闄edis play String app = json.getString("app"); @@ -251,6 +281,11 @@ logger.info("[stream: " + streamId + "] on_stream_changed->>" + schema); } if ("rtmp".equals(schema)){ + if (regist) { + mediaServerService.addCount(mediaServerId); + }else { + mediaServerService.removeCount(mediaServerId); + } if ("rtp".equals(app) && !regist ) { StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); if (streamInfo!=null){ @@ -262,10 +297,11 @@ } }else { if (!"rtp".equals(app) ){ + IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); if (regist) { - zlmMediaListManager.addMedia(app, streamId); + zlmMediaListManager.addMedia(mediaServerItem, app, streamId); }else { - zlmMediaListManager.removeMedia(app, streamId); + zlmMediaListManager.removeMedia( app, streamId); } } } @@ -288,7 +324,7 @@ if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_stream_none_reader API璋冪敤锛屽弬鏁帮細" + json.toString()); } - + String mediaServerId = json.getString("mediaServerId"); String streamId = json.getString("stream"); String app = json.getString("app"); @@ -329,11 +365,12 @@ @ResponseBody @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8") public ResponseEntity<String> onStreamNotFound(@RequestBody JSONObject json){ - if (logger.isDebugEnabled()) { logger.debug("ZLM HOOK on_stream_not_found API璋冪敤锛屽弬鏁帮細" + json.toString()); } - if (userSetup.isAutoApplyPlay()) { + String mediaServerId = json.getString("mediaServerId"); + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + if (userSetup.isAutoApplyPlay() && mediaInfo != null) { String app = json.getString("app"); String streamId = json.getString("stream"); if ("rtp".equals(app) && streamId.contains("gb_play") ) { @@ -344,9 +381,9 @@ Device device = storager.queryVideoDevice(deviceId); if (device != null) { UUID uuid = UUID.randomUUID(); - cmder.playStreamCmd(device, channelId, (JSONObject response) -> { + cmder.playStreamCmd(mediaInfo, device, channelId, (IMediaServerItem mediaServerItemInuse, JSONObject response) -> { logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + response.toJSONString()); - playService.onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString()); + playService.onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString()); }, null); } @@ -367,26 +404,19 @@ */ @ResponseBody @PostMapping(value = "/on_server_started", produces = "application/json;charset=UTF-8") - public ResponseEntity<String> onServerStarted(HttpServletRequest request, @RequestBody JSONObject json){ + public ResponseEntity<String> onServerStarted(HttpServletRequest request, @RequestBody JSONObject jsonObject){ if (logger.isDebugEnabled()) { - logger.debug("ZLM HOOK on_server_started API璋冪敤锛屽弬鏁帮細" + json.toString()); + logger.debug("ZLM HOOK on_server_started API璋冪敤锛屽弬鏁帮細" + jsonObject.toString()); } - -// String data = json.getString("data"); -// List<MediaServerConfig> mediaServerConfigs = JSON.parseArray(JSON.toJSONString(json), MediaServerConfig.class); -// MediaServerConfig mediaServerConfig = mediaServerConfigs.get(0); - + String remoteAddr = request.getRemoteAddr(); + jsonObject.put("ip", remoteAddr); List<ZLMHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(ZLMHttpHookSubscribe.HookType.on_server_started); - if (subscribes != null && subscribes.size() > 0) { + if (subscribes != null && subscribes.size() > 0) { for (ZLMHttpHookSubscribe.Event subscribe : subscribes) { - subscribe.response(json); + subscribe.response(null, jsonObject); } } - ZLMServerConfig ZLMServerConfig = JSON.toJavaObject(json, ZLMServerConfig.class); - zlmServerManger.updateServerCatch(ZLMServerConfig); - // 閲嶆柊鍙戣捣浠g悊 - JSONObject ret = new JSONObject(); ret.put("code", 0); ret.put("msg", "success"); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java index 4f832ae..62b18f5 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookSubscribe.java @@ -1,6 +1,8 @@ package com.genersoft.iot.vmp.media.zlm; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import org.springframework.stereotype.Component; import java.util.*; @@ -30,7 +32,7 @@ } public interface Event{ - void response(JSONObject response); + void response(IMediaServerItem mediaServerItem, JSONObject response); } private Map<HookType, Map<JSONObject, ZLMHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>(); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java index ed407d2..3876309 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java @@ -2,6 +2,8 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.gb28181.bean.GbStream; @@ -45,11 +47,11 @@ private ZLMHttpHookSubscribe subscribe; - public void updateMediaList() { + public void updateMediaList(MediaServerItem mediaServerItem) { storager.clearMediaList(); // 浣跨敤寮傛鐨勫綋鏃舵洿鏂板獟浣撴祦鍒楄〃 - zlmresTfulUtils.getMediaList((mediaList ->{ + zlmresTfulUtils.getMediaList(mediaServerItem, (mediaList ->{ if (mediaList == null) return; String dataStr = mediaList.getString("data"); @@ -57,10 +59,10 @@ Map<String, StreamPushItem> result = new HashMap<>(); List<StreamPushItem> streamPushItems = null; // 鑾峰彇鎵�鏈夌殑鍥芥爣鍏宠仈 - List<GbStream> gbStreams = gbStreamMapper.selectAll(); +// List<GbStream> gbStreams = gbStreamMapper.selectAllByMediaServerId(mediaServerItem.getId()); if (code == 0 ) { if (dataStr != null) { - streamPushItems = streamPushService.handleJSON(dataStr); + streamPushItems = streamPushService.handleJSON(dataStr, mediaServerItem); } }else { logger.warn("鏇存柊瑙嗛娴佸け璐ワ紝閿欒code锛� " + code); @@ -72,24 +74,27 @@ JSONObject jsonObject = new JSONObject(); jsonObject.put("app", streamPushItem.getApp()); jsonObject.put("stream", streamPushItem.getStream()); - subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject,(response)->{ - updateMedia(response.getString("app"), response.getString("stream")); - }); + jsonObject.put("mediaServerId", mediaServerItem.getId()); + subscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_play,jsonObject, + (IMediaServerItem mediaServerItemInuse, JSONObject response)->{ + updateMedia(mediaServerItem, response.getString("app"), response.getString("stream")); + } + ); } } })); } - public void addMedia(String app, String streamId) { + public void addMedia(IMediaServerItem mediaServerItem, String app, String streamId) { //浣跨敤寮傛鏇存柊鎺ㄦ祦 - updateMedia(app, streamId); + updateMedia(mediaServerItem, app, streamId); } - public void updateMedia(String app, String streamId) { + public void updateMedia(IMediaServerItem mediaServerItem, String app, String streamId) { //浣跨敤寮傛鏇存柊鎺ㄦ祦 - zlmresTfulUtils.getMediaList(app, streamId, "rtmp", json->{ + zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId, "rtmp", json->{ if (json == null) return; String dataStr = json.getString("data"); @@ -99,7 +104,7 @@ List<StreamPushItem> streamPushItems = null; if (code == 0 ) { if (dataStr != null) { - streamPushItems = streamPushService.handleJSON(dataStr); + streamPushItems = streamPushService.handleJSON(dataStr, mediaServerItem); } }else { logger.warn("鏇存柊瑙嗛娴佸け璐ワ紝閿欒code锛� " + code); @@ -122,32 +127,32 @@ } } - public void clearAllSessions() { - logger.info("娓呯┖鎵�鏈夊浗鏍囩浉鍏崇殑session"); - JSONObject allSessionJSON = zlmresTfulUtils.getAllSession(); - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); - HashSet<String> allLocalPorts = new HashSet(); - if (allSessionJSON.getInteger("code") == 0) { - JSONArray data = allSessionJSON.getJSONArray("data"); - if (data.size() > 0) { - for (int i = 0; i < data.size(); i++) { - JSONObject sessionJOSN = data.getJSONObject(i); - Integer local_port = sessionJOSN.getInteger("local_port"); - if (!local_port.equals(Integer.valueOf(mediaInfo.getHttpPort())) && - !local_port.equals(Integer.valueOf(mediaInfo.getHttpSSLport())) && - !local_port.equals(Integer.valueOf(mediaInfo.getRtmpPort())) && - !local_port.equals(Integer.valueOf(mediaInfo.getRtspPort())) && - !local_port.equals(Integer.valueOf(mediaInfo.getRtspSSlport())) && - !local_port.equals(Integer.valueOf(mediaInfo.getHookOnFlowReport()))){ - allLocalPorts.add(sessionJOSN.getInteger("local_port") + ""); - } - } - } - } - if (allLocalPorts.size() > 0) { - List<String> result = new ArrayList<>(allLocalPorts); - String localPortSStr = String.join(",", result); - zlmresTfulUtils.kickSessions(localPortSStr); - } - } +// public void clearAllSessions() { +// logger.info("娓呯┖鎵�鏈夊浗鏍囩浉鍏崇殑session"); +// JSONObject allSessionJSON = zlmresTfulUtils.getAllSession(); +// ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); +// HashSet<String> allLocalPorts = new HashSet(); +// if (allSessionJSON.getInteger("code") == 0) { +// JSONArray data = allSessionJSON.getJSONArray("data"); +// if (data.size() > 0) { +// for (int i = 0; i < data.size(); i++) { +// JSONObject sessionJOSN = data.getJSONObject(i); +// Integer local_port = sessionJOSN.getInteger("local_port"); +// if (!local_port.equals(Integer.valueOf(mediaInfo.getHttpPort())) && +// !local_port.equals(Integer.valueOf(mediaInfo.getHttpSSLport())) && +// !local_port.equals(Integer.valueOf(mediaInfo.getRtmpPort())) && +// !local_port.equals(Integer.valueOf(mediaInfo.getRtspPort())) && +// !local_port.equals(Integer.valueOf(mediaInfo.getRtspSSlport())) && +// !local_port.equals(Integer.valueOf(mediaInfo.getHookOnFlowReport()))){ +// allLocalPorts.add(sessionJOSN.getInteger("local_port") + ""); +// } +// } +// } +// } +// if (allLocalPorts.size() > 0) { +// List<String> result = new ArrayList<>(allLocalPorts); +// String localPortSStr = String.join(",", result); +// zlmresTfulUtils.kickSessions(localPortSStr); +// } +// } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java index 8425d03..8e12e57 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java @@ -3,6 +3,8 @@ import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.conf.MediaConfig; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import okhttp3.*; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -21,23 +23,18 @@ private final static Logger logger = LoggerFactory.getLogger(ZLMRESTfulUtils.class); - @Autowired - private MediaConfig mediaConfig; - - - public interface RequestCallback{ void run(JSONObject response); } - public JSONObject sendPost(String api, Map<String, Object> param, RequestCallback callback) { + public JSONObject sendPost(IMediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) { OkHttpClient client = new OkHttpClient(); - String url = String.format("http://%s:%s/index/api/%s", mediaConfig.getIp(), mediaConfig.getHttpPort(), api); + String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api); JSONObject responseJSON = null; logger.debug(url); FormBody.Builder builder = new FormBody.Builder(); - builder.add("secret",mediaConfig.getSecret()); + builder.add("secret",mediaServerItem.getSecret()); if (param != null && param.keySet().size() > 0) { for (String key : param.keySet()){ if (param.get(key) != null) { @@ -96,14 +93,14 @@ } - public void sendPostForImg(String api, Map<String, Object> param, String targetPath, String fileName) { + public void sendPostForImg(IMediaServerItem mediaServerItem, String api, Map<String, Object> param, String targetPath, String fileName) { OkHttpClient client = new OkHttpClient(); - String url = String.format("http://%s:%s/index/api/%s", mediaConfig.getIp(), mediaConfig.getHttpPort(), api); + String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api); JSONObject responseJSON = null; logger.debug(url); FormBody.Builder builder = new FormBody.Builder(); - builder.add("secret",mediaConfig.getSecret()); + builder.add("secret",mediaServerItem.getSecret()); if (param != null && param.keySet().size() > 0) { for (String key : param.keySet()){ if (param.get(key) != null) { @@ -142,39 +139,39 @@ } - public JSONObject getMediaList(String app, String stream, String schema, RequestCallback callback){ + public JSONObject getMediaList(IMediaServerItem mediaServerItem,String app, String stream, String schema, RequestCallback callback){ Map<String, Object> param = new HashMap<>(); if (app != null) param.put("app",app); if (stream != null) param.put("stream",stream); if (schema != null) param.put("schema",schema); param.put("vhost","__defaultVhost__"); - return sendPost("getMediaList",param, callback); + return sendPost(mediaServerItem, "getMediaList",param, callback); } - public JSONObject getMediaList(String app, String stream){ - return getMediaList(app, stream,null, null); + public JSONObject getMediaList(IMediaServerItem mediaServerItem,String app, String stream){ + return getMediaList(mediaServerItem, app, stream,null, null); } - public JSONObject getMediaList(RequestCallback callback){ - return sendPost("getMediaList",null, callback); + public JSONObject getMediaList(IMediaServerItem mediaServerItem,RequestCallback callback){ + return sendPost(mediaServerItem, "getMediaList",null, callback); } - public JSONObject getMediaInfo(String app, String schema, String stream){ + public JSONObject getMediaInfo(IMediaServerItem mediaServerItem,String app, String schema, String stream){ Map<String, Object> param = new HashMap<>(); param.put("app",app); param.put("schema",schema); param.put("stream",stream); param.put("vhost","__defaultVhost__"); - return sendPost("getMediaInfo",param, null); + return sendPost(mediaServerItem, "getMediaInfo",param, null); } - public JSONObject getRtpInfo(String stream_id){ + public JSONObject getRtpInfo(IMediaServerItem mediaServerItem,String stream_id){ Map<String, Object> param = new HashMap<>(); param.put("stream_id",stream_id); - return sendPost("getRtpInfo",param, null); + return sendPost(mediaServerItem, "getRtpInfo",param, null); } - public JSONObject addFFmpegSource(String src_url, String dst_url, String timeout_ms, + public JSONObject addFFmpegSource(IMediaServerItem mediaServerItem,String src_url, String dst_url, String timeout_ms, boolean enable_hls, boolean enable_mp4, String ffmpeg_cmd_key){ logger.info(src_url); logger.info(dst_url); @@ -185,44 +182,44 @@ param.put("enable_hls", enable_hls); param.put("enable_mp4", enable_mp4); param.put("ffmpeg_cmd_key", ffmpeg_cmd_key); - return sendPost("addFFmpegSource",param, null); + return sendPost(mediaServerItem, "addFFmpegSource",param, null); } - public JSONObject delFFmpegSource(String key){ + public JSONObject delFFmpegSource(IMediaServerItem mediaServerItem,String key){ Map<String, Object> param = new HashMap<>(); param.put("key", key); - return sendPost("delFFmpegSource",param, null); + return sendPost(mediaServerItem, "delFFmpegSource",param, null); } - public JSONObject getMediaServerConfig(){ - return sendPost("getServerConfig",null, null); + public JSONObject getMediaServerConfig(IMediaServerItem mediaServerItem){ + return sendPost(mediaServerItem, "getServerConfig",null, null); } - public JSONObject setServerConfig(Map<String, Object> param){ - return sendPost("setServerConfig",param, null); + public JSONObject setServerConfig(IMediaServerItem mediaServerItem, Map<String, Object> param){ + return sendPost(mediaServerItem,"setServerConfig",param, null); } - public JSONObject openRtpServer(Map<String, Object> param){ - return sendPost("openRtpServer",param, null); + public JSONObject openRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param){ + return sendPost(mediaServerItem, "openRtpServer",param, null); } - public JSONObject closeRtpServer(Map<String, Object> param) { - return sendPost("closeRtpServer",param, null); + public JSONObject closeRtpServer(IMediaServerItem mediaServerItem,Map<String, Object> param) { + return sendPost(mediaServerItem, "closeRtpServer",param, null); } - public JSONObject listRtpServer() { - return sendPost("listRtpServer",null, null); + public JSONObject listRtpServer(IMediaServerItem mediaServerItem) { + return sendPost(mediaServerItem, "listRtpServer",null, null); } - public JSONObject startSendRtp(Map<String, Object> param) { - return sendPost("startSendRtp",param, null); + public JSONObject startSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) { + return sendPost(mediaServerItem, "startSendRtp",param, null); } - public JSONObject stopSendRtp(Map<String, Object> param) { - return sendPost("stopSendRtp",param, null); + public JSONObject stopSendRtp(IMediaServerItem mediaServerItem,Map<String, Object> param) { + return sendPost(mediaServerItem, "stopSendRtp",param, null); } - public JSONObject addStreamProxy(String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) { + public JSONObject addStreamProxy(IMediaServerItem mediaServerItem,String app, String stream, String url, boolean enable_hls, boolean enable_mp4, String rtp_type) { Map<String, Object> param = new HashMap<>(); param.put("vhost", "__defaultVhost__"); param.put("app", app); @@ -231,33 +228,33 @@ param.put("enable_hls", enable_hls?1:0); param.put("enable_mp4", enable_mp4?1:0); param.put("rtp_type", rtp_type); - return sendPost("addStreamProxy",param, null); + return sendPost(mediaServerItem, "addStreamProxy",param, null); } - public JSONObject closeStreams(String app, String stream) { + public JSONObject closeStreams(IMediaServerItem mediaServerItem,String app, String stream) { Map<String, Object> param = new HashMap<>(); param.put("vhost", "__defaultVhost__"); param.put("app", app); param.put("stream", stream); param.put("force", 1); - return sendPost("close_streams",param, null); + return sendPost(mediaServerItem, "close_streams",param, null); } - public JSONObject getAllSession() { - return sendPost("getAllSession",null, null); + public JSONObject getAllSession(IMediaServerItem mediaServerItem) { + return sendPost(mediaServerItem, "getAllSession",null, null); } - public void kickSessions(String localPortSStr) { + public void kickSessions(IMediaServerItem mediaServerItem, String localPortSStr) { Map<String, Object> param = new HashMap<>(); param.put("local_port", localPortSStr); - sendPost("kick_sessions",param, null); + sendPost(mediaServerItem, "kick_sessions",param, null); } - public void getSnap(String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { + public void getSnap(IMediaServerItem mediaServerItem, String flvUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { Map<String, Object> param = new HashMap<>(); param.put("url", flvUrl); param.put("timeout_sec", timeout_sec); param.put("expire_sec", expire_sec); - sendPostForImg("getSnap",param, targetPath, fileName); + sendPostForImg(mediaServerItem, "getSnap",param, targetPath, fileName); } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java index ed069f8..5919c9f 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRTPServerFactory.java @@ -5,6 +5,8 @@ import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.gb28181.session.SsrcUtil; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -30,10 +32,10 @@ private Map<String, Integer> currentStreams = null; - public int createRTPServer(String streamId) { + public int createRTPServer(IMediaServerItem mediaServerItem, String streamId) { if (currentStreams == null) { currentStreams = new HashMap<>(); - JSONObject jsonObject = zlmresTfulUtils.listRtpServer(); + JSONObject jsonObject = zlmresTfulUtils.listRtpServer(mediaServerItem); if (jsonObject != null) { JSONArray data = jsonObject.getJSONArray("data"); if (data != null) { @@ -48,7 +50,7 @@ if (currentStreams.get(streamId) != null) { Map<String, Object> closeRtpServerParam = new HashMap<>(); closeRtpServerParam.put("stream_id", streamId); - zlmresTfulUtils.closeRtpServer(closeRtpServerParam); + zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); currentStreams.remove(streamId); } @@ -58,7 +60,7 @@ param.put("port", newPort); param.put("enable_tcp", 1); param.put("stream_id", streamId); - JSONObject jsonObject = zlmresTfulUtils.openRtpServer(param); + JSONObject jsonObject = zlmresTfulUtils.openRtpServer(mediaServerItem, param); if (jsonObject != null) { switch (jsonObject.getInteger("code")){ @@ -68,11 +70,11 @@ case -300: // id宸茬粡瀛樺湪, 鍙兘宸茬粡鍦ㄥ叾浠栫鍙f帹娴� Map<String, Object> closeRtpServerParam = new HashMap<>(); closeRtpServerParam.put("stream_id", streamId); - zlmresTfulUtils.closeRtpServer(closeRtpServerParam); + zlmresTfulUtils.closeRtpServer(mediaServerItem, closeRtpServerParam); result = newPort; break; case -400: // 绔彛鍗犵敤 - result= createRTPServer(streamId); + result= createRTPServer(mediaServerItem, streamId); break; default: logger.error("鍒涘缓RTP Server 澶辫触 {}: " + jsonObject.getString("msg"), newPort); @@ -85,20 +87,22 @@ return result; } - public boolean closeRTPServer(String streamId) { + public boolean closeRTPServer(IMediaServerItem serverItem, String streamId) { boolean result = false; - Map<String, Object> param = new HashMap<>(); - param.put("stream_id", streamId); - JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(param); - if (jsonObject != null ) { - if (jsonObject.getInteger("code") == 0) { - result = jsonObject.getInteger("hit") == 1; + if (serverItem !=null){ + Map<String, Object> param = new HashMap<>(); + param.put("stream_id", streamId); + JSONObject jsonObject = zlmresTfulUtils.closeRtpServer(serverItem, param); + if (jsonObject != null ) { + if (jsonObject.getInteger("code") == 0) { + result = jsonObject.getInteger("hit") == 1; + }else { + logger.error("鍏抽棴RTP Server 澶辫触: " + jsonObject.getString("msg")); + } }else { - logger.error("鍏抽棴RTP Server 澶辫触: " + jsonObject.getString("msg")); + // 妫�鏌LM鐘舵�� + logger.error("鍏抽棴RTP Server 澶辫触: 璇锋鏌LM鏈嶅姟"); } - }else { - // 妫�鏌LM鐘舵�� - logger.error("鍏抽棴RTP Server 澶辫触: 璇锋鏌LM鏈嶅姟"); } return result; } @@ -131,11 +135,11 @@ * @param tcp 鏄惁涓簍cp * @return SendRtpItem */ - public SendRtpItem createSendRtpItem(String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){ + public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp){ String playSsrc = SsrcUtil.getPlaySsrc(); - int localPort = createRTPServer(SsrcUtil.getPlaySsrc()); + int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc()); if (localPort != -1) { - closeRTPServer(playSsrc); + closeRTPServer(serverItem, playSsrc); }else { logger.error("娌℃湁鍙敤鐨勭鍙�"); return null; @@ -150,6 +154,7 @@ sendRtpItem.setTcp(tcp); sendRtpItem.setApp("rtp"); sendRtpItem.setLocalPort(localPort); + sendRtpItem.setMediaServerId(serverItem.getId()); return sendRtpItem; } @@ -163,11 +168,11 @@ * @param tcp 鏄惁涓簍cp * @return SendRtpItem */ - public SendRtpItem createSendRtpItem(String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){ + public SendRtpItem createSendRtpItem(IMediaServerItem serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp){ String playSsrc = SsrcUtil.getPlaySsrc(); - int localPort = createRTPServer(SsrcUtil.getPlaySsrc()); + int localPort = createRTPServer(serverItem, SsrcUtil.getPlaySsrc()); if (localPort != -1) { - closeRTPServer(playSsrc); + closeRTPServer(serverItem, playSsrc); }else { logger.error("娌℃湁鍙敤鐨勭鍙�"); return null; @@ -182,21 +187,21 @@ sendRtpItem.setChannelId(channelId); sendRtpItem.setTcp(tcp); sendRtpItem.setLocalPort(localPort); + sendRtpItem.setMediaServerId(serverItem.getId()); return sendRtpItem; } /** * 璋冪敤zlm RESTful API 鈥斺�� startSendRtp */ - public Boolean startSendRtpStream(Map<String, Object>param) { + public Boolean startSendRtpStream(IMediaServerItem mediaServerItem, Map<String, Object>param) { Boolean result = false; - JSONObject jsonObject = zlmresTfulUtils.startSendRtp(param); - logger.info(jsonObject.toJSONString()); + JSONObject jsonObject = zlmresTfulUtils.startSendRtp(mediaServerItem, param); if (jsonObject == null) { logger.error("RTP鎺ㄦ祦澶辫触: 璇锋鏌LM鏈嶅姟"); } else if (jsonObject.getInteger("code") == 0) { result= true; - logger.info("RTP鎺ㄦ祦璇锋眰鎴愬姛锛屾湰鍦版帹娴佺鍙o細" + jsonObject.getString("local_port")); + logger.info("RTP鎺ㄦ祦[ {}/{} ]璇锋眰鎴愬姛锛屾湰鍦版帹娴佺鍙o細{}" ,param.get("app"), param.get("stream"), jsonObject.getString("local_port")); } else { logger.error("RTP鎺ㄦ祦澶辫触: " + jsonObject.getString("msg")); } @@ -206,16 +211,16 @@ /** * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁� */ - public Boolean isRtpReady(String streamId) { - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo("rtp", "rtmp", streamId); + public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) { + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtmp", streamId); return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); } /** * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁� */ - public Boolean isStreamReady(String app, String streamId) { - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(app, "rtmp", streamId); + public Boolean isStreamReady(IMediaServerItem mediaServerItem, String app, String streamId) { + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); return (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")); } @@ -224,18 +229,17 @@ * @param streamId * @return */ - public int totalReaderCount(String app, String streamId) { - JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(app, "rtmp", streamId); + public int totalReaderCount(IMediaServerItem mediaServerItem, String app, String streamId) { + JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtmp", streamId); return mediaInfo.getInteger("totalReaderCount"); } /** * 璋冪敤zlm RESTful API 鈥斺�� stopSendRtp */ - public Boolean stopSendRtpStream(Map<String, Object>param) { + public Boolean stopSendRtpStream(IMediaServerItem mediaServerItem,Map<String, Object>param) { Boolean result = false; - JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(param); - logger.info(jsonObject.toJSONString()); + JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); if (jsonObject == null) { logger.error("鍋滄RTP鎺ㄦ祦澶辫触: 璇锋鏌LM鏈嶅姟"); } else if (jsonObject.getInteger("code") == 0) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java index 956db14..d06c6c3 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java @@ -4,7 +4,10 @@ import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.conf.MediaConfig; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.service.IStreamProxyService; import org.slf4j.Logger; @@ -14,10 +17,10 @@ import org.springframework.boot.CommandLineRunner; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import javax.print.attribute.standard.Media; +import java.util.*; @Component @Order(value=1) @@ -25,140 +28,131 @@ private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class); - @Autowired - private IVideoManagerStorager storager; - - @Autowired - private MediaConfig mediaConfig; - - @Value("${server.port}") - private String serverPort; - - @Value("${server.ssl.enabled:false}") - private boolean sslEnabled; - - private boolean startGetMedia = false; + private Map<String, Boolean> startGetMedia; @Autowired private ZLMRESTfulUtils zlmresTfulUtils; @Autowired - private ZLMMediaListManager zlmMediaListManager; - - @Autowired private ZLMHttpHookSubscribe hookSubscribe; - - @Autowired - private ZLMServerManger zlmServerManger; @Autowired private IStreamProxyService streamProxyService; + @Autowired + private IMediaServerService mediaServerService; + + @Autowired + private MediaConfig mediaConfig; + @Override public void run(String... strings) throws Exception { - // 璁㈤槄 zlm鍚姩浜嬩欢 - hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null,(response)->{ - ZLMServerConfig ZLMServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class); - zLmRunning(ZLMServerConfig); + IMediaServerItem presetMediaServer = mediaServerService.getOneByHostAndPort( + mediaConfig.getIp(), mediaConfig.getHttpPort()); + if (presetMediaServer != null) { + mediaConfig.setId(presetMediaServer.getId()); + mediaServerService.update(mediaConfig); + } + + // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁� + hookSubscribe.addSubscribe(ZLMHttpHookSubscribe.HookType.on_server_started,null, + (IMediaServerItem mediaServerItem, JSONObject response)->{ + ZLMServerConfig zlmServerConfig = JSONObject.toJavaObject(response, ZLMServerConfig.class); + if (zlmServerConfig !=null ) { + startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId()); + mediaServerService.handLeZLMServerConfig(zlmServerConfig); +// zLmRunning(zlmServerConfig); + } }); // 鑾峰彇zlm淇℃伅 - logger.info("绛夊緟zlm鎺ュ叆..."); - startGetMedia = true; - ZLMServerConfig ZLMServerConfig = getMediaServerConfig(); + logger.info("绛夊緟榛樿zlm鎺ュ叆..."); - if (ZLMServerConfig != null) { - zLmRunning(ZLMServerConfig); + // 鑾峰彇鎵�鏈夌殑zlm锛� 骞跺紑鍚富鍔ㄨ繛鎺� + List<IMediaServerItem> all = mediaServerService.getAll(); + if (presetMediaServer == null) { + all.add(mediaConfig.getMediaSerItem()); } + for (IMediaServerItem mediaServerItem : all) { + if (startGetMedia == null) startGetMedia = new HashMap<>(); + startGetMedia.put(mediaServerItem.getId(), true); + new Thread(() -> { + ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem); + if (zlmServerConfig != null) { + startGetMedia.remove(mediaServerItem.getId()); + mediaServerService.handLeZLMServerConfig(zlmServerConfig); + } + }).start(); + } + Timer timer = new Timer(); + // 1鍒嗛挓鍚庢湭杩炴帴鍒板垯涓嶅啀鍘讳富鍔ㄨ繛鎺� + timer.schedule(new TimerTask() { + @Override + public void run() { + if (startGetMedia != null) { + Set<String> allZlmId = startGetMedia.keySet(); + for (String id : allZlmId) { + logger.error("[ {} ]]涓诲姩杩炴帴澶辫触锛屼笉鍐嶄富鍔ㄨ繛鎺�", id); + startGetMedia.put(id, false); + } + } + } + }, 60 * 1000 * 2); } - public ZLMServerConfig getMediaServerConfig() { - if (!startGetMedia) return null; - JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(); + public ZLMServerConfig getMediaServerConfig(IMediaServerItem mediaServerItem) { + if ( startGetMedia.get(mediaServerItem.getId()) == null || !startGetMedia.get(mediaServerItem.getId())) return null; + JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); ZLMServerConfig ZLMServerConfig = null; if (responseJSON != null) { JSONArray data = responseJSON.getJSONArray("data"); if (data != null && data.size() > 0) { ZLMServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); - + ZLMServerConfig.setIp(mediaServerItem.getIp()); } } else { - logger.error("getMediaServerConfig澶辫触, 1s鍚庨噸璇�"); + logger.error("[ {} ]-[ {}:{} ]涓诲姩杩炴帴澶辫触澶辫触, 2s鍚庨噸璇�", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); try { - Thread.sleep(1000); + Thread.sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } - ZLMServerConfig = getMediaServerConfig(); + ZLMServerConfig = getMediaServerConfig(mediaServerItem); } return ZLMServerConfig; - } - private void saveZLMConfig() { - logger.info("璁剧疆zlm..."); - String protocol = sslEnabled ? "https" : "http"; - String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaConfig.getHookIp(), serverPort); - String recordHookPrex = null; - if (mediaConfig.getRecordAssistPort() != 0) { - recordHookPrex = String.format("http://127.0.0.1:%s/api/record", mediaConfig.getRecordAssistPort()); - } - Map<String, Object> param = new HashMap<>(); - param.put("api.secret",mediaConfig.getSecret()); // -profile:v Baseline - param.put("ffmpeg.cmd","%s -fflags nobuffer -rtsp_transport tcp -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"); - param.put("hook.enable","1"); - param.put("hook.on_flow_report",""); - param.put("hook.on_play",String.format("%s/on_play", hookPrex)); - param.put("hook.on_http_access",""); - param.put("hook.on_publish", String.format("%s/on_publish", hookPrex)); - param.put("hook.on_record_mp4",recordHookPrex != null? String.format("%s/on_record_mp4", recordHookPrex): ""); - param.put("hook.on_record_ts",""); - param.put("hook.on_rtsp_auth",""); - param.put("hook.on_rtsp_realm",""); - param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrex)); - param.put("hook.on_shell_login",String.format("%s/on_shell_login", hookPrex)); - param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrex)); - param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex)); - param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex)); - param.put("hook.timeoutSec","20"); - param.put("general.streamNoneReaderDelayMS",mediaConfig.getStreamNoneReaderDelayMS()); - - JSONObject responseJSON = zlmresTfulUtils.setServerConfig(param); - - if (responseJSON != null && responseJSON.getInteger("code") == 0) { - logger.info("璁剧疆zlm鎴愬姛"); - }else { - logger.info("璁剧疆zlm澶辫触"); - } } /** * zlm 杩炴帴鎴愬姛鎴栬�厇lm閲嶅惎鍚� */ - private void zLmRunning(ZLMServerConfig zlmServerConfig){ - logger.info( "[ id: " + zlmServerConfig.getGeneralMediaServerId() + "] zlm鎺ュ叆鎴愬姛..."); - // 鍏抽棴寰幆鑾峰彇zlm閰嶇疆 - startGetMedia = false; - if (mediaConfig.isAutoConfig()) saveZLMConfig(); - zlmServerManger.updateServerCatch(zlmServerConfig); - - // 娓呯┖鎵�鏈塻ession -// zlmMediaListManager.clearAllSessions(); - - // 鏇存柊娴佸垪琛� - zlmMediaListManager.updateMediaList(); - // 鎭㈠娴佷唬鐞� - List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnable(true); - for (StreamProxyItem streamProxyDto : streamProxyListForEnable) { - logger.info("鎭㈠娴佷唬鐞嗭紝" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); - JSONObject jsonObject = streamProxyService.addStreamProxyToZlm(streamProxyDto); - if (jsonObject == null) { - // 璁剧疆涓烘湭鍚敤 - logger.info("鎭㈠娴佷唬鐞嗗け璐ワ紝璇锋鏌ユ祦鍦板潃鍚庨噸鏂板惎鐢�" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); - streamProxyService.stop(streamProxyDto.getApp(), streamProxyDto.getStream()); - }else if (jsonObject.getInteger("code") != 0){ // TODO 灏嗛敊璇俊鎭瓨鍏ユ暟鎹簱锛� 鍓嶇灞曠ず - logger.info("鎭㈠娴佷唬鐞嗗け璐ワ細" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream() + "[ " + JSONObject.toJSONString(jsonObject) + " ]"); - streamProxyService.stop(streamProxyDto.getApp(), streamProxyDto.getStream()); - } - } - } +// private void zLmRunning(ZLMServerConfig zlmServerConfig){ +// logger.info( "[ id: " + zlmServerConfig.getGeneralMediaServerId() + "] zlm鎺ュ叆鎴愬姛..."); +// // 鍏抽棴寰幆鑾峰彇zlm閰嶇疆 +// startGetMedia = false; +// MediaServerItem mediaServerItem = new MediaServerItem(zlmServerConfig, sipIp); +// storager.updateMediaServer(mediaServerItem); +// +// if (mediaServerItem.isAutoConfig()) setZLMConfig(mediaServerItem); +// zlmServerManger.updateServerCatchFromHook(zlmServerConfig); +// +// // 娓呯┖鎵�鏈塻ession +//// zlmMediaListManager.clearAllSessions(); +// +// // 鏇存柊娴佸垪琛� +// zlmMediaListManager.updateMediaList(mediaServerItem); +// // 鎭㈠娴佷唬鐞�, 鍙煡鎵捐繖涓繖涓祦濯掍綋 +// List<StreamProxyItem> streamProxyListForEnable = storager.getStreamProxyListForEnableInMediaServer( +// mediaServerItem.getId(), true); +// for (StreamProxyItem streamProxyDto : streamProxyListForEnable) { +// logger.info("鎭㈠娴佷唬鐞嗭紝" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); +// JSONObject jsonObject = streamProxyService.addStreamProxyToZlm(streamProxyDto); +// if (jsonObject == null) { +// // 璁剧疆涓烘湭鍚敤 +// logger.info("鎭㈠娴佷唬鐞嗗け璐ワ紝璇锋鏌ユ祦鍦板潃鍚庨噸鏂板惎鐢�" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); +// streamProxyService.stop(streamProxyDto.getApp(), streamProxyDto.getStream()); +// } +// } +// } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java index 21fcebf..c1a9bd2 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java @@ -34,11 +34,14 @@ @JSONField(name = "general.streamNoneReaderDelayMS") private String generalStreamNoneReaderDelayMS; + @JSONField(name = "ip") private String ip; private String sdpIp; private String streamIp; + + private String hookIp; private String updateTime; @@ -66,7 +69,7 @@ private String hookEnable; @JSONField(name = "hook.on_flow_report") - private Integer hookOnFlowReport; + private String hookOnFlowReport; @JSONField(name = "hook.on_http_access") private String hookOnHttpAccess; @@ -117,7 +120,7 @@ private String httpNotFound; @JSONField(name = "http.port") - private Integer httpPort; + private int httpPort; @JSONField(name = "http.rootPath") private String httpRootPath; @@ -126,7 +129,7 @@ private String httpSendBufSize; @JSONField(name = "http.sslport") - private Integer httpSSLport; + private int httpSSLport; @JSONField(name = "multicast.addrMax") private String multicastAddrMax; @@ -159,10 +162,10 @@ private String rtmpModifyStamp; @JSONField(name = "rtmp.port") - private Integer rtmpPort; + private int rtmpPort; @JSONField(name = "rtmp.sslport") - private Integer rtmpSslPort; + private int rtmpSslPort; @JSONField(name = "rtp.audioMtuSize") private String rtpAudioMtuSize; @@ -186,7 +189,7 @@ private String rtpProxyDumpDir; @JSONField(name = "rtp_proxy.port") - private Integer rtpProxyPort; + private int rtpProxyPort; @JSONField(name = "rtp_proxy.timeoutSec") private String rtpProxyTimeoutSec; @@ -201,16 +204,25 @@ private String rtspKeepAliveSecond; @JSONField(name = "rtsp.port") - private Integer rtspPort; + private int rtspPort; @JSONField(name = "rtsp.sslport") - private Integer rtspSSlport; + private int rtspSSlport; @JSONField(name = "shell.maxReqSize") private String shellMaxReqSize; @JSONField(name = "shell.shell") private String shellPhell; + + + public String getHookIp() { + return hookIp; + } + + public void setHookIp(String hookIp) { + this.hookIp = hookIp; + } public String getApiDebug() { return apiDebug; @@ -388,11 +400,11 @@ this.hookEnable = hookEnable; } - public Integer getHookOnFlowReport() { + public String getHookOnFlowReport() { return hookOnFlowReport; } - public void setHookOnFlowReport(Integer hookOnFlowReport) { + public void setHookOnFlowReport(String hookOnFlowReport) { this.hookOnFlowReport = hookOnFlowReport; } @@ -524,11 +536,11 @@ this.httpNotFound = httpNotFound; } - public Integer getHttpPort() { + public int getHttpPort() { return httpPort; } - public void setHttpPort(Integer httpPort) { + public void setHttpPort(int httpPort) { this.httpPort = httpPort; } @@ -548,11 +560,11 @@ this.httpSendBufSize = httpSendBufSize; } - public Integer getHttpSSLport() { + public int getHttpSSLport() { return httpSSLport; } - public void setHttpSSLport(Integer httpSSLport) { + public void setHttpSSLport(int httpSSLport) { this.httpSSLport = httpSSLport; } @@ -636,19 +648,19 @@ this.rtmpModifyStamp = rtmpModifyStamp; } - public Integer getRtmpPort() { + public int getRtmpPort() { return rtmpPort; } - public void setRtmpPort(Integer rtmpPort) { + public void setRtmpPort(int rtmpPort) { this.rtmpPort = rtmpPort; } - public Integer getRtmpSslPort() { + public int getRtmpSslPort() { return rtmpSslPort; } - public void setRtmpSslPort(Integer rtmpSslPort) { + public void setRtmpSslPort(int rtmpSslPort) { this.rtmpSslPort = rtmpSslPort; } @@ -708,11 +720,11 @@ this.rtpProxyDumpDir = rtpProxyDumpDir; } - public Integer getRtpProxyPort() { + public int getRtpProxyPort() { return rtpProxyPort; } - public void setRtpProxyPort(Integer rtpProxyPort) { + public void setRtpProxyPort(int rtpProxyPort) { this.rtpProxyPort = rtpProxyPort; } @@ -748,19 +760,19 @@ this.rtspKeepAliveSecond = rtspKeepAliveSecond; } - public Integer getRtspPort() { + public int getRtspPort() { return rtspPort; } - public void setRtspPort(Integer rtspPort) { + public void setRtspPort(int rtspPort) { this.rtspPort = rtspPort; } - public Integer getRtspSSlport() { + public int getRtspSSlport() { return rtspSSlport; } - public void setRtspSSlport(Integer rtspSSlport) { + public void setRtspSSlport(int rtspSSlport) { this.rtspSSlport = rtspSSlport; } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerManger.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerManger.java deleted file mode 100644 index fde3b44..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerManger.java +++ /dev/null @@ -1,45 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm; - -import com.genersoft.iot.vmp.conf.MediaConfig; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.springframework.util.StringUtils; - -@Component -public class ZLMServerManger { - - @Autowired - private IRedisCatchStorage redisCatchStorage; - - @Autowired - private MediaConfig mediaConfig; - - public void updateServerCatch(ZLMServerConfig zlmServerConfig) { - - zlmServerConfig.setIp(mediaConfig.getIp()); - zlmServerConfig.setStreamIp(mediaConfig.getStreamIp()); - zlmServerConfig.setSdpIp(mediaConfig.getSdpIp()); - zlmServerConfig.setHttpPort(mediaConfig.getHttpPort()); - - if(!StringUtils.isEmpty(mediaConfig.getHttpSSlPort())) - zlmServerConfig.setHttpSSLport(mediaConfig.getHttpSSlPort()); - - if(!StringUtils.isEmpty(mediaConfig.getRtspPort())) - zlmServerConfig.setRtspPort(mediaConfig.getRtspPort()); - - if(!StringUtils.isEmpty(mediaConfig.getRtspSSLPort())) - zlmServerConfig.setRtspSSlport(mediaConfig.getRtspSSLPort()); - - if(!StringUtils.isEmpty(mediaConfig.getRtmpPort())) - zlmServerConfig.setRtmpPort(mediaConfig.getRtmpPort()); - - if(!StringUtils.isEmpty(mediaConfig.getRtmpSSlPort())) - zlmServerConfig.setRtmpSslPort(mediaConfig.getRtmpSSlPort()); - - if(!StringUtils.isEmpty(mediaConfig.getRtpProxyPort())) - zlmServerConfig.setRtpProxyPort(mediaConfig.getRtpProxyPort()); - - redisCatchStorage.updateMediaInfo(zlmServerConfig); - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java new file mode 100644 index 0000000..6497162 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IMediaServerItem.java @@ -0,0 +1,92 @@ +package com.genersoft.iot.vmp.media.zlm.dto; + +public interface IMediaServerItem { + + String getId(); + + void setId(String id); + + String getIp(); + + void setIp(String ip); + + String getHookIp(); + + void setHookIp(String hookIp); + + String getSdpIp(); + + void setSdpIp(String sdpIp); + + String getStreamIp(); + + void setStreamIp(String streamIp); + + int getHttpPort(); + + void setHttpPort(int httpPort); + + int getHttpSSlPort(); + + void setHttpSSlPort(int httpSSlPort); + + int getRtmpPort(); + + void setRtmpPort(int rtmpPort); + + int getRtmpSSlPort(); + + void setRtmpSSlPort(int rtmpSSlPort); + + int getRtpProxyPort(); + + void setRtpProxyPort(int rtpProxyPort); + + int getRtspPort(); + + void setRtspPort(int rtspPort); + + int getRtspSSLPort(); + + void setRtspSSLPort(int rtspSSLPort); + + boolean isAutoConfig(); + + void setAutoConfig(boolean autoConfig); + + String getSecret(); + + void setSecret(String secret); + + String getStreamNoneReaderDelayMS(); + + void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS); + + boolean isRtpEnable(); + + void setRtpEnable(boolean rtpEnable); + + String getRtpPortRange(); + + void setRtpPortRange(String rtpPortRange); + + int getRecordAssistPort(); + + void setRecordAssistPort(int recordAssistPort); + + boolean isDocker(); + + void setDocker(boolean docker); + + String getUpdateTime(); + + void setUpdateTime(String updateTime); + + String getCreateTime(); + + void setCreateTime(String createTime); + + int getCount(); + + void setCount(int count); +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java index 24bfcc1..6d9ceee 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaItem.java @@ -78,6 +78,10 @@ */ private String vhost; + /** + * 鏄惁鏄痙ocker閮ㄧ讲锛� docker閮ㄧ讲涓嶄細鑷姩鏇存柊zlm浣跨敤鐨勭鍙o紝闇�瑕佽嚜宸辨墜鍔ㄤ慨鏀� + */ + private boolean docker; public static class MediaTrack { /** @@ -364,4 +368,12 @@ public OriginSock getOriginSock() { return originSock; } + + public boolean isDocker() { + return docker; + } + + public void setDocker(boolean docker) { + this.docker = docker; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java new file mode 100644 index 0000000..b56881f --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java @@ -0,0 +1,254 @@ +package com.genersoft.iot.vmp.media.zlm.dto; + + +import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import org.springframework.util.StringUtils; + +public class MediaServerItem implements IMediaServerItem{ + + private String id; + + private String ip; + + private String hookIp; + + private String sdpIp; + + private String streamIp; + + private int httpPort; + + private int httpSSlPort; + + private int rtmpPort; + + private int rtmpSSlPort; + + private int rtpProxyPort; + + private int rtspPort; + + private int rtspSSLPort; + + private boolean autoConfig; + + private String secret; + + private String streamNoneReaderDelayMS; + + private boolean rtpEnable; + + private String rtpPortRange; + + private int recordAssistPort; + + private String createTime; + + private String updateTime; + + private boolean docker; + + private int count; + + public MediaServerItem() { + } + + public MediaServerItem(ZLMServerConfig zlmServerConfig, String sipIp) { + id = zlmServerConfig.getGeneralMediaServerId(); + ip = zlmServerConfig.getIp(); + hookIp = StringUtils.isEmpty(zlmServerConfig.getHookIp())? sipIp: zlmServerConfig.getHookIp(); + sdpIp = StringUtils.isEmpty(zlmServerConfig.getSdpIp())? zlmServerConfig.getIp(): zlmServerConfig.getSdpIp(); + streamIp = StringUtils.isEmpty(zlmServerConfig.getStreamIp())? zlmServerConfig.getIp(): zlmServerConfig.getStreamIp(); + httpPort = zlmServerConfig.getHttpPort(); + httpSSlPort = zlmServerConfig.getHttpSSLport(); + rtmpPort = zlmServerConfig.getRtmpPort(); + rtmpSSlPort = zlmServerConfig.getRtmpSslPort(); + rtpProxyPort = zlmServerConfig.getRtpProxyPort(); + rtspPort = zlmServerConfig.getRtspPort(); + rtspSSLPort = zlmServerConfig.getRtspSSlport(); + autoConfig = true; // 榛樿鍊紅rue; + secret = zlmServerConfig.getApiSecret(); + streamNoneReaderDelayMS = zlmServerConfig.getGeneralStreamNoneReaderDelayMS(); + rtpEnable = false; // 榛樿浣跨敤鍗曠鍙�;鐩村埌鐢ㄦ埛鑷繁璁剧疆寮�鍚绔彛 + recordAssistPort = 0; // 榛樿鍏抽棴 + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getIp() { + return ip; + } + + public void setIp(String ip) { + this.ip = ip; + } + + public String getHookIp() { + return hookIp; + } + + public void setHookIp(String hookIp) { + this.hookIp = hookIp; + } + + public String getSdpIp() { + return sdpIp; + } + + public void setSdpIp(String sdpIp) { + this.sdpIp = sdpIp; + } + + public String getStreamIp() { + return streamIp; + } + + public void setStreamIp(String streamIp) { + this.streamIp = streamIp; + } + + public int getHttpPort() { + return httpPort; + } + + public void setHttpPort(int httpPort) { + this.httpPort = httpPort; + } + + public int getHttpSSlPort() { + return httpSSlPort; + } + + public void setHttpSSlPort(int httpSSlPort) { + this.httpSSlPort = httpSSlPort; + } + + public int getRtmpPort() { + return rtmpPort; + } + + public void setRtmpPort(int rtmpPort) { + this.rtmpPort = rtmpPort; + } + + public int getRtmpSSlPort() { + return rtmpSSlPort; + } + + public void setRtmpSSlPort(int rtmpSSlPort) { + this.rtmpSSlPort = rtmpSSlPort; + } + + public int getRtpProxyPort() { + return rtpProxyPort; + } + + public void setRtpProxyPort(int rtpProxyPort) { + this.rtpProxyPort = rtpProxyPort; + } + + public int getRtspPort() { + return rtspPort; + } + + public void setRtspPort(int rtspPort) { + this.rtspPort = rtspPort; + } + + public int getRtspSSLPort() { + return rtspSSLPort; + } + + public void setRtspSSLPort(int rtspSSLPort) { + this.rtspSSLPort = rtspSSLPort; + } + + public boolean isAutoConfig() { + return autoConfig; + } + + public void setAutoConfig(boolean autoConfig) { + this.autoConfig = autoConfig; + } + + public String getSecret() { + return secret; + } + + public void setSecret(String secret) { + this.secret = secret; + } + + public String getStreamNoneReaderDelayMS() { + return streamNoneReaderDelayMS; + } + + public void setStreamNoneReaderDelayMS(String streamNoneReaderDelayMS) { + this.streamNoneReaderDelayMS = streamNoneReaderDelayMS; + } + + public boolean isRtpEnable() { + return rtpEnable; + } + + public void setRtpEnable(boolean rtpEnable) { + this.rtpEnable = rtpEnable; + } + + public String getRtpPortRange() { + return rtpPortRange; + } + + public void setRtpPortRange(String rtpPortRange) { + this.rtpPortRange = rtpPortRange; + } + + public int getRecordAssistPort() { + return recordAssistPort; + } + + public void setRecordAssistPort(int recordAssistPort) { + this.recordAssistPort = recordAssistPort; + } + + @Override + public boolean isDocker() { + return docker; + } + + @Override + public void setDocker(boolean docker) { + this.docker = docker; + } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } + + public String getUpdateTime() { + return updateTime; + } + + public void setUpdateTime(String updateTime) { + this.updateTime = updateTime; + } + + public int getCount() { + return count; + } + + public void setCount(int count) { + this.count = count; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java index 3f997a6..40ba215 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamProxyItem.java @@ -7,6 +7,7 @@ private String type; private String app; private String stream; + private String mediaServerId; private String url; private String src_url; private String dst_url; @@ -17,6 +18,7 @@ private boolean enable_hls; private boolean enable_mp4; private String platformGbId; + private String createTime; public String getType() { return type; @@ -40,6 +42,16 @@ public void setStream(String stream) { this.stream = stream; + } + + @Override + public String getMediaServerId() { + return mediaServerId; + } + + @Override + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; } public String getUrl() { @@ -122,4 +134,12 @@ public void setPlatformGbId(String platformGbId) { this.platformGbId = platformGbId; } + + public String getCreateTime() { + return createTime; + } + + public void setCreateTime(String createTime) { + this.createTime = createTime; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java index 7a1c49b..73e162a 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java @@ -76,6 +76,11 @@ */ private String vhost; + /** + * 浣跨敤鐨勬祦濯掍綋ID + */ + private String mediaServerId; + public String getVhost() { return vhost; } @@ -202,5 +207,14 @@ } + @Override + public String getMediaServerId() { + return mediaServerId; + } + + @Override + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMRunInfo.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMRunInfo.java new file mode 100644 index 0000000..624e4e1 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMRunInfo.java @@ -0,0 +1,33 @@ +package com.genersoft.iot.vmp.media.zlm.dto; + +/** + * 璁板綍zlm杩愯涓竴浜涘弬鏁� + */ +public class ZLMRunInfo { + + /** + * zlm褰撳墠娴佹暟閲� + */ + private int mediaCount; + + /** + * 鍦ㄧ嚎鐘舵�� + */ + private boolean online; + + public int getMediaCount() { + return mediaCount; + } + + public void setMediaCount(int mediaCount) { + this.mediaCount = mediaCount; + } + + public boolean isOnline() { + return online; + } + + public void setOnline(boolean online) { + this.online = online; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java new file mode 100644 index 0000000..7a57bed --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java @@ -0,0 +1,44 @@ +package com.genersoft.iot.vmp.service; + +import com.genersoft.iot.vmp.conf.MediaConfig; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; + +import java.util.List; + +/** + * 濯掍綋鏈嶅姟鑺傜偣 + */ +public interface IMediaServerService { + + List<IMediaServerItem> getAll(); + + IMediaServerItem getOne(String generalMediaServerId); + + IMediaServerItem getOneByHostAndPort(String host, int port); + + /** + * 鏂扮殑鑺傜偣鍔犲叆 + * @param zlmServerConfig + * @return + */ + void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig); + + void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean b); + + IMediaServerItem getMediaServerForMinimumLoad(); + + void setZLMConfig(IMediaServerItem mediaServerItem); + + void init(); + + void closeRTPServer(Device device, String channelId); + + void update(MediaConfig mediaConfig); + + void addCount(String mediaServerId); + + void removeCount(String mediaServerId); +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java index 010870a..868a831 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java @@ -2,6 +2,8 @@ import com.alibaba.fastjson.JSONArray; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; /** * 濯掍綋淇℃伅涓氬姟 @@ -14,23 +16,8 @@ * @param stream * @return */ - StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream); + StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId,String addr); - /** - * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴 - * @param app - * @param stream - * @return - */ - StreamInfo getStreamInfoByAppAndStream(String app, String stream, JSONArray tracks); - - /** - * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴锛岃繑鍥炵殑ip浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌 - * @param app - * @param stream - * @return - */ - StreamInfo getStreamInfoByAppAndStream(String app, String stream, JSONArray tracks, String addr); /** * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 閫氳繃zlm鎺ュ彛妫�鏌ユ槸鍚﹀瓨鍦�, 杩斿洖鐨刬p浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌 @@ -38,5 +25,21 @@ * @param stream * @return */ - StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String addr); + StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId); + + /** + * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴 + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaServerItem, String app, String stream, JSONArray tracks); + + /** + * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴锛岃繑鍥炵殑ip浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌 + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java index a649267..fdc86d6 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -1,8 +1,11 @@ package com.genersoft.iot.vmp.service; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; /** @@ -10,8 +13,10 @@ */ public interface IPlayService { - void onPublishHandlerForPlayBack(JSONObject resonse, String deviceId, String channelId, String uuid); - void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid); + void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem,JSONObject resonse, String deviceId, String channelId, String uuid); + void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid); - PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); + PlayResult play(IMediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event event, SipSubscribe.Event errorEvent); + + IMediaServerItem getNewMediaServerItem(Device device); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java index 2f7388a..fa79d69 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java @@ -1,6 +1,8 @@ package com.genersoft.iot.vmp.service; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.github.pagehelper.PageInfo; @@ -61,5 +63,5 @@ * 鑾峰彇ffmpeg.cmd妯℃澘 * @return */ - JSONObject getFFmpegCMDs(); + JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java index e66480a..eaf2490 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.service; import com.genersoft.iot.vmp.gb28181.bean.GbStream; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.github.pagehelper.PageInfo; @@ -8,7 +9,7 @@ public interface IStreamPushService { - List<StreamPushItem> handleJSON(String json); + List<StreamPushItem> handleJSON(String json, IMediaServerItem mediaServerItem); /** * 灏嗗簲鐢ㄥ悕鍜屾祦ID鍔犲叆鍥芥爣鍏宠仈 diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java new file mode 100644 index 0000000..a90225a --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -0,0 +1,340 @@ +package com.genersoft.iot.vmp.service.impl; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.conf.MediaConfig; +import com.genersoft.iot.vmp.conf.ProxyServletConfig; +import com.genersoft.iot.vmp.gb28181.bean.Device; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.ZLMRTPServerFactory; +import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.ZLMRunInfo; +import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; +import org.mitre.dsmiley.httpproxy.ProxyServlet; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Service; + +import java.text.SimpleDateFormat; +import java.util.*; + +/** + * 濯掍綋鏈嶅姟鍣ㄨ妭鐐圭鐞� + */ +@Service +public class MediaServerServiceImpl implements IMediaServerService { + + private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); + + private Map<String, IMediaServerItem> zlmServers = new HashMap<>(); // 鎵�鏈夋暟鎹簱鐨剒lm鐨勭紦瀛� + private Map<String, Integer> zlmServerStatus = new LinkedHashMap<>(); // 鎵�鏈変笂绾跨殑zlm鐨勭紦瀛樹互鍙婅礋杞� + + @Value("${sip.ip}") + private String sipIp; + + @Value("${server.ssl.enabled:false}") + private boolean sslEnabled; + + @Value("${server.port}") + private String serverPort; + + @Autowired + private MediaConfig mediaConfig; + + @Autowired + private ZLMRESTfulUtils zlmresTfulUtils; + + @Autowired + private MediaServerMapper mediaServerMapper; + + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private VideoStreamSessionManager streamSession; + + @Autowired + private ZLMRTPServerFactory zlmrtpServerFactory; + + private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); + + /** + * 鍒濆鍖� + */ + @Override + public void init() { + zlmServers.clear(); + zlmServerStatus.clear(); + List<MediaServerItem> mediaServerItemList = mediaServerMapper.queryAll(); + for (IMediaServerItem mediaServerItem : mediaServerItemList) { + zlmServers.put(mediaServerItem.getId(), mediaServerItem); + } + } + + @Override + public void closeRTPServer(Device device, String channelId) { + StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(device.getDeviceId(), channelId); + IMediaServerItem mediaServerItem = null; + if (streamInfo != null) { + mediaServerItem = this.getOne (streamInfo.getMediaServerId()); + } + String streamId = String.format("gb_play_%s_%s", device.getDeviceId(), channelId); + zlmrtpServerFactory.closeRTPServer(mediaServerItem, streamId); + streamSession.remove(device.getDeviceId(), channelId); + } + + @Override + public void update(MediaConfig mediaConfig) { + + } + + @Override + public List<IMediaServerItem> getAll() { + if (zlmServers.size() == 0) { + init(); + } + List<IMediaServerItem> result = new ArrayList<>(); + for (String id : zlmServers.keySet()) { + IMediaServerItem mediaServerItem = zlmServers.get(id); + mediaServerItem.setCount(zlmServerStatus.get(id) == null ? 0 : zlmServerStatus.get(id)); + result.add(mediaServerItem); + } + return result; + + +// return mediaServerMapper.queryAll(); + } + + /** + * 鑾峰彇鍗曚釜zlm鏈嶅姟鍣� + * @param mediaServerId 鏈嶅姟id + * @return MediaServerItem + */ + @Override + public IMediaServerItem getOne(String mediaServerId) { + if (mediaServerId ==null) return null; + IMediaServerItem mediaServerItem = zlmServers.get(mediaServerId); + if (mediaServerItem != null) { + mediaServerItem.setCount(zlmServerStatus.get(mediaServerId) == null ? 0 : zlmServerStatus.get(mediaServerId)); + return mediaServerItem; + }else { + IMediaServerItem item = mediaServerMapper.queryOne(mediaServerId); + if (item != null) { + zlmServers.put(item.getId(), item); + } + return item; + } + } + + @Override + public IMediaServerItem getOneByHostAndPort(String host, int port) { + return mediaServerMapper.queryOneByHostAndPort(host, port); + } + + /** + * 澶勭悊zlm涓婄嚎 + * @param zlmServerConfig zlm涓婄嚎鎼哄甫鐨勫弬鏁� + */ + @Override + public void handLeZLMServerConfig(ZLMServerConfig zlmServerConfig) { + logger.info("[ {} ]-[ {}:{} ]宸茶繛鎺�", + zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); + + IMediaServerItem serverItem = getOne(zlmServerConfig.getGeneralMediaServerId()); + String now = this.format.format(new Date(System.currentTimeMillis())); + if (serverItem != null) { + serverItem.setSecret(zlmServerConfig.getApiSecret()); + serverItem.setIp(zlmServerConfig.getIp()); + // 濡傛灉鏄厤缃枃浠朵腑鐨剒lm銆� 涔熷氨鏄粯璁lm銆� 涓�鍒囦互閰嶇疆鏂囦欢鍐呭涓哄噯 + // docker閮ㄧ讲涓嶄細浣跨敤zlm閰嶇疆鐨勭鍙e彿; + // 鐩存帴缂栬瘧閮ㄧ讲鐨勪娇鐢ㄩ厤缃枃浠剁殑绔彛鍙凤紝濡傛灉zlm淇敼閰嶆敼浜嗛厤缃紝wvp鑷姩淇敼 + + if (serverItem.getId().equals(mediaConfig.getId()) + || (serverItem.getIp().equals(mediaConfig.getIp()) && serverItem.getHttpPort() == mediaConfig.getHttpPort())) { + // 閰嶇疆鏂囦欢鐨剒lm + mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId()); + mediaConfig.setUpdateTime(now); + if (mediaConfig.getHttpPort() == 0) mediaConfig.setHttpPort(zlmServerConfig.getHttpPort()); + if (mediaConfig.getHttpSSlPort() == 0) mediaConfig.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); + if (mediaConfig.getRtmpPort() == 0) mediaConfig.setRtmpPort(zlmServerConfig.getRtmpPort()); + if (mediaConfig.getRtmpSSlPort() == 0) mediaConfig.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); + if (mediaConfig.getRtspPort() == 0) mediaConfig.setRtspPort(zlmServerConfig.getRtspPort()); + if (mediaConfig.getRtspSSLPort() == 0) mediaConfig.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); + if (mediaConfig.getRtpProxyPort() == 0) mediaConfig.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); + mediaServerMapper.update(mediaConfig); + serverItem = mediaConfig.getMediaSerItem(); + setZLMConfig(mediaConfig); + }else { + if (!serverItem.isDocker()) { + serverItem.setHttpPort(zlmServerConfig.getHttpPort()); + serverItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); + serverItem.setRtmpPort(zlmServerConfig.getRtmpPort()); + serverItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); + serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); + serverItem.setRtspPort(zlmServerConfig.getRtspPort()); + + } + serverItem.setUpdateTime(now); + mediaServerMapper.update(serverItem); + setZLMConfig(serverItem); + } + }else { + if (zlmServerConfig.getGeneralMediaServerId().equals(mediaConfig.getId()) + || (zlmServerConfig.getIp().equals(mediaConfig.getIp()) && zlmServerConfig.getHttpPort() == mediaConfig.getHttpPort())) { + mediaConfig.setId(zlmServerConfig.getGeneralMediaServerId()); + mediaConfig.setCreateTime(now); + mediaConfig.setUpdateTime(now); + serverItem = mediaConfig; + mediaServerMapper.add(mediaConfig); + }else { + // 涓�涓柊鐨剒lm鎺ュ叆wvp + serverItem = new MediaServerItem(zlmServerConfig, sipIp); + serverItem.setCreateTime(now); + serverItem.setUpdateTime(now); + mediaServerMapper.add(serverItem); + } + } + // 鏇存柊缂撳瓨 + if (zlmServerStatus.get(serverItem.getId()) == null) { + zlmServers.put(serverItem.getId(), serverItem); + zlmServerStatus.put(serverItem.getId(),0); + } + // 鏌ヨ鏈嶅姟娴佹暟閲� + IMediaServerItem finalServerItem = serverItem; + zlmresTfulUtils.getMediaList(serverItem, null, null, "rtmp",(mediaList ->{ + Integer code = mediaList.getInteger("code"); + if (code == 0) { + JSONArray data = mediaList.getJSONArray("data"); + if (data != null) { + zlmServerStatus.put(finalServerItem.getId(),data.size()); + }else { + zlmServerStatus.put(finalServerItem.getId(),0); + } + + } + })); + + } + + /** + * 鏇存柊缂撳瓨 + * @param mediaServerItem zlm鏈嶅姟 + * @param count 鍦ㄧ嚎鏁� + * @param online 鍦ㄧ嚎鐘舵�� + */ + @Override + public void updateServerCatch(IMediaServerItem mediaServerItem, Integer count, Boolean online) { + if (mediaServerItem != null) { + zlmServers.put(mediaServerItem.getId(), mediaServerItem); + Collection<Integer> values = zlmServerStatus.values(); + if (online != null && count != null) { + zlmServerStatus.put(mediaServerItem.getId(), count); + } + } + } + + @Override + public void addCount(String mediaServerId) { + if (zlmServerStatus.get(mediaServerId) != null) { + zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) + 1); + } + } + + @Override + public void removeCount(String mediaServerId) { + if (zlmServerStatus.get(mediaServerId) != null) { + zlmServerStatus.put(mediaServerId, zlmServerStatus.get(mediaServerId) - 1); + } + } + + /** + * 鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣 + * @return MediaServerItem + */ + @Override + public IMediaServerItem getMediaServerForMinimumLoad() { + int mediaCount = -1; + String key = null; + System.out.println(JSON.toJSONString(zlmServerStatus)); + if (zlmServerStatus.size() == 1) { + Map.Entry entry = zlmServerStatus.entrySet().iterator().next(); + key= (String) entry.getKey(); + }else { + for (String id : zlmServerStatus.keySet()) { + if (key == null) { + key = id; + mediaCount = zlmServerStatus.get(id); + } + if (zlmServerStatus.get(id) == 0) { + key = id; + break; + }else if (mediaCount >= zlmServerStatus.get(id)){ + mediaCount = zlmServerStatus.get(id); + key = id; + } + } + } + + if (key == null) { + logger.info("鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣鏃舵棤鍦ㄧ嚎鑺傜偣"); + return null; + }else{ + return zlmServers.get(key); + } + } + + /** + * 瀵箊lm鏈嶅姟鍣ㄨ繘琛屽熀纭�閰嶇疆 + * @param mediaServerItem 鏈嶅姟ID + */ + @Override + public void setZLMConfig(IMediaServerItem mediaServerItem) { + logger.info("[ {} ]-[ {}:{} ]璁剧疆zlm", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + String protocol = sslEnabled ? "https" : "http"; + String hookPrex = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort); + String recordHookPrex = null; + if (mediaServerItem.getRecordAssistPort() != 0) { + recordHookPrex = String.format("http://127.0.0.1:%s/api/record", mediaServerItem.getRecordAssistPort()); + } + Map<String, Object> param = new HashMap<>(); + param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline + param.put("ffmpeg.cmd","%s -fflags nobuffer -i %s -c:a aac -strict -2 -ar 44100 -ab 48k -c:v libx264 -f flv %s"); + param.put("hook.enable","1"); + param.put("hook.on_flow_report",""); + param.put("hook.on_play",String.format("%s/on_play", hookPrex)); + param.put("hook.on_http_access",""); + param.put("hook.on_publish", String.format("%s/on_publish", hookPrex)); + param.put("hook.on_record_mp4",recordHookPrex != null? String.format("%s/on_record_mp4", recordHookPrex): ""); + param.put("hook.on_record_ts",""); + param.put("hook.on_rtsp_auth",""); + param.put("hook.on_rtsp_realm",""); + param.put("hook.on_server_started",String.format("%s/on_server_started", hookPrex)); + param.put("hook.on_shell_login",String.format("%s/on_shell_login", hookPrex)); + param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrex)); + param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrex)); + param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrex)); + param.put("hook.timeoutSec","20"); + param.put("general.streamNoneReaderDelayMS",mediaServerItem.getStreamNoneReaderDelayMS()); + + JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); + + if (responseJSON != null && responseJSON.getInteger("code") == 0) { + logger.info("[ {} ]-[ {}:{} ]璁剧疆zlm鎴愬姛", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + }else { + logger.info("[ {} ]-[ {}:{} ]璁剧疆zlm澶辫触" + responseJSON.getString("msg"), + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java index e40f4b1..465ca88 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java @@ -6,6 +6,9 @@ import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.service.IMediaService; @@ -22,29 +25,52 @@ private IVideoManagerStorager storager; @Autowired + private IMediaServerService mediaServerService; + + @Autowired private ZLMRESTfulUtils zlmresTfulUtils; @Override - public StreamInfo getStreamInfoByAppAndStream(String app, String stream, JSONArray tracks) { - return getStreamInfoByAppAndStream(app, stream, tracks, null); + public StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks) { + return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null); } @Override - public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream) { - return getStreamInfoByAppAndStreamWithCheck(app, stream, null); + public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr) { + StreamInfo streamInfo = null; + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + if (mediaInfo == null) { + return streamInfo; + } + JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, app, stream); + if (mediaList != null) { + if (mediaList.getInteger("code") == 0) { + JSONArray data = mediaList.getJSONArray("data"); + if (data == null) return null; + JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class); + JSONArray tracks = mediaJSON.getJSONArray("tracks"); + streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks); + } + } + return streamInfo; } @Override - public StreamInfo getStreamInfoByAppAndStream(String app, String stream, JSONArray tracks, String addr) { - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId) { + return getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, null); + } + + @Override + public StreamInfo getStreamInfoByAppAndStream(IMediaServerItem mediaInfo, String app, String stream, JSONArray tracks, String addr) { StreamInfo streamInfoResult = new StreamInfo(); streamInfoResult.setStreamId(stream); streamInfoResult.setApp(app); if (addr == null) { addr = mediaInfo.getStreamIp(); } + streamInfoResult.setMediaServerId(mediaInfo.getId()); streamInfoResult.setRtmp(String.format("rtmp://%s:%s/%s/%s", addr, mediaInfo.getRtmpPort(), app, stream)); streamInfoResult.setRtsp(String.format("rtsp://%s:%s/%s/%s", addr, mediaInfo.getRtspPort(), app, stream)); streamInfoResult.setFlv(String.format("http://%s:%s/%s/%s.flv", addr, mediaInfo.getHttpPort(), app, stream)); @@ -60,19 +86,4 @@ return streamInfoResult; } - @Override - public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String addr) { - StreamInfo streamInfo = null; - JSONObject mediaList = zlmresTfulUtils.getMediaList(app, stream); - if (mediaList != null) { - if (mediaList.getInteger("code") == 0) { - JSONArray data = mediaList.getJSONArray("data"); - if (data == null) return null; - JSONObject mediaJSON = JSON.parseObject(JSON.toJSONString(data.get(0)), JSONObject.class); - JSONArray tracks = mediaJSON.getJSONArray("tracks"); - streamInfo = getStreamInfoByAppAndStream(app, stream, tracks, addr); - } - } - return streamInfo; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java index 172d980..85a4f48 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -14,6 +14,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.media.zlm.ZLMHttpHookSubscribe; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; @@ -60,6 +63,9 @@ private IMediaService mediaService; @Autowired + private IMediaServerService mediaServerService; + + @Autowired private VideoStreamSessionManager streamSession; @Autowired @@ -67,8 +73,18 @@ @Override - public PlayResult play(String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) { + public PlayResult play(IMediaServerItem mediaServerItem, String deviceId, String channelId, ZLMHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent) { PlayResult playResult = new PlayResult(); + if (mediaServerItem == null) { + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid()); + WVPResult wvpResult = new WVPResult(); + wvpResult.setCode(-1); + wvpResult.setMsg("鏈壘鍒板彲鐢ㄧ殑zlm"); + msg.setData(wvpResult); + resultHolder.invokeResult(msg); + return playResult; + } Device device = storager.queryVideoDevice(deviceId); StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); playResult.setDevice(device); @@ -82,7 +98,7 @@ result.onTimeout(()->{ logger.warn(String.format("璁惧鐐规挱瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId)); // 閲婃斁rtpserver - cmder.closeRTPServer(playResult.getDevice(), channelId); + mediaServerService.closeRTPServer(playResult.getDevice(), channelId); RequestMessage msg = new RequestMessage(); msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + playResult.getUuid()); WVPResult wvpResult = new WVPResult(); @@ -115,9 +131,10 @@ WVPResult wvpResult = (WVPResult)responseEntity.getBody(); if (wvpResult.getCode() == 0) { StreamInfo streamInfoForSuccess = (StreamInfo)wvpResult.getData(); + IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfoForSuccess.getMediaServerId()); String streamUrl = streamInfoForSuccess.getFmp4(); // 璇锋眰鎴浘 - zlmresTfulUtils.getSnap(streamUrl, 15, 1, path, fileName); + zlmresTfulUtils.getSnap(mediaInfo, streamUrl, 15, 1, path, fileName); } } } catch (FileNotFoundException e) { @@ -126,17 +143,17 @@ }); if (streamInfo == null) { // 鍙戦�佺偣鎾秷鎭� - cmder.playStreamCmd(device, channelId, (JSONObject response) -> { + cmder.playStreamCmd(mediaServerItem, device, channelId, (IMediaServerItem mediaServerItemInUse, JSONObject response) -> { logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + response.toJSONString()); - onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString()); + onPublishHandlerForPlay(mediaServerItemInUse, response, deviceId, channelId, uuid.toString()); if (hookEvent != null) { - hookEvent.response(response); + hookEvent.response(mediaServerItem, response); } - }, event -> { + }, (event) -> { RequestMessage msg = new RequestMessage(); msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); Response response = event.getResponse(); - cmder.closeRTPServer(playResult.getDevice(), channelId); + mediaServerService.closeRTPServer(playResult.getDevice(), channelId); WVPResult wvpResult = new WVPResult(); wvpResult.setCode(-1); wvpResult.setMsg(String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase())); @@ -158,7 +175,10 @@ resultHolder.invokeResult(msg); return playResult; } - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); + String mediaServerId = streamInfo.getMediaServerId(); + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); if (rtpInfo != null && rtpInfo.getBoolean("exist")) { RequestMessage msg = new RequestMessage(); msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); @@ -171,16 +191,16 @@ resultHolder.invokeResult(msg); if (hookEvent != null) { - hookEvent.response(JSONObject.parseObject(JSON.toJSONString(streamInfo))); + hookEvent.response(mediaServerItem, JSONObject.parseObject(JSON.toJSONString(streamInfo))); } } else { redisCatchStorage.stopPlay(streamInfo); storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); - cmder.playStreamCmd(device, channelId, (JSONObject response) -> { + cmder.playStreamCmd(mediaServerItem, device, channelId, (IMediaServerItem mediaServerItemInuse, JSONObject response) -> { logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + response.toJSONString()); - onPublishHandlerForPlay(response, deviceId, channelId, uuid.toString()); - }, event -> { - cmder.closeRTPServer(playResult.getDevice(), channelId); + onPublishHandlerForPlay(mediaServerItemInuse, response, deviceId, channelId, uuid.toString()); + }, (event) -> { + mediaServerService.closeRTPServer(playResult.getDevice(), channelId); RequestMessage msg = new RequestMessage(); msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); Response response = event.getResponse(); @@ -198,10 +218,10 @@ } @Override - public void onPublishHandlerForPlay(JSONObject resonse, String deviceId, String channelId, String uuid) { + public void onPublishHandlerForPlay(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { RequestMessage msg = new RequestMessage(); msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); - StreamInfo streamInfo = onPublishHandler(resonse, deviceId, channelId, uuid); + StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); if (streamInfo != null) { DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); if (deviceChannel != null) { @@ -234,10 +254,26 @@ } @Override - public void onPublishHandlerForPlayBack(JSONObject resonse, String deviceId, String channelId, String uuid) { + public IMediaServerItem getNewMediaServerItem(Device device) { + if (device == null) return null; + String mediaServerId = device.getMediaServerId(); + IMediaServerItem mediaServerItem = null; + if (mediaServerId == null) { + mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(); + }else { + mediaServerItem = mediaServerService.getOne(mediaServerId); + } + if (mediaServerItem == null) { + logger.warn("鐐规挱鏃舵湭鎵惧埌鍙娇鐢ㄧ殑ZLM..."); + } + return mediaServerItem; + } + + @Override + public void onPublishHandlerForPlayBack(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { RequestMessage msg = new RequestMessage(); msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); - StreamInfo streamInfo = onPublishHandler(resonse, deviceId, channelId, uuid); + StreamInfo streamInfo = onPublishHandler(mediaServerItem, resonse, deviceId, channelId, uuid); if (streamInfo != null) { redisCatchStorage.startPlayback(streamInfo); msg.setData(JSON.toJSONString(streamInfo)); @@ -249,10 +285,10 @@ } } - public StreamInfo onPublishHandler(JSONObject resonse, String deviceId, String channelId, String uuid) { + public StreamInfo onPublishHandler(IMediaServerItem mediaServerItem, JSONObject resonse, String deviceId, String channelId, String uuid) { String streamId = resonse.getString("stream"); JSONArray tracks = resonse.getJSONArray("tracks"); - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream("rtp", streamId, tracks); + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem,"rtp", streamId, tracks); streamInfo.setDeviceID(deviceId); streamInfo.setChannelId(channelId); return streamInfo; diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java index 2eb99b8..fe49c3b 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java @@ -2,10 +2,12 @@ import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.gb28181.bean.GbStream; -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.service.IGbStreamService; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorager; import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; @@ -13,6 +15,8 @@ import com.genersoft.iot.vmp.storager.dao.StreamProxyMapper; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.github.pagehelper.PageInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -25,6 +29,8 @@ @Service public class StreamProxyServiceImpl implements IStreamProxyService { + private final static Logger logger = LoggerFactory.getLogger(StreamProxyServiceImpl.class); + @Autowired private IVideoManagerStorager videoManagerStorager; @@ -32,7 +38,7 @@ private IRedisCatchStorage redisCatchStorage; @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; + private ZLMRESTfulUtils zlmresTfulUtils;; @Autowired private StreamProxyMapper streamProxyMapper; @@ -46,15 +52,28 @@ @Autowired private IGbStreamService gbStreamService; + @Autowired + private IMediaServerService mediaServerService; + @Override public String save(StreamProxyItem param) { - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + IMediaServerItem mediaInfo; + if ("auto".equals(param.getMediaServerId())){ + mediaInfo = mediaServerService.getMediaServerForMinimumLoad(); + }else { + mediaInfo = mediaServerService.getOne(param.getMediaServerId()); + } + if (mediaInfo == null) { + logger.warn("淇濆瓨浠g悊鏈壘鍒板湪绾跨殑ZLM..."); + return "淇濆瓨澶辫触"; + } String dstUrl = String.format("rtmp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtmpPort(), param.getApp(), param.getStream() ); param.setDst_url(dstUrl); StringBuffer result = new StringBuffer(); boolean streamLive = false; + param.setMediaServerId(mediaInfo.getId()); // 鏇存柊 if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) { if (videoManagerStorager.updateStreamProxy(param)) { @@ -81,6 +100,8 @@ videoManagerStorager.updateStreamProxy(param); } } + }else { + result.append("淇濆瓨澶辫触"); } } @@ -99,11 +120,18 @@ @Override public JSONObject addStreamProxyToZlm(StreamProxyItem param) { JSONObject result = null; + IMediaServerItem mediaServerItem = null; + if (param.getMediaServerId() == null) { + logger.warn("娣诲姞浠g悊鏃禡ediaServerId 涓簄ull"); + return null; + }else { + mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); + } if ("default".equals(param.getType())){ - result = zlmresTfulUtils.addStreamProxy(param.getApp(), param.getStream(), param.getUrl(), + result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl(), param.isEnable_hls(), param.isEnable_mp4(), param.getRtp_type()); }else if ("ffmpeg".equals(param.getType())) { - result = zlmresTfulUtils.addFFmpegSource(param.getSrc_url(), param.getDst_url(), + result = zlmresTfulUtils.addFFmpegSource(mediaServerItem, param.getSrc_url(), param.getDst_url(), param.getTimeout_ms() + "", param.isEnable_hls(), param.isEnable_mp4(), param.getFfmpeg_cmd_key()); } @@ -112,8 +140,9 @@ @Override public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) { - JSONObject result = zlmresTfulUtils.closeStreams(param.getApp(), param.getStream()); - + if (param ==null) return null; + IMediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); + JSONObject result = zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream()); return result; } @@ -124,17 +153,18 @@ @Override public void del(String app, String stream) { - StreamProxyItem streamProxyItem = new StreamProxyItem(); - streamProxyItem.setApp(app); - streamProxyItem.setStream(stream); - JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyItem); - if (jsonObject.getInteger("code") == 0) { + StreamProxyItem streamProxyItem = videoManagerStorager.queryStreamProxy(app, stream); + if (streamProxyItem != null) { videoManagerStorager.deleteStreamProxy(app, stream); - // 濡傛灉鍏宠仈浜嗗浗鏍囬偅涔堢Щ闄ゅ叧鑱� - gbStreamMapper.del(app, stream); - platformGbStreamMapper.delByAppAndStream(app, stream); - // TODO 濡傛灉鍏宠仈鐨勬帹娴侊紝 閭d箞鐘舵�佽缃负绂荤嚎 + JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyItem); + if (jsonObject != null && jsonObject.getInteger("code") == 0) { + // 濡傛灉鍏宠仈浜嗗浗鏍囬偅涔堢Щ闄ゅ叧鑱� + gbStreamMapper.del(app, stream); + platformGbStreamMapper.delByAppAndStream(app, stream); + // TODO 濡傛灉鍏宠仈鐨勬帹娴侊紝 閭d箞鐘舵�佽缃负绂荤嚎 + } } + } @Override @@ -168,9 +198,9 @@ } @Override - public JSONObject getFFmpegCMDs() { + public JSONObject getFFmpegCMDs(IMediaServerItem mediaServerItem) { JSONObject result = new JSONObject(); - JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(); + JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0 && mediaServerConfigResuly.getJSONArray("data").size() > 0){ JSONObject mediaServerConfig = mediaServerConfigResuly.getJSONArray("data").getJSONObject(0); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java index 7ebfb54..3692e54 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java @@ -5,9 +5,13 @@ import com.alibaba.fastjson.TypeReference; import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.MediaItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IStreamPushService; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; import com.genersoft.iot.vmp.storager.dao.StreamPushMapper; import com.github.pagehelper.PageHelper; @@ -32,8 +36,14 @@ @Autowired private ZLMRESTfulUtils zlmresTfulUtils; + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IMediaServerService mediaServerService; + @Override - public List<StreamPushItem> handleJSON(String jsonData) { + public List<StreamPushItem> handleJSON(String jsonData, IMediaServerItem mediaServerItem) { if (jsonData == null) return null; Map<String, StreamPushItem> result = new HashMap<>(); @@ -50,6 +60,7 @@ if (streamPushItem == null) { streamPushItem = new StreamPushItem(); streamPushItem.setApp(item.getApp()); + streamPushItem.setMediaServerId(mediaServerItem.getId()); streamPushItem.setStream(item.getStream()); streamPushItem.setAliveSecond(item.getAliveSecond()); streamPushItem.setCreateStamp(item.getCreateStamp()); @@ -87,7 +98,8 @@ @Override public boolean removeFromGB(GbStream stream) { int del = gbStreamMapper.del(stream.getApp(), stream.getStream()); - JSONObject mediaList = zlmresTfulUtils.getMediaList(stream.getApp(), stream.getStream()); + IMediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId()); + JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream()); if (mediaList == null) { streamPushMapper.del(stream.getApp(), stream.getStream()); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java index 56c31c1..a4edb08 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -2,10 +2,11 @@ import com.alibaba.fastjson.JSONObject; import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import java.util.List; import java.util.Map; @@ -39,19 +40,6 @@ StreamInfo queryPlaybackByStreamId(String steamId); StreamInfo queryPlayByDevice(String deviceId, String channelId); - - /** - * 鏇存柊娴佸獟浣撲俊鎭� - * @param ZLMServerConfig - * @return - */ - boolean updateMediaInfo(ZLMServerConfig ZLMServerConfig); - - /** - * 鑾峰彇娴佸獟浣撲俊鎭� - * @return - */ - ZLMServerConfig getMediaInfo(); Map<String, StreamInfo> queryPlayByDeviceId(String deviceId); @@ -115,6 +103,13 @@ void clearCatchByDeviceId(String deviceId); /** + * 鑾峰彇mediaServer鑺傜偣 + * @param mediaServerId + * @return + */ +// MediaServerItem getMediaInfo(String mediaServerId); + + /** * 璁剧疆鎵�鏈夎澶囩绾� */ void outlineForAll(); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java index 5d838c5..97c3794 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IVideoManagerStorager.java @@ -3,6 +3,8 @@ import java.util.List; import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.vmanager.gb28181.platform.bean.ChannelReduce; @@ -365,4 +367,12 @@ * @param online */ void updateParentPlatformStatus(String platformGbID, boolean online); + + /** + * 鏇存柊濯掍綋鑺傜偣 + * @param mediaServerItem + */ + void updateMediaServer(MediaServerItem mediaServerItem); + + List<StreamProxyItem> getStreamProxyListForEnableInMediaServer(String id, boolean b); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java index 80397d2..230afbc 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/GbStreamMapper.java @@ -12,9 +12,10 @@ public interface GbStreamMapper { @Insert("INSERT INTO gb_stream (app, stream, gbId, name, " + - "longitude, latitude, streamType, status) VALUES" + + "longitude, latitude, streamType, mediaServerId, status) VALUES" + "('${app}', '${stream}', '${gbId}', '${name}', " + - "'${longitude}', '${latitude}', '${streamType}', ${status})") + "'${longitude}', '${latitude}', '${streamType}', " + + "'${mediaServerId}', ${status})") int add(GbStream gbStream); @Update("UPDATE gb_stream " + @@ -25,6 +26,7 @@ "streamType=#{streamType}," + "longitude=#{longitude}, " + "latitude=#{latitude}," + + "mediaServerId=#{mediaServerId}," + "status=${status} " + "WHERE app=#{app} AND stream=#{stream} AND gbId=#{gbId}") int update(GbStream gbStream); @@ -52,4 +54,7 @@ "SET status=${status} " + "WHERE app=#{app} AND stream=#{stream}") void setStatus(String app, String stream, boolean status); + + @Select("SELECT gs.*, pgs.platformId FROM gb_stream gs LEFT JOIN platform_gb_stream pgs ON gs.app = pgs.app AND gs.stream = pgs.stream WHERE mediaServerId=#{mediaServerId} ") + List<GbStream> selectAllByMediaServerId(String mediaServerId); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java new file mode 100644 index 0000000..475ec6d --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java @@ -0,0 +1,99 @@ +package com.genersoft.iot.vmp.storager.dao; + +import com.genersoft.iot.vmp.conf.MediaConfig; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; +import org.apache.ibatis.annotations.Update; +import org.springframework.stereotype.Repository; + +import java.util.List; + + +@Mapper +@Repository +public interface MediaServerMapper { + + @Insert("INSERT INTO media_server (" + + "id, " + + "ip, " + + "hookIp, " + + "sdpIp, " + + "streamIp, " + + "httpPort, " + + "httpSSlPort, " + + "rtmpPort, " + + "rtmpSSlPort, " + + "rtpProxyPort, " + + "rtspPort, " + + "rtspSSLPort, " + + "autoConfig, " + + "secret, " + + "streamNoneReaderDelayMS, " + + "rtpEnable, " + + "rtpPortRange, " + + "recordAssistPort, " + + "createTime, " + + "updateTime" + + ") VALUES " + + "(" + + "'${id}', " + + "'${ip}', " + + "'${hookIp}', " + + "'${sdpIp}', " + + "'${streamIp}', " + + "${httpPort}, " + + "${httpSSlPort}, " + + "${rtmpPort}, " + + "${rtmpSSlPort}, " + + "${rtpProxyPort}, " + + "${rtspPort}, " + + "${rtspSSLPort}, " + + "${autoConfig}, " + + "'${secret}', " + + "${streamNoneReaderDelayMS}, " + + "${rtpEnable}, " + + "'${rtpPortRange}', " + + "${recordAssistPort}, " + + "'${createTime}', " + + "'${updateTime}')") + int add(IMediaServerItem mediaServerItem); + + @Update(value = {" <script>" + + "UPDATE media_server " + + "SET updateTime='${updateTime}'" + + "<if test=\"ip != null\">, ip='${ip}'</if>" + + "<if test=\"hookIp != null\">, hookIp='${hookIp}'</if>" + + "<if test=\"sdpIp != null\">, sdpIp='${sdpIp}'</if>" + + "<if test=\"streamIp != null\">, streamIp='${streamIp}'</if>" + + "<if test=\"httpPort != null\">, httpPort=${httpPort}</if>" + + "<if test=\"httpSSlPort != null\">, httpSSlPort=${httpSSlPort}</if>" + + "<if test=\"rtmpPort != null\">, rtmpPort=${rtmpPort}</if>" + + "<if test=\"rtmpSSlPort != null\">, rtmpSSlPort=${rtmpSSlPort}</if>" + + "<if test=\"rtpProxyPort != null\">, rtpProxyPort=${rtpProxyPort}</if>" + + "<if test=\"rtspPort != null\">, rtspPort=${rtspPort}</if>" + + "<if test=\"rtspSSLPort != null\">, rtspSSLPort=${rtspSSLPort}</if>" + + "<if test=\"autoConfig != null\">, autoConfig=${autoConfig}</if>" + + "<if test=\"streamNoneReaderDelayMS != null\">, streamNoneReaderDelayMS=${streamNoneReaderDelayMS}</if>" + + "<if test=\"rtpEnable != null\">, rtpEnable=${rtpEnable}</if>" + + "<if test=\"rtpPortRange != null\">, rtpPortRange='${rtpPortRange}'</if>" + + "<if test=\"secret != null\">, secret='${secret}'</if>" + + "<if test=\"recordAssistPort != null\">, recordAssistPort=${recordAssistPort}</if>" + + "WHERE id='${id}'"+ + " </script>"}) + int update(IMediaServerItem mediaServerItem); + + @Select("SELECT * FROM media_server WHERE id='${id}'") + MediaServerItem queryOne(String id); + + @Select("SELECT * FROM media_server") + List<MediaServerItem> queryAll(); + + @Select("DELETE FROM media_server WHERE id='${id}'") + int delOne(String secret); + + @Select("SELECT * FROM media_server WHERE ip='${host}' and httpPort=${port}") + MediaServerItem queryOneByHostAndPort(String host, int port); +} diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java index 3f53c36..7346da5 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamProxyMapper.java @@ -10,10 +10,10 @@ @Repository public interface StreamProxyMapper { - @Insert("INSERT INTO stream_proxy (type, app, stream, url, src_url, dst_url, " + - "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable) VALUES" + - "('${type}','${app}', '${stream}', '${url}', '${src_url}', '${dst_url}', " + - "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable} )") + @Insert("INSERT INTO stream_proxy (type, app, stream,mediaServerId, url, src_url, dst_url, " + + "timeout_ms, ffmpeg_cmd_key, rtp_type, enable_hls, enable_mp4, enable, createTime) VALUES" + + "('${type}','${app}', '${stream}', '${mediaServerId}','${url}', '${src_url}', '${dst_url}', " + + "'${timeout_ms}', '${ffmpeg_cmd_key}', '${rtp_type}', ${enable_hls}, ${enable_mp4}, ${enable}, '${createTime}' )") int add(StreamProxyItem streamProxyDto); @Update("UPDATE stream_proxy " + @@ -21,6 +21,7 @@ "app=#{app}," + "stream=#{stream}," + "url=#{url}, " + + "mediaServerId=#{mediaServerId}, " + "src_url=#{src_url}," + "dst_url=#{dst_url}, " + "timeout_ms=#{timeout_ms}, " + @@ -35,12 +36,17 @@ @Delete("DELETE FROM stream_proxy WHERE app=#{app} AND stream=#{stream}") int del(String app, String stream); - @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream") + @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream order by st.createTime desc") List<StreamProxyItem> selectAll(); - @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.enable=${enable}") + @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.enable=${enable} order by st.createTime desc") List<StreamProxyItem> selectForEnable(boolean enable); - @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.app=#{app} AND st.stream=#{stream}") + @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream WHERE st.app=#{app} AND st.stream=#{stream} order by st.createTime desc") StreamProxyItem selectOne(String app, String stream); + + @Select("SELECT st.*, pgs.gbId, pgs.name, pgs.longitude, pgs.latitude FROM stream_proxy st " + + "LEFT JOIN gb_stream pgs on st.app = pgs.app AND st.stream = pgs.stream " + + "WHERE st.enable=${enable} and st.mediaServerId = '${id}' order by st.createTime desc") + List<StreamProxyItem> selectForEnableInMediaServer(String id, boolean enable); } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java index 455aa2c..41e4c44 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/StreamPushMapper.java @@ -11,14 +11,15 @@ public interface StreamPushMapper { @Insert("INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + - "createStamp, aliveSecond) VALUES" + + "createStamp, aliveSecond, mediaServerId) VALUES" + "('${app}', '${stream}', '${totalReaderCount}', '${originType}', '${originTypeStr}', " + - "'${createStamp}', '${aliveSecond}' )") + "'${createStamp}', '${aliveSecond}', '${mediaServerId}' )") int add(StreamPushItem streamPushItem); @Update("UPDATE stream_push " + "SET app=#{app}," + "stream=#{stream}," + + "mediaServerId=#{mediaServerId}," + "totalReaderCount=#{totalReaderCount}, " + "originType=#{originType}," + "originTypeStr=#{originTypeStr}, " + @@ -41,10 +42,10 @@ @Insert("<script>" + "INSERT INTO stream_push (app, stream, totalReaderCount, originType, originTypeStr, " + - "createStamp, aliveSecond) " + + "createStamp, aliveSecond, mediaServerId) " + "VALUES <foreach collection='streamPushItems' item='item' index='index' >" + "( '${item.app}', '${item.stream}', '${item.totalReaderCount}', '${item.originType}', " + - "'${item.originTypeStr}','${item.createStamp}', '${item.aliveSecond}' )" + + "'${item.originTypeStr}','${item.createStamp}', '${item.aliveSecond}', '${item.mediaServerId}' )" + " </foreach>" + "</script>") void addAll(List<StreamPushItem> streamPushItems); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java index 86909c7..eafb8a0 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -5,6 +5,8 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.utils.redis.RedisUtil; @@ -85,26 +87,6 @@ channelId)); if (playLeys == null || playLeys.size() == 0) return null; return (StreamInfo)redis.get(playLeys.get(0).toString()); - } - - /** - * 鏇存柊娴佸獟浣撲俊鎭� - * @param ZLMServerConfig - * @return - */ - @Override - public boolean updateMediaInfo(ZLMServerConfig ZLMServerConfig) { - ZLMServerConfig.setUpdateTime(format.format(new Date(System.currentTimeMillis()))); - return redis.set(VideoManagerConstants.MEDIA_SERVER_PREFIX, ZLMServerConfig); - } - - /** - * 鑾峰彇娴佸獟浣撲俊鎭� - * @return - */ - @Override - public ZLMServerConfig getMediaInfo() { - return (ZLMServerConfig)redis.get(VideoManagerConstants.MEDIA_SERVER_PREFIX); } @Override @@ -297,7 +279,7 @@ @Override public void outlineForAll() { - List<Object> onlineDevices = redis.scan(String.format("%S*", VideoManagerConstants.KEEPLIVEKEY_PREFIX)); + List<Object> onlineDevices = redis.scan(VideoManagerConstants.KEEPLIVEKEY_PREFIX + "*" ); for (int i = 0; i < onlineDevices.size(); i++) { String key = (String) onlineDevices.get(i); redis.del(key); @@ -308,4 +290,5 @@ public void updateWVPInfo(JSONObject jsonObject) { } + } diff --git a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java index bbe8c2b..4e24753 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/VideoManagerStoragerImpl.java @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -69,6 +70,9 @@ @Autowired private VideoStreamSessionManager streamSession; + + @Autowired + private MediaServerMapper mediaServerMapper; private SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); @@ -459,6 +463,8 @@ boolean result = false; streamProxyItem.setStreamType("proxy"); streamProxyItem.setStatus(true); + String now = this.format.format(new Date(System.currentTimeMillis())); + streamProxyItem.setCreateTime(now); try { if (gbStreamMapper.add(streamProxyItem)<0 || streamProxyMapper.add(streamProxyItem) < 0) { //浜嬪姟鍥炴粴 @@ -467,6 +473,7 @@ result = true; dataSourceTransactionManager.commit(transactionStatus); //鎵嬪姩鎻愪氦 }catch (Exception e) { + logger.error("鍚戞暟鎹簱娣诲姞娴佷唬鐞嗗け璐ワ細", e); dataSourceTransactionManager.rollback(transactionStatus); } return result; @@ -599,4 +606,21 @@ public void updateParentPlatformStatus(String platformGbID, boolean online) { platformMapper.updateParentPlatformStatus(platformGbID, online); } + + @Override + public void updateMediaServer(MediaServerItem mediaServerItem) { + String now = this.format.format(new Date(System.currentTimeMillis())); + mediaServerItem.setUpdateTime(now); + if (mediaServerMapper.queryOne(mediaServerItem.getId()) != null) { + mediaServerMapper.update(mediaServerItem); + }else { + mediaServerItem.setCreateTime(now); + mediaServerMapper.add(mediaServerItem); + } + } + + @Override + public List<StreamProxyItem> getStreamProxyListForEnableInMediaServer(String id, boolean enable) { + return streamProxyMapper.selectForEnableInMediaServer(id, enable); + } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java index eab00bc..6caf8d9 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceConfig.java @@ -25,6 +25,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; @@ -78,7 +79,7 @@ cmder.deviceBasicConfigCmd(device, channelId, name, expiration, heartBeatInterval, heartBeatCount, event -> { Response response = event.getResponse(); RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); msg.setData(String.format("璁惧閰嶇疆鎿嶄綔澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase())); resultHolder.invokeResult(msg); }); @@ -87,7 +88,7 @@ logger.warn(String.format("璁惧閰嶇疆鎿嶄綔瓒呮椂, 璁惧鏈繑鍥炲簲绛旀寚浠�")); // 閲婃斁rtpserver RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); JSONObject json = new JSONObject(); json.put("DeviceID", deviceId); json.put("Status", "Timeout"); @@ -95,7 +96,7 @@ msg.setData(json); //("鐪嬪畧浣嶆帶鍒舵搷浣滆秴鏃�, 璁惧鏈繑鍥炲簲绛旀寚浠�"); resultHolder.invokeResult(msg); }); - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONFIG + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result); return result; } @@ -123,7 +124,7 @@ cmder.deviceConfigQuery(device, channelId, configType, event -> { Response response = event.getResponse(); RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); msg.setData(String.format("鑾峰彇璁惧閰嶇疆澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase())); resultHolder.invokeResult(msg); }); @@ -132,11 +133,11 @@ logger.warn(String.format("鑾峰彇璁惧閰嶇疆瓒呮椂")); // 閲婃斁rtpserver RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); msg.setData("Timeout. Device did not response to this command."); resultHolder.invokeResult(msg); }); - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_CONFIGDOWNLOAD + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result); return result; } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java index 45059aa..874d9a9 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/device/DeviceControl.java @@ -26,6 +26,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; @@ -97,7 +98,7 @@ cmder.recordCmd(device, channelId, recordCmdStr, event -> { Response response = event.getResponse(); RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); msg.setData(String.format("寮�濮�/鍋滄褰曞儚鎿嶄綔澶辫触锛岄敊璇爜锛� %s, %s", response.getStatusCode(), response.getReasonPhrase())); resultHolder.invokeResult(msg); }); @@ -106,11 +107,11 @@ logger.warn(String.format("寮�濮�/鍋滄褰曞儚鎿嶄綔瓒呮椂, 璁惧鏈繑鍥炲簲绛旀寚浠�")); // 閲婃斁rtpserver RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); msg.setData("Timeout. Device did not response to this command."); resultHolder.invokeResult(msg); }); - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result); return result; } @@ -254,7 +255,7 @@ cmder.homePositionCmd(device, channelId, enabled, resetTime, presetIndex, event -> { Response response = event.getResponse(); RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); msg.setData(String.format("鐪嬪畧浣嶆帶鍒舵搷浣滃け璐ワ紝閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase())); resultHolder.invokeResult(msg); }); @@ -263,7 +264,7 @@ logger.warn(String.format("鐪嬪畧浣嶆帶鍒舵搷浣滆秴鏃�, 璁惧鏈繑鍥炲簲绛旀寚浠�")); // 閲婃斁rtpserver RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); JSONObject json = new JSONObject(); json.put("DeviceID", deviceId); json.put("Status", "Timeout"); @@ -271,7 +272,7 @@ msg.setData(json); //("鐪嬪畧浣嶆帶鍒舵搷浣滆秴鏃�, 璁惧鏈繑鍥炲簲绛旀寚浠�"); resultHolder.invokeResult(msg); }); - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_DEVICECONTROL + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result); return result; } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java index 5db9478..450c54a 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java @@ -43,11 +43,13 @@ @ApiImplicitParams({ @ApiImplicitParam(name = "app", value = "搴旂敤鍚�", dataTypeClass = String.class), @ApiImplicitParam(name = "stream", value = "娴乮d", dataTypeClass = String.class), + @ApiImplicitParam(name = "mediaServerId", value = "濯掍綋鏈嶅姟鍣╥d", dataTypeClass = String.class), }) @GetMapping(value = "/stream_info_by_app_and_stream") @ResponseBody - public StreamInfo getStreamInfoByAppAndStream(String app, String stream){ - return mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream); + public StreamInfo getStreamInfoByAppAndStream(@RequestParam String app, @RequestParam String stream, @RequestParam String mediaServerId){ + + return mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream,mediaServerId); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java index 4297bb2..aae9cce 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java @@ -8,6 +8,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.PlayResult; @@ -72,6 +75,9 @@ @Autowired private IMediaService mediaService; + @Autowired + private IMediaServerService mediaServerService; + @ApiOperation("寮�濮嬬偣鎾�") @ApiImplicitParams({ @ApiImplicitParam(name = "deviceId", value = "璁惧ID", dataTypeClass = String.class), @@ -81,8 +87,10 @@ public DeferredResult<ResponseEntity<String>> play(@PathVariable String deviceId, @PathVariable String channelId) { - PlayResult playResult = playService.play(deviceId, channelId, null, null); - + // 鑾峰彇鍙敤鐨剒lm + Device device = storager.queryVideoDevice(deviceId); + IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); + PlayResult playResult = playService.play(newMediaServerItem, deviceId, channelId, null, null); return playResult.getResult(); } @@ -102,8 +110,8 @@ // 褰曞儚鏌ヨ浠hannelId浣滀负deviceId鏌ヨ resultHolder.put(DeferredResultHolder.CALLBACK_CMD_STOP + uuid, result); - - cmder.streamByeCmd(deviceId, channelId, event -> { + Device device = storager.queryVideoDevice(deviceId); + cmder.streamByeCmd(deviceId, channelId, (event) -> { StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(deviceId, channelId); if (streamInfo == null) { RequestMessage msg = new RequestMessage(); @@ -120,6 +128,7 @@ msg.setData(String.format("success")); resultHolder.invokeResult(msg); } + mediaServerService.closeRTPServer(device, channelId); }); if (deviceId != null || channelId != null) { @@ -165,16 +174,16 @@ logger.warn("瑙嗛杞爜API璋冪敤澶辫触锛�, 瑙嗛娴佸凡缁忓仠姝�!"); return new ResponseEntity<String>("鏈壘鍒拌棰戞祦淇℃伅, 瑙嗛娴佸彲鑳藉凡缁忓仠姝�", HttpStatus.OK); } - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(streamId); + IMediaServerItem mediaInfo = mediaServerService.getOne(streamInfo.getMediaServerId()); + JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); if (!rtpInfo.getBoolean("exist")) { logger.warn("瑙嗛杞爜API璋冪敤澶辫触锛�, 瑙嗛娴佸凡鍋滄鎺ㄦ祦!"); return new ResponseEntity<String>("鎺ㄦ祦淇℃伅鍦ㄦ祦濯掍綋涓笉瀛樺湪, 瑙嗛娴佸彲鑳藉凡鍋滄鎺ㄦ祦", HttpStatus.OK); } else { - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); String dstUrl = String.format("rtmp://%s:%s/convert/%s", "127.0.0.1", mediaInfo.getRtmpPort(), streamId ); String srcUrl = String.format("rtsp://%s:%s/rtp/%s", "127.0.0.1", mediaInfo.getRtspPort(), streamId); - JSONObject jsonObject = zlmresTfulUtils.addFFmpegSource(srcUrl, dstUrl, "1000000", true, false, null); + JSONObject jsonObject = zlmresTfulUtils.addFFmpegSource(mediaInfo, srcUrl, dstUrl, "1000000", true, false, null); logger.info(jsonObject.toJSONString()); JSONObject result = new JSONObject(); if (jsonObject != null && jsonObject.getInteger("code") == 0) { @@ -182,7 +191,7 @@ JSONObject data = jsonObject.getJSONObject("data"); if (data != null) { result.put("key", data.getString("key")); - StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId); + StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId, mediaInfo.getId()); result.put("data", streamInfoResult); } }else { @@ -203,25 +212,38 @@ @ApiImplicitParam(name = "key", value = "瑙嗛娴乲ey", dataTypeClass = String.class), }) @PostMapping("/convertStop/{key}") - public ResponseEntity<String> playConvertStop(@PathVariable String key) { - - JSONObject jsonObject = zlmresTfulUtils.delFFmpegSource(key); - logger.info(jsonObject.toJSONString()); + public ResponseEntity<String> playConvertStop(@PathVariable String key, String mediaServerId) { JSONObject result = new JSONObject(); - if (jsonObject != null && jsonObject.getInteger("code") == 0) { - result.put("code", 0); - JSONObject data = jsonObject.getJSONObject("data"); - if (data != null && data.getBoolean("flag")) { - result.put("code", "0"); - result.put("msg", "success"); - }else { - - } - }else { - result.put("code", 1); - result.put("msg", "delFFmpegSource fail"); + if (mediaServerId == null) { + result.put("code", 400); + result.put("msg", "mediaServerId is null"); + return new ResponseEntity<String>( result.toJSONString(), HttpStatus.BAD_REQUEST); } - return new ResponseEntity<String>( result.toJSONString(), HttpStatus.OK); + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + if (mediaInfo == null) { + result.put("code", 0); + result.put("msg", "浣跨敤鐨勬祦濯掍綋宸茬粡鍋滄杩愯"); + return new ResponseEntity<String>( result.toJSONString(), HttpStatus.OK); + }else { + JSONObject jsonObject = zlmresTfulUtils.delFFmpegSource(mediaInfo, key); + logger.info(jsonObject.toJSONString()); + if (jsonObject != null && jsonObject.getInteger("code") == 0) { + result.put("code", 0); + JSONObject data = jsonObject.getJSONObject("data"); + if (data != null && data.getBoolean("flag")) { + result.put("code", "0"); + result.put("msg", "success"); + }else { + + } + }else { + result.put("code", 1); + result.put("msg", "delFFmpegSource fail"); + } + return new ResponseEntity<String>( result.toJSONString(), HttpStatus.OK); + } + + } @ApiOperation("璇煶骞挎挱鍛戒护") @@ -249,7 +271,7 @@ resultHolder.invokeResult(msg); return result; } - cmder.audioBroadcastCmd(device, event -> { + cmder.audioBroadcastCmd(device, (event) -> { Response response = event.getResponse(); RequestMessage msg = new RequestMessage(); msg.setId(DeferredResultHolder.CALLBACK_CMD_BROADCAST + deviceId); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java index 11c210e..d2a30fa 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/playback/PlaybackController.java @@ -4,6 +4,8 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; //import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.service.IPlayService; import io.swagger.annotations.Api; @@ -87,9 +89,18 @@ cmder.streamByeCmd(deviceId, channelId); } resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid, result); - cmder.playbackStreamCmd(device, channelId, startTime, endTime, (JSONObject response) -> { + IMediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); + if (newMediaServerItem == null) { + logger.warn(String.format("璁惧鍥炴斁瓒呮椂锛宒eviceId锛�%s 锛宑hannelId锛�%s", deviceId, channelId)); + RequestMessage msg = new RequestMessage(); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PlAY + uuid); + msg.setData("Timeout"); + resultHolder.invokeResult(msg); + return result; + } + cmder.playbackStreamCmd(newMediaServerItem, device, channelId, startTime, endTime, (IMediaServerItem mediaServerItem, JSONObject response) -> { logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + response.toJSONString()); - playService.onPublishHandlerForPlayBack(response, deviceId, channelId, uuid.toString()); + playService.onPublishHandlerForPlayBack(mediaServerItem, response, deviceId, channelId, uuid.toString()); }, event -> { Response response = event.getResponse(); RequestMessage msg = new RequestMessage(); diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java index 7e57e0d..f78b333 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/ptz/PtzController.java @@ -9,6 +9,7 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; @@ -104,7 +105,7 @@ cmder.presetQuery(device, channelId, event -> { Response response = event.getResponse(); RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); msg.setData(String.format("鑾峰彇璁惧棰勭疆浣嶅け璐ワ紝閿欒鐮侊細 %s, %s", response.getStatusCode(), response.getReasonPhrase())); resultHolder.invokeResult(msg); }); @@ -113,11 +114,11 @@ logger.warn(String.format("鑾峰彇璁惧棰勭疆浣嶈秴鏃�")); // 閲婃斁rtpserver RequestMessage msg = new RequestMessage(); - msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId)); + msg.setId(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId)); msg.setData("鑾峰彇璁惧棰勭疆浣嶈秴鏃�"); resultHolder.invokeResult(msg); }); - resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (XmlUtil.isEmpty(channelId) ? deviceId : channelId), result); + resultHolder.put(DeferredResultHolder.CALLBACK_CMD_PRESETQUERY + (StringUtils.isEmpty(channelId) ? deviceId : channelId), result); return result; } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/record/RecoderProxyController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/record/RecoderProxyController.java index 734f62f..f00e2ab 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/record/RecoderProxyController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/record/RecoderProxyController.java @@ -2,6 +2,9 @@ import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; @@ -27,6 +30,8 @@ @Autowired private IRedisCatchStorage redisCatchStorage; + @Autowired + private IMediaServerService mediaServerService; @Autowired private MediaConfig mediaConfig; @@ -48,7 +53,11 @@ return null; } // 鍚庣画鏀逛负鏍规嵁Id鑾峰彇瀵瑰簲鐨刏LM - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); + IMediaServerItem mediaInfo = mediaServerService.getOne(mediaId); + if (mediaInfo == null) { + response.setStatus(HttpStatus.NOT_FOUND.value()); + return null; + } String requestURI = String.format("http://%s:%s%s?%s", mediaInfo.getSdpIp(), mediaConfig.getRecordAssistPort(), diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java index bbd4bd5..45eeac8 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java @@ -2,8 +2,11 @@ import com.genersoft.iot.vmp.VManageBootstrap; import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.utils.SpringBeanFactory; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import gov.nist.javax.sip.SipStackImpl; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -16,6 +19,7 @@ import javax.sip.SipProvider; import java.util.ArrayList; import java.util.Iterator; +import java.util.List; @SuppressWarnings("rawtypes") @Api(tags = "鏈嶅姟鎺у埗") @@ -28,17 +32,28 @@ private ConfigurableApplicationContext context; @Autowired - private IRedisCatchStorage redisCatchStorage; + private IMediaServerService mediaServerService; @ApiOperation("娴佸獟浣撴湇鍔″垪琛�") @GetMapping(value = "/media_server/list") @ResponseBody - public Object getMediaServerList(){ - // TODO 涓哄悗缁涓獄lm鏀寔鍑嗗 - ZLMServerConfig mediaInfo = redisCatchStorage.getMediaInfo(); - ArrayList<ZLMServerConfig> result = new ArrayList<>(); - result.add(mediaInfo); + public WVPResult<List<IMediaServerItem>> getMediaServerList(){ + WVPResult<List<IMediaServerItem>> result = new WVPResult<>(); + result.setCode(0); + result.setMsg("success"); + result.setData(mediaServerService.getAll()); + return result; + } + + @ApiOperation("鑾峰彇娴佸獟浣撴湇鍔�") + @GetMapping(value = "/media_server/one/{id}") + @ResponseBody + public WVPResult<IMediaServerItem> getMediaServer(@PathVariable String id){ + WVPResult<IMediaServerItem> result = new WVPResult<>(); + result.setCode(0); + result.setMsg("success"); + result.setData(mediaServerService.getOne(id)); return result; } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java index 51c8c8e..f099631 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java @@ -1,11 +1,15 @@ package com.genersoft.iot.vmp.vmanager.streamProxy; import com.alibaba.fastjson.JSONObject; +import com.genersoft.iot.vmp.media.zlm.dto.IMediaServerItem; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; +import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.github.pagehelper.PageInfo; +import io.netty.util.internal.StringUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; @@ -14,6 +18,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; +import org.springframework.util.StringUtils; import org.springframework.web.bind.annotation.*; @SuppressWarnings("rawtypes") @@ -30,6 +35,10 @@ @Autowired private IRedisCatchStorage redisCatchStorage; + + + @Autowired + private IMediaServerService mediaServerService; @Autowired private IStreamProxyService streamProxyService; @@ -60,6 +69,7 @@ @ResponseBody public WVPResult save(@RequestBody StreamProxyItem param){ logger.info("娣诲姞浠g悊锛� " + JSONObject.toJSONString(param)); + if (StringUtils.isEmpty(param.getMediaServerId())) param.setMediaServerId("auto"); String msg = streamProxyService.save(param); WVPResult<Object> result = new WVPResult<>(); result.setCode(0); @@ -69,10 +79,15 @@ @ApiOperation("鑾峰彇ffmpeg.cmd妯℃澘") @GetMapping(value = "/ffmpeg_cmd/list") + @ApiImplicitParams({ + @ApiImplicitParam(name = "mediaServerId", value = "娴佸獟浣揑D", dataTypeClass = String.class), + }) @ResponseBody - public WVPResult getFFmpegCMDs(){ - logger.debug("鑾峰彇ffmpeg.cmd妯℃澘锛�" ); - JSONObject data = streamProxyService.getFFmpegCMDs(); + public WVPResult getFFmpegCMDs(@RequestParam String mediaServerId){ + logger.debug("鑾峰彇鑺傜偣[ {} ]ffmpeg.cmd妯℃澘", mediaServerId ); + + IMediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + JSONObject data = streamProxyService.getFFmpegCMDs(mediaServerItem); WVPResult<JSONObject> result = new WVPResult<>(); result.setCode(0); result.setMsg("success"); @@ -82,12 +97,12 @@ @ApiOperation("绉婚櫎浠g悊") @ApiImplicitParams({ - @ApiImplicitParam(name = "app", value = "搴旂敤鍚�", dataTypeClass = String.class), - @ApiImplicitParam(name = "stream", value = "娴両D", dataTypeClass = String.class), + @ApiImplicitParam(name = "app", value = "搴旂敤鍚�", required = true, dataTypeClass = String.class), + @ApiImplicitParam(name = "stream", value = "娴両D", required = true, dataTypeClass = String.class), }) @DeleteMapping(value = "/del") @ResponseBody - public WVPResult del(String app, String stream){ + public WVPResult del(@RequestParam String app, @RequestParam String stream){ logger.info("绉婚櫎浠g悊锛� " + app + "/" + stream); WVPResult<Object> result = new WVPResult<>(); if (app == null || stream == null) { diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java index c55824a..a8e0de4 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/ApiControlController.java @@ -10,7 +10,7 @@ import org.springframework.web.bind.annotation.*; /** - * 鍏煎LiveGBS鐨凙PI锛氳澶囨帶鍒� + * API鍏煎锛氳澶囨帶鍒� */ @CrossOrigin @RestController diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiController.java index 43ae7d9..8035810 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/ApiController.java @@ -11,7 +11,7 @@ import org.springframework.web.bind.annotation.ResponseBody; /** - * 鍏煎LiveGBS鐨凙PI锛氱郴缁熸帴鍙� + * API鍏煎锛氱郴缁熸帴鍙� */ @Controller @CrossOrigin diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java index 09c94bd..264f2b2 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/ApiDeviceController.java @@ -14,7 +14,7 @@ import java.util.List; /** - * 鍏煎LiveGBS鐨凙PI锛氳澶囦俊鎭� + * API鍏煎锛氳澶囦俊鎭� */ @SuppressWarnings("unchecked") @CrossOrigin diff --git a/src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java b/src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java index 932684a..ae7e921 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/ApiStreamController.java @@ -17,7 +17,7 @@ import org.springframework.web.context.request.async.DeferredResult; /** - * 鍏煎LiveGBS鐨凙PI锛氬疄鏃剁洿鎾� + * API鍏煎锛氬疄鏃剁洿鎾� */ @SuppressWarnings(value = {"rawtypes", "unchecked"}) @CrossOrigin diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index 127cbcf..2552e01 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -70,9 +70,13 @@ keepalive-timeout: 180 # [鍙�塢 鍥芥爣绾ц仈娉ㄥ唽澶辫触锛屽啀娆″彂璧锋敞鍐岀殑鏃堕棿闂撮殧銆� 榛樿60绉� register-time-interval: 60 + # TODO [鍙�塢 鏀跺埌蹇冭烦鍚庤嚜鍔ㄤ笂绾匡紝 閲嶅惎鏈嶅姟鍚庝細灏嗘墍鏈夎澶囩疆涓虹绾匡紝榛樿false锛岀瓑寰呮敞鍐屽悗涓婄嚎銆傝缃负true鍒欐敹鍒板績璺宠缃负涓婄嚎銆� + # keepalliveToOnline: false #zlm 榛樿鏈嶅姟鍣ㄩ厤缃� media: + # [鍙�塢 zlm鏈嶅姟鍣ㄥ敮涓�id锛岀敤浜庤Е鍙慼ook鏃跺尯鍒槸鍝彴鏈嶅姟鍣�,general.mediaServerId + id: # [蹇呴』淇敼] zlm鏈嶅姟鍣ㄧ殑鍐呯綉IP ip: 192.168.0.100 # [鍙�塢 杩斿洖娴佸湴鍧�鏃剁殑ip锛岀疆绌轰娇鐢� media.ip diff --git a/src/main/resources/wvp.sqlite b/src/main/resources/wvp.sqlite index 7c38c43..f399e6e 100644 --- a/src/main/resources/wvp.sqlite +++ b/src/main/resources/wvp.sqlite Binary files differ diff --git a/web_src/src/components/CloudRecord.vue b/web_src/src/components/CloudRecord.vue index c269270..284578b 100644 --- a/web_src/src/components/CloudRecord.vue +++ b/web_src/src/components/CloudRecord.vue @@ -7,22 +7,23 @@ <el-main> <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> <span style="font-size: 1rem; font-weight: bold;">浜戠褰曞儚</span> + <div style="position: absolute; right: 5rem; top: 0.3rem;"> + 鑺傜偣閫夋嫨: <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServer" placeholder="璇烽�夋嫨" default-first-option> + <el-option + v-for="item in mediaServerList" + :key="item.id" + :label="item.id + '( ' + item.streamIp + ' )'" + :value="item"> + </el-option> + </el-select> + </div> <div style="position: absolute; right: 1rem; top: 0.3rem;"> <el-button v-if="!recordDetail" icon="el-icon-refresh-right" circle size="mini" :loading="loading" @click="getRecordList()"></el-button> <el-button v-if="recordDetail" icon="el-icon-arrow-left" circle size="mini" @click="backToList()"></el-button> </div> </div> <div v-if="!recordDetail"> - <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;font-size: 14px;"> - 鑺傜偣閫夋嫨: <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServer" placeholder="璇烽�夋嫨" default-first-option> - <el-option - v-for="item in mediaServerList" - :key="item.generalMediaServerId" - :label="item.generalMediaServerId + '( ' + item.wanIp + ' )'" - :value="item"> - </el-option> - </el-select> - </div> + <!--璁惧鍒楄〃--> <el-table :data="recordList" border style="width: 100%" :height="winHeight"> <el-table-column prop="app" label="搴旂敤鍚�" align="center"> @@ -60,6 +61,7 @@ <script> import uiHeader from './UiHeader.vue' import cloudRecordDetail from './CloudRecordDetail.vue' + import MediaServer from './service/MediaServer' export default { name: 'app', components: { @@ -78,6 +80,7 @@ count:15, total:0, loading: false, + mediaServerObj : new MediaServer(), recordDetail: false }; @@ -107,20 +110,13 @@ }, getMediaServerList: function (){ let that = this; - this.$axios({ - method: 'get', - url:`/api/server/media_server/list`, - }).then(function (res) { - console.log(res) - that.mediaServerList = res.data; + that.mediaServerObj.getMediaServerList((data)=>{ + that.mediaServerList = data; if (that.mediaServerList.length > 0) { that.mediaServer = that.mediaServerList[0] that.getRecordList(); } - - }).catch(function (error) { - console.log(error); - }); + }) }, getRecordList: function (){ let that = this; diff --git a/web_src/src/components/PushVideoList.vue b/web_src/src/components/PushVideoList.vue index f40fe3c..bdc086c 100644 --- a/web_src/src/components/PushVideoList.vue +++ b/web_src/src/components/PushVideoList.vue @@ -17,6 +17,8 @@ </el-table-column> <el-table-column prop="gbId" label="鍥芥爣缂栫爜" width="150" align="center"> </el-table-column> + <el-table-column prop="mediaServerId" label="娴佸獟浣�" width="150" align="center"> + </el-table-column> <el-table-column label="寮�濮嬫椂闂�" align="center" > <template slot-scope="scope"> <el-button-group> @@ -29,7 +31,7 @@ {{(scope.row.status == false && scope.row.gbId == null) || scope.row.status ?'鏄�':'鍚�'}} </template> </el-table-column> - + <el-table-column label="鎿嶄綔" width="360" align="center" fixed="right"> <template slot-scope="scope"> <el-button-group> @@ -125,7 +127,7 @@ that.getDeviceListLoading = false; }); }, - + playPuhsh: function(row){ let that = this; this.getListLoading = true; @@ -134,7 +136,8 @@ url:`/api/media/stream_info_by_app_and_stream`, params: { app: row.app, - stream: row.stream + stream: row.stream, + mediaServerId: row.mediaServerId } }).then(function (res) { that.getListLoading = false; diff --git a/web_src/src/components/StreamProxyList.vue b/web_src/src/components/StreamProxyList.vue index 90425b5..45fd573 100644 --- a/web_src/src/components/StreamProxyList.vue +++ b/web_src/src/components/StreamProxyList.vue @@ -32,6 +32,15 @@ </div> </template> </el-table-column> + <el-table-column prop="mediaServerId" label="娴佸獟浣�" width="150" align="center"></el-table-column> + <el-table-column label="绫诲瀷" width="100" align="center"> + <template slot-scope="scope"> + <div slot="reference" class="name-wrapper"> + <el-tag size="medium">{{scope.row.type}}</el-tag> + </div> + </template> + </el-table-column> + <el-table-column prop="gbId" label="鍥芥爣缂栫爜" width="180" align="center" show-overflow-tooltip/> <el-table-column label="鍚敤" width="120" align="center"> <template slot-scope="scope"> @@ -147,8 +156,6 @@ count: that.count } }).then(function (res) { - console.log(res); - console.log(res.data.list); that.total = res.data.total; that.streamProxyList = res.data.list; that.getListLoading = false; @@ -170,7 +177,6 @@ this.getListLoading = false; if (res.data.code == 0 ){ if (res.data.data.length > 0) { - console.log(res.data.data) this.$refs.onvifEdit.openDialog(res.data.data, (url)=>{ if (url != null) { this.$refs.onvifEdit.close(); @@ -200,7 +206,8 @@ url:`/api/media/stream_info_by_app_and_stream`, params: { app: row.app, - stream: row.stream + stream: row.stream, + mediaServerId: row.mediaServerId } }).then(function (res) { that.getListLoading = false; diff --git a/web_src/src/components/control.vue b/web_src/src/components/control.vue index 51bcb0a..b8b0efc 100644 --- a/web_src/src/components/control.vue +++ b/web_src/src/components/control.vue @@ -7,6 +7,17 @@ <el-main> <div style="background-color: #FFFFFF; margin-bottom: 1rem; position: relative; padding: 0.5rem; text-align: left;"> <span style="font-size: 1rem; font-weight: bold;">鎺у埗鍙�</span> + <div style="position: absolute; right: 17rem; top: 0.3rem;"> + 鑺傜偣閫夋嫨: <el-select size="mini" @change="chooseMediaChange" style="width: 16rem; margin-right: 1rem;" v-model="mediaServerChoose" placeholder="璇烽�夋嫨" default-first-option> + <el-option + v-for="item in mediaServerList" + :key="item.id" + :label="item.id + '( ' + item.streamIp + ' )'" + :value="item.id"> + </el-option> + </el-select> + <span >{{loadCount}}</span> + </div> <div style="position: absolute; right: 1rem; top: 0.3rem;"> <el-popover placement="bottom" width="750" height="300" trigger="click"> <div style="height: 600px;overflow:auto;"> @@ -53,6 +64,7 @@ <script> import uiHeader from './UiHeader.vue' +import MediaServer from './service/MediaServer' import echarts from 'echarts'; export default { @@ -87,68 +99,101 @@ chartInterval: 0, //鏇存柊鍥捐〃缁熻鍥惧畾鏃朵换鍔℃爣璇� allSessionData: [], visible: false, - serverConfig: {} + serverConfig: {}, + mediaServer : new MediaServer(), + mediaServerChoose : null, + loadCount : 0, + mediaServerList : [] }; }, mounted() { - this.getAllSession(); + this.initTable(); this.updateData(); this.chartInterval = setInterval(this.updateData, 3000); + this.mediaServer.getMediaServerList((data)=>{ + this.mediaServerList = data.data; + if (this.mediaServerList && this.mediaServerList.length > 0) { + this.mediaServerChoose = this.mediaServerList[0].id + this.loadCount = this.mediaServerList[0].count; + this.getThreadsLoad(); + this.getAllSession(); + } + }) }, destroyed() { clearInterval(this.chartInterval); //閲婃斁瀹氭椂浠诲姟 }, methods: { + chooseMediaChange: function (val) { + this.loadCount = 0 + this.initTable() + this.updateData(); + }, updateData: function () { this.getThreadsLoad(); + this.getLoadCount(); + this.getAllSession(); }, /** * 鑾峰彇绾跨▼鐘舵�� */ getThreadsLoad: function () { let that = this; - this.$axios({ + if (that.mediaServerChoose != null) { + this.$axios({ method: 'get', - url: '/zlm/index/api/getThreadsLoad' - }).then(function (res) { + url: '/zlm/' + that.mediaServerChoose +'/index/api/getThreadsLoad' + }).then(function (res) { if (res.data.code == 0) { - that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', { - hour12: false - })); - that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', { - hour12: false - })); + that.tableOption.xAxis.data.push(new Date().toLocaleTimeString('chinese', { + hour12: false + })); + that.table1Option.xAxis.data.push(new Date().toLocaleTimeString('chinese', { + hour12: false + })); - for (var i = 0; i < res.data.data.length; i++) { - if (that.tableOption.series[i] === undefined) { - let data = { - data: [], - type: 'line' - }; - let data1 = { - data: [], - type: 'line' - }; - data.data.push(res.data.data[i].delay); - data1.data.push(res.data.data[i].load); - that.tableOption.series.push(data); - that.table1Option.series.push(data1); - } else { - that.tableOption.series[i].data.push(res.data.data[i].delay); - that.table1Option.series[i].data.push(res.data.data[i].load); - } + for (var i = 0; i < res.data.data.length; i++) { + if (that.tableOption.series[i] === undefined) { + let data = { + data: [], + type: 'line' + }; + let data1 = { + data: [], + type: 'line' + }; + data.data.push(res.data.data[i].delay); + data1.data.push(res.data.data[i].load); + that.tableOption.series.push(data); + that.table1Option.series.push(data1); + } else { + that.tableOption.series[i].data.push(res.data.data[i].delay); + that.table1Option.series[i].data.push(res.data.data[i].load); } - that.tableOption.dataZoom[0].start = that.charZoomStart; - that.tableOption.dataZoom[0].end = that.charZoomEnd; - that.table1Option.dataZoom[0].start = that.charZoomStart; - that.table1Option.dataZoom[0].end = that.charZoomEnd; - //that.myChart = echarts.init(document.getElementById('ThreadsLoad')); - that.myChart.setOption(that.tableOption, true); - // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad')); - that.myChart1.setOption(that.table1Option, true); + } + that.tableOption.dataZoom[0].start = that.charZoomStart; + that.tableOption.dataZoom[0].end = that.charZoomEnd; + that.table1Option.dataZoom[0].start = that.charZoomStart; + that.table1Option.dataZoom[0].end = that.charZoomEnd; + //that.myChart = echarts.init(document.getElementById('ThreadsLoad')); + that.myChart.setOption(that.tableOption, true); + // that.myChart1 = echarts.init(document.getElementById('WorkThreadsLoad')); + that.myChart1.setOption(that.table1Option, true); } - }); + }); + } + + }, + getLoadCount: function (){ + let that = this; + if (that.mediaServerChoose != null) { + that.mediaServer.getMediaServer(that.mediaServerChoose, (data)=>{ + if (data.code == 0) { + that.loadCount = data.data.count + } + }) + } }, initTable: function () { let that = this; @@ -242,10 +287,9 @@ getAllSession: function () { let that = this; that.allSessionData = []; - console.log("鍦板潃锛�" + '/zlm/index/api/getAllSession'); this.$axios({ method: 'get', - url: '/zlm/index/api/getAllSession' + url: '/zlm/' + that.mediaServerChoose +'/index/api/getAllSession' }).then(function (res) { res.data.data.forEach(item => { let data = { diff --git a/web_src/src/components/dialog/StreamProxyEdit.vue b/web_src/src/components/dialog/StreamProxyEdit.vue index e1d224a..3310d9c 100644 --- a/web_src/src/components/dialog/StreamProxyEdit.vue +++ b/web_src/src/components/dialog/StreamProxyEdit.vue @@ -39,6 +39,22 @@ <el-form-item label="瓒呮椂鏃堕棿:姣" prop="timeout_ms" v-if="proxyParam.type=='ffmpeg'"> <el-input v-model="proxyParam.timeout_ms" clearable></el-input> </el-form-item> + <el-form-item label="鑺傜偣閫夋嫨" prop="rtp_type"> + <el-select + v-model="proxyParam.mediaServerId" + @change="mediaServerIdChange" + style="width: 100%" + placeholder="璇烽�夋嫨鎷夋祦鑺傜偣" + > + <el-option label="鑷姩閫夋嫨" value="auto"></el-option> + <el-option + v-for="item in mediaServerList" + :key="item.id" + :label="item.id" + :value="item.id"> + </el-option> + </el-select> + </el-form-item> <el-form-item label="FFmpeg鍛戒护妯℃澘" prop="ffmpeg_cmd_key" v-if="proxyParam.type=='ffmpeg'"> <!-- <el-input v-model="proxyParam.ffmpeg_cmd_key" clearable></el-input>--> <el-select @@ -68,6 +84,7 @@ <el-option label="缁勬挱" value="2"></el-option> </el-select> </el-form-item> + <el-form-item label="鍥芥爣骞冲彴"> <el-select v-model="proxyParam.platformGbId" @@ -106,6 +123,8 @@ </template> <script> +import MediaServer from './../service/MediaServer' + export default { name: "streamProxyEdit", props: {}, @@ -134,27 +153,8 @@ isLoging: false, dialogLoading: false, onSubmit_text: "绔嬪嵆鍒涘缓", - platformList: [{ - id: 1, - enable: true, - name: "141", - serverGBId: "34020000002000000001", - serverGBDomain: "3402000000", - serverIP: "192.168.1.141", - serverPort: 15060, - deviceGBId: "34020000002000000001", - deviceIp: "192.168.1.20", - devicePort: "5060", - username: "34020000002000000001", - password: "12345678", - expires: "300", - keepTimeout: "60", - transport: "UDP", - characterSet: "GB2312", - ptz: false, - rtcp: false, - status: true, - }], + platformList: [], + mediaServer: new MediaServer(), proxyParam: { name: null, type: "default", @@ -170,7 +170,9 @@ enable_hls: true, enable_mp4: false, platformGbId: null, + mediaServerId: "auto", }, + mediaServerList:{}, ffmpegCmdList:{}, rules: { @@ -193,7 +195,6 @@ } let that = this; - this.$axios({ method: 'get', url:`/api/platform/query/10000/0` @@ -202,17 +203,28 @@ }).catch(function (error) { console.log(error); }); - this.$axios({ - method: 'get', - url:`/api/proxy/ffmpeg_cmd/list` - }).then(function (res) { - that.ffmpegCmdList = res.data.data; - }).catch(function (error) { - console.log(error); - }); + this.mediaServer.getMediaServerList((data)=>{ + this.mediaServerList = data; + }) + }, + mediaServerIdChange:function (){ + let that = this; + if (that.proxyParam.mediaServerId !== "auto"){ + that.$axios({ + method: 'get', + url:`/api/proxy/ffmpeg_cmd/list`, + params: { + mediaServerId: that.proxyParam.mediaServerId + } + }).then(function (res) { + that.ffmpegCmdList = res.data.data; + }).catch(function (error) { + console.log(error); + }); + } + }, onSubmit: function () { - console.log("onSubmit"); this.dialogLoading = true; var that = this; that.$axios({ @@ -239,7 +251,6 @@ }); }, close: function () { - console.log("鍏抽棴娣诲姞瑙嗛骞冲彴"); this.showDialog = false; this.dialogLoading = false; this.$refs.streamProxy.resetFields(); diff --git a/web_src/src/components/dialog/devicePlayer.vue b/web_src/src/components/dialog/devicePlayer.vue index b7187b7..020cc22 100644 --- a/web_src/src/components/dialog/devicePlayer.vue +++ b/web_src/src/components/dialog/devicePlayer.vue @@ -181,6 +181,7 @@ showVideoDialog: false, streamId: '', app : '', + mediaServerId : '', convertKey: '', deviceId: '', channelId: '', @@ -218,7 +219,7 @@ if (tab.name == "codec") { this.$axios({ method: 'get', - url: '/zlm/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId + url: '/zlm/' +this.mediaServerId+ '/index/api/getMediaInfo?vhost=__defaultVhost__&schema=rtmp&app='+ this.app +'&stream='+ this.streamId }).then(function (res) { that.tracksLoading = false; if (res.data.code == 0 && res.data.online) { @@ -235,12 +236,11 @@ } }, openDialog: function (tab, deviceId, channelId, param) { - console.log("openDialog") - console.log(param) this.tabActiveName = tab; this.channelId = channelId; this.deviceId = deviceId; this.streamId = ""; + this.mediaServerId = ""; this.app = ""; this.videoUrl = "" if (!!this.$refs.videoPlayer) { @@ -257,8 +257,8 @@ break; case "streamPlay": this.tabActiveName = "media"; - this.showRrecord = false, - this.showPtz = false, + this.showRrecord = false; + this.showPtz = false; this.play(param.streamInfo, param.hasAudio) break; case "control": @@ -269,19 +269,17 @@ console.log(val) }, play: function (streamInfo, hasAudio) { - this.hasAudio = hasAudio; this.isLoging = false; // this.videoUrl = streamInfo.rtc; this.videoUrl = this.getUrlByStreamInfo(streamInfo); this.streamId = streamInfo.streamId; this.app = streamInfo.app; + this.mediaServerId = streamInfo.mediaServerId; this.playFromStreamInfo(false, streamInfo) }, getUrlByStreamInfo(streamInfo){ let baseZlmApi = process.env.NODE_ENV === 'development'?`${location.host}/debug/zlm`:`${location.host}/zlm` - console.log(12121212) - console.log(baseZlmApi) // return `${baseZlmApi}/${streamInfo.app}/${streamInfo.streamId}.flv`; // return `http://${baseZlmApi}/${streamInfo.app}/${streamInfo.streamId}.flv`; return streamInfo.ws_flv; @@ -430,6 +428,7 @@ var streamInfo = res.data; that.app = streamInfo.app; that.streamId = streamInfo.streamId; + that.mediaServerId = streamInfo.mediaServerId; that.videoUrl = that.getUrlByStreamInfo(streamInfo); that.recordPlay = true; }); diff --git a/web_src/src/components/service/MediaServer.js b/web_src/src/components/service/MediaServer.js new file mode 100644 index 0000000..a63d19c --- /dev/null +++ b/web_src/src/components/service/MediaServer.js @@ -0,0 +1,32 @@ +import axios from 'axios'; + +class MediaServer{ + + constructor() { + this.$axios = axios; + } + + getMediaServerList(callback){ + this.$axios({ + method: 'get', + url:`/api/server/media_server/list`, + }).then(function (res) { + if (typeof (callback) == "function") callback(res.data) + }).catch(function (error) { + console.log(error); + }); + } + + getMediaServer(id, callback){ + this.$axios({ + method: 'get', + url:`/api/server/media_server/one/` + id, + }).then(function (res) { + if (typeof (callback) == "function") callback(res.data) + }).catch(function (error) { + console.log(error); + }); + } +} + +export default MediaServer; -- Gitblit v1.8.0