From 16b7e4a7ef473a6af29ec78aeb2f471fa398efdd Mon Sep 17 00:00:00 2001 From: leesam <leesam@leesam.cn> Date: 星期三, 10 四月 2024 20:49:44 +0800 Subject: [PATCH] Merge branch 'refs/heads/master' into develop-add-api-key --- src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerStatusEventListener.java | 19 web_src/src/components/service/MediaServer.js | 3 src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java | 6 src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java | 34 src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java | 13 src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java | 15 src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java | 2 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java | 32 src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java | 8 src/main/java/com/genersoft/iot/vmp/media/event/media/MediaPublishEvent.java | 33 src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java | 10 src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java | 22 src/main/java/com/genersoft/iot/vmp/service/IPlayService.java | 23 src/main/java/com/genersoft/iot/vmp/media/bean/RecordInfo.java | 92 src/main/java/com/genersoft/iot/vmp/media/event/media/MediaNotFoundEvent.java | 22 src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java | 129 src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerEventAbstract.java | 7 src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java | 554 ++-- src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java | 15 src/main/java/com/genersoft/iot/vmp/media/event/media/MediaDepartureEvent.java | 22 src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerOfflineEvent.java | 11 src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java | 9 src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java | 18 src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java | 24 src/main/java/com/genersoft/iot/vmp/media/event/media/MediaRecordMp4Event.java | 35 src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java | 278 + src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommander.java | 81 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaServerStatusManger.java | 306 ++ src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java | 70 pom.xml | 2 web_src/src/components/dialog/MediaServerEdit.vue | 11 src/main/java/com/genersoft/iot/vmp/media/bean/ResultForOnPublish.java | 59 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java | 25 src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java | 306 ++ src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java | 25 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMServerConfig.java | 2 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java | 4 src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java | 8 src/main/java/com/genersoft/iot/vmp/media/event/hook/HookSubscribe.java | 107 src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java | 14 src/main/java/com/genersoft/iot/vmp/utils/CloudRecordUtils.java | 4 src/main/java/com/genersoft/iot/vmp/media/event/hook/HookData.java | 132 + src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java | 88 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java | 749 ----- web_src/static/images/abl-logo.jpg | 0 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java | 29 src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java | 8 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/play/PlayController.java | 75 src/main/java/com/genersoft/iot/vmp/media/event/hook/HookType.java | 15 src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerOnlineEvent.java | 11 src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java | 64 src/main/java/com/genersoft/iot/vmp/vmanager/gb28181/media/MediaController.java | 14 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java | 349 ++ src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java | 55 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommander.java | 16 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookParam.java | 2 src/main/java/com/genersoft/iot/vmp/media/event/media/MediaEvent.java | 56 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java | 11 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java | 8 src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java | 145 + 数据库/2.7.1/更新-postgresql-kingbase-2.7.0.sql | 11 src/main/java/com/genersoft/iot/vmp/media/event/hook/Hook.java | 86 src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java | 34 src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java | 35 src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerChangeEvent.java | 34 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamPushItem.java | 43 数据库/2.7.1/初始化-postgresql-kingbase-2.7.0.sql | 6 src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java | 4 src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java | 837 ++++++ src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java | 13 数据库/2.7.1/更新-mysql-2.7.0.sql | 11 src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java | 4 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java | 72 数据库/2.7.1/初始化-mysql-2.7.0.sql | 6 src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerKeepaliveEvent.java | 24 src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java | 68 src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java | 19 src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java | 4 src/main/java/com/genersoft/iot/vmp/media/event/media/MediaRtpServerTimeoutEvent.java | 22 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaListManager.java | 17 src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java | 35 src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java | 5 src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java | 35 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java | 6 src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java | 2 src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java | 4 src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java | 5 src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java | 370 ++ src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java | 12 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java | 13 src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java | 17 src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java | 49 src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java | 98 web_src/src/components/MediaServerManger.vue | 10 src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java | 10 src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerStartEvent.java | 24 src/main/java/com/genersoft/iot/vmp/service/IMediaService.java | 37 src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java | 61 src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java | 5 src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java | 17 src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java | 20 src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaSendRtpStoppedEvent.java | 52 src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java | 10 src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java | 39 /dev/null | 756 ----- src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java | 38 src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/BroadcastNotifyMessageHandler.java | 31 src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerDeleteEvent.java | 11 src/main/java/com/genersoft/iot/vmp/media/event/media/MediaArrivalEvent.java | 46 src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java | 271 +- 110 files changed, 4,940 insertions(+), 2,786 deletions(-) diff --git a/pom.xml b/pom.xml index f38d693..e129b78 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ <groupId>com.genersoft</groupId> <artifactId>wvp-pro</artifactId> - <version>2.7.0</version> + <version>2.7.1</version> <name>web video platform</name> <description>鍥芥爣28181瑙嗛骞冲彴</description> <packaging>${project.packaging}</packaging> 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 979f54a..f477439 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/common/StreamInfo.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.common; +import com.genersoft.iot.vmp.media.bean.MediaInfo; import com.genersoft.iot.vmp.service.bean.DownloadFileInfo; import io.swagger.v3.oas.annotations.media.Schema; @@ -70,7 +71,7 @@ @Schema(description = "娴佸獟浣揑D") private String mediaServerId; @Schema(description = "娴佺紪鐮佷俊鎭�") - private Object tracks; + private MediaInfo mediaInfo; @Schema(description = "寮�濮嬫椂闂�") private String startTime; @Schema(description = "缁撴潫鏃堕棿") @@ -82,6 +83,9 @@ @Schema(description = "鏄惁鏆傚仠锛堝綍鍍忓洖鏀句娇鐢級") private boolean pause; + + @Schema(description = "浜х敓婧愮被鍨嬶紝鍖呮嫭 unknown = 0,rtmp_push=1,rtsp_push=2,rtp_push=3,pull=4,ffmpeg_pull=5,mp4_vod=6,device_chn=7") + private int originType; public void setFlv(StreamURL flv) { this.flv = flv; @@ -191,14 +195,22 @@ } } - public void setFlv(String host, int port, int sslPort, String app, String stream, String callIdParam) { - String file = String.format("%s/%s.live.flv%s", app, stream, callIdParam); + public void setFlv(String host, int port, int sslPort, String file) { if (port > 0) { this.flv = new StreamURL("http", host, port, file); } this.ws_flv = new StreamURL("ws", host, port, file); if (sslPort > 0) { this.https_flv = new StreamURL("https", host, sslPort, file); + this.wss_flv = new StreamURL("wss", host, sslPort, file); + } + } + + public void setWsFlv(String host, int port, int sslPort, String file) { + if (port > 0) { + this.ws_flv = new StreamURL("ws", host, port, file); + } + if (sslPort > 0) { this.wss_flv = new StreamURL("wss", host, sslPort, file); } } @@ -473,12 +485,12 @@ this.mediaServerId = mediaServerId; } - public Object getTracks() { - return tracks; + public MediaInfo getMediaInfo() { + return mediaInfo; } - public void setTracks(Object tracks) { - this.tracks = tracks; + public void setMediaInfo(MediaInfo mediaInfo) { + this.mediaInfo = mediaInfo; } public String getStartTime() { @@ -615,4 +627,12 @@ public void setDownLoadFilePath(DownloadFileInfo downLoadFilePath) { this.downLoadFilePath = downLoadFilePath; } + + public int getOriginType() { + return originType; + } + + public void setOriginType(int originType) { + this.originType = originType; + } } 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 d19b8f0..df230d4 100644 --- a/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java +++ b/src/main/java/com/genersoft/iot/vmp/common/VideoManagerConstants.java @@ -12,9 +12,9 @@ public static final String WVP_SERVER_STREAM_PREFIX = "VMP_SIGNALLING_STREAM_"; - 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_SERVERS_ONLINE_PREFIX = "VMP_MEDIA_ONLINE_SERVERS_"; + public static final String ONLINE_MEDIA_SERVERS_PREFIX = "VMP_ONLINE_MEDIA_SERVERS:"; public static final String DEVICE_PREFIX = "VMP_DEVICE_"; diff --git a/src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java b/src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java index f98977f..de87a9c 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/CloudRecordTimer.java @@ -1,14 +1,10 @@ package com.genersoft.iot.vmp.conf; -import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.bean.CloudRecordItem; import com.genersoft.iot.vmp.storager.dao.CloudRecordServiceMapper; -import com.genersoft.iot.vmp.vmanager.cloudRecord.CloudRecordController; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -16,7 +12,6 @@ import org.springframework.stereotype.Component; import java.io.File; -import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; @@ -35,9 +30,6 @@ @Autowired private CloudRecordServiceMapper cloudRecordServiceMapper; - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; - /** * 瀹氭椂鏌ヨ寰呭垹闄ょ殑褰曞儚鏂囦欢 */ @@ -46,12 +38,12 @@ public void execute(){ logger.info("[褰曞儚鏂囦欢瀹氭椂娓呯悊] 寮�濮嬫竻鐞嗚繃鏈熷綍鍍忔枃浠�"); // 鑾峰彇閰嶇疆浜哸ssist鐨勬祦濯掍綋鑺傜偣 - List<MediaServerItem> mediaServerItemList = mediaServerService.getAllOnline(); + List<MediaServer> mediaServerItemList = mediaServerService.getAllOnline(); if (mediaServerItemList.isEmpty()) { return; } long result = 0; - for (MediaServerItem mediaServerItem : mediaServerItemList) { + for (MediaServer mediaServerItem : mediaServerItemList) { Calendar lastCalendar = Calendar.getInstance(); if (mediaServerItem.getRecordDay() > 0) { @@ -69,10 +61,10 @@ // TODO 鍚庣画鍙互鍒犻櫎绌轰簡鐨勮繃鏈熸棩鏈熸枃浠跺す for (CloudRecordItem cloudRecordItem : cloudRecordItemList) { String date = new File(cloudRecordItem.getFilePath()).getParentFile().getName(); - JSONObject jsonObject = zlmresTfulUtils.deleteRecordDirectory(mediaServerItem, cloudRecordItem.getApp(), + boolean deleteResult = mediaServerService.deleteRecordDirectory(mediaServerItem, cloudRecordItem.getApp(), cloudRecordItem.getStream(), date, cloudRecordItem.getFileName()); - if (jsonObject.getInteger("code") != 0) { - logger.warn("[褰曞儚鏂囦欢瀹氭椂娓呯悊] 鍒犻櫎纾佺洏鏂囦欢閿欒锛� {}:{}", cloudRecordItem.getFilePath(), jsonObject); + if (deleteResult) { + logger.warn("[褰曞儚鏂囦欢瀹氭椂娓呯悊] 鍒犻櫎纾佺洏鏂囦欢鎴愬姛锛� {}", cloudRecordItem.getFilePath()); } } result += cloudRecordServiceMapper.deleteList(cloudRecordItemList); 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 884036a..eac7c11 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/MediaConfig.java @@ -1,6 +1,6 @@ package com.genersoft.iot.vmp.conf; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.utils.DateUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -42,11 +42,23 @@ @Value("${media.stream-ip:${media.ip}}") private String streamIp; - @Value("${media.http-port}") + @Value("${media.http-port:0}") private Integer httpPort; + + @Value("${media.flv-port:0}") + private Integer flvPort = 0; + + @Value("${media.ws-flv-port:0}") + private Integer wsFlvPort = 0; @Value("${media.http-ssl-port:0}") private Integer httpSSlPort = 0; + + @Value("${media.flv-ssl-port:0}") + private Integer flvSSlPort = 0; + + @Value("${media.ws-flv-ssl-port:0}") + private Integer wsFlvSSlPort = 0; @Value("${media.rtmp-port:0}") private Integer rtmpPort = 0; @@ -86,6 +98,9 @@ @Value("${media.record-path:}") private String recordPath; + + @Value("${media.type:zlm}") + private String type; public String getId() { return id; @@ -196,36 +211,59 @@ return sipDomain; } - public MediaServerItem getMediaSerItem(){ - MediaServerItem mediaServerItem = new MediaServerItem(); - mediaServerItem.setId(id); - mediaServerItem.setIp(ip); - mediaServerItem.setDefaultServer(true); - mediaServerItem.setHookIp(getHookIp()); - mediaServerItem.setSdpIp(getSdpIp()); - mediaServerItem.setStreamIp(getStreamIp()); - mediaServerItem.setHttpPort(httpPort); - mediaServerItem.setHttpSSlPort(httpSSlPort); - mediaServerItem.setRtmpPort(rtmpPort); - mediaServerItem.setRtmpSSlPort(rtmpSSlPort); - mediaServerItem.setRtpProxyPort(getRtpProxyPort()); - mediaServerItem.setRtspPort(rtspPort); - mediaServerItem.setRtspSSLPort(rtspSSLPort); - mediaServerItem.setAutoConfig(autoConfig); - mediaServerItem.setSecret(secret); - mediaServerItem.setRtpEnable(rtpEnable); - mediaServerItem.setRtpPortRange(rtpPortRange); - mediaServerItem.setSendRtpPortRange(rtpSendPortRange); - mediaServerItem.setRecordAssistPort(recordAssistPort); - mediaServerItem.setHookAliveInterval(30.00f); - mediaServerItem.setRecordDay(recordDay); - if (recordPath != null) { - mediaServerItem.setRecordPath(recordPath); + public MediaServer getMediaSerItem(){ + MediaServer mediaServer = new MediaServer(); + mediaServer.setId(id); + mediaServer.setIp(ip); + mediaServer.setDefaultServer(true); + mediaServer.setHookIp(getHookIp()); + mediaServer.setSdpIp(getSdpIp()); + mediaServer.setStreamIp(getStreamIp()); + mediaServer.setHttpPort(httpPort); + if (flvPort == 0) { + mediaServer.setFlvPort(httpPort); + }else { + mediaServer.setFlvPort(flvPort); } - mediaServerItem.setCreateTime(DateUtil.getNow()); - mediaServerItem.setUpdateTime(DateUtil.getNow()); + if (wsFlvPort == 0) { + mediaServer.setWsFlvPort(httpPort); + }else { + mediaServer.setWsFlvPort(wsFlvPort); + } + if (flvSSlPort == 0) { + mediaServer.setFlvSSLPort(httpSSlPort); + }else { + mediaServer.setFlvSSLPort(flvSSlPort); + } + if (wsFlvSSlPort == 0) { + mediaServer.setWsFlvSSLPort(httpSSlPort); + }else { + mediaServer.setWsFlvSSLPort(wsFlvSSlPort); + } - return mediaServerItem; + mediaServer.setHttpSSlPort(httpSSlPort); + mediaServer.setRtmpPort(rtmpPort); + mediaServer.setRtmpSSlPort(rtmpSSlPort); + mediaServer.setRtpProxyPort(getRtpProxyPort()); + mediaServer.setRtspPort(rtspPort); + mediaServer.setRtspSSLPort(rtspSSLPort); + mediaServer.setAutoConfig(autoConfig); + mediaServer.setSecret(secret); + mediaServer.setRtpEnable(rtpEnable); + mediaServer.setRtpPortRange(rtpPortRange); + mediaServer.setSendRtpPortRange(rtpSendPortRange); + mediaServer.setRecordAssistPort(recordAssistPort); + mediaServer.setHookAliveInterval(10f); + mediaServer.setRecordDay(recordDay); + mediaServer.setStatus(false); + mediaServer.setType(type); + if (recordPath != null) { + mediaServer.setRecordPath(recordPath); + } + mediaServer.setCreateTime(DateUtil.getNow()); + mediaServer.setUpdateTime(DateUtil.getNow()); + + return mediaServer; } public Integer getRecordDay() { 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 a7416a8..3948fdb 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/ProxyServletConfig.java @@ -1,7 +1,7 @@ package com.genersoft.iot.vmp.conf; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; import org.apache.http.HttpResponse; @@ -54,7 +54,7 @@ @Override protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) { String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString); - MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); + MediaServer mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); if (mediaInfo != null) { if (!ObjectUtils.isEmpty(queryStr)) { queryStr += "&secret=" + mediaInfo.getSecret(); @@ -103,7 +103,7 @@ @Override protected String getTargetUri(HttpServletRequest servletRequest) { String requestURI = servletRequest.getRequestURI(); - MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + MediaServer mediaInfo = getMediaInfoByUri(requestURI); String uri = null; if (mediaInfo != null) { @@ -121,7 +121,7 @@ @Override protected HttpHost getTargetHost(HttpServletRequest servletRequest) { String requestURI = servletRequest.getRequestURI(); - MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + MediaServer mediaInfo = getMediaInfoByUri(requestURI); HttpHost host; if (mediaInfo != null) { host = new HttpHost(mediaInfo.getIp(), mediaInfo.getHttpPort()); @@ -135,7 +135,7 @@ /** * 鏍规嵁uri鑾峰彇娴佸獟浣撲俊鎭� */ - MediaServerItem getMediaInfoByUri(String uri){ + MediaServer getMediaInfoByUri(String uri){ String[] split = uri.split("/"); String mediaServerId = split[2]; if ("default".equalsIgnoreCase(mediaServerId)) { @@ -151,7 +151,7 @@ @Override protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) { String requestURI = servletRequest.getRequestURI(); - MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + MediaServer mediaInfo = getMediaInfoByUri(requestURI); String url = super.rewriteUrlFromRequest(servletRequest); if (mediaInfo == null) { logger.error("[ZLM鏈嶅姟璁块棶浠g悊]锛岄敊璇細澶勭悊url淇℃伅鏃舵湭鎵惧埌娴佸獟浣撲俊鎭�=>{}", requestURI); @@ -181,7 +181,7 @@ @Override protected String rewriteQueryStringFromRequest(HttpServletRequest servletRequest, String queryString) { String queryStr = super.rewriteQueryStringFromRequest(servletRequest, queryString); - MediaServerItem mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); + MediaServer mediaInfo = getMediaInfoByUri(servletRequest.getRequestURI()); if (mediaInfo == null) { return null; } @@ -238,7 +238,7 @@ @Override protected String getTargetUri(HttpServletRequest servletRequest) { String requestURI = servletRequest.getRequestURI(); - MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + MediaServer mediaInfo = getMediaInfoByUri(requestURI); String uri = null; if (mediaInfo != null) { @@ -256,7 +256,7 @@ @Override protected HttpHost getTargetHost(HttpServletRequest servletRequest) { String requestURI = servletRequest.getRequestURI(); - MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + MediaServer mediaInfo = getMediaInfoByUri(requestURI); HttpHost host; if (mediaInfo != null) { host = new HttpHost(mediaInfo.getIp(), mediaInfo.getRecordAssistPort()); @@ -270,7 +270,7 @@ /** * 鏍规嵁uri鑾峰彇娴佸獟浣撲俊鎭� */ - MediaServerItem getMediaInfoByUri(String uri){ + MediaServer getMediaInfoByUri(String uri){ String[] split = uri.split("/"); String mediaServerId = split[2]; if ("default".equalsIgnoreCase(mediaServerId)) { @@ -287,7 +287,7 @@ @Override protected String rewriteUrlFromRequest(HttpServletRequest servletRequest) { String requestURI = servletRequest.getRequestURI(); - MediaServerItem mediaInfo = getMediaInfoByUri(requestURI); + MediaServer mediaInfo = getMediaInfoByUri(requestURI); String url = super.rewriteUrlFromRequest(servletRequest); if (mediaInfo == null) { logger.error("[褰曞儚鏈嶅姟璁块棶浠g悊]锛岄敊璇細澶勭悊url淇℃伅鏃舵湭鎵惧埌娴佸獟浣撲俊鎭�=>{}", requestURI); diff --git a/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java b/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java index 77d83ee..c586255 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/WVPTimerTask.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.conf; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -13,9 +12,6 @@ @Autowired private IRedisCatchStorage redisCatchStorage; - - @Autowired - private IMediaServerService mediaServerService; @Value("${server.port}") private int serverPort; diff --git a/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java b/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java index ad959d6..b035fcb 100644 --- a/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/conf/security/WebSecurityConfig.java @@ -117,7 +117,7 @@ .authorizeRequests() .requestMatchers(CorsUtils::isPreFlightRequest).permitAll() .antMatchers(userSetting.getInterfaceAuthenticationExcludes().toArray(new String[0])).permitAll() - .antMatchers("/api/user/login", "/index/hook/**", "/swagger-ui/**", "/doc.html").permitAll() + .antMatchers("/api/user/login", "/index/hook/**","/index/hook/abl/**", "/swagger-ui/**", "/doc.html").permitAll() .anyRequest().authenticated() // 寮傚父澶勭悊鍣� .and() diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java index 814d984..2b5e16b 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/AudioBroadcastCatch.java @@ -1,7 +1,7 @@ package com.genersoft.iot.vmp.gb28181.bean; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.vmanager.gb28181.play.bean.AudioBroadcastEvent; import gov.nist.javax.sip.message.SIPResponse; @@ -15,7 +15,7 @@ public AudioBroadcastCatch( String deviceId, String channelId, - MediaServerItem mediaServerItem, + MediaServer mediaServerItem, String app, String stream, AudioBroadcastEvent event, @@ -48,7 +48,7 @@ /** * 娴佸獟浣撲俊鎭� */ - private MediaServerItem mediaServerItem; + private MediaServer mediaServerItem; /** * 鍏宠仈鐨勬祦APP @@ -109,11 +109,11 @@ return sipTransactionInfo; } - public MediaServerItem getMediaServerItem() { + public MediaServer getMediaServerItem() { return mediaServerItem; } - public void setMediaServerItem(MediaServerItem mediaServerItem) { + public void setMediaServerItem(MediaServer mediaServerItem) { this.mediaServerItem = mediaServerItem; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java index 134930b..e1925fa 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/bean/InviteStreamInfo.java @@ -1,11 +1,11 @@ package com.genersoft.iot.vmp.gb28181.bean; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; public class InviteStreamInfo { - public InviteStreamInfo(MediaServerItem mediaServerItem, JSONObject response, String callId, String app, String stream) { + public InviteStreamInfo(MediaServer mediaServerItem, JSONObject response, String callId, String app, String stream) { this.mediaServerItem = mediaServerItem; this.response = response; this.callId = callId; @@ -13,17 +13,17 @@ this.stream = stream; } - private MediaServerItem mediaServerItem; + private MediaServer mediaServerItem; private JSONObject response; private String callId; private String app; private String stream; - public MediaServerItem getMediaServerItem() { + public MediaServer getMediaServerItem() { return mediaServerItem; } - public void setMediaServerItem(MediaServerItem mediaServerItem) { + public void setMediaServerItem(MediaServer mediaServerItem) { this.mediaServerItem = mediaServerItem; } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java index c0b66fe..299d59a 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/event/EventPublisher.java @@ -1,17 +1,16 @@ package com.genersoft.iot.vmp.gb28181.event; import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; import com.genersoft.iot.vmp.gb28181.event.device.RequestTimeoutEvent; import com.genersoft.iot.vmp.gb28181.event.record.RecordEndEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.event.subscribe.mobilePosition.MobilePositionEvent; -import com.genersoft.iot.vmp.media.zlm.event.ZLMOfflineEvent; -import com.genersoft.iot.vmp.media.zlm.event.ZLMOnlineEvent; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOfflineEvent; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerOnlineEvent; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationEventPublisher; import org.springframework.stereotype.Component; - -import com.genersoft.iot.vmp.gb28181.event.alarm.AlarmEvent; import javax.sip.TimeoutEvent; import java.util.ArrayList; @@ -40,14 +39,14 @@ applicationEventPublisher.publishEvent(alarmEvent); } - public void zlmOfflineEventPublish(String mediaServerId){ - ZLMOfflineEvent outEvent = new ZLMOfflineEvent(this); + public void mediaServerOfflineEventPublish(String mediaServerId){ + MediaServerOfflineEvent outEvent = new MediaServerOfflineEvent(this); outEvent.setMediaServerId(mediaServerId); applicationEventPublisher.publishEvent(outEvent); } - public void zlmOnlineEventPublish(String mediaServerId) { - ZLMOnlineEvent outEvent = new ZLMOnlineEvent(this); + public void mediaServerOnlineEventPublish(String mediaServerId) { + MediaServerOnlineEvent outEvent = new MediaServerOnlineEvent(this); outEvent.setMediaServerId(mediaServerId); applicationEventPublisher.publishEvent(outEvent); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java b/src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java index 343d2a6..24eadba 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/session/AudioBroadcastManager.java @@ -3,6 +3,8 @@ import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatch; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @@ -18,11 +20,14 @@ @Component public class AudioBroadcastManager { + private final static Logger logger = LoggerFactory.getLogger(AudioBroadcastManager.class); + @Autowired private SipConfig config; public static Map<String, AudioBroadcastCatch> data = new ConcurrentHashMap<>(); + public void update(AudioBroadcastCatch audioBroadcastCatch) { if (SipUtils.isFrontEnd(audioBroadcastCatch.getDeviceId())) { audioBroadcastCatch.setChannelId(audioBroadcastCatch.getDeviceId()); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java index 5ca95a0..b61a623 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/task/SipRunner.java @@ -1,16 +1,14 @@ package com.genersoft.iot.vmp.gb28181.task; -import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.IDeviceService; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlatformService; import com.genersoft.iot.vmp.service.impl.PlatformServiceImpl; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -52,9 +50,6 @@ @Autowired private IDeviceService deviceService; - - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; @Autowired private IMediaServerService mediaServerService; @@ -105,17 +100,12 @@ List<SendRtpItem> sendRtpItems = redisCatchStorage.queryAllSendRTPServer(); if (sendRtpItems.size() > 0) { for (SendRtpItem sendRtpItem : sendRtpItems) { - MediaServerItem mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaServerItem = mediaServerService.getOne(sendRtpItem.getMediaServerId()); redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(),sendRtpItem.getChannelId(), sendRtpItem.getCallId(),sendRtpItem.getStream()); if (mediaServerItem != null) { ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); - Map<String, Object> param = new HashMap<>(); - param.put("vhost","__defaultVhost__"); - param.put("app",sendRtpItem.getApp()); - param.put("stream",sendRtpItem.getStream()); - param.put("ssrc",sendRtpItem.getSsrc()); - JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaServerItem, param); - if (jsonObject != null && jsonObject.getInteger("code") == 0) { + boolean stopResult = mediaServerService.stopSendRtp(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc()); + if (stopResult) { ParentPlatform platform = platformService.queryPlatformByServerGBId(sendRtpItem.getPlatformId()); if (platform != null) { try { 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 66589a8..fcafbf7 100755 --- 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 @@ -7,8 +7,8 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.bean.SSRCInfo; import gov.nist.javax.sip.message.SIPRequest; @@ -100,7 +100,7 @@ * @param device 瑙嗛璁惧 * @param channel 棰勮閫氶亾 */ - void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + void playStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, HookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; /** * 璇锋眰鍥炴斁瑙嗛娴� @@ -110,7 +110,7 @@ * @param startTime 寮�濮嬫椂闂�,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss */ - void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime,ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + void playbackStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInf, Device device, String channelId, String startTime, String endTime, HookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; /** * 璇锋眰鍘嗗彶濯掍綋涓嬭浇 @@ -121,9 +121,9 @@ * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss * @param downloadSpeed 涓嬭浇鍊嶉�熷弬鏁� */ - void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, - String startTime, String endTime, int downloadSpeed, ZlmHttpHookSubscribe.Event hookEvent, - SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; + void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, + String startTime, String endTime, int downloadSpeed, HookSubscribe.Event hookEvent, + SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; /** @@ -131,7 +131,7 @@ */ void streamByeCmd(Device device, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; - void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; + void talkStreamCmd(MediaServer mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, HookSubscribe.Event event, HookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException; void streamByeCmd(Device device, String channelId, String stream, String callId) throws InvalidArgumentException, ParseException, SipException, SsrcTransactionNotFoundException; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java index a412a6c..bc999f0 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/ISIPCommanderForPlatform.java @@ -3,8 +3,8 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo; @@ -154,8 +154,8 @@ void streamByeCmd(ParentPlatform platform, String channelId, String stream, String callId, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException, SsrcTransactionNotFoundException; - void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, - SSRCInfo ssrcInfo, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, + void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServer mediaServerItem, + SSRCInfo ssrcInfo, HookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws ParseException, SipException, InvalidArgumentException; void broadcastResultCmd(ParentPlatform platform, DeviceChannel deviceChannel, String sn, boolean result, SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException; 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 3a5f812..dab039f 100755 --- 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 @@ -7,10 +7,6 @@ import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.gb28181.SipLayer; import com.genersoft.iot.vmp.gb28181.bean.*; -import com.genersoft.iot.vmp.gb28181.bean.Device; -import com.genersoft.iot.vmp.gb28181.bean.DeviceAlarm; -import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.gb28181.bean.SsrcTransaction; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.SIPSender; @@ -18,14 +14,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderProvider; import com.genersoft.iot.vmp.gb28181.utils.NumericUtil; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.event.hook.HookType; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamPush; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.utils.DateUtil; import gov.nist.javax.sip.message.SIPRequest; @@ -44,7 +38,6 @@ import javax.sip.header.CallIdHeader; import javax.sip.message.Request; import java.text.ParseException; -import java.util.ArrayList; import java.util.List; /** @@ -77,7 +70,7 @@ private UserSetting userSetting; @Autowired - private ZlmHttpHookSubscribe subscribe; + private HookSubscribe subscribe; @Autowired private IMediaServerService mediaServerService; @@ -275,8 +268,8 @@ * @param errorEvent sip閿欒璁㈤槄 */ @Override - public void playStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, - ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { + public void playStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, + HookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { String stream = ssrcInfo.getStream(); if (device == null) { @@ -284,11 +277,11 @@ } logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> { + Hook rtpHook = Hook.getInstance(HookType.on_media_arrival, "rtp", stream, mediaServerItem.getId()); + subscribe.addSubscribe(rtpHook, (hookData) -> { if (event != null) { - event.response(mediaServerItemInUse, hookParam); - subscribe.removeSubscribe(hookSubscribe); + event.response(hookData); + subscribe.removeSubscribe(rtpHook); } }); String sdpIp; @@ -384,8 +377,8 @@ * @param endTime 缁撴潫鏃堕棿,鏍煎紡瑕佹眰锛歽yyy-MM-dd HH:mm:ss */ @Override - public void playbackStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, - String startTime, String endTime, ZlmHttpHookSubscribe.Event hookEvent, + public void playbackStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, + String startTime, String endTime, HookSubscribe.Event hookEvent, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { @@ -458,13 +451,13 @@ //ssrc content.append("y=" + ssrcInfo.getSsrc() + "\r\n"); - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); + Hook rtpHook = Hook.getInstance(HookType.on_media_arrival, "rtp", ssrcInfo.getStream(), mediaServerItem.getId()); // 娣诲姞璁㈤槄 - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> { + subscribe.addSubscribe(rtpHook, (hookData) -> { if (hookEvent != null) { - hookEvent.response(mediaServerItemInUse, hookParam); + hookEvent.response(hookData); } - subscribe.removeSubscribe(hookSubscribe); + subscribe.removeSubscribe(rtpHook); }); Request request = headerProvider.createPlaybackInviteRequest(device, channelId, content.toString(), SipUtils.getNewViaTag(), SipUtils.getNewFromTag(), null,sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()),device.getTransport()), ssrcInfo.getSsrc()); @@ -486,10 +479,10 @@ * @param downloadSpeed 涓嬭浇鍊嶉�熷弬鏁� */ @Override - public void downloadStreamCmd(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, + public void downloadStreamCmd(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, String channelId, String startTime, String endTime, int downloadSpeed, - ZlmHttpHookSubscribe.Event hookEvent, - SipSubscribe.Event errorEvent,SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { + HookSubscribe.Event hookEvent, + SipSubscribe.Event errorEvent, SipSubscribe.Event okEvent) throws InvalidArgumentException, SipException, ParseException { logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", ssrcInfo.getStream(), mediaServerItem.getId(), mediaServerItem.getSdpIp(), ssrcInfo.getPort()); String sdpIp; @@ -559,19 +552,18 @@ content.append("y=" + ssrcInfo.getSsrc() + "\r\n");//ssrc logger.debug("姝ゆ椂璇锋眰涓嬭浇淇′护鐨剆src===>{}",ssrcInfo.getSsrc()); - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); + Hook rtpHook = Hook.getInstance(HookType.on_media_arrival, "rtp", ssrcInfo.getStream(), mediaServerItem.getId()); // 娣诲姞璁㈤槄 CallIdHeader newCallIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport()); String callId= newCallIdHeader.getCallId(); - subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam) -> { + subscribe.addSubscribe(rtpHook, (hookData) -> { logger.debug("sipc 娣诲姞璁㈤槄===callId {}",callId); - hookEvent.response(mediaServerItemInUse, hookParam); - subscribe.removeSubscribe(hookSubscribe); - hookSubscribe.getContent().put("regist", false); - hookSubscribe.getContent().put("schema", "rtsp"); + hookEvent.response(hookData); + subscribe.removeSubscribe(rtpHook); // 娣诲姞娴佹敞閿�鐨勮闃咃紝娉ㄩ攢浜嗗悗鍚戣澶囧彂閫乥ye - subscribe.addSubscribe(hookSubscribe, - (mediaServerItemForEnd, hookParam1) -> { + Hook departureHook = Hook.getInstance(HookType.on_media_departure, "rtp", ssrcInfo.getStream(), mediaServerItem.getId()); + subscribe.addSubscribe(departureHook, + (departureHookData) -> { logger.info("[褰曞儚]涓嬭浇缁撴潫锛� 鍙戦�丅YE"); try { streamByeCmd(device, channelId, ssrcInfo.getStream(), callId); @@ -595,7 +587,7 @@ } @Override - public void talkStreamCmd(MediaServerItem mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, ZlmHttpHookSubscribe.Event event, ZlmHttpHookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { + public void talkStreamCmd(MediaServer mediaServerItem, SendRtpItem sendRtpItem, Device device, String channelId, String callId, HookSubscribe.Event event, HookSubscribe.Event eventForPush, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws InvalidArgumentException, SipException, ParseException { String stream = sendRtpItem.getStream(); @@ -609,20 +601,20 @@ } logger.info("[璇煶鍠婅瘽] {} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), sendRtpItem.getPort()); - HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); - subscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItemInUse, hookParam) -> { + Hook hook = Hook.getInstance(HookType.on_media_arrival, "rtp", stream, mediaServerItem.getId()); + subscribe.addSubscribe(hook, (hookData) -> { if (event != null) { - event.response(mediaServerItemInUse, hookParam); - subscribe.removeSubscribe(hookSubscribeForStreamChange); + event.response(hookData); + subscribe.removeSubscribe(hook); } }); CallIdHeader callIdHeader = sipSender.getNewCallIdHeader(sipLayer.getLocalIp(device.getLocalIp()), device.getTransport()); callIdHeader.setCallId(callId); - HookSubscribeForStreamPush hookSubscribeForStreamPush = HookSubscribeFactory.on_publish("rtp", stream, null, mediaServerItem.getId()); - subscribe.addSubscribe(hookSubscribeForStreamPush, (mediaServerItemInUse, hookParam) -> { + Hook publishHook = Hook.getInstance(HookType.on_publish, "rtp", stream, mediaServerItem.getId()); + subscribe.addSubscribe(publishHook, (hookData) -> { if (eventForPush != null) { - eventForPush.response(mediaServerItemInUse, hookParam); + eventForPush.response(hookData); } }); // @@ -1265,7 +1257,6 @@ * @param startPriority 鎶ヨ璧峰绾у埆锛堝彲閫夛級 * @param endPriority 鎶ヨ缁堟绾у埆锛堝彲閫夛級 * @param alarmMethod 鎶ヨ鏂瑰紡鏉′欢锛堝彲閫夛級 - * @param alarmType 鎶ヨ绫诲瀷 * @param startTime 鎶ヨ鍙戠敓璧峰鏃堕棿锛堝彲閫夛級 * @param endTime 鎶ヨ鍙戠敓缁堟鏃堕棿锛堝彲閫夛級 * @return true = 鍛戒护鍙戦�佹垚鍔� diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java index 2964654..51f5c67 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/cmd/impl/SIPCommanderFroPlatform.java @@ -13,13 +13,12 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.SIPRequestHeaderPlarformProvider; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.event.hook.HookType; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -76,7 +75,7 @@ private SIPSender sipSender; @Autowired - private ZlmHttpHookSubscribe subscribe; + private HookSubscribe subscribe; @Autowired private UserSetting userSetting; @@ -844,7 +843,7 @@ } logger.info("[鍚戜笂绾у彂閫丅YE]锛� {}/{}", platform.getServerGBId(), sendRtpItem.getChannelId()); String mediaServerId = sendRtpItem.getMediaServerId(); - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem != null) { mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); zlmServerFactory.closeRtpServer(mediaServerItem, sendRtpItem.getStream()); @@ -895,8 +894,8 @@ } @Override - public void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, - SSRCInfo ssrcInfo, ZlmHttpHookSubscribe.Event event, SipSubscribe.Event okEvent, + public void broadcastInviteCmd(ParentPlatform platform, String channelId, MediaServer mediaServerItem, + SSRCInfo ssrcInfo, HookSubscribe.Event event, SipSubscribe.Event okEvent, SipSubscribe.Event errorEvent) throws ParseException, SipException, InvalidArgumentException { String stream = ssrcInfo.getStream(); @@ -905,11 +904,11 @@ } logger.info("{} 鍒嗛厤鐨刏LM涓�: {} [{}:{}]", stream, mediaServerItem.getId(), mediaServerItem.getIp(), ssrcInfo.getPort()); - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", stream, true, "rtsp", mediaServerItem.getId()); - subscribe.addSubscribe(hookSubscribe, (MediaServerItem mediaServerItemInUse, HookParam hookParam) -> { + Hook hook = Hook.getInstance(HookType.on_media_arrival, "rtp", stream, mediaServerItem.getId()); + subscribe.addSubscribe(hook, (hookData) -> { if (event != null) { - event.response(mediaServerItemInUse, hookParam); - subscribe.removeSubscribe(hookSubscribe); + event.response(hookData); + subscribe.removeSubscribe(hook); } }); String sdpIp = mediaServerItem.getSdpIp(); @@ -949,7 +948,7 @@ sipSender.transmitRequest(sipLayer.getLocalIp(platform.getDeviceIp()), request, (e -> { streamSession.remove(platform.getServerGBId(), channelId, ssrcInfo.getStream()); mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcInfo.getSsrc()); - subscribe.removeSubscribe(hookSubscribe); + subscribe.removeSubscribe(hook); errorEvent.response(e); }), e -> { ResponseEvent responseEvent = (ResponseEvent) e.event; diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java index 242e5ef..5410d67 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/AckRequestProcessor.java @@ -3,6 +3,9 @@ import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.conf.exception.ControllerException; +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; +import com.genersoft.iot.vmp.gb28181.bean.AudioBroadcastCatch; import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; @@ -10,10 +13,10 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.IDeviceService; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.bean.RequestPushStreamMsg; import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; @@ -25,12 +28,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import javax.sip.InvalidArgumentException; import javax.sip.RequestEvent; +import javax.sip.SipException; import javax.sip.address.SipURI; import javax.sip.header.CallIdHeader; import javax.sip.header.FromHeader; import javax.sip.header.HeaderAddress; import javax.sip.header.ToHeader; +import java.text.ParseException; import java.util.HashMap; import java.util.Map; @@ -69,7 +75,7 @@ private ZLMServerFactory zlmServerFactory; @Autowired - private ZlmHttpHookSubscribe hookSubscribe; + private HookSubscribe hookSubscribe; @Autowired private IMediaServerService mediaServerService; @@ -104,7 +110,7 @@ logger.info("鏀跺埌ACK锛宺tp/{} TCP涓诲姩鏂瑰紡鍚庣画澶勭悊", sendRtpItem.getStream()); return; } - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); logger.info("鏀跺埌ACK锛宺tp/{}寮�濮嬪悜涓婄骇鎺ㄦ祦, 鐩爣={}:{}锛孲SRC={}, 鍗忚:{}", sendRtpItem.getStream(), sendRtpItem.getIp(), @@ -115,19 +121,24 @@ ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(fromUserId); if (parentPlatform != null) { - Map<String, Object> param = getSendRtpParam(sendRtpItem); if (!userSetting.getServerId().equals(sendRtpItem.getServerId())) { RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( sendRtpItem.getMediaServerId(), sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { - playService.startSendRtpStreamHand(sendRtpItem, parentPlatform, json, param, callIdHeader); + playService.startSendRtpStreamFailHand(sendRtpItem, parentPlatform, callIdHeader); }); } else { - JSONObject startSendRtpStreamResult = sendRtp(sendRtpItem, mediaInfo, param); - if (startSendRtpStreamResult != null) { - playService.startSendRtpStreamHand(sendRtpItem, parentPlatform, startSendRtpStreamResult, param, callIdHeader); + try { + if (sendRtpItem.isTcpActive()) { + mediaServerService.startSendRtpPassive(mediaInfo, parentPlatform, sendRtpItem, null); + } else { + mediaServerService.startSendRtpStream(mediaInfo, parentPlatform, sendRtpItem); + } + }catch (ControllerException e) { + logger.error("RTP鎺ㄦ祦澶辫触: {}", e.getMessage()); + playService.startSendRtpStreamFailHand(sendRtpItem, parentPlatform, callIdHeader); } } }else { @@ -144,56 +155,17 @@ logger.warn("[鏀跺埌ACK]锛氭潵鑷獅}锛岀洰鏍囦负({})鐨勬帹娴佷俊鎭负鎵惧埌娴佷綋鏈嶅姟[{}]淇℃伅",fromUserId, toUserId, sendRtpItem.getMediaServerId()); return; } - Map<String, Object> param = getSendRtpParam(sendRtpItem); - JSONObject startSendRtpStreamResult = sendRtp(sendRtpItem, mediaInfo, param); - if (startSendRtpStreamResult != null) { - playService.startSendRtpStreamHand(sendRtpItem, device, startSendRtpStreamResult, param, callIdHeader); + try { + if (sendRtpItem.isTcpActive()) { + mediaServerService.startSendRtpPassive(mediaInfo, null, sendRtpItem, null); + } else { + mediaServerService.startSendRtpStream(mediaInfo, null, sendRtpItem); + } + }catch (ControllerException e) { + logger.error("RTP鎺ㄦ祦澶辫触: {}", e.getMessage()); + playService.startSendRtpStreamFailHand(sendRtpItem, null, callIdHeader); } } - } - - private Map<String, Object> getSendRtpParam(SendRtpItem sendRtpItem) { - String isUdp = sendRtpItem.isTcp() ? "0" : "1"; - Map<String, Object> param = new HashMap<>(12); - param.put("vhost","__defaultVhost__"); - param.put("app",sendRtpItem.getApp()); - param.put("stream",sendRtpItem.getStream()); - param.put("ssrc", sendRtpItem.getSsrc()); - param.put("dst_url",sendRtpItem.getIp()); - param.put("dst_port", sendRtpItem.getPort()); - param.put("src_port", sendRtpItem.getLocalPort()); - param.put("pt", sendRtpItem.getPt()); - param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); - param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); - param.put("is_udp", isUdp); - if (!sendRtpItem.isTcp()) { - // udp妯″紡涓嬪紑鍚痳tcp淇濇椿 - param.put("udp_rtcp_timeout", sendRtpItem.isRtcp()? "1":"0"); - } - return param; - } - - private JSONObject sendRtp(SendRtpItem sendRtpItem, MediaServerItem mediaInfo, Map<String, Object> param){ - JSONObject startSendRtpStreamResult = null; - if (sendRtpItem.getLocalPort() != 0) { - if (sendRtpItem.isTcpActive()) { - startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); - }else { - param.put("dst_url", sendRtpItem.getIp()); - param.put("dst_port", sendRtpItem.getPort()); - startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); - } - }else { - if (sendRtpItem.isTcpActive()) { - startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); - }else { - param.put("dst_url", sendRtpItem.getIp()); - param.put("dst_port", sendRtpItem.getPort()); - startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); - } - } - return startSendRtpStreamResult; - } } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java index ff7427b..b2d14a0 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/ByeRequestProcessor.java @@ -13,8 +13,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; @@ -145,7 +146,7 @@ redisGbPlayMsgListener.sendMsgForStopSendRtpStream(sendRtpItem.getServerId(), streamMsg); } }else { - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), callIdHeader.getCallId(), null); zlmServerFactory.stopSendRtpStream(mediaInfo, param); @@ -165,7 +166,7 @@ } } }else { - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), callIdHeader.getCallId(), null); zlmServerFactory.stopSendRtpStream(mediaInfo, param); @@ -173,7 +174,7 @@ mediaServerService.releaseSsrc(mediaInfo.getId(), sendRtpItem.getSsrc()); } } - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); if (mediaInfo != null) { AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); if (audioBroadcastCatch != null && audioBroadcastCatch.getSipTransactionInfo().getCallId().equals(callIdHeader.getCallId())) { @@ -245,7 +246,7 @@ } } // 閲婃斁ssrc - MediaServerItem mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId()); + MediaServer mediaServerItem = mediaServerService.getOne(ssrcTransaction.getMediaServerId()); if (mediaServerItem != null) { mediaServerService.releaseSsrc(mediaServerItem.getId(), ssrcTransaction.getSsrc()); } diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java index 96b8b11..b4d183e 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/InviteRequestProcessor.java @@ -18,12 +18,19 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.ISIPRequestProcessor; import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.event.hook.HookType; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.*; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; -import com.genersoft.iot.vmp.service.*; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; +import com.genersoft.iot.vmp.service.IInviteStreamService; +import com.genersoft.iot.vmp.service.IPlayService; +import com.genersoft.iot.vmp.service.IStreamProxyService; +import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.service.bean.InviteErrorCode; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; @@ -113,7 +120,7 @@ private IMediaServerService mediaServerService; @Autowired - private ZlmHttpHookSubscribe zlmHttpHookSubscribe; + private HookSubscribe hookSubscribe; @Autowired private SIPProcessorObserver sipProcessorObserver; @@ -192,7 +199,7 @@ GbStream gbStream = storager.queryStreamInParentPlatform(requesterId, channelId); PlatformCatalog catalog = storager.getCatalog(requesterId, channelId); - MediaServerItem mediaServerItem = null; + MediaServer mediaServerItem = null; StreamPushItem streamPushItem = null; StreamProxyItem proxyByAppAndStream = null; // 涓嶆槸閫氶亾鍙兘鏄洿鎾祦 @@ -398,7 +405,7 @@ Long finalStopTime = stopTime; ErrorCallback<Object> hookEvent = (code, msg, data) -> { StreamInfo streamInfo = (StreamInfo)data; - MediaServerItem mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId()); + MediaServer mediaServerItemInUSe = mediaServerService.getOne(streamInfo.getMediaServerId()); logger.info("[涓婄骇Invite]涓嬬骇宸茬粡寮�濮嬫帹娴併�� 鍥炲200OK(SDP)锛� {}/{}", streamInfo.getApp(), streamInfo.getStream()); // * 0 绛夊緟璁惧鎺ㄦ祦涓婃潵 // * 1 涓嬬骇宸茬粡鎺ㄦ祦锛岀瓑寰呬笂绾у钩鍙板洖澶峚ck @@ -455,7 +462,7 @@ responseSdpAck(request, content.toString(), platform); // tcp涓诲姩妯″紡锛屽洖澶峴dp鍚庡紑鍚洃鍚� if (sendRtpItem.isTcpActive()) { - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); Map<String, Object> param = new HashMap<>(12); param.put("vhost","__defaultVhost__"); param.put("app",sendRtpItem.getApp()); @@ -485,12 +492,11 @@ } }; ErrorCallback<Object> errorEvent = ((statusCode, msg, data) -> { + logger.info("[涓婄骇Invite] {}, 澶辫触, 骞冲彴锛歿}锛� 閫氶亾锛歿}, code锛� {}锛� msg锛泏}", sessionName, username, channelId, statusCode, msg); // 鏈煡閿欒銆傜洿鎺ヨ浆鍙戣澶囩偣鎾殑閿欒 try { - if (statusCode > 0) { - Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); - sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); - } + Response response = getMessageFactory().createResponse(statusCode, evt.getRequest()); + sipSender.transmitRequest(request.getLocalAddress().getHostAddress(), response); } catch (ParseException | SipException e) { logger.error("鏈鐞嗙殑寮傚父 ", e); } @@ -501,7 +507,7 @@ String startTimeStr = DateUtil.urlFormatter.format(start); String endTimeStr = DateUtil.urlFormatter.format(end); String stream = device.getDeviceId() + "_" + channelId + "_" + startTimeStr + "_" + endTimeStr; - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0,false, false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, stream, null, device.isSsrcCheck(), true, 0,false,!channel.isHasAudio(), false, device.getStreamModeForParam()); sendRtpItem.setStream(stream); // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� redisCatchStorage.updateSendRTPSever(sendRtpItem); @@ -531,7 +537,7 @@ } sendRtpItem.setPlayType(InviteStreamType.DOWNLOAD); - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,!channel.isHasAudio(), false, device.getStreamModeForParam()); sendRtpItem.setStream(ssrcInfo.getStream()); // 鍐欏叆redis锛� 瓒呮椂鏃跺洖澶� redisCatchStorage.updateSendRTPSever(sendRtpItem); @@ -581,12 +587,11 @@ if ("push".equals(gbStream.getStreamType())) { if (streamPushItem != null) { // 浠巖edis鏌ヨ鏄惁姝e湪鎺ユ敹杩欎釜鎺ㄦ祦 - OnStreamChangedHookParam pushListItem = redisCatchStorage.getPushListItem(gbStream.getApp(), gbStream.getStream()); + StreamPushItem pushListItem = redisCatchStorage.getPushListItem(gbStream.getApp(), gbStream.getStream()); if (pushListItem != null) { - StreamPushItem transform = streamPushService.transform(pushListItem); - transform.setSelf(userSetting.getServerId().equals(pushListItem.getSeverId())); + pushListItem.setSelf(userSetting.getServerId().equals(pushListItem.getServerId())); // 鎺ㄦ祦鐘舵�� - pushStream(evt, request, gbStream, transform, platform, callIdHeader, mediaServerItem, port, tcpActive, + pushStream(evt, request, gbStream, pushListItem, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); }else { // 鏈帹娴� 鎷夎捣 @@ -633,10 +638,10 @@ * 瀹夋帓鎺ㄦ祦 */ private void pushProxyStream(RequestEvent evt, SIPRequest request, GbStream gbStream, ParentPlatform platform, - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + CallIdHeader callIdHeader, MediaServer mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); + Boolean streamReady = mediaServerService.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); if (streamReady != null && streamReady) { // 鑷钩鍙板唴瀹� SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, @@ -671,12 +676,12 @@ } private void pushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + CallIdHeader callIdHeader, MediaServer mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { // 鎺ㄦ祦 if (streamPushItem.isSelf()) { - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); + Boolean streamReady = mediaServerService.isStreamReady(mediaServerItem, gbStream.getApp(), gbStream.getStream()); if (streamReady != null && streamReady) { // 鑷钩鍙板唴瀹� SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, addressStr, port, ssrc, requesterId, @@ -723,24 +728,23 @@ * 閫氱煡娴佷笂绾� */ private void notifyStreamOnline(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + CallIdHeader callIdHeader, MediaServer mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { if ("proxy".equals(gbStream.getStreamType())) { // TODO 鎺у埗鍚敤浠ヤ娇璁惧涓婄嚎 logger.info("[ app={}, stream={} ]閫氶亾鏈帹娴侊紝鍚敤娴佸悗寮�濮嬫帹娴�", gbStream.getApp(), gbStream.getStream()); // 鐩戝惉娴佷笂绾� - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(gbStream.getApp(), gbStream.getStream(), true, "rtsp", mediaServerItem.getId()); - zlmHttpHookSubscribe.addSubscribe(hookSubscribe, (mediaServerItemInUSe, hookParam) -> { - OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; - logger.info("[涓婄骇鐐规挱]鎷夋祦浠g悊宸茬粡灏辩华锛� {}/{}", streamChangedHookParam.getApp(), streamChangedHookParam.getStream()); + Hook hook = Hook.getInstance(HookType.on_media_arrival, gbStream.getApp(), gbStream.getStream(), mediaServerItem.getId()); + this.hookSubscribe.addSubscribe(hook, (hookData) -> { + logger.info("[涓婄骇鐐规挱]鎷夋祦浠g悊宸茬粡灏辩华锛� {}/{}", hookData.getApp(), hookData.getStream()); dynamicTask.stop(callIdHeader.getCallId()); pushProxyStream(evt, request, gbStream, platform, callIdHeader, mediaServerItem, port, tcpActive, mediaTransmissionTCP, channelId, addressStr, ssrc, requesterId); }); dynamicTask.startDelay(callIdHeader.getCallId(), () -> { logger.info("[ app={}, stream={} ] 绛夊緟鎷夋祦浠g悊娴佽秴鏃�", gbStream.getApp(), gbStream.getStream()); - zlmHttpHookSubscribe.removeSubscribe(hookSubscribe); + this.hookSubscribe.removeSubscribe(hook); }, userSetting.getPlatformPlayTimeout()); boolean start = streamProxyService.start(gbStream.getApp(), gbStream.getStream()); if (!start) { @@ -749,7 +753,7 @@ } catch (SipException | InvalidArgumentException | ParseException e) { logger.error("[鍛戒护鍙戦�佸け璐 invite 閫氶亾鏈帹娴�: {}", e.getMessage()); } - zlmHttpHookSubscribe.removeSubscribe(hookSubscribe); + this.hookSubscribe.removeSubscribe(hook); dynamicTask.stop(callIdHeader.getCallId()); } } else if ("push".equals(gbStream.getStreamType())) { @@ -846,7 +850,7 @@ * 鏉ヨ嚜鍏朵粬wvp鐨勬帹娴� */ private void otherWvpPushStream(RequestEvent evt, SIPRequest request, GbStream gbStream, StreamPushItem streamPushItem, ParentPlatform platform, - CallIdHeader callIdHeader, MediaServerItem mediaServerItem, + CallIdHeader callIdHeader, MediaServer mediaServerItem, int port, Boolean tcpActive, boolean mediaTransmissionTCP, String channelId, String addressStr, String ssrc, String requesterId) { logger.info("[绾ц仈鐐规挱]鐩存挱娴佹潵鑷叾浠栧钩鍙帮紝鍙戦�乺edis娑堟伅"); @@ -909,7 +913,7 @@ }); } - public SIPResponse sendStreamAck(MediaServerItem mediaServerItem, SIPRequest request, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) { + public SIPResponse sendStreamAck(MediaServer mediaServerItem, SIPRequest request, SendRtpItem sendRtpItem, ParentPlatform platform, RequestEvent evt) { String sdpIp = mediaServerItem.getSdpIp(); if (!ObjectUtils.isEmpty(platform.getSendStreamIp())) { @@ -1055,7 +1059,7 @@ logger.info("璁惧{}璇锋眰璇煶娴侊紝鍦板潃锛歿}:{}锛宻src锛歿}, {}", requesterId, addressStr, port, gb28181Sdp.getSsrc(), mediaTransmissionTCP ? (tcpActive ? "TCP涓诲姩" : "TCP琚姩") : "UDP"); - MediaServerItem mediaServerItem = broadcastCatch.getMediaServerItem(); + MediaServer mediaServerItem = broadcastCatch.getMediaServerItem(); if (mediaServerItem == null) { logger.warn("鏈壘鍒拌闊冲枈璇濅娇鐢ㄧ殑zlm"); try { @@ -1104,7 +1108,7 @@ redisCatchStorage.updateSendRTPSever(sendRtpItem); - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, broadcastCatch.getApp(), broadcastCatch.getStream()); + Boolean streamReady = mediaServerService.isStreamReady(mediaServerItem, broadcastCatch.getApp(), broadcastCatch.getStream()); if (streamReady) { sendOk(device, sendRtpItem, sdp, request, mediaServerItem, mediaTransmissionTCP, gb28181Sdp.getSsrc()); } else { @@ -1132,7 +1136,7 @@ } } - SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServerItem mediaServerItem, boolean mediaTransmissionTCP, String ssrc) { + SIPResponse sendOk(Device device, SendRtpItem sendRtpItem, SessionDescription sdp, SIPRequest request, MediaServer mediaServerItem, boolean mediaTransmissionTCP, String ssrc) { SIPResponse sipResponse = null; try { sendRtpItem.setStatus(2); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java index 0c23ace..34d7077 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/MessageRequestProcessor.java @@ -37,7 +37,7 @@ private final String method = "MESSAGE"; - private static Map<String, IMessageHandler> messageHandlerMap = new ConcurrentHashMap<>(); + private static final Map<String, IMessageHandler> messageHandlerMap = new ConcurrentHashMap<>(); @Autowired private SIPProcessorObserver sipProcessorObserver; @@ -100,9 +100,9 @@ deviceNotFoundEvent.setCallId(callIdHeader.getCallId()); SipSubscribe.EventResult eventResult = new SipSubscribe.EventResult(deviceNotFoundEvent); sipSubscribe.getErrorSubscribe(callIdHeader.getCallId()).response(eventResult); - }; + } }else { - Element rootElement = null; + Element rootElement; try { rootElement = getRootElement(evt); if (rootElement == null) { @@ -110,23 +110,23 @@ responseAck(request, Response.BAD_REQUEST, "content is null"); return; } + String name = rootElement.getName(); + IMessageHandler messageHandler = messageHandlerMap.get(name); + if (messageHandler != null) { + if (device != null) { + messageHandler.handForDevice(evt, device, rootElement); + }else { // 鐢变簬涓婇潰宸茬粡鍒ゆ柇閮戒负null鍒欑洿鎺ヨ繑鍥烇紝鎵�浠ヨ繖閲宒evice鍜宲arentPlatform蹇呮湁涓�涓笉涓簄ull + messageHandler.handForPlatform(evt, parentPlatform, rootElement); + } + }else { + // 涓嶆敮鎸佺殑message + // 涓嶅瓨鍦ㄥ垯鍥炲415 + responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response"); + } } catch (DocumentException e) { logger.warn("瑙f瀽XML娑堟伅鍐呭寮傚父", e); // 涓嶅瓨鍦ㄥ垯鍥炲404 responseAck(request, Response.BAD_REQUEST, e.getMessage()); - } - String name = rootElement.getName(); - IMessageHandler messageHandler = messageHandlerMap.get(name); - if (messageHandler != null) { - if (device != null) { - messageHandler.handForDevice(evt, device, rootElement); - }else { // 鐢变簬涓婇潰宸茬粡鍒ゆ柇閮戒负null鍒欑洿鎺ヨ繑鍥烇紝鎵�浠ヨ繖閲宒evice鍜宲arentPlatform蹇呮湁涓�涓笉涓簄ull - messageHandler.handForPlatform(evt, parentPlatform, rootElement); - } - }else { - // 涓嶆敮鎸佺殑message - // 涓嶅瓨鍦ㄥ垯鍥炲415 - responseAck(request, Response.UNSUPPORTED_MEDIA_TYPE, "Unsupported message type, must Control/Notify/Query/Response"); } } } catch (SipException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/BroadcastNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/BroadcastNotifyMessageHandler.java index a05847a..08be1f3 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/BroadcastNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/BroadcastNotifyMessageHandler.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.cmd; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; @@ -9,10 +8,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.IDeviceService; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlatformService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -121,15 +119,14 @@ return; } - MediaServerItem mediaServerForMinimumLoad = mediaServerService.getMediaServerForMinimumLoad(null); + MediaServer mediaServerForMinimumLoad = mediaServerService.getMediaServerForMinimumLoad(null); commanderForPlatform.broadcastResultCmd(platform, deviceChannel, sn, true, eventResult->{ logger.info("[鍥芥爣绾ц仈] 璇煶鍠婅瘽 鍥炲澶辫触 platform锛� {}锛� 閿欒锛歿}/{}", platform.getServerGBId(), eventResult.statusCode, eventResult.msg); }, eventResult->{ // 娑堟伅鍙戦�佹垚鍔燂紝 鍚戜笂绾у彂閫乮nvite锛岃幏鍙栨帹娴� try { - platformService.broadcastInvite(platform, deviceChannel.getChannelId(), mediaServerForMinimumLoad, (mediaServerItem, hookParam)->{ - OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; + platformService.broadcastInvite(platform, deviceChannel.getChannelId(), mediaServerForMinimumLoad, (hookData)->{ // 涓婄骇骞冲彴鎺ㄦ祦鎴愬姛 AudioBroadcastCatch broadcastCatch = audioBroadcastManager.get(device.getDeviceId(), targetId); if (broadcastCatch != null ) { @@ -137,20 +134,20 @@ logger.info("[鍥芥爣绾ц仈] 璇煶鍠婅瘽 璁惧姝e湪浣跨敤涓� platform锛� {}锛� channel: {}", platform.getServerGBId(), deviceChannel.getChannelId()); // 鏌ョ湅璇煶閫氶亾宸茬粡寤虹珛涓斿凡缁忓崰鐢� 鍥炲BYE - platformService.stopBroadcast(platform, deviceChannel, streamChangedHookParam.getStream(), true, mediaServerItem); + platformService.stopBroadcast(platform, deviceChannel, hookData.getStream(), true, hookData.getMediaServer()); }else { // 鏌ョ湅璇煶閫氶亾宸茬粡寤虹珛浣嗘槸鏈崰鐢� - broadcastCatch.setApp(streamChangedHookParam.getApp()); - broadcastCatch.setStream(streamChangedHookParam.getStream()); - broadcastCatch.setMediaServerItem(mediaServerItem); + broadcastCatch.setApp(hookData.getApp()); + broadcastCatch.setStream(hookData.getStream()); + broadcastCatch.setMediaServerItem(hookData.getMediaServer()); audioBroadcastManager.update(broadcastCatch); // 鎺ㄦ祦鍒拌澶� - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, targetId, streamChangedHookParam.getStream(), null); + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, targetId, hookData.getStream(), null); if (sendRtpItem == null) { - logger.warn("[鍥芥爣绾ц仈] 璇煶鍠婅瘽 寮傚父锛屾湭鎵惧埌鍙戞祦淇℃伅锛� channelId: {}, stream: {}", targetId, streamChangedHookParam.getStream()); - logger.info("[鍥芥爣绾ц仈] 璇煶鍠婅瘽 閲嶆柊寮�濮嬶紝channelId: {}, stream: {}", targetId, streamChangedHookParam.getStream()); + logger.warn("[鍥芥爣绾ц仈] 璇煶鍠婅瘽 寮傚父锛屾湭鎵惧埌鍙戞祦淇℃伅锛� channelId: {}, stream: {}", targetId, hookData.getStream()); + logger.info("[鍥芥爣绾ц仈] 璇煶鍠婅瘽 閲嶆柊寮�濮嬶紝channelId: {}, stream: {}", targetId, hookData.getStream()); try { - playService.audioBroadcastCmd(device, targetId, mediaServerItem, streamChangedHookParam.getApp(), streamChangedHookParam.getStream(), 60, true, msg -> { + playService.audioBroadcastCmd(device, targetId, hookData.getMediaServer(), hookData.getApp(), hookData.getStream(), 60, true, msg -> { logger.info("[璇煶鍠婅瘽] 閫氶亾寤虹珛鎴愬姛, device: {}, channel: {}", device.getDeviceId(), targetId); }); } catch (SipException | InvalidArgumentException | ParseException e) { @@ -158,7 +155,7 @@ } }else { // 鍙戞祦 - JSONObject jsonObject = zlmServerFactory.startSendRtp(mediaServerItem, sendRtpItem); + JSONObject jsonObject = zlmServerFactory.startSendRtp(hookData.getMediaServer(), sendRtpItem); if (jsonObject != null && jsonObject.getInteger("code") == 0 ) { logger.info("[璇煶鍠婅瘽] 鑷姩鎺ㄦ祦鎴愬姛, device: {}, channel: {}", device.getDeviceId(), targetId); }else { @@ -168,7 +165,7 @@ } }else { try { - playService.audioBroadcastCmd(device, targetId, mediaServerItem, streamChangedHookParam.getApp(), streamChangedHookParam.getStream(), 60, true, msg -> { + playService.audioBroadcastCmd(device, targetId, hookData.getMediaServer(), hookData.getApp(), hookData.getStream(), 60, true, msg -> { logger.info("[璇煶鍠婅瘽] 閫氶亾寤虹珛鎴愬姛, device: {}, channel: {}", device.getDeviceId(), targetId); }); } catch (SipException | InvalidArgumentException | ParseException e) { diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java index 55094f9..f8ff69c 100755 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/message/notify/cmd/MediaStatusNotifyMessageHandler.java @@ -13,9 +13,9 @@ import com.genersoft.iot.vmp.gb28181.transmit.event.request.SIPRequestProcessorParent; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.IMessageHandler; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.notify.NotifyMessageHandler; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.event.hook.HookType; import com.genersoft.iot.vmp.service.IInviteStreamService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; @@ -64,7 +64,7 @@ private VideoStreamSessionManager sessionManager; @Autowired - private ZlmHttpHookSubscribe subscribe; + private HookSubscribe subscribe; @Autowired private IInviteStreamService inviteStreamService; @@ -106,9 +106,8 @@ logger.error("[褰曞儚娴乚鎺ㄩ�佸畬姣曪紝鏀跺埌鍏虫祦閫氱煡锛� 鍙戦�丅YE澶辫触 {}", e.getMessage()); } // 鍘婚櫎鐩戝惉娴佹敞閿�鑷姩鍋滄涓嬭浇鐨勭洃鍚� - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcTransaction.getStream(), false, "rtsp", ssrcTransaction.getMediaServerId()); - subscribe.removeSubscribe(hookSubscribe); - + Hook hook = Hook.getInstance(HookType.on_media_arrival, "rtp", ssrcTransaction.getStream(), ssrcTransaction.getMediaServerId()); + subscribe.removeSubscribe(hook); // 濡傛灉绾ц仈鎾斁锛岄渶瑕佺粰涓婄骇鍙戦�佹閫氱煡 TODO 澶氫釜涓婄骇鍚屾椂瑙傜湅涓�涓笅绾� 鍙兘瀛樺湪鍋滈敊鐨勯棶棰橈紝闇�瑕佸皢鐐规挱CallId杩涜涓婁笅绾х粦瀹� SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, ssrcTransaction.getChannelId(), null, null); if (sendRtpItem != null) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java b/src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java new file mode 100755 index 0000000..fb9de3f --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/MediaServerConfig.java @@ -0,0 +1,64 @@ +package com.genersoft.iot.vmp.media; + +import com.genersoft.iot.vmp.conf.MediaConfig; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent; +import com.genersoft.iot.vmp.media.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.CommandLineRunner; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 鍚姩鏄粠閰嶇疆鏂囦欢鍔犺浇鑺傜偣淇℃伅锛屼互鍙婂彂閫佷釜鑺傜偣鐘舵�佺鐞嗗幓鎺у埗鑺傜偣鐘舵�� + */ +@Component +@Order(value=12) +public class MediaServerConfig implements CommandLineRunner { + + private final static Logger logger = LoggerFactory.getLogger(MediaServerConfig.class); + + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + + @Autowired + private IMediaServerService mediaServerService; + + @Autowired + private MediaConfig mediaConfig; + + + @Override + public void run(String... strings) throws Exception { + // 娓呯悊鎵�鏈夊湪绾胯妭鐐圭殑缂撳瓨淇℃伅 + mediaServerService.clearMediaServerForOnline(); + MediaServer defaultMediaServer = mediaServerService.getDefaultMediaServer(); + MediaServer mediaSerItemInConfig = mediaConfig.getMediaSerItem(); + if (defaultMediaServer != null && mediaSerItemInConfig.getId().equals(defaultMediaServer.getId())) { + mediaServerService.update(mediaSerItemInConfig); + }else { + if (defaultMediaServer != null) { + mediaServerService.delete(defaultMediaServer.getId()); + } + MediaServer mediaServerItem = mediaServerService.getOneFromDatabase(mediaSerItemInConfig.getId()); + if (mediaServerItem == null) { + mediaServerService.add(mediaSerItemInConfig); + }else { + mediaServerService.update(mediaSerItemInConfig); + } + } + // 鍙戦�佸獟浣撹妭鐐瑰彉鍖栦簨浠� + mediaServerService.syncCatchFromDatabase(); + // 鑾峰彇鎵�鏈夌殑zlm锛� 骞跺紑鍚富鍔ㄨ繛鎺� + List<MediaServer> all = mediaServerService.getAllFromDatabase(); + logger.info("[濯掍綋鑺傜偣] 鍔犺浇鑺傜偣鍒楄〃锛� 鍏眥}涓妭鐐�", all.size()); + MediaServerChangeEvent event = new MediaServerChangeEvent(this); + event.setMediaServerItemList(all); + applicationEventPublisher.publishEvent(event); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java new file mode 100644 index 0000000..f1c3d58 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaInfo.java @@ -0,0 +1,306 @@ +package com.genersoft.iot.vmp.media.bean; + +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; +import io.swagger.v3.oas.annotations.media.Schema; + +import java.util.List; + +/** + * 瑙嗛淇℃伅 + */ +@Schema(description = "瑙嗛淇℃伅") +public class MediaInfo { + @Schema(description = "搴旂敤鍚�") + private String app; + @Schema(description = "娴両D") + private String stream; + @Schema(description = "娴佸獟浣撹妭鐐�") + private MediaServer mediaServer; + @Schema(description = "鍗忚") + private String schema; + + @Schema(description = "瑙傜湅浜烘暟") + private Integer readerCount; + @Schema(description = "瑙嗛缂栫爜绫诲瀷") + private String videoCodec; + @Schema(description = "瑙嗛瀹藉害") + private Integer width; + @Schema(description = "瑙嗛楂樺害") + private Integer height; + @Schema(description = "闊抽缂栫爜绫诲瀷") + private String audioCodec; + @Schema(description = "闊抽閫氶亾鏁�") + private Integer audioChannels; + @Schema(description = "闊抽閲囨牱鐜�") + private Integer audioSampleRate; + @Schema(description = "闊抽閲囨牱鐜�") + private Long duration; + @Schema(description = "鍦ㄧ嚎") + private Boolean online; + @Schema(description = "unknown = 0,rtmp_push=1,rtsp_push=2,rtp_push=3,pull=4,ffmpeg_pull=5,mp4_vod=6,device_chn=7") + private Integer originType; + @Schema(description = "瀛樻椿鏃堕棿锛屽崟浣嶇") + private Long aliveSecond; + @Schema(description = "鏁版嵁浜х敓閫熷害锛屽崟浣峛yte/s") + private Long bytesSpeed; + + public static MediaInfo getInstance(JSONObject jsonObject, MediaServer mediaServer) { + MediaInfo mediaInfo = new MediaInfo(); + mediaInfo.setMediaServer(mediaServer); + String app = jsonObject.getString("app"); + mediaInfo.setApp(app); + String stream = jsonObject.getString("stream"); + mediaInfo.setStream(stream); + String schema = jsonObject.getString("schema"); + mediaInfo.setSchema(schema); + Integer totalReaderCount = jsonObject.getInteger("totalReaderCount"); + Boolean online = jsonObject.getBoolean("online"); + Integer originType = jsonObject.getInteger("originType"); + Long aliveSecond = jsonObject.getLong("aliveSecond"); + Long bytesSpeed = jsonObject.getLong("bytesSpeed"); + if (totalReaderCount != null) { + mediaInfo.setReaderCount(totalReaderCount); + } + if (online != null) { + mediaInfo.setOnline(online); + } + if (originType != null) { + mediaInfo.setOriginType(originType); + } + if (aliveSecond != null) { + mediaInfo.setAliveSecond(aliveSecond); + } + if (bytesSpeed != null) { + mediaInfo.setBytesSpeed(bytesSpeed); + } + JSONArray jsonArray = jsonObject.getJSONArray("tracks"); + if (jsonArray.isEmpty()) { + return null; + } + for (int i = 0; i < jsonArray.size(); i++) { + JSONObject trackJson = jsonArray.getJSONObject(i); + Integer channels = trackJson.getInteger("channels"); + Integer codecId = trackJson.getInteger("codec_id"); + Integer codecType = trackJson.getInteger("codec_type"); + Integer sampleRate = trackJson.getInteger("sample_rate"); + Integer height = trackJson.getInteger("height"); + Integer width = trackJson.getInteger("height"); + Long duration = trackJson.getLongValue("duration"); + if (channels != null) { + mediaInfo.setAudioChannels(channels); + } + if (sampleRate != null) { + mediaInfo.setAudioSampleRate(sampleRate); + } + if (height != null) { + mediaInfo.setHeight(height); + } + if (width != null) { + mediaInfo.setWidth(width); + } + if (duration > 0L) { + mediaInfo.setDuration(duration); + } + if (codecId != null) { + switch (codecId) { + case 0: + mediaInfo.setVideoCodec("H264"); + break; + case 1: + mediaInfo.setVideoCodec("H265"); + break; + case 2: + mediaInfo.setAudioCodec("AAC"); + break; + case 3: + mediaInfo.setAudioCodec("G711A"); + break; + case 4: + mediaInfo.setAudioCodec("G711U"); + break; + } + } + } + return mediaInfo; + } + + public static MediaInfo getInstance(OnStreamChangedHookParam param, MediaServer mediaServer) { + + MediaInfo mediaInfo = new MediaInfo(); + mediaInfo.setApp(param.getApp()); + mediaInfo.setStream(param.getStream()); + mediaInfo.setSchema(param.getSchema()); + mediaInfo.setMediaServer(mediaServer); + mediaInfo.setReaderCount(param.getTotalReaderCount()); + mediaInfo.setOnline(param.isRegist()); + mediaInfo.setOriginType(param.getOriginType()); + mediaInfo.setAliveSecond(param.getAliveSecond()); + mediaInfo.setBytesSpeed(param.getBytesSpeed()); + List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks(); + if (tracks == null || tracks.isEmpty()) { + return mediaInfo; + } + for (OnStreamChangedHookParam.MediaTrack mediaTrack : tracks) { + switch (mediaTrack.getCodec_id()) { + case 0: + mediaInfo.setVideoCodec("H264"); + break; + case 1: + mediaInfo.setVideoCodec("H265"); + break; + case 2: + mediaInfo.setAudioCodec("AAC"); + break; + case 3: + mediaInfo.setAudioCodec("G711A"); + break; + case 4: + mediaInfo.setAudioCodec("G711U"); + break; + } + if (mediaTrack.getSample_rate() > 0) { + mediaInfo.setAudioSampleRate(mediaTrack.getSample_rate()); + } + if (mediaTrack.getChannels() > 0) { + mediaInfo.setAudioChannels(mediaTrack.getChannels()); + } + if (mediaTrack.getHeight() > 0) { + mediaInfo.setHeight(mediaTrack.getHeight()); + } + if (mediaTrack.getWidth() > 0) { + mediaInfo.setWidth(mediaTrack.getWidth()); + } + } + return mediaInfo; + } + + public Integer getReaderCount() { + return readerCount; + } + + public void setReaderCount(Integer readerCount) { + this.readerCount = readerCount; + } + + public String getVideoCodec() { + return videoCodec; + } + + public void setVideoCodec(String videoCodec) { + this.videoCodec = videoCodec; + } + + public Integer getWidth() { + return width; + } + + public void setWidth(Integer width) { + this.width = width; + } + + public Integer getHeight() { + return height; + } + + public void setHeight(Integer height) { + this.height = height; + } + + public String getAudioCodec() { + return audioCodec; + } + + public void setAudioCodec(String audioCodec) { + this.audioCodec = audioCodec; + } + + public Integer getAudioChannels() { + return audioChannels; + } + + public void setAudioChannels(Integer audioChannels) { + this.audioChannels = audioChannels; + } + + public Integer getAudioSampleRate() { + return audioSampleRate; + } + + public void setAudioSampleRate(Integer audioSampleRate) { + this.audioSampleRate = audioSampleRate; + } + + public Long getDuration() { + return duration; + } + + public void setDuration(Long duration) { + this.duration = duration; + } + + public Boolean getOnline() { + return online; + } + + public void setOnline(Boolean online) { + this.online = online; + } + + public Integer getOriginType() { + return originType; + } + + public void setOriginType(Integer originType) { + this.originType = originType; + } + + public Long getAliveSecond() { + return aliveSecond; + } + + public void setAliveSecond(Long aliveSecond) { + this.aliveSecond = aliveSecond; + } + + public Long getBytesSpeed() { + return bytesSpeed; + } + + public void setBytesSpeed(Long bytesSpeed) { + this.bytesSpeed = bytesSpeed; + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public MediaServer getMediaServer() { + return mediaServer; + } + + public void setMediaServer(MediaServer mediaServer) { + this.mediaServer = mediaServer; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java similarity index 82% rename from src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java rename to src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java index cebfec3..decbd4e 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItem.java +++ b/src/main/java/com/genersoft/iot/vmp/media/bean/MediaServer.java @@ -1,12 +1,12 @@ -package com.genersoft.iot.vmp.media.zlm.dto; +package com.genersoft.iot.vmp.media.bean; -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig; import io.swagger.v3.oas.annotations.media.Schema; import org.springframework.util.ObjectUtils; @Schema(description = "娴佸獟浣撴湇鍔′俊鎭�") -public class MediaServerItem{ +public class MediaServer { @Schema(description = "ID") private String id; @@ -31,6 +31,18 @@ @Schema(description = "RTMP绔彛") private int rtmpPort; + + @Schema(description = "flv绔彛") + private int flvPort; + + @Schema(description = "https-flv绔彛") + private int flvSSLPort; + + @Schema(description = "ws-flv绔彛") + private int wsFlvPort; + + @Schema(description = "wss-flv绔彛") + private int wsFlvSSLPort; @Schema(description = "RTMPS绔彛") private int rtmpSSlPort; @@ -85,18 +97,24 @@ @Schema(description = "褰曞儚瀛樺偍璺緞") private String recordPath; + @Schema(description = "绫诲瀷锛� zlm/abl") + private String type; - public MediaServerItem() { + public MediaServer() { } - public MediaServerItem(ZLMServerConfig zlmServerConfig, String sipIp) { + public MediaServer(ZLMServerConfig zlmServerConfig, String sipIp) { id = zlmServerConfig.getGeneralMediaServerId(); ip = zlmServerConfig.getIp(); hookIp = ObjectUtils.isEmpty(zlmServerConfig.getHookIp())? sipIp: zlmServerConfig.getHookIp(); sdpIp = ObjectUtils.isEmpty(zlmServerConfig.getSdpIp())? zlmServerConfig.getIp(): zlmServerConfig.getSdpIp(); streamIp = ObjectUtils.isEmpty(zlmServerConfig.getStreamIp())? zlmServerConfig.getIp(): zlmServerConfig.getStreamIp(); httpPort = zlmServerConfig.getHttpPort(); + flvPort = zlmServerConfig.getHttpPort(); + wsFlvPort = zlmServerConfig.getHttpPort(); httpSSlPort = zlmServerConfig.getHttpSSLport(); + flvSSLPort = zlmServerConfig.getHttpSSLport(); + wsFlvSSLPort = zlmServerConfig.getHttpSSLport(); rtmpPort = zlmServerConfig.getRtmpPort(); rtmpSSlPort = zlmServerConfig.getRtmpSslPort(); rtpProxyPort = zlmServerConfig.getRtpProxyPort(); @@ -318,4 +336,44 @@ public void setRecordPath(String recordPath) { this.recordPath = recordPath; } + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public int getFlvPort() { + return flvPort; + } + + public void setFlvPort(int flvPort) { + this.flvPort = flvPort; + } + + public int getFlvSSLPort() { + return flvSSLPort; + } + + public void setFlvSSLPort(int flvSSLPort) { + this.flvSSLPort = flvSSLPort; + } + + public int getWsFlvPort() { + return wsFlvPort; + } + + public void setWsFlvPort(int wsFlvPort) { + this.wsFlvPort = wsFlvPort; + } + + public int getWsFlvSSLPort() { + return wsFlvSSLPort; + } + + public void setWsFlvSSLPort(int wsFlvSSLPort) { + this.wsFlvSSLPort = wsFlvSSLPort; + } } diff --git a/src/main/java/com/genersoft/iot/vmp/media/bean/RecordInfo.java b/src/main/java/com/genersoft/iot/vmp/media/bean/RecordInfo.java new file mode 100644 index 0000000..aafc5db --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/bean/RecordInfo.java @@ -0,0 +1,92 @@ +package com.genersoft.iot.vmp.media.bean; + +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; + +public class RecordInfo { + private String fileName; + private String filePath; + private long fileSize; + private String folder; + private String url; + private long startTime; + private double timeLen; + + public static RecordInfo getInstance(OnRecordMp4HookParam hookParam) { + RecordInfo recordInfo = new RecordInfo(); + recordInfo.setFileName(hookParam.getFile_name()); + recordInfo.setUrl(hookParam.getUrl()); + recordInfo.setFolder(hookParam.getFolder()); + recordInfo.setFilePath(hookParam.getFile_path()); + recordInfo.setFileSize(hookParam.getFile_size()); + recordInfo.setStartTime(hookParam.getStart_time()); + recordInfo.setTimeLen(hookParam.getTime_len()); + return recordInfo; + } + + public String getFileName() { + return fileName; + } + + public void setFileName(String fileName) { + this.fileName = fileName; + } + + public String getFilePath() { + return filePath; + } + + public void setFilePath(String filePath) { + this.filePath = filePath; + } + + public long getFileSize() { + return fileSize; + } + + public void setFileSize(long fileSize) { + this.fileSize = fileSize; + } + + public String getFolder() { + return folder; + } + + public void setFolder(String folder) { + this.folder = folder; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public long getStartTime() { + return startTime; + } + + public void setStartTime(long startTime) { + this.startTime = startTime; + } + + public double getTimeLen() { + return timeLen; + } + + public void setTimeLen(double timeLen) { + this.timeLen = timeLen; + } + + @Override + public String toString() { + return "RecordInfo{" + + "鏂囦欢鍚嶇О='" + fileName + '\'' + + ", 鏂囦欢璺緞='" + filePath + '\'' + + ", 鏂囦欢澶у皬=" + fileSize + + ", 寮�濮嬫椂闂�=" + startTime + + ", 鏃堕暱=" + timeLen + + '}'; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/bean/ResultForOnPublish.java b/src/main/java/com/genersoft/iot/vmp/media/bean/ResultForOnPublish.java new file mode 100644 index 0000000..88f7387 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/bean/ResultForOnPublish.java @@ -0,0 +1,59 @@ +package com.genersoft.iot.vmp.media.bean; + +public class ResultForOnPublish { + + private boolean enable_audio; + private boolean enable_mp4; + private int mp4_max_second; + private String mp4_save_path; + private String stream_replace; + private Integer modify_stamp; + + public boolean isEnable_audio() { + return enable_audio; + } + + public void setEnable_audio(boolean enable_audio) { + this.enable_audio = enable_audio; + } + + public boolean isEnable_mp4() { + return enable_mp4; + } + + public void setEnable_mp4(boolean enable_mp4) { + this.enable_mp4 = enable_mp4; + } + + public int getMp4_max_second() { + return mp4_max_second; + } + + public void setMp4_max_second(int mp4_max_second) { + this.mp4_max_second = mp4_max_second; + } + + public String getMp4_save_path() { + return mp4_save_path; + } + + public void setMp4_save_path(String mp4_save_path) { + this.mp4_save_path = mp4_save_path; + } + + public String getStream_replace() { + return stream_replace; + } + + public void setStream_replace(String stream_replace) { + this.stream_replace = stream_replace; + } + + public Integer getModify_stamp() { + return modify_stamp; + } + + public void setModify_stamp(Integer modify_stamp) { + this.modify_stamp = modify_stamp; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/hook/Hook.java b/src/main/java/com/genersoft/iot/vmp/media/event/hook/Hook.java new file mode 100755 index 0000000..a0dc7c3 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/hook/Hook.java @@ -0,0 +1,86 @@ +package com.genersoft.iot.vmp.media.event.hook; + +/** + * zlm hook浜嬩欢鐨勫弬鏁� + * @author lin + */ +public class Hook { + + private HookType hookType; + + private String app; + + private String stream; + + private String mediaServerId; + + private Long createTime; + + public static Hook getInstance(HookType hookType, String app, String stream, String mediaServerId) { + Hook hookSubscribe = new Hook(); + hookSubscribe.setApp(app); + hookSubscribe.setStream(stream); + hookSubscribe.setHookType(hookType); + hookSubscribe.setMediaServerId(mediaServerId); + hookSubscribe.setCreateTime(System.currentTimeMillis()); + return hookSubscribe; + } + + public HookType getHookType() { + return hookType; + } + + public void setHookType(HookType hookType) { + this.hookType = hookType; + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public Long getCreateTime() { + return createTime; + } + + public void setCreateTime(Long createTime) { + this.createTime = createTime; + } + + public String getMediaServerId() { + return mediaServerId; + } + + public void setMediaServerId(String mediaServerId) { + this.mediaServerId = mediaServerId; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof Hook) { + Hook param = (Hook) obj; + return param.getHookType().equals(this.hookType) + && param.getApp().equals(this.app) + && param.getStream().equals(this.stream) + && param.getMediaServerId().equals(this.mediaServerId); + }else { + return false; + } + } + + @Override + public String toString() { + return this.getHookType() + this.getApp() + this.getStream() + this.getMediaServerId(); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookData.java b/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookData.java new file mode 100644 index 0000000..d4a82a7 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookData.java @@ -0,0 +1,132 @@ +package com.genersoft.iot.vmp.media.event.hook; + +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.bean.RecordInfo; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; +import com.genersoft.iot.vmp.media.event.media.MediaEvent; +import com.genersoft.iot.vmp.media.event.media.MediaPublishEvent; +import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import io.swagger.v3.oas.annotations.media.Schema; + +/** + * Hook杩斿洖鐨勫唴瀹� + */ +public class HookData { + /** + * 搴旂敤鍚� + */ + private String app; + /** + * 娴両D + */ + private String stream; + /** + * 娴佸獟浣撹妭鐐� + */ + private MediaServer mediaServer; + /** + * 鍗忚 + */ + private String schema; + + /** + * 娴佷俊鎭� + */ + private MediaInfo mediaInfo; + + /** + * 褰曞儚淇℃伅 + */ + private RecordInfo recordInfo; + + @Schema(description = "鎺ㄦ祦鐨勯澶栧弬鏁�") + private String params; + public static HookData getInstance(MediaEvent mediaEvent) { + HookData hookData = new HookData(); + if (mediaEvent instanceof MediaPublishEvent) { + MediaPublishEvent event = (MediaPublishEvent) mediaEvent; + hookData.setApp(event.getApp()); + hookData.setStream(event.getStream()); + hookData.setSchema(event.getSchema()); + hookData.setMediaServer(event.getMediaServer()); + hookData.setParams(event.getParams()); + }else if (mediaEvent instanceof MediaArrivalEvent) { + MediaArrivalEvent event = (MediaArrivalEvent) mediaEvent; + hookData.setApp(event.getApp()); + hookData.setStream(event.getStream()); + hookData.setSchema(event.getSchema()); + hookData.setMediaServer(event.getMediaServer()); + hookData.setMediaInfo(event.getMediaInfo()); + }else if (mediaEvent instanceof MediaRecordMp4Event) { + MediaRecordMp4Event event = (MediaRecordMp4Event) mediaEvent; + hookData.setApp(event.getApp()); + hookData.setStream(event.getStream()); + hookData.setSchema(event.getSchema()); + hookData.setMediaServer(event.getMediaServer()); + hookData.setRecordInfo(event.getRecordInfo()); + }else { + hookData.setApp(mediaEvent.getApp()); + hookData.setStream(mediaEvent.getStream()); + hookData.setSchema(mediaEvent.getSchema()); + hookData.setMediaServer(mediaEvent.getMediaServer()); + } + return hookData; + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public MediaServer getMediaServer() { + return mediaServer; + } + + public void setMediaServer(MediaServer mediaServer) { + this.mediaServer = mediaServer; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + + public MediaInfo getMediaInfo() { + return mediaInfo; + } + + public void setMediaInfo(MediaInfo mediaInfo) { + this.mediaInfo = mediaInfo; + } + + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } + + public RecordInfo getRecordInfo() { + return recordInfo; + } + + public void setRecordInfo(RecordInfo recordInfo) { + this.recordInfo = recordInfo; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookSubscribe.java new file mode 100755 index 0000000..907e904 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookSubscribe.java @@ -0,0 +1,107 @@ +package com.genersoft.iot.vmp.media.event.hook; + +import com.genersoft.iot.vmp.media.event.media.*; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * zlm hook浜嬩欢鐨勫弬鏁� + * @author lin + */ +@Component +public class HookSubscribe { + + /** + * 璁㈤槄鏁版嵁杩囨湡鏃堕棿 + */ + private final long subscribeExpire = 5 * 60 * 1000; + + @FunctionalInterface + public interface Event{ + void response(HookData data); + } + + /** + * 娴佸埌鏉ョ殑澶勭悊 + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaArrivalEvent event) { + if (event.getSchema() == null || "rtsp".equals(event.getSchema())) { + sendNotify(HookType.on_media_arrival, event); + } + + } + + /** + * 娴佺粨鏉熶簨浠� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaDepartureEvent event) { + if (event.getSchema() == null || "rtsp".equals(event.getSchema())) { + sendNotify(HookType.on_media_departure, event); + } + + } + /** + * 鎺ㄦ祦閴存潈浜嬩欢 + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaPublishEvent event) { + sendNotify(HookType.on_publish, event); + } + /** + * 鎺ㄦ祦閴存潈浜嬩欢 + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaRecordMp4Event event) { + sendNotify(HookType.on_record_mp4, event); + } + + private final Map<String, Event> allSubscribes = new ConcurrentHashMap<>(); + private final Map<String, Hook> allHook = new ConcurrentHashMap<>(); + + private void sendNotify(HookType hookType, MediaEvent event) { + Hook paramHook = Hook.getInstance(hookType, event.getApp(), event.getStream(), event.getMediaServer().getId()); + Event hookSubscribeEvent = allSubscribes.get(paramHook.toString()); + if (hookSubscribeEvent != null) { + HookData data = HookData.getInstance(event); + hookSubscribeEvent.response(data); + } + } + + public void addSubscribe(Hook hook, HookSubscribe.Event event) { + if (hook.getCreateTime() == null) { + hook.setCreateTime(System.currentTimeMillis()); + } + allSubscribes.put(hook.toString(), event); + allHook.put(hook.toString(), hook); + } + + public void removeSubscribe(Hook hook) { + allSubscribes.remove(hook.toString()); + allHook.remove(hook.toString()); + } + + /** + * 瀵硅闃呮暟鎹繘琛岃繃鏈熸竻鐞� + */ + @Scheduled(fixedRate=subscribeExpire) //姣�5鍒嗛挓鎵ц涓�娆� + public void execute(){ + long expireTime = System.currentTimeMillis() - subscribeExpire; + for (Hook hook : allHook.values()) { + if (hook.getCreateTime() < expireTime) { + allSubscribes.remove(hook.toString()); + allHook.remove(hook.toString()); + } + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookType.java b/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookType.java new file mode 100755 index 0000000..58bd656 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/hook/HookType.java @@ -0,0 +1,15 @@ +package com.genersoft.iot.vmp.media.event.hook; + +/** + * hook绫诲瀷 + * @author lin + */ + +public enum HookType { + + on_publish, + on_record_mp4, + on_media_arrival, + on_media_departure, + on_rtp_server_timeout, +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaArrivalEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaArrivalEvent.java new file mode 100644 index 0000000..2379321 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaArrivalEvent.java @@ -0,0 +1,46 @@ +package com.genersoft.iot.vmp.media.event.media; + +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; + +/** + * 娴佸埌鏉ヤ簨浠� + */ +public class MediaArrivalEvent extends MediaEvent { + public MediaArrivalEvent(Object source) { + super(source); + } + + public static MediaArrivalEvent getInstance(Object source, OnStreamChangedHookParam hookParam, MediaServer mediaServer){ + MediaArrivalEvent mediaArrivalEvent = new MediaArrivalEvent(source); + mediaArrivalEvent.setMediaInfo(MediaInfo.getInstance(hookParam, mediaServer)); + mediaArrivalEvent.setApp(hookParam.getApp()); + mediaArrivalEvent.setStream(hookParam.getStream()); + mediaArrivalEvent.setMediaServer(mediaServer); + mediaArrivalEvent.setSchema(hookParam.getSchema()); + mediaArrivalEvent.setCallId(hookParam.getCallId()); + return mediaArrivalEvent; + } + + private MediaInfo mediaInfo; + + private String callId; + + public MediaInfo getMediaInfo() { + return mediaInfo; + } + + public void setMediaInfo(MediaInfo mediaInfo) { + this.mediaInfo = mediaInfo; + } + + + public String getCallId() { + return callId; + } + + public void setCallId(String callId) { + this.callId = callId; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaDepartureEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaDepartureEvent.java new file mode 100644 index 0000000..edd945a --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaDepartureEvent.java @@ -0,0 +1,22 @@ +package com.genersoft.iot.vmp.media.event.media; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; + +/** + * 娴佺寮�浜嬩欢 + */ +public class MediaDepartureEvent extends MediaEvent { + public MediaDepartureEvent(Object source) { + super(source); + } + + public static MediaDepartureEvent getInstance(Object source, OnStreamChangedHookParam hookParam, MediaServer mediaServer){ + MediaDepartureEvent mediaDepartureEven = new MediaDepartureEvent(source); + mediaDepartureEven.setApp(hookParam.getApp()); + mediaDepartureEven.setStream(hookParam.getStream()); + mediaDepartureEven.setSchema(hookParam.getSchema()); + mediaDepartureEven.setMediaServer(mediaServer); + return mediaDepartureEven; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaEvent.java new file mode 100644 index 0000000..b6fb890 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaEvent.java @@ -0,0 +1,56 @@ +package com.genersoft.iot.vmp.media.event.media; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import org.springframework.context.ApplicationEvent; + +/** + * 娴佸埌鏉ヤ簨浠� + */ +public class MediaEvent extends ApplicationEvent { + + public MediaEvent(Object source) { + super(source); + } + + private String app; + + private String stream; + + private MediaServer mediaServer; + + private String schema; + + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public MediaServer getMediaServer() { + return mediaServer; + } + + public void setMediaServer(MediaServer mediaServer) { + this.mediaServer = mediaServer; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaNotFoundEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaNotFoundEvent.java new file mode 100644 index 0000000..2415566 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaNotFoundEvent.java @@ -0,0 +1,22 @@ +package com.genersoft.iot.vmp.media.event.media; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamNotFoundHookParam; + +/** + * 娴佹湭鎵惧埌 + */ +public class MediaNotFoundEvent extends MediaEvent { + public MediaNotFoundEvent(Object source) { + super(source); + } + + public static MediaNotFoundEvent getInstance(Object source, OnStreamNotFoundHookParam hookParam, MediaServer mediaServer){ + MediaNotFoundEvent mediaDepartureEven = new MediaNotFoundEvent(source); + mediaDepartureEven.setApp(hookParam.getApp()); + mediaDepartureEven.setStream(hookParam.getStream()); + mediaDepartureEven.setSchema(hookParam.getSchema()); + mediaDepartureEven.setMediaServer(mediaServer); + return mediaDepartureEven; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaPublishEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaPublishEvent.java new file mode 100644 index 0000000..0d9f032 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaPublishEvent.java @@ -0,0 +1,33 @@ +package com.genersoft.iot.vmp.media.event.media; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnPublishHookParam; + +/** + * 鎺ㄦ祦閴存潈浜嬩欢 + */ +public class MediaPublishEvent extends MediaEvent { + public MediaPublishEvent(Object source) { + super(source); + } + + public static MediaPublishEvent getInstance(Object source, OnPublishHookParam hookParam, MediaServer mediaServer){ + MediaPublishEvent mediaPublishEvent = new MediaPublishEvent(source); + mediaPublishEvent.setApp(hookParam.getApp()); + mediaPublishEvent.setStream(hookParam.getStream()); + mediaPublishEvent.setMediaServer(mediaServer); + mediaPublishEvent.setSchema(hookParam.getSchema()); + mediaPublishEvent.setParams(hookParam.getParams()); + return mediaPublishEvent; + } + + private String params; + + public String getParams() { + return params; + } + + public void setParams(String params) { + this.params = params; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaRecordMp4Event.java b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaRecordMp4Event.java new file mode 100644 index 0000000..093c3c2 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaRecordMp4Event.java @@ -0,0 +1,35 @@ +package com.genersoft.iot.vmp.media.event.media; + +import com.genersoft.iot.vmp.media.bean.RecordInfo; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; + +/** + * 褰曞儚鏂囦欢鐢熸垚浜嬩欢 + */ +public class MediaRecordMp4Event extends MediaEvent { + public MediaRecordMp4Event(Object source) { + super(source); + } + + private RecordInfo recordInfo; + + public static MediaRecordMp4Event getInstance(Object source, OnRecordMp4HookParam hookParam, MediaServer mediaServer){ + MediaRecordMp4Event mediaRecordMp4Event = new MediaRecordMp4Event(source); + mediaRecordMp4Event.setApp(hookParam.getApp()); + mediaRecordMp4Event.setStream(hookParam.getStream()); + RecordInfo recordInfo = RecordInfo.getInstance(hookParam); + mediaRecordMp4Event.setRecordInfo(recordInfo); + mediaRecordMp4Event.setMediaServer(mediaServer); + return mediaRecordMp4Event; + } + + public RecordInfo getRecordInfo() { + return recordInfo; + } + + public void setRecordInfo(RecordInfo recordInfo) { + this.recordInfo = recordInfo; + } + +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaRtpServerTimeoutEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaRtpServerTimeoutEvent.java new file mode 100644 index 0000000..b700dd5 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/media/MediaRtpServerTimeoutEvent.java @@ -0,0 +1,22 @@ +package com.genersoft.iot.vmp.media.event.media; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; + +/** + * RtpServer鏀舵祦瓒呮椂浜嬩欢 + */ +public class MediaRtpServerTimeoutEvent extends MediaEvent { + public MediaRtpServerTimeoutEvent(Object source) { + super(source); + } + + public static MediaRtpServerTimeoutEvent getInstance(Object source, OnStreamChangedHookParam hookParam, MediaServer mediaServer){ + MediaRtpServerTimeoutEvent mediaDepartureEven = new MediaRtpServerTimeoutEvent(source); + mediaDepartureEven.setApp(hookParam.getApp()); + mediaDepartureEven.setStream(hookParam.getStream()); + mediaDepartureEven.setSchema(hookParam.getSchema()); + mediaDepartureEven.setMediaServer(mediaServer); + return mediaDepartureEven; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaSendRtpStoppedEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaSendRtpStoppedEvent.java new file mode 100644 index 0000000..d37a4c2 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaSendRtpStoppedEvent.java @@ -0,0 +1,52 @@ +package com.genersoft.iot.vmp.media.event.mediaServer; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamNotFoundHookParam; +import org.springframework.context.ApplicationEvent; + +/** + * 鍙戦�佹祦鍋滄浜嬩欢 + */ +public class MediaSendRtpStoppedEvent extends ApplicationEvent { + public MediaSendRtpStoppedEvent(Object source) { + super(source); + } + + private String app; + + private String stream; + + private MediaServer mediaServer; + + public static MediaSendRtpStoppedEvent getInstance(Object source, OnStreamNotFoundHookParam hookParam, MediaServer mediaServer){ + MediaSendRtpStoppedEvent mediaDepartureEven = new MediaSendRtpStoppedEvent(source); + mediaDepartureEven.setApp(hookParam.getApp()); + mediaDepartureEven.setStream(hookParam.getStream()); + mediaDepartureEven.setMediaServer(mediaServer); + return mediaDepartureEven; + } + + public String getApp() { + return app; + } + + public void setApp(String app) { + this.app = app; + } + + public String getStream() { + return stream; + } + + public void setStream(String stream) { + this.stream = stream; + } + + public MediaServer getMediaServer() { + return mediaServer; + } + + public void setMediaServer(MediaServer mediaServer) { + this.mediaServer = mediaServer; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerChangeEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerChangeEvent.java new file mode 100644 index 0000000..ecbe332 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerChangeEvent.java @@ -0,0 +1,34 @@ +package com.genersoft.iot.vmp.media.event.mediaServer; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import org.springframework.context.ApplicationEvent; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MediaServerChangeEvent extends ApplicationEvent { + + public MediaServerChangeEvent(Object source) { + super(source); + } + + private List<MediaServer> mediaServerItemList; + + public List<MediaServer> getMediaServerItemList() { + return mediaServerItemList; + } + + public void setMediaServerItemList(List<MediaServer> mediaServerItemList) { + this.mediaServerItemList = mediaServerItemList; + } + + public void setMediaServerItemList(MediaServer... mediaServerItemArray) { + this.mediaServerItemList = new ArrayList<>(); + this.mediaServerItemList.addAll(Arrays.asList(mediaServerItemArray)); + } + + public void setMediaServerItem(List<MediaServer> mediaServerItemList) { + this.mediaServerItemList = mediaServerItemList; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerDeleteEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerDeleteEvent.java new file mode 100755 index 0000000..a716ff0 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerDeleteEvent.java @@ -0,0 +1,11 @@ +package com.genersoft.iot.vmp.media.event.mediaServer; + +/** + * zlm鍦ㄧ嚎浜嬩欢 + */ +public class MediaServerDeleteEvent extends MediaServerEventAbstract { + + public MediaServerDeleteEvent(Object source) { + super(source); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMEventAbstract.java b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerEventAbstract.java similarity index 62% rename from src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMEventAbstract.java rename to src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerEventAbstract.java index 8ffbdde..a9bf769 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMEventAbstract.java +++ b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerEventAbstract.java @@ -1,9 +1,8 @@ -package com.genersoft.iot.vmp.media.zlm.event; +package com.genersoft.iot.vmp.media.event.mediaServer; -import com.genersoft.iot.vmp.media.zlm.ZLMServerConfig; import org.springframework.context.ApplicationEvent; -public abstract class ZLMEventAbstract extends ApplicationEvent { +public abstract class MediaServerEventAbstract extends ApplicationEvent { private static final long serialVersionUID = 1L; @@ -11,7 +10,7 @@ private String mediaServerId; - public ZLMEventAbstract(Object source) { + public MediaServerEventAbstract(Object source) { super(source); } diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerOfflineEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerOfflineEvent.java new file mode 100755 index 0000000..2f9ac23 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerOfflineEvent.java @@ -0,0 +1,11 @@ +package com.genersoft.iot.vmp.media.event.mediaServer; + +/** + * zlm绂荤嚎浜嬩欢绫� + */ +public class MediaServerOfflineEvent extends MediaServerEventAbstract { + + public MediaServerOfflineEvent(Object source) { + super(source); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerOnlineEvent.java b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerOnlineEvent.java new file mode 100755 index 0000000..673dce4 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerOnlineEvent.java @@ -0,0 +1,11 @@ +package com.genersoft.iot.vmp.media.event.mediaServer; + +/** + * zlm鍦ㄧ嚎浜嬩欢 + */ +public class MediaServerOnlineEvent extends MediaServerEventAbstract { + + public MediaServerOnlineEvent(Object source) { + super(source); + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerStatusEventListener.java similarity index 70% rename from src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java rename to src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerStatusEventListener.java index bad8e56..2413f56 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMStatusEventListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/event/mediaServer/MediaServerStatusEventListener.java @@ -1,6 +1,5 @@ -package com.genersoft.iot.vmp.media.zlm.event; +package com.genersoft.iot.vmp.media.event.mediaServer; -import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamPushService; @@ -20,9 +19,9 @@ * @date: 2020骞�5鏈�6鏃� 涓嬪崍1:51:23 */ @Component -public class ZLMStatusEventListener { +public class MediaServerStatusEventListener { - private final static Logger logger = LoggerFactory.getLogger(ZLMStatusEventListener.class); + private final static Logger logger = LoggerFactory.getLogger(MediaServerStatusEventListener.class); @Autowired private IStreamPushService streamPushService; @@ -31,15 +30,12 @@ private IStreamProxyService streamProxyService; @Autowired - private IMediaServerService mediaServerService; - - @Autowired private IPlayService playService; @Async("taskExecutor") @EventListener - public void onApplicationEvent(ZLMOnlineEvent event) { - logger.info("[ZLM] 涓婄嚎 ID锛�" + event.getMediaServerId()); + public void onApplicationEvent(MediaServerOnlineEvent event) { + logger.info("[濯掍綋鑺傜偣] 涓婄嚎 ID锛�" + event.getMediaServerId()); streamPushService.zlmServerOnline(event.getMediaServerId()); streamProxyService.zlmServerOnline(event.getMediaServerId()); playService.zlmServerOnline(event.getMediaServerId()); @@ -47,11 +43,10 @@ @Async("taskExecutor") @EventListener - public void onApplicationEvent(ZLMOfflineEvent event) { + public void onApplicationEvent(MediaServerOfflineEvent event) { - logger.info("[ZLM] 绂荤嚎锛孖D锛�" + event.getMediaServerId()); + logger.info("[濯掍綋鑺傜偣] 绂荤嚎锛孖D锛�" + event.getMediaServerId()); // 澶勭悊ZLM绂荤嚎 - mediaServerService.zlmServerOffline(event.getMediaServerId()); streamProxyService.zlmServerOffline(event.getMediaServerId()); streamPushService.zlmServerOffline(event.getMediaServerId()); playService.zlmServerOffline(event.getMediaServerId()); diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java new file mode 100644 index 0000000..8739938 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaNodeServerService.java @@ -0,0 +1,61 @@ +package com.genersoft.iot.vmp.media.service; + +import com.genersoft.iot.vmp.common.CommonCallback; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; + +import java.util.List; +import java.util.Map; + +public interface IMediaNodeServerService { + int createRTPServer(MediaServer mediaServer, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode); + + void closeRtpServer(MediaServer mediaServer, String streamId); + + void closeRtpServer(MediaServer mediaServer, String streamId, CommonCallback<Boolean> callback); + + void closeStreams(MediaServer mediaServer, String app, String stream); + + Boolean updateRtpServerSSRC(MediaServer mediaServer, String stream, String ssrc); + + boolean checkNodeId(MediaServer mediaServer); + + void online(MediaServer mediaServer); + + MediaServer checkMediaServer(String ip, int port, String secret); + + boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc); + + boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName); + + List<StreamInfo> getMediaList(MediaServer mediaServer, String app, String stream, String callId); + + Boolean connectRtpServer(MediaServer mediaServer, String address, int port, String stream); + + void getSnap(MediaServer mediaServer, String streamUrl, int timeoutSec, int expireSec, String path, String fileName); + + MediaInfo getMediaInfo(MediaServer mediaServer, String app, String stream); + + Boolean pauseRtpCheck(MediaServer mediaServer, String streamKey); + + Boolean resumeRtpCheck(MediaServer mediaServer, String streamKey); + + String getFfmpegCmd(MediaServer mediaServer, String cmdKey); + + WVPResult<String> addFFmpegSource(MediaServer mediaServer, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey); + + WVPResult<String> addStreamProxy(MediaServer mediaServer, String app, String stream, String url, boolean enableAudio, boolean enableMp4, String rtpType); + + Boolean delFFmpegSource(MediaServer mediaServer, String streamKey); + + Boolean delStreamProxy(MediaServer mediaServer, String streamKey); + + Map<String, String> getFFmpegCMDs(MediaServer mediaServer); + + void startSendRtpPassive(MediaServer mediaServer, SendRtpItem sendRtpItem, Integer timeout); + + void startSendRtpStream(MediaServer mediaServer, SendRtpItem sendRtpItem); +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java new file mode 100755 index 0000000..fb56ab6 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/service/IMediaServerService.java @@ -0,0 +1,145 @@ +package com.genersoft.iot.vmp.media.service; + +import com.genersoft.iot.vmp.common.CommonCallback; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.service.bean.MediaServerLoad; +import com.genersoft.iot.vmp.service.bean.SSRCInfo; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; + +import java.util.List; +import java.util.Map; + +/** + * 濯掍綋鏈嶅姟鑺傜偣 + */ +public interface IMediaServerService { + + List<MediaServer> getAllOnlineList(); + + List<MediaServer> getAll(); + + List<MediaServer> getAllFromDatabase(); + + List<MediaServer> getAllOnline(); + + MediaServer getOne(String generalMediaServerId); + + void syncCatchFromDatabase(); + + MediaServer getMediaServerForMinimumLoad(Boolean hasAssist); + + void updateVmServer(List<MediaServer> mediaServerItemList); + + SSRCInfo openRTPServer(MediaServer mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, + boolean isPlayback, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode); + + void closeRTPServer(MediaServer mediaServerItem, String streamId); + + void closeRTPServer(MediaServer mediaServerItem, String streamId, CommonCallback<Boolean> callback); + Boolean updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc); + + void closeRTPServer(String mediaServerId, String streamId); + + void clearRTPServer(MediaServer mediaServerItem); + + void update(MediaServer mediaSerItem); + + void addCount(String mediaServerId); + + void removeCount(String mediaServerId); + + void releaseSsrc(String mediaServerItemId, String ssrc); + + void clearMediaServerForOnline(); + + void add(MediaServer mediaSerItem); + + void resetOnlineServerItem(MediaServer serverItem); + + MediaServer checkMediaServer(String ip, int port, String secret, String type); + + boolean checkMediaRecordServer(String ip, int port); + + void delete(String id); + + MediaServer getDefaultMediaServer(); + + MediaServerLoad getLoad(MediaServer mediaServerItem); + + List<MediaServer> getAllWithAssistPort(); + + MediaServer getOneFromDatabase(String id); + + boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc); + + boolean deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName); + + List<StreamInfo> getMediaList(MediaServer mediaInfo, String app, String stream, String callId); + + Boolean connectRtpServer(MediaServer mediaServerItem, String address, int port, String stream); + + void getSnap(MediaServer mediaServerItemInuse, String streamUrl, int timeoutSec, int expireSec, String path, String fileName); + + MediaInfo getMediaInfo(MediaServer mediaServerItem, String app, String stream); + + Boolean pauseRtpCheck(MediaServer mediaServerItem, String streamKey); + + boolean resumeRtpCheck(MediaServer mediaServerItem, String streamKey); + + String getFfmpegCmd(MediaServer mediaServer, String cmdKey); + + void closeStreams(MediaServer mediaServerItem, String app, String stream); + + WVPResult<String> addFFmpegSource(MediaServer mediaServerItem, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey); + + WVPResult<String> addStreamProxy(MediaServer mediaServerItem, String app, String stream, String url, boolean enableAudio, boolean enableMp4, String rtpType); + + Boolean delFFmpegSource(MediaServer mediaServerItem, String streamKey); + + Boolean delStreamProxy(MediaServer mediaServerItem, String streamKey); + + Map<String, String> getFFmpegCMDs(MediaServer mediaServer); + + /** + * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 閫氳繃zlm鎺ュ彛妫�鏌ユ槸鍚﹀瓨鍦� + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId,String addr, boolean authority); + + + /** + * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 閫氳繃zlm鎺ュ彛妫�鏌ユ槸鍚﹀瓨鍦�, 杩斿洖鐨刬p浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌 + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority); + + /** + * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴 + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String callId); + + /** + * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴锛岃繑鍥炵殑ip浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌 + * @param app + * @param stream + * @return + */ + StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServer, String app, String stream, MediaInfo mediaInfo, String addr, String callId, boolean isPlay); + + Boolean isStreamReady(MediaServer mediaServer, String rtp, String streamId); + + void startSendRtpPassive(MediaServer mediaServer, ParentPlatform platform, SendRtpItem sendRtpItem, Integer timeout); + + void startSendRtpStream(MediaServer mediaServer, ParentPlatform platform, SendRtpItem sendRtpItem); +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java new file mode 100755 index 0000000..6214ccb --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/service/impl/MediaServerServiceImpl.java @@ -0,0 +1,837 @@ +package com.genersoft.iot.vmp.media.service.impl; + +import com.baomidou.dynamic.datasource.annotation.DS; +import com.genersoft.iot.vmp.common.CommonCallback; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.MediaConfig; +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.conf.exception.ControllerException; +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; +import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerDeleteEvent; +import com.genersoft.iot.vmp.media.service.IMediaNodeServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; +import com.genersoft.iot.vmp.service.IInviteStreamService; +import com.genersoft.iot.vmp.service.bean.MediaServerLoad; +import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; +import com.genersoft.iot.vmp.service.bean.SSRCInfo; +import com.genersoft.iot.vmp.storager.IRedisCatchStorage; +import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; +import com.genersoft.iot.vmp.utils.DateUtil; +import com.genersoft.iot.vmp.utils.JsonUtil; +import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.ApplicationEventPublisher; +import org.springframework.context.event.EventListener; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.annotation.Async; +import org.springframework.stereotype.Service; +import org.springframework.util.ObjectUtils; + +import java.time.LocalDateTime; +import java.util.*; + +/** + * 濯掍綋鏈嶅姟鍣ㄨ妭鐐圭鐞� + */ +@Service +@DS("master") +public class MediaServerServiceImpl implements IMediaServerService { + + private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); + + @Autowired + private SSRCFactory ssrcFactory; + + @Autowired + private UserSetting userSetting; + + @Autowired + private MediaServerMapper mediaServerMapper; + + @Autowired + private IRedisCatchStorage redisCatchStorage; + + @Autowired + private IInviteStreamService inviteStreamService; + + @Autowired + private RedisTemplate<Object, Object> redisTemplate; + + @Autowired + private Map<String, IMediaNodeServerService> nodeServerServiceMap; + + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + + @Autowired + private MediaConfig mediaConfig; + + + + /** + * 娴佸埌鏉ョ殑澶勭悊 + */ + @Async("taskExecutor") + @org.springframework.context.event.EventListener + public void onApplicationEvent(MediaArrivalEvent event) { + if ("rtsp".equals(event.getSchema())) { + logger.info("娴佸彉鍖栵細娉ㄥ唽 app->{}, stream->{}", event.getApp(), event.getStream()); + addCount(event.getMediaServer().getId()); + } + } + + /** + * 娴佺寮�鐨勫鐞� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaDepartureEvent event) { + if ("rtsp".equals(event.getSchema())) { + logger.info("娴佸彉鍖栵細娉ㄩ攢, app->{}, stream->{}", event.getApp(), event.getStream()); + removeCount(event.getMediaServer().getId()); + } + } + + + /** + * 鍒濆鍖� + */ + @Override + public void updateVmServer(List<MediaServer> mediaServerList) { + logger.info("[濯掍綋鏈嶅姟鑺傜偣] 缂撳瓨鍒濆鍖� "); + for (MediaServer mediaServer : mediaServerList) { + if (ObjectUtils.isEmpty(mediaServer.getId())) { + continue; + } + // 鏇存柊 + if (!ssrcFactory.hasMediaServerSSRC(mediaServer.getId())) { + ssrcFactory.initMediaServerSSRC(mediaServer.getId(), null); + } + // 鏌ヨredis鏄惁瀛樺湪姝ediaServer + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + ":" + mediaServer.getId(); + Boolean hasKey = redisTemplate.hasKey(key); + if (hasKey != null && ! hasKey) { + redisTemplate.opsForValue().set(key, mediaServer); + } + } + } + + + @Override + public SSRCInfo openRTPServer(MediaServer mediaServer, String streamId, String presetSsrc, boolean ssrcCheck, + boolean isPlayback, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode) { + if (mediaServer == null || mediaServer.getId() == null) { + logger.info("[openRTPServer] 澶辫触, mediaServer == null || mediaServer.getId() == null"); + return null; + } + // 鑾峰彇mediaServer鍙敤鐨剆src + String ssrc; + if (presetSsrc != null) { + ssrc = presetSsrc; + }else { + if (isPlayback) { + ssrc = ssrcFactory.getPlayBackSsrc(mediaServer.getId()); + }else { + ssrc = ssrcFactory.getPlaySsrc(mediaServer.getId()); + } + } + + if (streamId == null) { + streamId = String.format("%08x", Long.parseLong(ssrc)).toUpperCase(); + } + if (ssrcCheck && tcpMode > 0) { + // 鐩墠zlm涓嶆敮鎸� tcp妯″紡鏇存柊ssrc锛屾殏鏃跺叧闂璼src鏍¢獙 + logger.warn("[openRTPServer] 骞冲彴瀵规帴鏃朵笅绾у彲鑳借嚜瀹氫箟ssrc锛屼絾鏄痶cp妯″紡zlm鏀舵祦鐩墠鏃犳硶鏇存柊ssrc锛屽彲鑳芥敹娴佽秴鏃讹紝姝ゆ椂璇蜂娇鐢╱dp鏀舵祦鎴栬�呭叧闂璼src鏍¢獙"); + } + int rtpServerPort; + if (mediaServer.isRtpEnable()) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[openRTPServer] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return null; + } + rtpServerPort = mediaNodeServerService.createRTPServer(mediaServer, streamId, ssrcCheck ? Long.parseLong(ssrc) : 0, port, onlyAuto, disableAudio, reUsePort, tcpMode); + } else { + rtpServerPort = mediaServer.getRtpProxyPort(); + } + return new SSRCInfo(rtpServerPort, ssrc, streamId); + } + + @Override + public void closeRTPServer(MediaServer mediaServer, String streamId) { + if (mediaServer == null) { + return; + } + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[closeRTPServer] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return; + } + mediaNodeServerService.closeRtpServer(mediaServer, streamId); + } + + @Override + public void closeRTPServer(MediaServer mediaServer, String streamId, CommonCallback<Boolean> callback) { + if (mediaServer == null) { + callback.run(false); + return; + } + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[closeRTPServer] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return; + } + mediaNodeServerService.closeRtpServer(mediaServer, streamId, callback); + } + + @Override + public void closeRTPServer(String mediaServerId, String streamId) { + MediaServer mediaServer = this.getOne(mediaServerId); + if (mediaServer == null) { + return; + } + if (mediaServer.isRtpEnable()) { + closeRTPServer(mediaServer, streamId); + } + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[closeRTPServer] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return; + } + mediaNodeServerService.closeStreams(mediaServer, "rtp", streamId); + } + + @Override + public Boolean updateRtpServerSSRC(MediaServer mediaServer, String streamId, String ssrc) { + if (mediaServer == null) { + return false; + } + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[updateRtpServerSSRC] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return false; + } + return mediaNodeServerService.updateRtpServerSSRC(mediaServer, streamId, ssrc); + } + + @Override + public void releaseSsrc(String mediaServerId, String ssrc) { + MediaServer mediaServer = getOne(mediaServerId); + if (mediaServer == null || ssrc == null) { + return; + } + ssrcFactory.releaseSsrc(mediaServerId, ssrc); + } + + /** + * 濯掍綋鏈嶅姟鑺傜偣 閲嶅惎鍚庨噸缃粬鐨勬帹娴佷俊鎭紝 TODO 缁欐鍦ㄤ娇鐢ㄧ殑璁惧鍙戦�佸仠姝㈠懡浠� + */ + @Override + public void clearRTPServer(MediaServer mediaServer) { + ssrcFactory.reset(mediaServer.getId()); + } + + + @Override + public void update(MediaServer mediaSerItem) { + mediaServerMapper.update(mediaSerItem); + MediaServer mediaServerInRedis = getOne(mediaSerItem.getId()); + MediaServer mediaServerInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); + if (mediaServerInDataBase == null) { + return; + } + mediaServerInDataBase.setStatus(mediaSerItem.isStatus()); + if (mediaServerInRedis == null || !ssrcFactory.hasMediaServerSSRC(mediaServerInDataBase.getId())) { + ssrcFactory.initMediaServerSSRC(mediaServerInDataBase.getId(),null); + } + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + ":" + mediaServerInDataBase.getId(); + redisTemplate.opsForValue().set(key, mediaServerInDataBase); + if (mediaServerInDataBase.isStatus()) { + resetOnlineServerItem(mediaServerInDataBase); + }else { + // 鍙戦�佷簨浠� + MediaServerChangeEvent event = new MediaServerChangeEvent(this); + event.setMediaServerItemList(mediaServerInDataBase); + applicationEventPublisher.publishEvent(event); + } + } + + + @Override + public List<MediaServer> getAllOnlineList() { + List<MediaServer> result = new ArrayList<>(); + List<Object> mediaServerKeys = RedisUtil.scan(redisTemplate, String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX+ userSetting.getServerId() + ":" )); + String onlineKey = VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(); + for (Object mediaServerKey : mediaServerKeys) { + String key = (String) mediaServerKey; + MediaServer mediaServer = JsonUtil.redisJsonToObject(redisTemplate, key, MediaServer.class); + if (Objects.isNull(mediaServer)) { + continue; + } + // 妫�鏌ョ姸鎬� + Double aDouble = redisTemplate.opsForZSet().score(onlineKey, mediaServer.getId()); + if (aDouble != null) { + mediaServer.setStatus(true); + } + result.add(mediaServer); + } + result.sort((serverItem1, serverItem2)->{ + int sortResult = 0; + LocalDateTime localDateTime1 = LocalDateTime.parse(serverItem1.getCreateTime(), DateUtil.formatter); + LocalDateTime localDateTime2 = LocalDateTime.parse(serverItem2.getCreateTime(), DateUtil.formatter); + + sortResult = localDateTime1.compareTo(localDateTime2); + return sortResult; + }); + return result; + } + + @Override + public List<MediaServer> getAll() { + List<MediaServer> mediaServerList = mediaServerMapper.queryAll(); + if (mediaServerList.isEmpty()) { + return new ArrayList<>(); + } + for (MediaServer mediaServer : mediaServerList) { + MediaServer mediaServerInRedis = getOne(mediaServer.getId()); + if (mediaServerInRedis != null) { + mediaServer.setStatus(mediaServerInRedis.isStatus()); + } + } + return mediaServerList; + } + + + @Override + public List<MediaServer> getAllFromDatabase() { + return mediaServerMapper.queryAll(); + } + + @Override + public List<MediaServer> getAllOnline() { + String key = VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(); + Set<Object> mediaServerIdSet = redisTemplate.opsForZSet().reverseRange(key, 0, -1); + + List<MediaServer> result = new ArrayList<>(); + if (mediaServerIdSet != null && mediaServerIdSet.size() > 0) { + for (Object mediaServerId : mediaServerIdSet) { + String mediaServerIdStr = (String) mediaServerId; + String serverKey = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + ":" + mediaServerIdStr; + result.add((MediaServer) redisTemplate.opsForValue().get(serverKey)); + } + } + Collections.reverse(result); + return result; + } + + /** + * 鑾峰彇鍗曚釜濯掍綋鏈嶅姟鑺傜偣鏈嶅姟鍣� + * @param mediaServerId 鏈嶅姟id + * @return mediaServer + */ + @Override + public MediaServer getOne(String mediaServerId) { + if (mediaServerId == null) { + return null; + } + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + ":" + mediaServerId; + return JsonUtil.redisJsonToObject(redisTemplate, key, MediaServer.class); + } + + + @Override + public MediaServer getDefaultMediaServer() { + return mediaServerMapper.queryDefault(); + } + + @Override + public void clearMediaServerForOnline() { + String key = VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(); + redisTemplate.delete(key); + } + + @Override + public void add(MediaServer mediaServer) { + mediaServer.setCreateTime(DateUtil.getNow()); + mediaServer.setUpdateTime(DateUtil.getNow()); + if (mediaServer.getHookAliveInterval() == null || mediaServer.getHookAliveInterval() == 0F) { + mediaServer.setHookAliveInterval(10F); + } + if (mediaServer.getType() == null) { + logger.info("[娣诲姞濯掍綋鑺傜偣] 澶辫触, mediaServer鐨勭被鍨嬶細涓虹┖"); + return; + } + if (mediaServerMapper.queryOne(mediaServer.getId()) != null) { + logger.info("[娣诲姞濯掍綋鑺傜偣] 澶辫触, 濯掍綋鏈嶅姟ID宸插瓨鍦紝璇蜂慨鏀瑰獟浣撴湇鍔″櫒閰嶇疆, {}", mediaServer.getId()); + throw new ControllerException(ErrorCode.ERROR100.getCode(),"淇濆瓨澶辫触锛屽獟浣撴湇鍔D [ " + mediaServer.getId() + " ] 宸插瓨鍦紝璇蜂慨鏀瑰獟浣撴湇鍔″櫒閰嶇疆"); + } + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[娣诲姞濯掍綋鑺傜偣] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return; + } + mediaServerMapper.add(mediaServer); + if (mediaServer.isStatus()) { + mediaNodeServerService.online(mediaServer); + }else { + // 鍙戦�佷簨浠� + MediaServerChangeEvent event = new MediaServerChangeEvent(this); + event.setMediaServerItemList(mediaServer); + applicationEventPublisher.publishEvent(event); + } + } + + @Override + public void resetOnlineServerItem(MediaServer serverItem) { + // 鏇存柊缂撳瓨 + String key = VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(); + // 浣跨敤zset鐨勫垎鏁颁綔涓哄綋鍓嶅苟鍙戦噺锛� 榛樿鍊艰缃负0 + if (redisTemplate.opsForZSet().score(key, serverItem.getId()) == null) { // 涓嶅瓨鍦ㄥ垯璁剧疆榛樿鍊� 宸插瓨鍦ㄥ垯閲嶇疆 + redisTemplate.opsForZSet().add(key, serverItem.getId(), 0L); + // 鏌ヨ鏈嶅姟娴佹暟閲� + int count = getMediaList(serverItem); + redisTemplate.opsForZSet().add(key, serverItem.getId(), count); + }else { + clearRTPServer(serverItem); + } + } + + private int getMediaList(MediaServer serverItem) { + + return 0; + } + + + @Override + public void addCount(String mediaServerId) { + if (mediaServerId == null) { + return; + } + String key = VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(); + redisTemplate.opsForZSet().incrementScore(key, mediaServerId, 1); + + } + + @Override + public void removeCount(String mediaServerId) { + String key = VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(); + redisTemplate.opsForZSet().incrementScore(key, mediaServerId, - 1); + } + + /** + * 鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣 + * @return mediaServer + */ + @Override + public MediaServer getMediaServerForMinimumLoad(Boolean hasAssist) { + String key = VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(); + Long size = redisTemplate.opsForZSet().zCard(key); + if (size == null || size == 0) { + logger.info("鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣鏃舵棤鍦ㄧ嚎鑺傜偣"); + return null; + } + + // 鑾峰彇鍒嗘暟鏈�浣庣殑锛屽強骞跺彂鏈�浣庣殑 + Set<Object> objects = redisTemplate.opsForZSet().range(key, 0, -1); + ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects); + MediaServer mediaServer = null; + if (hasAssist == null) { + String mediaServerId = (String)mediaServerObjectS.get(0); + mediaServer = getOne(mediaServerId); + }else if (hasAssist) { + for (Object mediaServerObject : mediaServerObjectS) { + String mediaServerId = (String)mediaServerObject; + MediaServer serverItem = getOne(mediaServerId); + if (serverItem.getRecordAssistPort() > 0) { + mediaServer = serverItem; + break; + } + } + }else if (!hasAssist) { + for (Object mediaServerObject : mediaServerObjectS) { + String mediaServerId = (String)mediaServerObject; + MediaServer serverItem = getOne(mediaServerId); + if (serverItem.getRecordAssistPort() == 0) { + mediaServer = serverItem; + break; + } + } + } + + return mediaServer; + } + + @Override + public MediaServer checkMediaServer(String ip, int port, String secret, String type) { + if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "姝よ繛鎺ュ凡瀛樺湪"); + } + + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(type); + if (mediaNodeServerService == null) { + logger.info("[closeRTPServer] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", type); + return null; + } + MediaServer mediaServer = mediaNodeServerService.checkMediaServer(ip, port, secret); + if (mediaServer != null) { + if (mediaServerMapper.queryOne(mediaServer.getId()) != null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "濯掍綋鏈嶅姟ID [" + mediaServer.getId() + " ] 宸插瓨鍦紝璇蜂慨鏀瑰獟浣撴湇鍔″櫒閰嶇疆"); + } + } + return mediaServer; + } + + @Override + public boolean checkMediaRecordServer(String ip, int port) { + boolean result = false; + OkHttpClient client = new OkHttpClient(); + String url = String.format("http://%s:%s/index/api/record", ip, port); + Request request = new Request.Builder() + .get() + .url(url) + .build(); + try { + Response response = client.newCall(request).execute(); + if (response != null) { + result = true; + } + } catch (Exception e) {} + + return result; + } + + @Override + public void delete(String id) { + mediaServerMapper.delOne(id); + redisTemplate.opsForZSet().remove(VideoManagerConstants.ONLINE_MEDIA_SERVERS_PREFIX + userSetting.getServerId(), id); + String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + ":" + id; + redisTemplate.delete(key); + // 鍙戦�佽妭鐐圭Щ闄ら�氱煡 + MediaServerDeleteEvent event = new MediaServerDeleteEvent(this); + event.setMediaServerId(id); + applicationEventPublisher.publishEvent(event); + } + + @Override + public MediaServer getOneFromDatabase(String mediaServerId) { + return mediaServerMapper.queryOne(mediaServerId); + } + + @Override + public void syncCatchFromDatabase() { + List<MediaServer> allInCatch = getAllOnlineList(); + List<MediaServer> allInDatabase = mediaServerMapper.queryAll(); + Map<String, MediaServer> mediaServerMap = new HashMap<>(); + + for (MediaServer mediaServer : allInDatabase) { + mediaServerMap.put(mediaServer.getId(), mediaServer); + } + for (MediaServer mediaServer : allInCatch) { + // 娓呴櫎鏁版嵁涓笉瀛樺湪浣唕edis缂撳瓨鏁版嵁 + if (!mediaServerMap.containsKey(mediaServer.getId())) { + delete(mediaServer.getId()); + } + } + } + + @Override + public MediaServerLoad getLoad(MediaServer mediaServer) { + MediaServerLoad result = new MediaServerLoad(); + result.setId(mediaServer.getId()); + result.setPush(redisCatchStorage.getPushStreamCount(mediaServer.getId())); + result.setProxy(redisCatchStorage.getProxyStreamCount(mediaServer.getId())); + + result.setGbReceive(inviteStreamService.getStreamInfoCount(mediaServer.getId())); + result.setGbSend(redisCatchStorage.getGbSendCount(mediaServer.getId())); + return result; + } + + @Override + public List<MediaServer> getAllWithAssistPort() { + return mediaServerMapper.queryAllWithAssistPort(); + } + + + @Override + public boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaInfo.getType()); + if (mediaNodeServerService == null) { + logger.info("[stopSendRtp] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaInfo.getType()); + return false; + } + return mediaNodeServerService.stopSendRtp(mediaInfo, app, stream, ssrc); + } + + @Override + public boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[stopSendRtp] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return false; + } + return mediaNodeServerService.deleteRecordDirectory(mediaServer, app, stream, date, fileName); + } + + @Override + public List<StreamInfo> getMediaList(MediaServer mediaServer, String app, String stream, String callId) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[getMediaList] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return new ArrayList<>(); + } + return mediaNodeServerService.getMediaList(mediaServer, app, stream, callId); + } + + @Override + public Boolean connectRtpServer(MediaServer mediaServer, String address, int port, String stream) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[connectRtpServer] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return false; + } + return mediaNodeServerService.connectRtpServer(mediaServer, address, port, stream); + } + + @Override + public void getSnap(MediaServer mediaServer, String streamUrl, int timeoutSec, int expireSec, String path, String fileName) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[getSnap] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return; + } + mediaNodeServerService.getSnap(mediaServer, streamUrl, timeoutSec, expireSec, path, fileName); + } + + @Override + public MediaInfo getMediaInfo(MediaServer mediaServer, String app, String stream) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[getMediaInfo] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return null; + } + return mediaNodeServerService.getMediaInfo(mediaServer, app, stream); + } + + @Override + public Boolean pauseRtpCheck(MediaServer mediaServer, String streamKey) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[pauseRtpCheck] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return false; + } + return mediaNodeServerService.pauseRtpCheck(mediaServer, streamKey); + } + + @Override + public boolean resumeRtpCheck(MediaServer mediaServer, String streamKey) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[pauseRtpCheck] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return false; + } + return mediaNodeServerService.resumeRtpCheck(mediaServer, streamKey); + } + + @Override + public String getFfmpegCmd(MediaServer mediaServer, String cmdKey) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[getFfmpegCmd] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return null; + } + return mediaNodeServerService.getFfmpegCmd(mediaServer, cmdKey); + } + + @Override + public void closeStreams(MediaServer mediaServer, String app, String stream) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[closeStreams] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return; + } + mediaNodeServerService.closeStreams(mediaServer, app, stream); + } + + @Override + public WVPResult<String> addFFmpegSource(MediaServer mediaServer, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[addFFmpegSource] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return WVPResult.fail(ErrorCode.ERROR400); + } + return mediaNodeServerService.addFFmpegSource(mediaServer, srcUrl, dstUrl, timeoutMs, enableAudio, enableMp4, ffmpegCmdKey); + } + + @Override + public WVPResult<String> addStreamProxy(MediaServer mediaServer, String app, String stream, String url, boolean enableAudio, boolean enableMp4, String rtpType) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[addStreamProxy] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return WVPResult.fail(ErrorCode.ERROR400); + } + return mediaNodeServerService.addStreamProxy(mediaServer, app, stream, url, enableAudio, enableMp4, rtpType); + } + + @Override + public Boolean delFFmpegSource(MediaServer mediaServer, String streamKey) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[delFFmpegSource] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return false; + } + return mediaNodeServerService.delFFmpegSource(mediaServer, streamKey); + } + + @Override + public Boolean delStreamProxy(MediaServer mediaServerItem, String streamKey) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServerItem.getType()); + if (mediaNodeServerService == null) { + logger.info("[delStreamProxy] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServerItem.getType()); + return false; + } + return mediaNodeServerService.delStreamProxy(mediaServerItem, streamKey); + } + + @Override + public Map<String, String> getFFmpegCMDs(MediaServer mediaServer) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[getFFmpegCMDs] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return new HashMap<>(); + } + return mediaNodeServerService.getFFmpegCMDs(mediaServer); + } + + @Override + public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServerItem, String app, String stream, MediaInfo mediaInfo, String callId) { + return getStreamInfoByAppAndStream(mediaServerItem, app, stream, mediaInfo, null, callId, true); + } + + @Override + public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr, boolean authority) { + StreamInfo streamInfo = null; + if (mediaServerId == null) { + mediaServerId = mediaConfig.getId(); + } + MediaServer mediaInfo = getOne(mediaServerId); + if (mediaInfo == null) { + return null; + } + String calld = null; + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream); + if (streamAuthorityInfo != null) { + calld = streamAuthorityInfo.getCallId(); + } + List<StreamInfo> streamInfoList = getMediaList(mediaInfo, app, stream, calld); + if (streamInfoList.isEmpty()) { + return null; + }else { + return streamInfoList.get(0); + } + } + + + + @Override + public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority) { + return getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, null, authority); + } + + @Override + public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServer, String app, String stream, MediaInfo mediaInfo, String addr, String callId, boolean isPlay) { + StreamInfo streamInfoResult = new StreamInfo(); + streamInfoResult.setStream(stream); + streamInfoResult.setApp(app); + if (addr == null) { + addr = mediaServer.getStreamIp(); + } + + streamInfoResult.setIp(addr); + streamInfoResult.setMediaServerId(mediaServer.getId()); + String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId; + streamInfoResult.setRtmp(addr, mediaServer.getRtmpPort(),mediaServer.getRtmpSSlPort(), app, stream, callIdParam); + streamInfoResult.setRtsp(addr, mediaServer.getRtspPort(),mediaServer.getRtspSSLPort(), app, stream, callIdParam); + + + if ("abl".equals(mediaServer.getType())) { + String flvFile = String.format("%s/%s.flv%s", app, stream, callIdParam); + streamInfoResult.setFlv(addr, mediaServer.getFlvPort(),mediaServer.getFlvSSLPort(), flvFile); + streamInfoResult.setWsFlv(addr, mediaServer.getWsFlvPort(),mediaServer.getWsFlvSSLPort(), flvFile); + }else { + String flvFile = String.format("%s/%s.live.flv%s", app, stream, callIdParam); + streamInfoResult.setFlv(addr, mediaServer.getFlvPort(),mediaServer.getFlvSSLPort(), flvFile); + streamInfoResult.setWsFlv(addr, mediaServer.getWsFlvPort(),mediaServer.getWsFlvSSLPort(), flvFile); + } + + streamInfoResult.setFmp4(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); + streamInfoResult.setHls(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); + streamInfoResult.setTs(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); + streamInfoResult.setRtc(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam, isPlay); + + streamInfoResult.setMediaInfo(mediaInfo); + return streamInfoResult; + } + + @Override + public Boolean isStreamReady(MediaServer mediaServer, String rtp, String streamId) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[isStreamReady] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + return false; + } + MediaInfo mediaInfo = mediaNodeServerService.getMediaInfo(mediaServer, rtp, streamId); + return mediaInfo != null; + } + + @Override + public void startSendRtpPassive(MediaServer mediaServer, ParentPlatform platform, SendRtpItem sendRtpItem, Integer timeout) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[startSendRtpPassive] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒癿ediaServer瀵瑰簲鐨勫疄鐜扮被"); + } + mediaNodeServerService.startSendRtpPassive(mediaServer, sendRtpItem, timeout); + sendPlatformStartPlayMsg(platform, sendRtpItem); + } + + @Override + public void startSendRtpStream(MediaServer mediaServer, ParentPlatform platform, SendRtpItem sendRtpItem) { + IMediaNodeServerService mediaNodeServerService = nodeServerServiceMap.get(mediaServer.getType()); + if (mediaNodeServerService == null) { + logger.info("[startSendRtpStream] 澶辫触, mediaServer鐨勭被鍨嬶細 {}锛屾湭鎵惧埌瀵瑰簲鐨勫疄鐜扮被", mediaServer.getType()); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒癿ediaServer瀵瑰簲鐨勫疄鐜扮被"); + } + logger.info("[寮�濮嬫帹娴乚 rtp/{}, 鐩爣={}:{}锛孲SRC={}, RTCP={}", sendRtpItem.getStream(), + sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp()); + mediaNodeServerService.startSendRtpStream(mediaServer, sendRtpItem); + sendPlatformStartPlayMsg(platform, sendRtpItem); + + } + + private void sendPlatformStartPlayMsg(ParentPlatform platform, SendRtpItem sendRtpItem) { + if (sendRtpItem.getPlayType() == InviteStreamType.PUSH && platform != null) { + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, sendRtpItem.getApp(), sendRtpItem.getStream(), + sendRtpItem.getChannelId(), platform.getServerGBId(), platform.getName(), userSetting.getServerId(), + sendRtpItem.getMediaServerId()); + messageForPushChannel.setPlatFormIndex(platform.getId()); + redisCatchStorage.sendPlatformStartPlayMsg(messageForPushChannel); + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java index 5735f37..6f6d5ea 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/AssistRESTfulUtils.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.utils.SSLSocketClientUtil; import okhttp3.*; import okhttp3.logging.HttpLoggingInterceptor; @@ -70,7 +70,7 @@ } - public JSONObject sendGet(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) { + public JSONObject sendGet(MediaServer mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) { OkHttpClient client = getClient(); if (mediaServerItem == null) { @@ -155,7 +155,7 @@ return responseJSON; } - public JSONObject sendPost(MediaServerItem mediaServerItem, String url, + public JSONObject sendPost(MediaServer mediaServerItem, String url, JSONObject param, ZLMRESTfulUtils.RequestCallback callback, Integer readTimeOut) { OkHttpClient client = getClient(readTimeOut); @@ -244,12 +244,12 @@ return responseJSON; } - public JSONObject getInfo(MediaServerItem mediaServerItem, RequestCallback callback){ + public JSONObject getInfo(MediaServer mediaServerItem, RequestCallback callback){ Map<String, Object> param = new HashMap<>(); return sendGet(mediaServerItem, "api/record/info",param, callback); } - public JSONObject addTask(MediaServerItem mediaServerItem, String app, String stream, String startTime, + public JSONObject addTask(MediaServer mediaServerItem, String app, String stream, String startTime, String endTime, String callId, List<String> filePathList, String remoteHost) { JSONObject videoTaskInfoJSON = new JSONObject(); @@ -266,7 +266,7 @@ return sendPost(mediaServerItem, urlStr, videoTaskInfoJSON, null, 30); } - public JSONObject queryTaskList(MediaServerItem mediaServerItem, String app, String stream, String callId, + public JSONObject queryTaskList(MediaServer mediaServerItem, String app, String stream, String callId, String taskId, Boolean isEnd, String scheme) { Map<String, Object> param = new HashMap<>(); if (!ObjectUtils.isEmpty(app)) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java index 3f28d02..7fffc10 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/SendRtpPortManager.java @@ -3,7 +3,7 @@ import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import org.apache.commons.lang3.math.NumberUtils; import org.slf4j.Logger; @@ -30,7 +30,7 @@ private final String KEY = "VM_MEDIA_SEND_RTP_PORT_"; - public synchronized int getNextPort(MediaServerItem mediaServer) { + public synchronized int getNextPort(MediaServer mediaServer) { if (mediaServer == null) { logger.warn("[鍙戦�佺鍙g鐞哴 鍙傛暟閿欒锛宮ediaServer涓篘ULL"); return -1; @@ -83,6 +83,7 @@ } private synchronized int getSendPort(int startPort, int endPort, String sendIndexKey, Map<Integer, SendRtpItem> sendRtpItemMap){ + // TODO 杩欓噷鏀逛负鍙彇鍋舵暟绔彛 RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(sendIndexKey , redisTemplate.getConnectionFactory()); if (redisAtomicInteger.get() < startPort) { redisAtomicInteger.set(startPort); 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 6076db4..f5b1b6c 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMHttpHookListener.java @@ -2,55 +2,40 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.common.InviteInfo; -import com.genersoft.iot.vmp.common.InviteSessionType; -import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.common.VideoManagerConstants; import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; -import com.genersoft.iot.vmp.gb28181.bean.*; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.session.AudioBroadcastManager; -import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; -import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.media.zlm.dto.HookType; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; -import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; +import com.genersoft.iot.vmp.media.bean.ResultForOnPublish; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.event.media.*; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaSendRtpStoppedEvent; +import com.genersoft.iot.vmp.media.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig; import com.genersoft.iot.vmp.media.zlm.dto.hook.*; +import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerKeepaliveEvent; +import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerStartEvent; import com.genersoft.iot.vmp.service.*; -import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; -import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; -import com.genersoft.iot.vmp.utils.DateUtil; -import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; -import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; -import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; -import com.genersoft.iot.vmp.vmanager.bean.StreamContent; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.context.ApplicationEventPublisher; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import org.springframework.util.ObjectUtils; import org.springframework.web.bind.annotation.*; -import org.springframework.web.context.request.async.DeferredResult; import javax.servlet.http.HttpServletRequest; -import javax.sip.InvalidArgumentException; -import javax.sip.SipException; -import java.text.ParseException; import java.util.HashMap; -import java.util.List; import java.util.Map; -import java.util.UUID; /** * @description:閽堝 ZLMediaServer鐨刪ook浜嬩欢鐩戝惉 @@ -106,7 +91,7 @@ private ZLMMediaListManager zlmMediaListManager; @Autowired - private ZlmHttpHookSubscribe subscribe; + private HookSubscribe subscribe; @Autowired private UserSetting userSetting; @@ -130,25 +115,25 @@ @Autowired private RedisTemplate<Object, Object> redisTemplate; + @Autowired + private ApplicationEventPublisher applicationEventPublisher; + /** * 鏈嶅姟鍣ㄥ畾鏃朵笂鎶ユ椂闂达紝涓婃姤闂撮殧鍙厤缃紝榛樿10s涓婃姤涓�娆� */ @ResponseBody - @PostMapping(value = "/on_server_keepalive", produces = "application/json;charset=UTF-8") public HookResult onServerKeepalive(@RequestBody OnServerKeepaliveHookParam param) { - - - taskExecutor.execute(() -> { - List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_keepalive); - if (subscribes != null && !subscribes.isEmpty()) { - for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { - subscribe.response(null, param); - } + try { + HookZlmServerKeepaliveEvent event = new HookZlmServerKeepaliveEvent(this); + MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); + if (mediaServerItem != null) { + event.setMediaServerItem(mediaServerItem); + applicationEventPublisher.publishEvent(event); } - }); - mediaServerService.updateMediaServerKeepalive(param.getMediaServerId(), param.getData()); - + }catch (Exception e) { + logger.info("[ZLM-HOOK-蹇冭烦] 鍙戦�侀�氱煡澶辫触 ", e); + } return HookResult.SUCCESS(); } @@ -156,32 +141,17 @@ * 鎾斁鍣ㄩ壌鏉冧簨浠讹紝rtsp/rtmp/http-flv/ws-flv/hls鐨勬挱鏀鹃兘灏嗚Е鍙戞閴存潈浜嬩欢銆� */ @ResponseBody - @PostMapping(value = "/on_play", produces = "application/json;charset=UTF-8") public HookResult onPlay(@RequestBody OnPlayHookParam param) { - if (logger.isDebugEnabled()) { - logger.debug("[ZLM HOOK] 鎾斁閴存潈锛歿}->{}", param.getMediaServerId(), param); - } - String mediaServerId = param.getMediaServerId(); - taskExecutor.execute(() -> { - JSONObject json = (JSONObject) JSON.toJSON(param); - ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_play, json); - if (subscribe != null) { - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); - if (mediaInfo != null) { - subscribe.response(mediaInfo, param); - } - } - }); - if (!"rtp".equals(param.getApp())) { - Map<String, String> paramMap = urlParamToMap(param.getParams()); - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); - if (streamAuthorityInfo != null && streamAuthorityInfo.getCallId() != null && !streamAuthorityInfo.getCallId().equals(paramMap.get("callId"))) { - return new HookResult(401, "Unauthorized"); - } + Map<String, String> paramMap = urlParamToMap(param.getParams()); + // 瀵逛簬鎾斁娴佽繘琛岄壌鏉� + boolean authenticateResult = mediaService.authenticatePlay(param.getApp(), param.getStream(), paramMap.get("callId")); + if (!authenticateResult) { + logger.info("[ZLM HOOK] 鎾斁閴存潈 澶辫触锛歿}->{}", param.getMediaServerId(), param); + return new HookResult(401, "Unauthorized"); } - + logger.info("[ZLM HOOK] 鎾斁閴存潈鎴愬姛锛歿}->{}", param.getMediaServerId(), param); return HookResult.SUCCESS(); } @@ -195,136 +165,24 @@ JSONObject json = (JSONObject) JSON.toJSON(param); logger.info("[ZLM HOOK]鎺ㄦ祦閴存潈锛歿}->{}", param.getMediaServerId(), param); + // TODO 鍔犲揩澶勭悊閫熷害 String mediaServerId = json.getString("mediaServerId"); - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); - if (mediaInfo == null) { - return new HookResultForOnPublish(200, "success"); - } - // 鎺ㄦ祦閴存潈鐨勫鐞� - if (!"rtp".equals(param.getApp())) { - StreamProxyItem stream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); - if (stream != null) { - HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); - result.setEnable_audio(stream.isEnableAudio()); - result.setEnable_mp4(stream.isEnableMp4()); - return result; - } - if (userSetting.getPushAuthority()) { - // 鎺ㄦ祦閴存潈 - if (param.getParams() == null) { - logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯蹇呰鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)"); - return new HookResultForOnPublish(401, "Unauthorized"); - } - Map<String, String> paramMap = urlParamToMap(param.getParams()); - String sign = paramMap.get("sign"); - if (sign == null) { - logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯蹇呰鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)"); - return new HookResultForOnPublish(401, "Unauthorized"); - } - // 鎺ㄦ祦鑷畾涔夋挱鏀鹃壌鏉冪爜 - String callId = paramMap.get("callId"); - // 閴存潈閰嶇疆 - boolean hasAuthority = userService.checkPushAuthority(callId, sign); - if (!hasAuthority) { - logger.info("鎺ㄦ祦閴存潈澶辫触锛� sign 鏃犳潈闄�: callId={}. sign={}", callId, sign); - return new HookResultForOnPublish(401, "Unauthorized"); - } - StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); - streamAuthorityInfo.setCallId(callId); - streamAuthorityInfo.setSign(sign); - // 閴存潈閫氳繃 - redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); - } - } else { - zlmMediaListManager.sendStreamEvent(param.getApp(), param.getStream(), param.getMediaServerId()); + MediaServer mediaServer = mediaServerService.getOne(mediaServerId); + if (mediaServer == null) { + return new HookResultForOnPublish(0, "success"); } - - HookResultForOnPublish result = HookResultForOnPublish.SUCCESS(); - result.setEnable_audio(true); - taskExecutor.execute(() -> { - ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_publish, json); - if (subscribe != null) { - subscribe.response(mediaInfo, param); - } - }); - - // 鏄惁褰曞儚 - if ("rtp".equals(param.getApp())) { - result.setEnable_mp4(userSetting.getRecordSip()); - } else { - result.setEnable_mp4(userSetting.isRecordPushLive()); + ResultForOnPublish resultForOnPublish = mediaService.authenticatePublish(mediaServer, param.getApp(), param.getStream(), param.getParams()); + if (resultForOnPublish != null) { + HookResultForOnPublish successResult = HookResultForOnPublish.getInstance(resultForOnPublish); + logger.info("[ZLM HOOK]鎺ㄦ祦閴存潈 鍝嶅簲锛歿}->{}->>>>{}", param.getMediaServerId(), param, successResult); + return successResult; + }else { + HookResultForOnPublish fail = HookResultForOnPublish.Fail(); + logger.info("[ZLM HOOK]鎺ㄦ祦閴存潈 鍝嶅簲锛歿}->{}->>>>{}", param.getMediaServerId(), param, fail); + return fail; } - // 鍥芥爣娴� - if ("rtp".equals(param.getApp())) { - - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); - - // 鍗曠鍙fā寮忎笅淇敼娴� ID - if (!mediaInfo.isRtpEnable() && inviteInfo == null) { - String ssrc = String.format("%010d", Long.parseLong(param.getStream(), 16)); - inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc); - if (inviteInfo != null) { - result.setStream_replace(inviteInfo.getStream()); - logger.info("[ZLM HOOK]鎺ㄦ祦閴存潈 stream: {} 鏇挎崲涓� {}", param.getStream(), inviteInfo.getStream()); - } - } - - // 璁剧疆闊抽淇℃伅鍙婂綍鍒朵俊鎭� - List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, param.getStream()); - if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) { - - // 涓哄綍鍒跺浗鏍囨ā鎷熶竴涓壌鏉冧俊鎭�, 鏂逛究鍚庣画鍐欏叆褰曞儚鏂囦欢鏃朵娇鐢� - StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); - streamAuthorityInfo.setApp(param.getApp()); - streamAuthorityInfo.setStream(ssrcTransactionForAll.get(0).getStream()); - streamAuthorityInfo.setCallId(ssrcTransactionForAll.get(0).getSipTransactionInfo().getCallId()); - - redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), ssrcTransactionForAll.get(0).getStream(), streamAuthorityInfo); - - String deviceId = ssrcTransactionForAll.get(0).getDeviceId(); - String channelId = ssrcTransactionForAll.get(0).getChannelId(); - DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); - if (deviceChannel != null) { - result.setEnable_audio(deviceChannel.isHasAudio()); - } - // 濡傛灉鏄綍鍍忎笅杞藉氨璁剧疆瑙嗛闂撮殧鍗佺 - if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) { - // 鑾峰彇褰曞儚鐨勬�绘椂闀匡紝鐒跺悗璁剧疆涓鸿繖涓棰戠殑鏃堕暱 - InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, param.getStream()); - if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) { - String startTime = inviteInfoForDownload.getStreamInfo().getStartTime(); - String endTime = inviteInfoForDownload.getStreamInfo().getEndTime(); - long difference = DateUtil.getDifference(startTime, endTime) / 1000; - result.setMp4_max_second((int) difference); - result.setEnable_mp4(true); - // 璁剧疆涓�2淇濊瘉寰楀埌鐨刴p4鐨勬椂闀挎槸姝e父鐨� - result.setModify_stamp(2); - } - } - // 濡傛灉鏄痶alk瀵硅锛屽垯榛樿鑾峰彇澹伴煶 - if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.TALK) { - result.setEnable_audio(true); - } - } - } else if (param.getApp().equals("broadcast")) { - result.setEnable_audio(true); - } else if (param.getApp().equals("talk")) { - result.setEnable_audio(true); - } - if (param.getApp().equalsIgnoreCase("rtp")) { - String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + param.getStream(); - OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo) redisTemplate.opsForValue().get(receiveKey); - - String receiveKeyForPS = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_" + param.getStream(); - OtherPsSendInfo otherPsSendInfo = (OtherPsSendInfo) redisTemplate.opsForValue().get(receiveKeyForPS); - if (otherRtpSendInfo != null || otherPsSendInfo != null) { - result.setEnable_mp4(true); - } - } - logger.info("[ZLM HOOK]鎺ㄦ祦閴存潈 鍝嶅簲锛歿}->{}->>>>{}", param.getMediaServerId(), param, result); - return result; } @@ -335,226 +193,20 @@ @PostMapping(value = "/on_stream_changed", produces = "application/json;charset=UTF-8") public HookResult onStreamChanged(@RequestBody OnStreamChangedHookParam param) { - if (param.isRegist()) { - logger.info("[ZLM HOOK] 娴佹敞鍐�, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); - } else { - logger.info("[ZLM HOOK] 娴佹敞閿�, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); + MediaServer mediaServer = mediaServerService.getOne(param.getMediaServerId()); + if (mediaServer == null) { + return HookResult.SUCCESS(); } - JSONObject json = (JSONObject) JSON.toJSON(param); - taskExecutor.execute(() -> { - ZlmHttpHookSubscribe.Event subscribe = this.subscribe.sendNotify(HookType.on_stream_changed, json); - MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); - if (mediaInfo == null) { - logger.info("[ZLM HOOK] 娴佸彉鍖栨湭鎵惧埌ZLM, {}", param.getMediaServerId()); - return; - } - if (subscribe != null) { - subscribe.response(mediaInfo, param); - } - - List<OnStreamChangedHookParam.MediaTrack> tracks = param.getTracks(); - // TODO 閲嶆瀯姝ゅ閫昏緫 - if (param.isRegist()) { - // 澶勭悊娴佹敞鍐岀殑閴存潈淇℃伅锛� 娴佹敞閿�杩欓噷涓嶅啀鍒犻櫎閴存潈淇℃伅锛屼笅娆℃潵浜嗘柊鐨勯壌鏉冧俊鎭細瀵瑰氨鐨勮繘琛岃鐩� - if (param.getOriginType() == OriginType.RTMP_PUSH.ordinal() - || param.getOriginType() == OriginType.RTSP_PUSH.ordinal() - || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); - if (streamAuthorityInfo == null) { - streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(param); - } else { - streamAuthorityInfo.setOriginType(param.getOriginType()); - streamAuthorityInfo.setOriginTypeStr(param.getOriginTypeStr()); - } - redisCatchStorage.updateStreamAuthorityInfo(param.getApp(), param.getStream(), streamAuthorityInfo); - } - } - if ("rtsp".equals(param.getSchema())) { - logger.info("娴佸彉鍖栵細娉ㄥ唽->{}, app->{}, stream->{}", param.isRegist(), param.getApp(), param.getStream()); - if (param.isRegist()) { - mediaServerService.addCount(param.getMediaServerId()); - } else { - mediaServerService.removeCount(param.getMediaServerId()); - } - - int updateStatusResult = streamProxyService.updateStatus(param.isRegist(), param.getApp(), param.getStream()); - if (updateStatusResult > 0) { - - } - - if ("rtp".equals(param.getApp()) && !param.isRegist()) { - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); - if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) { - inviteStreamService.removeInviteInfo(inviteInfo); - storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); - } - } else if ("broadcast".equals(param.getApp())) { - // 璇煶瀵硅鎺ㄦ祦 stream闇�瑕佹弧瓒虫牸寮廳eviceId_channelId - if (param.getStream().indexOf("_") > 0) { - String[] streamArray = param.getStream().split("_"); - if (streamArray.length == 2) { - String deviceId = streamArray[0]; - String channelId = streamArray[1]; - Device device = deviceService.getDevice(deviceId); - if (device != null) { - if (param.isRegist()) { - if (audioBroadcastManager.exit(deviceId, channelId)) { - playService.stopAudioBroadcast(deviceId, channelId); - } - // 寮�鍚闊冲璁查�氶亾 - try { - playService.audioBroadcastCmd(device, channelId, mediaInfo, param.getApp(), param.getStream(), 60, false, (msg) -> { - logger.info("[璇煶瀵硅] 閫氶亾寤虹珛鎴愬姛, device: {}, channel: {}", deviceId, channelId); - }); - } catch (InvalidArgumentException | ParseException | SipException e) { - logger.error("[鍛戒护鍙戦�佸け璐 璇煶瀵硅: {}", e.getMessage()); - } - } else { - // 娴佹敞閿� - playService.stopAudioBroadcast(deviceId, channelId); - } - } else { - logger.info("[璇煶瀵硅] 鏈壘鍒拌澶囷細{}", deviceId); - } - } - } - } else if ("talk".equals(param.getApp())) { - // 璇煶瀵硅鎺ㄦ祦 stream闇�瑕佹弧瓒虫牸寮廳eviceId_channelId - if (param.getStream().indexOf("_") > 0) { - String[] streamArray = param.getStream().split("_"); - if (streamArray.length == 2) { - String deviceId = streamArray[0]; - String channelId = streamArray[1]; - Device device = deviceService.getDevice(deviceId); - if (device != null) { - if (param.isRegist()) { - if (audioBroadcastManager.exit(deviceId, channelId)) { - playService.stopAudioBroadcast(deviceId, channelId); - } - // 寮�鍚闊冲璁查�氶亾 - playService.talkCmd(device, channelId, mediaInfo, param.getStream(), (msg) -> { - logger.info("[璇煶瀵硅] 閫氶亾寤虹珛鎴愬姛, device: {}, channel: {}", deviceId, channelId); - }); - } else { - // 娴佹敞閿� - playService.stopTalk(device, channelId, param.isRegist()); - } - } else { - logger.info("[璇煶瀵硅] 鏈壘鍒拌澶囷細{}", deviceId); - } - } - } - - } else { - if (!"rtp".equals(param.getApp())) { - String type = OriginType.values()[param.getOriginType()].getType(); - if (param.isRegist()) { - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo( - param.getApp(), param.getStream()); - String callId = null; - if (streamAuthorityInfo != null) { - callId = streamAuthorityInfo.getCallId(); - } - StreamInfo streamInfoByAppAndStream = mediaService.getStreamInfoByAppAndStream(mediaInfo, - param.getApp(), param.getStream(), tracks, callId); - param.setStreamInfo(new StreamContent(streamInfoByAppAndStream)); - redisCatchStorage.addStream(mediaInfo, type, param.getApp(), param.getStream(), param); - if (param.getOriginType() == OriginType.RTSP_PUSH.ordinal() - || param.getOriginType() == OriginType.RTMP_PUSH.ordinal() - || param.getOriginType() == OriginType.RTC_PUSH.ordinal()) { - param.setSeverId(userSetting.getServerId()); - zlmMediaListManager.addPush(param); - - // 鍐椾綑鏁版嵁锛岃嚜宸辩郴缁熶腑鑷敤 - redisCatchStorage.addPushListItem(param.getApp(), param.getStream(), param); - } - } else { - // 鍏煎娴佹敞閿�鏃剁被鍨嬩粠redis璁板綍鑾峰彇 - OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo( - param.getApp(), param.getStream(), param.getMediaServerId()); - if (onStreamChangedHookParam != null) { - type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType(); - redisCatchStorage.removeStream(mediaInfo.getId(), type, param.getApp(), param.getStream()); - if ("PUSH".equalsIgnoreCase(type)) { - // 鍐椾綑鏁版嵁锛岃嚜宸辩郴缁熶腑鑷敤 - redisCatchStorage.removePushListItem(param.getApp(), param.getStream(), param.getMediaServerId()); - } - } - GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); - if (gbStream != null) { -// eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); - } - zlmMediaListManager.removeMedia(param.getApp(), param.getStream()); - } - GbStream gbStream = storager.getGbStream(param.getApp(), param.getStream()); - if (gbStream != null) { - if (userSetting.isUsePushingAsStatus()) { - eventPublisher.catalogEventPublishForStream(null, gbStream, param.isRegist() ? CatalogEvent.ON : CatalogEvent.OFF); - } - } - if (type != null) { - // 鍙戦�佹祦鍙樺寲redis娑堟伅 - JSONObject jsonObject = new JSONObject(); - jsonObject.put("serverId", userSetting.getServerId()); - jsonObject.put("app", param.getApp()); - jsonObject.put("stream", param.getStream()); - jsonObject.put("register", param.isRegist()); - jsonObject.put("mediaServerId", param.getMediaServerId()); - redisCatchStorage.sendStreamChangeMsg(type, jsonObject); - } - } - } - if (!param.isRegist()) { - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream()); - if (!sendRtpItems.isEmpty()) { - for (SendRtpItem sendRtpItem : sendRtpItems) { - if (sendRtpItem == null) { - continue; - } - - if (sendRtpItem.getApp().equals(param.getApp())) { - logger.info(sendRtpItem.toString()); - if (userSetting.getServerId().equals(sendRtpItem.getServerId())) { - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, - sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), - sendRtpItem.getPlatformId(), null, userSetting.getServerId(), param.getMediaServerId()); - // 閫氱煡鍏朵粬wvp鍋滄鍙戞祦 - redisCatchStorage.sendPushStreamClose(messageForPushChannel); - }else { - String platformId = sendRtpItem.getPlatformId(); - ParentPlatform platform = storager.queryParentPlatByServerGBId(platformId); - Device device = deviceService.getDevice(platformId); - - try { - if (platform != null) { - commanderFroPlatform.streamByeCmd(platform, sendRtpItem); - redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), - sendRtpItem.getCallId(), sendRtpItem.getStream()); - } else { - cmder.streamByeCmd(device, sendRtpItem.getChannelId(), param.getStream(), sendRtpItem.getCallId()); - if (sendRtpItem.getPlayType().equals(InviteStreamType.BROADCAST) - || sendRtpItem.getPlayType().equals(InviteStreamType.TALK)) { - AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); - if (audioBroadcastCatch != null) { - // 鏉ヨ嚜涓婄骇骞冲彴鐨勫仠姝㈠璁� - logger.info("[鍋滄瀵硅] 鏉ヨ嚜涓婄骇锛屽钩鍙帮細{}, 閫氶亾锛歿}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); - audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); - } - } - } - } catch (SipException | InvalidArgumentException | ParseException | - SsrcTransactionNotFoundException e) { - logger.error("[鍛戒护鍙戦�佸け璐 鍙戦�丅YE: {}", e.getMessage()); - } - } - - } - } - } - } - } - }); + if (param.isRegist()) { + logger.info("[ZLM HOOK] 娴佹敞鍐�, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); + MediaArrivalEvent mediaArrivalEvent = MediaArrivalEvent.getInstance(this, param, mediaServer); + applicationEventPublisher.publishEvent(mediaArrivalEvent); + } else { + logger.info("[ZLM HOOK] 娴佹敞閿�, {}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); + MediaDepartureEvent mediaDepartureEvent = MediaDepartureEvent.getInstance(this, param, mediaServer); + applicationEventPublisher.publishEvent(mediaDepartureEvent); + } return HookResult.SUCCESS(); } @@ -568,104 +220,9 @@ logger.info("[ZLM HOOK]娴佹棤浜鸿鐪嬶細{}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); JSONObject ret = new JSONObject(); - ret.put("code", 0); - // 鍥芥爣绫诲瀷鐨勬祦 - if ("rtp".equals(param.getApp())) { - ret.put("close", userSetting.getStreamOnDemand()); - // 鍥芥爣娴侊紝 鐐规挱/褰曞儚鍥炴斁/褰曞儚涓嬭浇 - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, param.getStream()); - // 鐐规挱 - if (inviteInfo != null) { - // 褰曞儚涓嬭浇 - if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) { - ret.put("close", false); - return ret; - } - // 鏀跺埌鏃犱汉瑙傜湅璇存槑娴佷篃娌℃湁鍦ㄥ線涓婄骇鎺ㄩ�� - if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChannelId( - inviteInfo.getChannelId()); - if (!sendRtpItems.isEmpty()) { - for (SendRtpItem sendRtpItem : sendRtpItems) { - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); - try { - commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); - } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage()); - } - redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), - sendRtpItem.getCallId(), sendRtpItem.getStream()); - if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) { - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, - sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), - sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); - messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); - redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); - } - } - } - } - Device device = deviceService.getDevice(inviteInfo.getDeviceId()); - if (device != null) { - try { - // 澶氭煡璇竴娆¢槻姝㈠凡缁忚澶勭悊浜� - InviteInfo info = inviteStreamService.getInviteInfo(inviteInfo.getType(), - inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); - if (info != null) { - cmder.streamByeCmd(device, inviteInfo.getChannelId(), - inviteInfo.getStream(), null); - } else { - logger.info("[鏃犱汉瑙傜湅] 鏈壘鍒拌澶囩殑鐐规挱淇℃伅锛� {}锛� 娴侊細{}", inviteInfo.getDeviceId(), param.getStream()); - } - } catch (InvalidArgumentException | ParseException | SipException | - SsrcTransactionNotFoundException e) { - logger.error("[鏃犱汉瑙傜湅]鐐规挱锛� 鍙戦�丅YE澶辫触 {}", e.getMessage()); - } - } else { - logger.info("[鏃犱汉瑙傜湅] 鏈壘鍒拌澶囷細 {}锛屾祦锛歿}", inviteInfo.getDeviceId(), param.getStream()); - } - inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), - inviteInfo.getChannelId(), inviteInfo.getStream()); - storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); - return ret; - } - SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, param.getStream(), null); - if (sendRtpItem != null && "talk".equals(sendRtpItem.getApp())) { - ret.put("close", false); - return ret; - } - } else if ("talk".equals(param.getApp()) || "broadcast".equals(param.getApp())) { - ret.put("close", false); - } else { - // 闈炲浗鏍囨祦 鎺ㄦ祦/鎷夋祦浠g悊 - // 鎷夋祦浠g悊 - StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); - if (streamProxyItem != null) { - if (streamProxyItem.isEnableRemoveNoneReader()) { - // 鏃犱汉瑙傜湅鑷姩绉婚櫎 - ret.put("close", true); - streamProxyService.del(param.getApp(), param.getStream()); - String url = streamProxyItem.getUrl() != null ? streamProxyItem.getUrl() : streamProxyItem.getSrcUrl(); - logger.info("[{}/{}]<-[{}] 鎷夋祦浠g悊鏃犱汉瑙傜湅宸茬粡绉婚櫎", param.getApp(), param.getStream(), url); - } else if (streamProxyItem.isEnableDisableNoneReader()) { - // 鏃犱汉瑙傜湅鍋滅敤 - ret.put("close", true); - // 淇敼鏁版嵁 - streamProxyService.stop(param.getApp(), param.getStream()); - } else { - // 鏃犱汉瑙傜湅涓嶅仛澶勭悊 - ret.put("close", false); - } - return ret; - } - // TODO 鎺ㄦ祦鍏锋湁涓诲姩鎬э紝鏆傛椂涓嶅仛澶勭悊 -// StreamPushItem streamPushItem = streamPushService.getPush(app, streamId); -// if (streamPushItem != null) { -// // TODO 鍙戦�佸仠姝� -// -// } - } + boolean close = mediaService.closeStreamOnNoneReader(param.getMediaServerId(), param.getApp(), param.getStream(), param.getSchema()); + ret.put("code", close); return ret; } @@ -674,119 +231,17 @@ */ @ResponseBody @PostMapping(value = "/on_stream_not_found", produces = "application/json;charset=UTF-8") - public DeferredResult<HookResult> onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param) { + public HookResult onStreamNotFound(@RequestBody OnStreamNotFoundHookParam param) { logger.info("[ZLM HOOK] 娴佹湭鎵惧埌锛歿}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); - DeferredResult<HookResult> defaultResult = new DeferredResult<>(); - MediaServerItem mediaInfo = mediaServerService.getOne(param.getMediaServerId()); - if (!userSetting.isAutoApplyPlay() || mediaInfo == null) { - defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); - return defaultResult; + MediaServer mediaServer = mediaServerService.getOne(param.getMediaServerId()); + if (!userSetting.isAutoApplyPlay() || mediaServer == null) { + return HookResult.SUCCESS(); } - - if ("rtp".equals(param.getApp())) { - String[] s = param.getStream().split("_"); - if ((s.length != 2 && s.length != 4)) { - defaultResult.setResult(HookResult.SUCCESS()); - return defaultResult; - } - String deviceId = s[0]; - String channelId = s[1]; - Device device = redisCatchStorage.getDevice(deviceId); - if (device == null || !device.isOnLine()) { - defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); - return defaultResult; - } - DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); - if (deviceChannel == null) { - defaultResult.setResult(new HookResult(ErrorCode.ERROR404.getCode(), ErrorCode.ERROR404.getMsg())); - return defaultResult; - } - if (s.length == 2) { - logger.info("[ZLM HOOK] 棰勮娴佹湭鎵惧埌, 鍙戣捣鑷姩鐐规挱锛歿}->{}->{}/{}", param.getMediaServerId(), param.getSchema(), param.getApp(), param.getStream()); - - RequestMessage msg = new RequestMessage(); - String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; - boolean exist = resultHolder.exist(key, null); - msg.setKey(key); - String uuid = UUID.randomUUID().toString(); - msg.setId(uuid); - DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); - - result.onTimeout(() -> { - logger.info("[ZLM HOOK] 棰勮娴佽嚜鍔ㄧ偣鎾�, 绛夊緟瓒呮椂"); - msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "鐐规挱瓒呮椂")); - resultHolder.invokeAllResult(msg); - inviteStreamService.removeInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); - storager.stopPlay(deviceId, channelId); - }); - - resultHolder.put(key, uuid, result); - - if (!exist) { - playService.play(mediaInfo, deviceId, channelId, null, (code, message, data) -> { - msg.setData(new HookResult(code, message)); - resultHolder.invokeResult(msg); - }); - } - return result; - } else if (s.length == 4) { - // 姝ゆ椂涓哄綍鍍忓洖鏀撅紝 褰曞儚鍥炴斁鏍煎紡涓�> 璁惧ID_閫氶亾ID_寮�濮嬫椂闂確缁撴潫鏃堕棿 - String startTimeStr = s[2]; - String endTimeStr = s[3]; - if (startTimeStr == null || endTimeStr == null || startTimeStr.length() != 14 || endTimeStr.length() != 14) { - defaultResult.setResult(HookResult.SUCCESS()); - return defaultResult; - } - String startTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(startTimeStr); - String endTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(endTimeStr); - logger.info("[ZLM HOOK] 鍥炴斁娴佹湭鎵惧埌, 鍙戣捣鑷姩鐐规挱锛歿}->{}->{}/{}-{}-{}", - param.getMediaServerId(), param.getSchema(), - param.getApp(), param.getStream(), - startTime, endTime - ); - RequestMessage msg = new RequestMessage(); - String key = DeferredResultHolder.CALLBACK_CMD_PLAYBACK + deviceId + channelId; - boolean exist = resultHolder.exist(key, null); - msg.setKey(key); - String uuid = UUID.randomUUID().toString(); - msg.setId(uuid); - DeferredResult<HookResult> result = new DeferredResult<>(userSetting.getPlayTimeout().longValue()); - - result.onTimeout(() -> { - logger.info("[ZLM HOOK] 鍥炴斁娴佽嚜鍔ㄧ偣鎾�, 绛夊緟瓒呮椂"); - // 閲婃斁rtpserver - msg.setData(new HookResult(ErrorCode.ERROR100.getCode(), "鐐规挱瓒呮椂")); - resultHolder.invokeResult(msg); - }); - - resultHolder.put(key, uuid, result); - - if (!exist) { - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaInfo, param.getStream(), null, - device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); - playService.playBack(mediaInfo, ssrcInfo, deviceId, channelId, startTime, endTime, (code, message, data) -> { - msg.setData(new HookResult(code, message)); - resultHolder.invokeResult(msg); - }); - } - return result; - } else { - defaultResult.setResult(HookResult.SUCCESS()); - return defaultResult; - } - - } else { - // 鎷夋祦浠g悊 - StreamProxyItem streamProxyByAppAndStream = streamProxyService.getStreamProxyByAppAndStream(param.getApp(), param.getStream()); - if (streamProxyByAppAndStream != null && streamProxyByAppAndStream.isEnableDisableNoneReader()) { - streamProxyService.start(param.getApp(), param.getStream()); - } - DeferredResult<HookResult> result = new DeferredResult<>(); - result.setResult(HookResult.SUCCESS()); - return result; - } + MediaNotFoundEvent mediaNotFoundEvent = MediaNotFoundEvent.getInstance(this, param, mediaServer); + applicationEventPublisher.publishEvent(mediaNotFoundEvent); + return HookResult.SUCCESS(); } /** @@ -800,15 +255,16 @@ ZLMServerConfig zlmServerConfig = JSON.to(ZLMServerConfig.class, jsonObject); zlmServerConfig.setIp(request.getRemoteAddr()); logger.info("[ZLM HOOK] zlm 鍚姩 " + zlmServerConfig.getGeneralMediaServerId()); - taskExecutor.execute(() -> { - List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_server_started); - if (subscribes != null && !subscribes.isEmpty()) { - for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { - subscribe.response(null, zlmServerConfig); - } + try { + HookZlmServerStartEvent event = new HookZlmServerStartEvent(this); + MediaServer mediaServerItem = mediaServerService.getOne(zlmServerConfig.getMediaServerId()); + if (mediaServerItem != null) { + event.setMediaServerItem(mediaServerItem); + applicationEventPublisher.publishEvent(event); } - mediaServerService.zlmServerOnline(zlmServerConfig); - }); + }catch (Exception e) { + logger.info("[ZLM-HOOK-ZLM鍚姩] 鍙戦�侀�氱煡澶辫触 ", e); + } return HookResult.SUCCESS(); } @@ -826,22 +282,16 @@ if (!"rtp".equals(param.getApp())) { return HookResult.SUCCESS(); } - taskExecutor.execute(() -> { - List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(param.getStream()); - if (sendRtpItems.size() > 0) { - for (SendRtpItem sendRtpItem : sendRtpItems) { - ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); - ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); - try { - commanderFroPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); - } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage()); - } - redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), - sendRtpItem.getCallId(), sendRtpItem.getStream()); - } + try { + MediaSendRtpStoppedEvent event = new MediaSendRtpStoppedEvent(this); + MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); + if (mediaServerItem != null) { + event.setMediaServer(mediaServerItem); + applicationEventPublisher.publishEvent(event); } - }); + }catch (Exception e) { + logger.info("[ZLM-HOOK-rtp鍙戦�佸叧闂璢 鍙戦�侀�氱煡澶辫触 ", e); + } return HookResult.SUCCESS(); } @@ -855,14 +305,17 @@ param) { logger.info("[ZLM HOOK] rtpServer鏀舵祦瓒呮椂锛歿}->{}({})", param.getMediaServerId(), param.getStream_id(), param.getSsrc()); - taskExecutor.execute(() -> { - List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_rtp_server_timeout); - if (subscribes != null && !subscribes.isEmpty()) { - for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { - subscribe.response(null, param); - } + try { + MediaRtpServerTimeoutEvent event = new MediaRtpServerTimeoutEvent(this); + MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); + if (mediaServerItem != null) { + event.setMediaServer(mediaServerItem); + event.setApp("rtp"); + applicationEventPublisher.publishEvent(event); } - }); + }catch (Exception e) { + logger.info("[ZLM-HOOK-rtpServer鏀舵祦瓒呮椂] 鍙戦�侀�氱煡澶辫触 ", e); + } return HookResult.SUCCESS(); } @@ -875,16 +328,16 @@ public HookResult onRecordMp4(HttpServletRequest request, @RequestBody OnRecordMp4HookParam param) { logger.info("[ZLM HOOK] 褰曞儚瀹屾垚浜嬩欢锛歿}->{}", param.getMediaServerId(), param.getFile_path()); - taskExecutor.execute(() -> { - List<ZlmHttpHookSubscribe.Event> subscribes = this.subscribe.getSubscribes(HookType.on_record_mp4); - if (subscribes != null && !subscribes.isEmpty()) { - for (ZlmHttpHookSubscribe.Event subscribe : subscribes) { - subscribe.response(null, param); - } + try { + MediaServer mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); + if (mediaServerItem != null) { + MediaRecordMp4Event event = MediaRecordMp4Event.getInstance(this, param, mediaServerItem); + event.setMediaServer(mediaServerItem); + applicationEventPublisher.publishEvent(event); } - cloudRecordService.addRecord(param); - - }); + }catch (Exception e) { + logger.info("[ZLM-HOOK-rtpServer鏀舵祦瓒呮椂] 鍙戦�侀�氱煡澶辫触 ", e); + } return HookResult.SUCCESS(); } 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 cbc5fde..84df2e7 100755 --- 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,12 +2,13 @@ import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.GbStream; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; import com.genersoft.iot.vmp.media.zlm.dto.*; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.service.IStreamPushService; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; import com.genersoft.iot.vmp.storager.dao.PlatformGbStreamMapper; @@ -31,12 +32,6 @@ private Logger logger = LoggerFactory.getLogger("ZLMMediaListManager"); @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; - - @Autowired - private IRedisCatchStorage redisCatchStorage; - - @Autowired private IVideoManagerStorage storager; @Autowired @@ -55,7 +50,7 @@ private StreamPushMapper streamPushMapper; @Autowired - private ZlmHttpHookSubscribe subscribe; + private HookSubscribe subscribe; @Autowired private UserSetting userSetting; @@ -95,9 +90,9 @@ } public void sendStreamEvent(String app, String stream, String mediaServerId) { - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId); // 鏌ョ湅鎺ㄦ祦鐘舵�� - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream); + Boolean streamReady = mediaServerService.isStreamReady(mediaServerItem, app, stream); if (streamReady != null && streamReady) { ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(app, stream); if (channelOnlineEventLister != null) { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java new file mode 100644 index 0000000..707ea01 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaNodeServerService.java @@ -0,0 +1,349 @@ +package com.genersoft.iot.vmp.media.zlm; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.common.CommonCallback; +import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.conf.exception.ControllerException; +import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.service.IMediaNodeServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig; +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; +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 org.springframework.util.ObjectUtils; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service("zlm") +public class ZLMMediaNodeServerService implements IMediaNodeServerService { + + private final static Logger logger = LoggerFactory.getLogger(ZLMMediaNodeServerService.class); + + @Autowired + private ZLMRESTfulUtils zlmresTfulUtils; + + @Autowired + private ZLMServerFactory zlmServerFactory; + + @Value("${sip.ip}") + private String sipIp; + + @Override + public int createRTPServer(MediaServer mediaServer, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean disableAudio, Boolean reUsePort, Integer tcpMode) { + return zlmServerFactory.createRTPServer(mediaServer, streamId, ssrc, port, onlyAuto, reUsePort, tcpMode); + } + + @Override + public void closeRtpServer(MediaServer mediaServer, String streamId) { + zlmServerFactory.closeRtpServer(mediaServer, streamId); + } + + @Override + public void closeRtpServer(MediaServer mediaServer, String streamId, CommonCallback<Boolean> callback) { + zlmServerFactory.closeRtpServer(mediaServer, streamId, callback); + } + + @Override + public void closeStreams(MediaServer mediaServer, String app, String stream) { + zlmresTfulUtils.closeStreams(mediaServer, app, stream); + } + + @Override + public Boolean updateRtpServerSSRC(MediaServer mediaServer, String streamId, String ssrc) { + return zlmServerFactory.updateRtpServerSSRC(mediaServer, streamId, ssrc); + } + + @Override + public boolean checkNodeId(MediaServer mediaServer) { + if (mediaServer == null) { + return false; + } + JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServer); + if (responseJSON != null) { + JSONArray data = responseJSON.getJSONArray("data"); + if (data != null && !data.isEmpty()) { + ZLMServerConfig zlmServerConfig= JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); + return zlmServerConfig.getGeneralMediaServerId().equals(mediaServer.getId()); + }else { + return false; + } + + }else { + return false; + } + } + + @Override + public void online(MediaServer mediaServer) { + + } + + @Override + public MediaServer checkMediaServer(String ip, int port, String secret) { + MediaServer mediaServer = new MediaServer(); + mediaServer.setIp(ip); + mediaServer.setHttpPort(port); + mediaServer.setSecret(secret); + JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServer); + if (responseJSON == null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "杩炴帴澶辫触"); + } + JSONArray data = responseJSON.getJSONArray("data"); + if (data == null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "璇诲彇閰嶇疆澶辫触"); + } + ZLMServerConfig zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); + if (zlmServerConfig == null) { + throw new ControllerException(ErrorCode.ERROR100.getCode(), "璇诲彇閰嶇疆澶辫触"); + } + mediaServer.setId(zlmServerConfig.getGeneralMediaServerId()); + mediaServer.setHttpSSlPort(zlmServerConfig.getHttpPort()); + mediaServer.setRtmpPort(zlmServerConfig.getRtmpPort()); + mediaServer.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); + mediaServer.setRtspPort(zlmServerConfig.getRtspPort()); + mediaServer.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); + mediaServer.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); + mediaServer.setStreamIp(ip); + mediaServer.setHookIp(sipIp.split(",")[0]); + mediaServer.setSdpIp(ip); + mediaServer.setType("zlm"); + return mediaServer; + } + + @Override + public boolean stopSendRtp(MediaServer mediaInfo, String app, String stream, String ssrc) { + Map<String, Object> param = new HashMap<>(); + param.put("vhost", "__defaultVhost__"); + param.put("app", app); + param.put("stream", stream); + if (!ObjectUtils.isEmpty(ssrc)) { + param.put("ssrc", ssrc); + } + JSONObject jsonObject = zlmresTfulUtils.stopSendRtp(mediaInfo, param); + return (jsonObject != null && jsonObject.getInteger("code") == 0); + + } + + @Override + public boolean deleteRecordDirectory(MediaServer mediaServer, String app, String stream, String date, String fileName) { + logger.info("[zlm-deleteRecordDirectory] 鍒犻櫎纾佺洏鏂囦欢, server: {} {}:{}->{}/{}", mediaServer.getId(), app, stream, date, fileName); + JSONObject jsonObject = zlmresTfulUtils.deleteRecordDirectory(mediaServer, app, + stream, date, fileName); + if (jsonObject.getInteger("code") == 0) { + return true; + }else { + logger.info("[zlm-deleteRecordDirectory] 鍒犻櫎纾佺洏鏂囦欢閿欒, server: {} {}:{}->{}/{}, 缁撴灉锛� {}", mediaServer.getId(), app, stream, date, fileName, jsonObject); + return false; + } + } + + @Override + public List<StreamInfo> getMediaList(MediaServer mediaServer, String app, String stream, String callId) { + List<StreamInfo> streamInfoList = new ArrayList<>(); + JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaServer, app, stream); + if (mediaList != null) { + if (mediaList.getInteger("code") == 0) { + JSONArray data = mediaList.getJSONArray("data"); + if (data == null) { + return null; + } + JSONObject mediaJSON = data.getJSONObject(0); + MediaInfo mediaInfo = MediaInfo.getInstance(mediaJSON, mediaServer); + StreamInfo streamInfo = getStreamInfoByAppAndStream(mediaServer, app, stream, mediaInfo, callId, true); + if (streamInfo != null) { + streamInfoList.add(streamInfo); + } + } + } + return streamInfoList; + } + + public StreamInfo getStreamInfoByAppAndStream(MediaServer mediaServer, String app, String stream, MediaInfo mediaInfo, String callId, boolean isPlay) { + StreamInfo streamInfoResult = new StreamInfo(); + streamInfoResult.setStream(stream); + streamInfoResult.setApp(app); + String addr = mediaServer.getStreamIp(); + streamInfoResult.setIp(addr); + streamInfoResult.setMediaServerId(mediaServer.getId()); + String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId; + streamInfoResult.setRtmp(addr, mediaServer.getRtmpPort(),mediaServer.getRtmpSSlPort(), app, stream, callIdParam); + streamInfoResult.setRtsp(addr, mediaServer.getRtspPort(),mediaServer.getRtspSSLPort(), app, stream, callIdParam); + String flvFile = String.format("%s/%s.live.flv%s", app, stream, callIdParam); + streamInfoResult.setFlv(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), flvFile); + streamInfoResult.setWsFlv(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), flvFile); + streamInfoResult.setFmp4(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); + streamInfoResult.setHls(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); + streamInfoResult.setTs(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam); + streamInfoResult.setRtc(addr, mediaServer.getHttpPort(),mediaServer.getHttpSSlPort(), app, stream, callIdParam, isPlay); + + streamInfoResult.setMediaInfo(mediaInfo); + streamInfoResult.setOriginType(mediaInfo.getOriginType()); + return streamInfoResult; + } + + @Override + public Boolean connectRtpServer(MediaServer mediaServer, String address, int port, String stream) { + JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServer, address, port, stream); + logger.info("[TCP涓诲姩杩炴帴瀵规柟] 缁撴灉锛� {}", jsonObject); + return jsonObject.getInteger("code") == 0; + } + + @Override + public void getSnap(MediaServer mediaServer, String streamUrl, int timeoutSec, int expireSec, String path, String fileName) { + zlmresTfulUtils.getSnap(mediaServer, streamUrl, timeoutSec, expireSec, path, fileName); + } + + @Override + public MediaInfo getMediaInfo(MediaServer mediaServer, String app, String stream) { + JSONObject jsonObject = zlmresTfulUtils.getMediaInfo(mediaServer, app, "rtsp", stream); + if (jsonObject.getInteger("code") != 0) { + return null; + } + return MediaInfo.getInstance(jsonObject, mediaServer); + } + + @Override + public Boolean pauseRtpCheck(MediaServer mediaServer, String streamKey) { + JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServer, streamKey); + return jsonObject.getInteger("code") == 0; + } + + @Override + public Boolean resumeRtpCheck(MediaServer mediaServer, String streamKey) { + JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServer, streamKey); + return jsonObject.getInteger("code") == 0; + } + + @Override + public String getFfmpegCmd(MediaServer mediaServer, String cmdKey) { + JSONObject jsonObject = zlmresTfulUtils.getMediaServerConfig(mediaServer); + if (jsonObject.getInteger("code") != 0) { + logger.warn("[getFfmpegCmd] 鑾峰彇娴佸獟浣撻厤缃け璐�"); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "鑾峰彇娴佸獟浣撻厤缃け璐�"); + } + JSONArray dataArray = jsonObject.getJSONArray("data"); + JSONObject mediaServerConfig = dataArray.getJSONObject(0); + if (ObjectUtils.isEmpty(cmdKey)) { + cmdKey = "ffmpeg.cmd"; + } + return mediaServerConfig.getString(cmdKey); + } + + @Override + public WVPResult<String> addFFmpegSource(MediaServer mediaServer, String srcUrl, String dstUrl, int timeoutMs, boolean enableAudio, boolean enableMp4, String ffmpegCmdKey) { + JSONObject jsonObject = zlmresTfulUtils.addFFmpegSource(mediaServer, srcUrl, dstUrl, timeoutMs, enableAudio, enableMp4, ffmpegCmdKey); + if (jsonObject.getInteger("code") != 0) { + logger.warn("[getFfmpegCmd] 娣诲姞FFMPEG浠g悊澶辫触"); + return WVPResult.fail(ErrorCode.ERROR100.getCode(), "娣诲姞FFMPEG浠g悊澶辫触"); + }else { + JSONObject data = jsonObject.getJSONObject("data"); + if (data == null) { + return WVPResult.fail(ErrorCode.ERROR100.getCode(), "浠g悊缁撴灉寮傚父锛� " + jsonObject); + }else { + return WVPResult.success(data.getString("key")); + } + } + } + + @Override + public WVPResult<String> addStreamProxy(MediaServer mediaServer, String app, String stream, String url, boolean enableAudio, boolean enableMp4, String rtpType) { + JSONObject jsonObject = zlmresTfulUtils.addStreamProxy(mediaServer, app, stream, url, enableAudio, enableMp4, rtpType); + if (jsonObject.getInteger("code") != 0) { + return WVPResult.fail(ErrorCode.ERROR100.getCode(), "娣诲姞浠g悊澶辫触"); + }else { + JSONObject data = jsonObject.getJSONObject("data"); + if (data == null) { + return WVPResult.fail(ErrorCode.ERROR100.getCode(), "浠g悊缁撴灉寮傚父锛� " + jsonObject); + }else { + return WVPResult.success(data.getString("key")); + } + } + } + + @Override + public Boolean delFFmpegSource(MediaServer mediaServer, String streamKey) { + JSONObject jsonObject = zlmresTfulUtils.delFFmpegSource(mediaServer, streamKey); + return jsonObject.getInteger("code") == 0; + } + + @Override + public Boolean delStreamProxy(MediaServer mediaServer, String streamKey) { + JSONObject jsonObject = zlmresTfulUtils.delStreamProxy(mediaServer, streamKey); + return jsonObject.getInteger("code") == 0; + } + + @Override + public Map<String, String> getFFmpegCMDs(MediaServer mediaServer) { + Map<String, String> result = new HashMap<>(); + JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServer); + if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0 + && mediaServerConfigResuly.getJSONArray("data").size() > 0){ + JSONObject mediaServerConfig = mediaServerConfigResuly.getJSONArray("data").getJSONObject(0); + + for (String key : mediaServerConfig.keySet()) { + if (key.startsWith("ffmpeg.cmd")){ + result.put(key, mediaServerConfig.getString(key)); + } + } + } + return result; + } + + @Override + public void startSendRtpPassive(MediaServer mediaServer, SendRtpItem sendRtpItem, Integer timeout) { + Map<String, Object> param = new HashMap<>(12); + param.put("vhost","__defaultVhost__"); + param.put("app", sendRtpItem.getApp()); + param.put("stream", sendRtpItem.getStream()); + param.put("ssrc", sendRtpItem.getSsrc()); + param.put("src_port", sendRtpItem.getLocalPort()); + param.put("pt", sendRtpItem.getPt()); + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); + param.put("is_udp", sendRtpItem.isTcp() ? "0" : "1"); + param.put("recv_stream_id", sendRtpItem.getReceiveStream()); + if (timeout != null) { + param.put("close_delay_ms", timeout); + } + + JSONObject jsonObject = zlmServerFactory.startSendRtpPassive(mediaServer, param, null); + if (jsonObject == null || jsonObject.getInteger("code") != 0 ) { + throw new ControllerException(jsonObject.getInteger("code"), jsonObject.getString("msg")); + } + } + + @Override + public void startSendRtpStream(MediaServer mediaServer, SendRtpItem sendRtpItem) { + Map<String, Object> param = new HashMap<>(12); + param.put("vhost", "__defaultVhost__"); + param.put("app", sendRtpItem.getApp()); + param.put("stream", sendRtpItem.getStream()); + param.put("ssrc", sendRtpItem.getSsrc()); + param.put("src_port", sendRtpItem.getLocalPort()); + param.put("pt", sendRtpItem.getPt()); + param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); + param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); + param.put("is_udp", sendRtpItem.isTcp() ? "0" : "1"); + if (!sendRtpItem.isTcp()) { + // udp妯″紡涓嬪紑鍚痳tcp淇濇椿 + param.put("udp_rtcp_timeout", sendRtpItem.isRtcp() ? "1" : "0"); + } + param.put("dst_url", sendRtpItem.getIp()); + param.put("dst_port", sendRtpItem.getPort()); + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServer, param); + if (jsonObject == null || jsonObject.getInteger("code") != 0 ) { + throw new ControllerException(jsonObject.getInteger("code"), jsonObject.getString("msg")); + } + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaServerStatusManger.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaServerStatusManger.java new file mode 100644 index 0000000..cdf1e3f --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMMediaServerStatusManger.java @@ -0,0 +1,306 @@ +package com.genersoft.iot.vmp.media.zlm; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONArray; +import com.alibaba.fastjson2.JSONObject; +import com.genersoft.iot.vmp.conf.DynamicTask; +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerChangeEvent; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaServerDeleteEvent; +import com.genersoft.iot.vmp.media.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.ZLMServerConfig; +import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerKeepaliveEvent; +import com.genersoft.iot.vmp.media.zlm.event.HookZlmServerStartEvent; +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.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; +import org.springframework.util.ObjectUtils; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +/** + * 绠$悊zlm娴佸獟浣撹妭鐐圭殑鐘舵�� + */ +@Component +public class ZLMMediaServerStatusManger { + + private final static Logger logger = LoggerFactory.getLogger(ZLMMediaServerStatusManger.class); + + private final Map<Object, MediaServer> offlineZlmPrimaryMap = new ConcurrentHashMap<>(); + private final Map<Object, MediaServer> offlineZlmsecondaryMap = new ConcurrentHashMap<>(); + private final Map<Object, Long> offlineZlmTimeMap = new ConcurrentHashMap<>(); + + @Autowired + private ZLMRESTfulUtils zlmresTfulUtils; + + @Autowired + private IMediaServerService mediaServerService; + + @Autowired + private DynamicTask dynamicTask; + + @Value("${server.ssl.enabled:false}") + private boolean sslEnabled; + + @Value("${server.port}") + private Integer serverPort; + + @Value("${server.servlet.context-path:}") + private String serverServletContextPath; + + @Autowired + private UserSetting userSetting; + + private final String type = "zlm"; + + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaServerChangeEvent event) { + if (event.getMediaServerItemList() == null + || event.getMediaServerItemList().isEmpty()) { + return; + } + for (MediaServer mediaServerItem : event.getMediaServerItemList()) { + if (!type.equals(mediaServerItem.getType())) { + continue; + } + logger.info("[ZLM-娣诲姞寰呬笂绾胯妭鐐筣 ID锛�" + mediaServerItem.getId()); + offlineZlmPrimaryMap.put(mediaServerItem.getId(), mediaServerItem); + offlineZlmTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis()); + execute(); + } + } + + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(HookZlmServerStartEvent event) { + if (event.getMediaServerItem() == null + || !type.equals(event.getMediaServerItem().getType()) + || event.getMediaServerItem().isStatus()) { + return; + } + MediaServer serverItem = mediaServerService.getOne(event.getMediaServerItem().getId()); + if (serverItem == null) { + return; + } + logger.info("[ZLM-HOOK浜嬩欢-鏈嶅姟鍚姩] ID锛�" + event.getMediaServerItem().getId()); + online(serverItem, null); + } + + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(HookZlmServerKeepaliveEvent event) { + if (event.getMediaServerItem() == null) { + return; + } + MediaServer serverItem = mediaServerService.getOne(event.getMediaServerItem().getId()); + if (serverItem == null) { + return; + } + logger.info("[ZLM-HOOK浜嬩欢-蹇冭烦] ID锛�" + event.getMediaServerItem().getId()); + online(serverItem, null); + } + + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaServerDeleteEvent event) { + if (event.getMediaServerId() == null) { + return; + } + logger.info("[ZLM-鑺傜偣琚Щ闄 ID锛�" + event.getMediaServerId()); + offlineZlmPrimaryMap.remove(event.getMediaServerId()); + offlineZlmsecondaryMap.remove(event.getMediaServerId()); + offlineZlmTimeMap.remove(event.getMediaServerId()); + } + + @Scheduled(fixedDelay = 10*1000) //姣忛殧10绉掓鏌ヤ竴娆� + public void execute(){ + // 鍒濇鍔犲叆鐨勭绾胯妭鐐逛細鍦�30鍒嗛挓鍐咃紝姣忛棿闅斿崄绉掑皾璇曚竴娆★紝30鍒嗛挓鍚庡鏋滀粛鐒舵病鏈変笂绾匡紝鍒欐瘡闅�30鍒嗛挓灏濊瘯涓�娆¤繛鎺� + if (offlineZlmPrimaryMap.isEmpty() && offlineZlmsecondaryMap.isEmpty()) { + return; + } + if (!offlineZlmPrimaryMap.isEmpty()) { + for (MediaServer mediaServerItem : offlineZlmPrimaryMap.values()) { + if (offlineZlmTimeMap.get(mediaServerItem.getId()) < System.currentTimeMillis() - 30*60*1000) { + offlineZlmsecondaryMap.put(mediaServerItem.getId(), mediaServerItem); + offlineZlmPrimaryMap.remove(mediaServerItem.getId()); + continue; + } + logger.info("[ZLM-灏濊瘯杩炴帴] ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + JSONObject responseJson = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); + ZLMServerConfig zlmServerConfig = null; + if (responseJson == null) { + logger.info("[ZLM-灏濊瘯杩炴帴]澶辫触, ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + continue; + } + JSONArray data = responseJson.getJSONArray("data"); + if (data == null || data.isEmpty()) { + logger.info("[ZLM-灏濊瘯杩炴帴]澶辫触, ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + }else { + zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); + initPort(mediaServerItem, zlmServerConfig); + online(mediaServerItem, zlmServerConfig); + } + } + } + if (!offlineZlmsecondaryMap.isEmpty()) { + for (MediaServer mediaServerItem : offlineZlmsecondaryMap.values()) { + if (offlineZlmTimeMap.get(mediaServerItem.getId()) < System.currentTimeMillis() - 30*60*1000) { + continue; + } + logger.info("[ZLM-灏濊瘯杩炴帴] ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + JSONObject responseJson = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); + ZLMServerConfig zlmServerConfig = null; + if (responseJson == null) { + logger.info("[ZLM-灏濊瘯杩炴帴]澶辫触, ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + offlineZlmTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis()); + continue; + } + JSONArray data = responseJson.getJSONArray("data"); + if (data == null || data.isEmpty()) { + logger.info("[ZLM-灏濊瘯杩炴帴]澶辫触, ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + offlineZlmTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis()); + }else { + zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); + initPort(mediaServerItem, zlmServerConfig); + online(mediaServerItem, zlmServerConfig); + } + } + } + } + + private void online(MediaServer mediaServerItem, ZLMServerConfig config) { + offlineZlmPrimaryMap.remove(mediaServerItem.getId()); + offlineZlmsecondaryMap.remove(mediaServerItem.getId()); + offlineZlmTimeMap.remove(mediaServerItem.getId()); + if (!mediaServerItem.isStatus()) { + logger.info("[ZLM-杩炴帴鎴愬姛] ID锛歿}, 鍦板潃锛� {}:{}", mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + mediaServerItem.setStatus(true); + mediaServerItem.setHookAliveInterval(10F); + mediaServerService.update(mediaServerItem); + if(mediaServerItem.isAutoConfig()) { + if (config == null) { + JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); + JSONArray data = responseJSON.getJSONArray("data"); + if (data != null && !data.isEmpty()) { + config = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); + } + } + if (config != null) { + initPort(mediaServerItem, config); + setZLMConfig(mediaServerItem, "0".equals(config.getHookEnable()) + || !Objects.equals(mediaServerItem.getHookAliveInterval(), config.getHookAliveInterval())); + } + } + mediaServerService.update(mediaServerItem); + } + // 璁剧疆涓ゆ蹇冭烦鏈敹鍒板垯璁や负zlm绂荤嚎 + String key = "zlm-keepalive-" + mediaServerItem.getId(); + dynamicTask.startDelay(key, ()->{ + logger.warn("[ZLM-蹇冭烦瓒呮椂] ID锛歿}", mediaServerItem.getId()); + mediaServerItem.setStatus(false); + offlineZlmPrimaryMap.put(mediaServerItem.getId(), mediaServerItem); + offlineZlmTimeMap.put(mediaServerItem.getId(), System.currentTimeMillis()); + // TODO 鍙戦�佺绾块�氱煡 + mediaServerService.update(mediaServerItem); + }, (int)(mediaServerItem.getHookAliveInterval() * 2 * 1000)); + } + private void initPort(MediaServer mediaServerItem, ZLMServerConfig zlmServerConfig) { + // 绔彛鍙細浠庨厤缃腑璇诲彇涓�娆★紝涓�鏃﹁嚜宸遍厤缃垨鑰呰鍙栬繃浜嗗皢涓嶅湪閰嶇疆 + if (mediaServerItem.getHttpSSlPort() == 0) { + mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); + } + if (mediaServerItem.getRtmpPort() == 0) { + mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort()); + } + if (mediaServerItem.getRtmpSSlPort() == 0) { + mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); + } + if (mediaServerItem.getRtspPort() == 0) { + mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort()); + } + if (mediaServerItem.getRtspSSLPort() == 0) { + mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); + } + if (mediaServerItem.getRtpProxyPort() == 0) { + mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); + } + mediaServerItem.setHookAliveInterval(10F); + } + + public void setZLMConfig(MediaServer mediaServerItem, boolean restart) { + logger.info("[濯掍綋鏈嶅姟鑺傜偣] 姝e湪璁剧疆 锛歿} -> {}:{}", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + String protocol = sslEnabled ? "https" : "http"; + String hookPrefix = String.format("%s://%s:%s%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort, (serverServletContextPath == null || "/".equals(serverServletContextPath)) ? "" : serverServletContextPath); + + Map<String, Object> param = new HashMap<>(); + param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline + if (mediaServerItem.getRtspPort() != 0) { + param.put("ffmpeg.snap", "%s -rtsp_transport tcp -i %s -y -f mjpeg -frames:v 1 %s"); + } + param.put("hook.enable","1"); + param.put("hook.on_flow_report",""); + param.put("hook.on_play",String.format("%s/on_play", hookPrefix)); + param.put("hook.on_http_access",""); + param.put("hook.on_publish", String.format("%s/on_publish", hookPrefix)); + 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", hookPrefix)); + param.put("hook.on_shell_login",""); + param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrefix)); + param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrefix)); + param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrefix)); + param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrefix)); + param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrefix)); + param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrefix)); + param.put("hook.on_record_mp4",String.format("%s/on_record_mp4", hookPrefix)); + param.put("hook.timeoutSec","30"); + param.put("hook.alive_interval", mediaServerItem.getHookAliveInterval()); + // 鎺ㄦ祦鏂紑鍚庡彲浠ュ湪瓒呮椂鏃堕棿鍐呴噸鏂拌繛鎺ヤ笂缁х画鎺ㄦ祦锛岃繖鏍锋挱鏀惧櫒浼氭帴鐫�鎾斁銆� + // 缃�0鍏抽棴姝ょ壒鎬�(鎺ㄦ祦鏂紑浼氬鑷寸珛鍗虫柇寮�鎾斁鍣�) + // 姝ゅ弬鏁颁笉搴斿ぇ浜庢挱鏀惧櫒瓒呮椂鏃堕棿 + // 浼樺寲姝ゆ秷鎭互鏇村揩鐨勬敹鍒版祦娉ㄩ攢浜嬩欢 + param.put("protocol.continue_push_ms", "3000" ); + // 鏈�澶氱瓑寰呮湭鍒濆鍖栫殑Track鏃堕棿锛屽崟浣嶆绉掞紝瓒呮椂涔嬪悗浼氬拷鐣ユ湭鍒濆鍖栫殑Track, 璁剧疆姝ら�夐」浼樺寲閭d簺闊抽閿欒鐨勪笉瑙勮寖娴侊紝 + // 绛墇lm鏀寔缁欐瘡涓猺tpServer璁剧疆鍏抽棴闊抽鐨勬椂鍊欏彲浠ヤ笉璁剧疆姝ら�夐」 + if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) { + param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); + } + + if (!ObjectUtils.isEmpty(mediaServerItem.getRecordPath())) { + File recordPathFile = new File(mediaServerItem.getRecordPath()); + param.put("protocol.mp4_save_path", recordPathFile.getParentFile().getPath()); + param.put("protocol.downloadRoot", recordPathFile.getParentFile().getPath()); + param.put("record.appName", recordPathFile.getName()); + } + + JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); + + if (responseJSON != null && responseJSON.getInteger("code") == 0) { + if (restart) { + logger.info("[濯掍綋鏈嶅姟鑺傜偣] 璁剧疆鎴愬姛,寮�濮嬮噸鍚互淇濊瘉閰嶇疆鐢熸晥 {} -> {}:{}", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + zlmresTfulUtils.restartServer(mediaServerItem); + }else { + logger.info("[濯掍綋鏈嶅姟鑺傜偣] 璁剧疆鎴愬姛 {} -> {}:{}", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + } + }else { + logger.info("[濯掍綋鏈嶅姟鑺傜偣] 璁剧疆濯掍綋鏈嶅姟鑺傜偣澶辫触 {} -> {}:{}", + mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); + } + } + +} 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 044f9f3..285b9e6 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRESTfulUtils.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson2.JSON; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import okhttp3.*; import okhttp3.logging.HttpLoggingInterceptor; import org.jetbrains.annotations.NotNull; @@ -60,12 +60,12 @@ } - public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) { + public JSONObject sendPost(MediaServer mediaServerItem, String api, Map<String, Object> param, RequestCallback callback) { return sendPost(mediaServerItem, api, param, callback, null); } - public JSONObject sendPost(MediaServerItem mediaServerItem, String api, Map<String, Object> param, RequestCallback callback, Integer readTimeOut) { + public JSONObject sendPost(MediaServer mediaServerItem, String api, Map<String, Object> param, RequestCallback callback, Integer readTimeOut) { OkHttpClient client = getClient(readTimeOut); if (mediaServerItem == null) { @@ -104,8 +104,6 @@ responseJSON = JSON.parseObject(responseStr); } }else { - System.out.println( 2222); - System.out.println( response.code()); response.close(); Objects.requireNonNull(response.body()).close(); } @@ -164,7 +162,7 @@ return responseJSON; } - public void sendGetForImg(MediaServerItem mediaServerItem, String api, Map<String, Object> params, String targetPath, String fileName) { + public void sendGetForImg(MediaServer mediaServerItem, String api, Map<String, Object> params, String targetPath, String fileName) { String url = String.format("http://%s:%s/index/api/%s", mediaServerItem.getIp(), mediaServerItem.getHttpPort(), api); HttpUrl parseUrl = HttpUrl.parse(url); if (parseUrl == null) { @@ -216,7 +214,7 @@ } } - public JSONObject isMediaOnline(MediaServerItem mediaServerItem, String app, String stream, String schema){ + public JSONObject isMediaOnline(MediaServer mediaServerItem, String app, String stream, String schema){ Map<String, Object> param = new HashMap<>(); if (app != null) { param.put("app",app); @@ -231,7 +229,7 @@ return sendPost(mediaServerItem, "isMediaOnline", param, null); } - public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream, String schema, RequestCallback callback){ + public JSONObject getMediaList(MediaServer mediaServerItem, String app, String stream, String schema, RequestCallback callback){ Map<String, Object> param = new HashMap<>(); if (app != null) { param.put("app",app); @@ -246,15 +244,15 @@ return sendPost(mediaServerItem, "getMediaList",param, callback); } - public JSONObject getMediaList(MediaServerItem mediaServerItem, String app, String stream){ + public JSONObject getMediaList(MediaServer mediaServerItem, String app, String stream){ return getMediaList(mediaServerItem, app, stream,null, null); } - public JSONObject getMediaList(MediaServerItem mediaServerItem, RequestCallback callback){ + public JSONObject getMediaList(MediaServer mediaServerItem, RequestCallback callback){ return sendPost(mediaServerItem, "getMediaList",null, callback); } - public JSONObject getMediaInfo(MediaServerItem mediaServerItem, String app, String schema, String stream){ + public JSONObject getMediaInfo(MediaServer mediaServerItem, String app, String schema, String stream){ Map<String, Object> param = new HashMap<>(); param.put("app",app); param.put("schema",schema); @@ -263,13 +261,13 @@ return sendPost(mediaServerItem, "getMediaInfo",param, null); } - public JSONObject getRtpInfo(MediaServerItem mediaServerItem, String stream_id){ + public JSONObject getRtpInfo(MediaServer mediaServerItem, String stream_id){ Map<String, Object> param = new HashMap<>(); param.put("stream_id",stream_id); return sendPost(mediaServerItem, "getRtpInfo",param, null); } - public JSONObject addFFmpegSource(MediaServerItem mediaServerItem, String src_url, String dst_url, String timeout_ms, + public JSONObject addFFmpegSource(MediaServer mediaServerItem, String src_url, String dst_url, Integer timeout_ms, boolean enable_audio, boolean enable_mp4, String ffmpeg_cmd_key){ logger.info(src_url); logger.info(dst_url); @@ -282,63 +280,63 @@ return sendPost(mediaServerItem, "addFFmpegSource",param, null); } - public JSONObject delFFmpegSource(MediaServerItem mediaServerItem, String key){ + public JSONObject delFFmpegSource(MediaServer mediaServerItem, String key){ Map<String, Object> param = new HashMap<>(); param.put("key", key); return sendPost(mediaServerItem, "delFFmpegSource",param, null); } - public JSONObject delStreamProxy(MediaServerItem mediaServerItem, String key){ + public JSONObject delStreamProxy(MediaServer mediaServerItem, String key){ Map<String, Object> param = new HashMap<>(); param.put("key", key); return sendPost(mediaServerItem, "delStreamProxy",param, null); } - public JSONObject getMediaServerConfig(MediaServerItem mediaServerItem){ + public JSONObject getMediaServerConfig(MediaServer mediaServerItem){ return sendPost(mediaServerItem, "getServerConfig",null, null); } - public JSONObject setServerConfig(MediaServerItem mediaServerItem, Map<String, Object> param){ + public JSONObject setServerConfig(MediaServer mediaServerItem, Map<String, Object> param){ return sendPost(mediaServerItem,"setServerConfig",param, null); } - public JSONObject openRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param){ + public JSONObject openRtpServer(MediaServer mediaServerItem, Map<String, Object> param){ return sendPost(mediaServerItem, "openRtpServer",param, null); } - public JSONObject closeRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param) { + public JSONObject closeRtpServer(MediaServer mediaServerItem, Map<String, Object> param) { return sendPost(mediaServerItem, "closeRtpServer",param, null); } - public void closeRtpServer(MediaServerItem mediaServerItem, Map<String, Object> param, RequestCallback callback) { + public void closeRtpServer(MediaServer mediaServerItem, Map<String, Object> param, RequestCallback callback) { sendPost(mediaServerItem, "closeRtpServer",param, callback); } - public JSONObject listRtpServer(MediaServerItem mediaServerItem) { + public JSONObject listRtpServer(MediaServer mediaServerItem) { return sendPost(mediaServerItem, "listRtpServer",null, null); } - public JSONObject startSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) { + public JSONObject startSendRtp(MediaServer mediaServerItem, Map<String, Object> param) { return sendPost(mediaServerItem, "startSendRtp",param, null); } - public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object> param) { + public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object> param) { return sendPost(mediaServerItem, "startSendRtpPassive",param, null); } - public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object> param, RequestCallback callback) { + public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object> param, RequestCallback callback) { return sendPost(mediaServerItem, "startSendRtpPassive",param, callback); } - public JSONObject stopSendRtp(MediaServerItem mediaServerItem, Map<String, Object> param) { + public JSONObject stopSendRtp(MediaServer mediaServerItem, Map<String, Object> param) { return sendPost(mediaServerItem, "stopSendRtp",param, null); } - public JSONObject restartServer(MediaServerItem mediaServerItem) { + public JSONObject restartServer(MediaServer mediaServerItem) { return sendPost(mediaServerItem, "restartServer",null, null); } - public JSONObject addStreamProxy(MediaServerItem mediaServerItem, String app, String stream, String url, boolean enable_audio, boolean enable_mp4, String rtp_type) { + public JSONObject addStreamProxy(MediaServer mediaServerItem, String app, String stream, String url, boolean enable_audio, boolean enable_mp4, String rtp_type) { Map<String, Object> param = new HashMap<>(); param.put("vhost", "__defaultVhost__"); param.put("app", app); @@ -350,7 +348,7 @@ return sendPost(mediaServerItem, "addStreamProxy",param, null, 20); } - public JSONObject closeStreams(MediaServerItem mediaServerItem, String app, String stream) { + public JSONObject closeStreams(MediaServer mediaServerItem, String app, String stream) { Map<String, Object> param = new HashMap<>(); param.put("vhost", "__defaultVhost__"); param.put("app", app); @@ -359,17 +357,17 @@ return sendPost(mediaServerItem, "close_streams",param, null); } - public JSONObject getAllSession(MediaServerItem mediaServerItem) { + public JSONObject getAllSession(MediaServer mediaServerItem) { return sendPost(mediaServerItem, "getAllSession",null, null); } - public void kickSessions(MediaServerItem mediaServerItem, String localPortSStr) { + public void kickSessions(MediaServer mediaServerItem, String localPortSStr) { Map<String, Object> param = new HashMap<>(); param.put("local_port", localPortSStr); sendPost(mediaServerItem, "kick_sessions",param, null); } - public void getSnap(MediaServerItem mediaServerItem, String streamUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { + public void getSnap(MediaServer mediaServerItem, String streamUrl, int timeout_sec, int expire_sec, String targetPath, String fileName) { Map<String, Object> param = new HashMap<>(3); param.put("url", streamUrl); param.put("timeout_sec", timeout_sec); @@ -377,19 +375,19 @@ sendGetForImg(mediaServerItem, "getSnap", param, targetPath, fileName); } - public JSONObject pauseRtpCheck(MediaServerItem mediaServerItem, String streamId) { + public JSONObject pauseRtpCheck(MediaServer mediaServerItem, String streamId) { Map<String, Object> param = new HashMap<>(1); param.put("stream_id", streamId); return sendPost(mediaServerItem, "pauseRtpCheck",param, null); } - public JSONObject resumeRtpCheck(MediaServerItem mediaServerItem, String streamId) { + public JSONObject resumeRtpCheck(MediaServer mediaServerItem, String streamId) { Map<String, Object> param = new HashMap<>(1); param.put("stream_id", streamId); return sendPost(mediaServerItem, "resumeRtpCheck",param, null); } - public JSONObject connectRtpServer(MediaServerItem mediaServerItem, String dst_url, int dst_port, String stream_id) { + public JSONObject connectRtpServer(MediaServer mediaServerItem, String dst_url, int dst_port, String stream_id) { Map<String, Object> param = new HashMap<>(1); param.put("dst_url", dst_url); param.put("dst_port", dst_port); @@ -397,14 +395,14 @@ return sendPost(mediaServerItem, "connectRtpServer",param, null); } - public JSONObject updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) { + public JSONObject updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) { Map<String, Object> param = new HashMap<>(1); param.put("ssrc", ssrc); param.put("stream_id", streamId); return sendPost(mediaServerItem, "updateRtpServerSSRC",param, null); } - public JSONObject deleteRecordDirectory(MediaServerItem mediaServerItem, String app, String stream, String date, String fileName) { + public JSONObject deleteRecordDirectory(MediaServer mediaServerItem, String app, String stream, String date, String fileName) { Map<String, Object> param = new HashMap<>(1); param.put("vhost", "__defaultVhost__"); param.put("app", app); 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 deleted file mode 100755 index 4a781f3..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMRunner.java +++ /dev/null @@ -1,173 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm; - -import com.alibaba.fastjson2.JSON; -import com.alibaba.fastjson2.JSONArray; -import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.conf.DynamicTask; -import com.genersoft.iot.vmp.conf.MediaConfig; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForServerStarted; -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 org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.boot.CommandLineRunner; -import org.springframework.core.annotation.Order; -import org.springframework.scheduling.annotation.Async; -import org.springframework.stereotype.Component; - -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -@Component -@Order(value=12) -public class ZLMRunner implements CommandLineRunner { - - private final static Logger logger = LoggerFactory.getLogger(ZLMRunner.class); - - private Map<String, Boolean> startGetMedia; - - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; - - @Autowired - private ZlmHttpHookSubscribe hookSubscribe; - - @Autowired - private EventPublisher publisher; - - @Autowired - private IMediaServerService mediaServerService; - - @Autowired - private MediaConfig mediaConfig; - - @Autowired - private DynamicTask dynamicTask; - - - @Override - public void run(String... strings) throws Exception { - mediaServerService.clearMediaServerForOnline(); - MediaServerItem defaultMediaServer = mediaServerService.getDefaultMediaServer(); - if (defaultMediaServer == null) { - mediaServerService.addToDatabase(mediaConfig.getMediaSerItem()); - }else { - MediaServerItem mediaSerItem = mediaConfig.getMediaSerItem(); - mediaServerService.updateToDatabase(mediaSerItem); - } - mediaServerService.syncCatchFromDatabase(); - HookSubscribeForServerStarted hookSubscribeForServerStarted = HookSubscribeFactory.on_server_started(); - // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁� - hookSubscribe.addSubscribe(hookSubscribeForServerStarted, - (mediaServerItem, hookParam)->{ - ZLMServerConfig zlmServerConfig = (ZLMServerConfig)hookParam; - if (zlmServerConfig !=null ) { - if (startGetMedia != null) { - startGetMedia.remove(zlmServerConfig.getGeneralMediaServerId()); - if (startGetMedia.size() == 0) { - hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started()); - } - } - } - }); - - // 鑾峰彇zlm淇℃伅 - logger.info("[zlm] 绛夊緟榛樿zlm涓�..."); - - // 鑾峰彇鎵�鏈夌殑zlm锛� 骞跺紑鍚富鍔ㄨ繛鎺� - List<MediaServerItem> all = mediaServerService.getAllFromDatabase(); - Map<String, MediaServerItem> allMap = new HashMap<>(); - mediaServerService.updateVmServer(all); - if (all.size() == 0) { - all.add(mediaConfig.getMediaSerItem()); - } - for (MediaServerItem mediaServerItem : all) { - if (startGetMedia == null) { - startGetMedia = new ConcurrentHashMap<>(); - } - startGetMedia.put(mediaServerItem.getId(), true); - connectZlmServer(mediaServerItem); - allMap.put(mediaServerItem.getId(), mediaServerItem); - } - String taskKey = "zlm-connect-timeout"; - dynamicTask.startDelay(taskKey, ()->{ - if (startGetMedia != null && startGetMedia.size() > 0) { - Set<String> allZlmId = startGetMedia.keySet(); - for (String id : allZlmId) { - logger.error("[ {} ]]涓诲姩杩炴帴澶辫触锛屼笉鍐嶅皾璇曡繛鎺�", id); - } - startGetMedia = null; - } - // 鑾峰彇redis涓墍鏈夌殑zlm - List<MediaServerItem> allInRedis = mediaServerService.getAll(); - for (MediaServerItem mediaServerItem : allInRedis) { - if (!allMap.containsKey(mediaServerItem.getId())) { - mediaServerService.delete(mediaServerItem.getId()); - } - } - }, 60 * 1000 ); - } - - @Async("taskExecutor") - public void connectZlmServer(MediaServerItem mediaServerItem){ - String connectZlmServerTaskKey = "connect-zlm-" + mediaServerItem.getId(); - ZLMServerConfig zlmServerConfigFirst = getMediaServerConfig(mediaServerItem); - if (zlmServerConfigFirst != null) { - zlmServerConfigFirst.setIp(mediaServerItem.getIp()); - zlmServerConfigFirst.setHttpPort(mediaServerItem.getHttpPort()); - startGetMedia.remove(mediaServerItem.getId()); - if (startGetMedia.size() == 0) { - hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started()); - } - mediaServerService.zlmServerOnline(zlmServerConfigFirst); - }else { - logger.info("[ {} ]-[ {}:{} ]涓诲姩杩炴帴澶辫触, 娓呯悊鐩稿叧璧勬簮锛� 寮�濮嬪皾璇曢噸璇曡繛鎺�", - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); - publisher.zlmOfflineEventPublish(mediaServerItem.getId()); - } - - dynamicTask.startCron(connectZlmServerTaskKey, ()->{ - ZLMServerConfig zlmServerConfig = getMediaServerConfig(mediaServerItem); - if (zlmServerConfig != null) { - dynamicTask.stop(connectZlmServerTaskKey); - zlmServerConfig.setIp(mediaServerItem.getIp()); - zlmServerConfig.setHttpPort(mediaServerItem.getHttpPort()); - startGetMedia.remove(mediaServerItem.getId()); - if (startGetMedia.size() == 0) { - hookSubscribe.removeSubscribe(HookSubscribeFactory.on_server_started()); - } - mediaServerService.zlmServerOnline(zlmServerConfig); - } - }, 2000); - } - - public ZLMServerConfig getMediaServerConfig(MediaServerItem mediaServerItem) { - if (startGetMedia == null) { return null;} - if (!mediaServerItem.isDefaultServer() && mediaServerService.getOne(mediaServerItem.getId()) == null) { - return null; - } - 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); - } - } else { - logger.error("[ {} ]-[ {}:{} ]涓诲姩杩炴帴澶辫触, 2s鍚庨噸璇�", - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); - } - return zlmServerConfig; - - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java index 027e990..14025ce 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java @@ -5,7 +5,8 @@ import com.genersoft.iot.vmp.common.CommonCallback; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; @@ -17,7 +18,7 @@ @Component public class ZLMServerFactory { - private Logger logger = LoggerFactory.getLogger("ZLMRTPServerFactory"); + private Logger logger = LoggerFactory.getLogger("ZLMServerFactory"); @Autowired private ZLMRESTfulUtils zlmresTfulUtils; @@ -26,7 +27,7 @@ private UserSetting userSetting; @Autowired - private ZlmHttpHookSubscribe hookSubscribe; + private HookSubscribe hookSubscribe; @Autowired private SendRtpPortManager sendRtpPortManager; @@ -42,7 +43,7 @@ * @param tcpMode 0/null udp 妯″紡锛�1 tcp 琚姩妯″紡, 2 tcp 涓诲姩妯″紡銆� * @return */ - public int createRTPServer(MediaServerItem mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { + public int createRTPServer(MediaServer mediaServerItem, String streamId, long ssrc, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { int result = -1; // 鏌ヨ姝tp server 鏄惁宸茬粡瀛樺湪 JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaServerItem, streamId); @@ -108,7 +109,7 @@ return result; } - public boolean closeRtpServer(MediaServerItem serverItem, String streamId) { + public boolean closeRtpServer(MediaServer serverItem, String streamId) { boolean result = false; if (serverItem !=null){ Map<String, Object> param = new HashMap<>(); @@ -129,7 +130,7 @@ return result; } - public void closeRtpServer(MediaServerItem serverItem, String streamId, CommonCallback<Boolean> callback) { + public void closeRtpServer(MediaServer serverItem, String streamId, CommonCallback<Boolean> callback) { if (serverItem == null) { callback.run(false); return; @@ -165,7 +166,7 @@ * @param tcp 鏄惁涓簍cp * @return SendRtpItem */ - public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, + public SendRtpItem createSendRtpItem(MediaServer serverItem, String ip, int port, String ssrc, String platformId, String deviceId, String channelId, boolean tcp, boolean rtcp){ int localPort = sendRtpPortManager.getNextPort(serverItem); @@ -198,7 +199,7 @@ * @param tcp 鏄惁涓簍cp * @return SendRtpItem */ - public SendRtpItem createSendRtpItem(MediaServerItem serverItem, String ip, int port, String ssrc, String platformId, + public SendRtpItem createSendRtpItem(MediaServer serverItem, String ip, int port, String ssrc, String platformId, String app, String stream, String channelId, boolean tcp, boolean rtcp){ int localPort = sendRtpPortManager.getNextPort(serverItem); @@ -224,25 +225,25 @@ /** * 璋冪敤zlm RESTFUL API 鈥斺�� startSendRtp */ - public JSONObject startSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) { + public JSONObject startSendRtpStream(MediaServer mediaServerItem, Map<String, Object>param) { return zlmresTfulUtils.startSendRtp(mediaServerItem, param); } /** * 璋冪敤zlm RESTFUL API 鈥斺�� startSendRtpPassive */ - public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object>param) { + public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object>param) { return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param); } - public JSONObject startSendRtpPassive(MediaServerItem mediaServerItem, Map<String, Object>param, ZLMRESTfulUtils.RequestCallback callback) { + public JSONObject startSendRtpPassive(MediaServer mediaServerItem, Map<String, Object>param, ZLMRESTfulUtils.RequestCallback callback) { return zlmresTfulUtils.startSendRtpPassive(mediaServerItem, param, callback); } /** * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁� */ - public Boolean isRtpReady(MediaServerItem mediaServerItem, String streamId) { + public Boolean isRtpReady(MediaServer mediaServerItem, String streamId) { JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem,"rtp", "rtsp", streamId); if (mediaInfo.getInteger("code") == -2) { return null; @@ -253,7 +254,7 @@ /** * 鏌ヨ寰呰浆鎺ㄧ殑娴佹槸鍚﹀氨缁� */ - public Boolean isStreamReady(MediaServerItem mediaServerItem, String app, String streamId) { + public Boolean isStreamReady(MediaServer mediaServerItem, String app, String streamId) { JSONObject mediaInfo = zlmresTfulUtils.getMediaList(mediaServerItem, app, streamId); if (mediaInfo == null || (mediaInfo.getInteger("code") == -2)) { return null; @@ -268,7 +269,7 @@ * @param streamId * @return */ - public int totalReaderCount(MediaServerItem mediaServerItem, String app, String streamId) { + public int totalReaderCount(MediaServer mediaServerItem, String app, String streamId) { JSONObject mediaInfo = zlmresTfulUtils.getMediaInfo(mediaServerItem, app, "rtsp", streamId); if (mediaInfo == null) { return 0; @@ -288,7 +289,7 @@ /** * 璋冪敤zlm RESTful API 鈥斺�� stopSendRtp */ - public Boolean stopSendRtpStream(MediaServerItem mediaServerItem, Map<String, Object>param) { + public Boolean stopSendRtpStream(MediaServer mediaServerItem, Map<String, Object>param) { if (mediaServerItem == null) { logger.error("[鍋滄RTP鎺ㄦ祦] 澶辫触: 濯掍綋鑺傜偣涓篘ULL"); return false; @@ -306,7 +307,7 @@ return result; } - public JSONObject startSendRtp(MediaServerItem mediaInfo, SendRtpItem sendRtpItem) { + public JSONObject startSendRtp(MediaServer mediaInfo, SendRtpItem sendRtpItem) { String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; logger.info("rtp/{}寮�濮嬫帹娴�, 鐩爣={}:{}锛孲SRC={}", sendRtpItem.getStream(), sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc()); Map<String, Object> param = new HashMap<>(12); @@ -351,7 +352,7 @@ return startSendRtpStreamResult; } - public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) { + public Boolean updateRtpServerSSRC(MediaServer mediaServerItem, String streamId, String ssrc) { boolean result = false; JSONObject jsonObject = zlmresTfulUtils.updateRtpServerSSRC(mediaServerItem, streamId, ssrc); if (jsonObject == null) { 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 deleted file mode 100755 index 5e46f55..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZlmHttpHookSubscribe.java +++ /dev/null @@ -1,161 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm; - -import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.media.zlm.dto.HookType; -import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Component; -import org.springframework.util.CollectionUtils; - -import java.time.Instant; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -/** - * ZLMediaServer鐨刪ook浜嬩欢璁㈤槄 - * @author lin - */ -@Component -public class ZlmHttpHookSubscribe { - - private final static Logger logger = LoggerFactory.getLogger(ZlmHttpHookSubscribe.class); - - @FunctionalInterface - public interface Event{ - void response(MediaServerItem mediaServerItem, HookParam hookParam); - } - - private Map<HookType, Map<IHookSubscribe, ZlmHttpHookSubscribe.Event>> allSubscribes = new ConcurrentHashMap<>(); - - public void addSubscribe(IHookSubscribe hookSubscribe, ZlmHttpHookSubscribe.Event event) { - if (hookSubscribe.getExpires() == null) { - // 榛樿5鍒嗛挓杩囨湡 - Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(5)); - hookSubscribe.setExpires(expiresInstant); - } - allSubscribes.computeIfAbsent(hookSubscribe.getHookType(), k -> new ConcurrentHashMap<>()).put(hookSubscribe, event); - System.out.println(allSubscribes); - } - - public ZlmHttpHookSubscribe.Event sendNotify(HookType type, JSONObject hookResponse) { - ZlmHttpHookSubscribe.Event event= null; - Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type); - if (eventMap == null) { - return null; - } - for (IHookSubscribe key : eventMap.keySet()) { - Boolean result = null; - - for (String s : key.getContent().keySet()) { - if (result == null) { - result = key.getContent().getString(s).equals(hookResponse.getString(s)); - }else { - if (key.getContent().getString(s) == null) { - continue; - } - result = result && key.getContent().getString(s).equals(hookResponse.getString(s)); - } - } - if (null != result && result) { - event = eventMap.get(key); - } - } - return event; - } - - public void removeSubscribe(IHookSubscribe hookSubscribe) { - Map<IHookSubscribe, Event> eventMap = allSubscribes.get(hookSubscribe.getHookType()); - if (eventMap == null) { - return; - } - - Set<Map.Entry<IHookSubscribe, Event>> entries = eventMap.entrySet(); - if (entries.size() > 0) { - List<Map.Entry<IHookSubscribe, ZlmHttpHookSubscribe.Event>> entriesToRemove = new ArrayList<>(); - for (Map.Entry<IHookSubscribe, ZlmHttpHookSubscribe.Event> entry : entries) { - JSONObject content = entry.getKey().getContent(); - if (content == null || content.size() == 0) { - entriesToRemove.add(entry); - continue; - } - Boolean result = null; - for (String s : content.keySet()) { - if (result == null) { - result = content.getString(s).equals(hookSubscribe.getContent().getString(s)); - }else { - if (content.getString(s) == null) { - continue; - } - result = result && content.getString(s).equals(hookSubscribe.getContent().getString(s)); - } - } - if (result){ - entriesToRemove.add(entry); - } - } - - if (!CollectionUtils.isEmpty(entriesToRemove)) { - for (Map.Entry<IHookSubscribe, ZlmHttpHookSubscribe.Event> entry : entriesToRemove) { - eventMap.remove(entry.getKey()); - } - if (eventMap.size() == 0) { - allSubscribes.remove(hookSubscribe.getHookType()); - } - } - - } - } - - /** - * 鑾峰彇鏌愪釜绫诲瀷鐨勬墍鏈夌殑璁㈤槄 - * @param type - * @return - */ - public List<ZlmHttpHookSubscribe.Event> getSubscribes(HookType type) { - Map<IHookSubscribe, Event> eventMap = allSubscribes.get(type); - if (eventMap == null) { - return null; - } - List<ZlmHttpHookSubscribe.Event> result = new ArrayList<>(); - for (IHookSubscribe key : eventMap.keySet()) { - result.add(eventMap.get(key)); - } - return result; - } - - public List<IHookSubscribe> getAll(){ - ArrayList<IHookSubscribe> result = new ArrayList<>(); - Collection<Map<IHookSubscribe, Event>> values = allSubscribes.values(); - for (Map<IHookSubscribe, Event> value : values) { - result.addAll(value.keySet()); - } - return result; - } - - /** - * 瀵硅闃呮暟鎹繘琛岃繃鏈熸竻鐞� - */ -// @Scheduled(cron="0 0/5 * * * ?") //姣�5鍒嗛挓鎵ц涓�娆� - @Scheduled(fixedRate = 2 * 1000) - public void execute(){ - Instant instant = Instant.now().minusMillis(TimeUnit.MINUTES.toMillis(5)); - int total = 0; - for (HookType hookType : allSubscribes.keySet()) { - Map<IHookSubscribe, Event> hookSubscribeEventMap = allSubscribes.get(hookType); - if (hookSubscribeEventMap.size() > 0) { - for (IHookSubscribe hookSubscribe : hookSubscribeEventMap.keySet()) { - if (hookSubscribe.getExpires().isBefore(instant)) { - // 杩囨湡鐨� - hookSubscribeEventMap.remove(hookSubscribe); - total ++; - } - } - } - } - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java deleted file mode 100755 index f828bdd..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeFactory.java +++ /dev/null @@ -1,71 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - - -import com.alibaba.fastjson2.JSONObject; - -/** - * hook 璁㈤槄宸ュ巶 - * @author lin - */ -public class HookSubscribeFactory { - - public static HookSubscribeForStreamChange on_stream_changed(String app, String stream, boolean regist, String scheam, String mediaServerId) { - HookSubscribeForStreamChange hookSubscribe = new HookSubscribeForStreamChange(); - JSONObject subscribeKey = new com.alibaba.fastjson2.JSONObject(); - subscribeKey.put("app", app); - subscribeKey.put("stream", stream); - subscribeKey.put("regist", regist); - if (scheam != null) { - subscribeKey.put("schema", scheam); - } - subscribeKey.put("mediaServerId", mediaServerId); - hookSubscribe.setContent(subscribeKey); - - return hookSubscribe; - } - - public static HookSubscribeForRtpServerTimeout on_rtp_server_timeout(String stream, String ssrc, String mediaServerId) { - HookSubscribeForRtpServerTimeout hookSubscribe = new HookSubscribeForRtpServerTimeout(); - JSONObject subscribeKey = new com.alibaba.fastjson2.JSONObject(); - subscribeKey.put("stream_id", stream); - subscribeKey.put("ssrc", ssrc); - subscribeKey.put("mediaServerId", mediaServerId); - hookSubscribe.setContent(subscribeKey); - - return hookSubscribe; - } - - public static HookSubscribeForStreamPush on_publish(String app, String stream, String scheam, String mediaServerId) { - HookSubscribeForStreamPush hookSubscribe = new HookSubscribeForStreamPush(); - JSONObject subscribeKey = new JSONObject(); - subscribeKey.put("app", app); - subscribeKey.put("stream", stream); - if (scheam != null) { - subscribeKey.put("schema", scheam); - } - subscribeKey.put("mediaServerId", mediaServerId); - hookSubscribe.setContent(subscribeKey); - - return hookSubscribe; - } - - - public static HookSubscribeForServerStarted on_server_started() { - HookSubscribeForServerStarted hookSubscribe = new HookSubscribeForServerStarted(); - hookSubscribe.setContent(new JSONObject()); - - return hookSubscribe; - } - - public static HookSubscribeForRecordMp4 on_record_mp4(String mediaServerId, String app, String stream) { - HookSubscribeForRecordMp4 hookSubscribe = new HookSubscribeForRecordMp4(); - JSONObject subscribeKey = new com.alibaba.fastjson2.JSONObject(); - subscribeKey.put("app", app); - subscribeKey.put("stream", stream); - subscribeKey.put("mediaServerId", mediaServerId); - hookSubscribe.setContent(subscribeKey); - - return hookSubscribe; - } - -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRecordMp4.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRecordMp4.java deleted file mode 100755 index 34c467c..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRecordMp4.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - -import com.alibaba.fastjson2.JSONObject; -import com.alibaba.fastjson2.annotation.JSONField; - -import java.time.Instant; - -/** - * hook璁㈤槄-褰曞儚瀹屾垚 - * @author lin - */ -public class HookSubscribeForRecordMp4 implements IHookSubscribe{ - - private HookType hookType = HookType.on_record_mp4; - - private JSONObject content; - - @JSONField(format="yyyy-MM-dd HH:mm:ss") - private Instant expires; - - @Override - public HookType getHookType() { - return hookType; - } - - @Override - public JSONObject getContent() { - return content; - } - - public void setContent(JSONObject content) { - this.content = content; - } - - @Override - public Instant getExpires() { - return expires; - } - - @Override - public void setExpires(Instant expires) { - this.expires = expires; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRtpServerTimeout.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRtpServerTimeout.java deleted file mode 100755 index d633560..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForRtpServerTimeout.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - -import com.alibaba.fastjson2.JSONObject; -import com.alibaba.fastjson2.annotation.JSONField; - -import java.time.Instant; - -/** - * hook璁㈤槄-鏀舵祦瓒呮椂 - * @author lin - */ -public class HookSubscribeForRtpServerTimeout implements IHookSubscribe{ - - private HookType hookType = HookType.on_rtp_server_timeout; - - private JSONObject content; - - @JSONField(format="yyyy-MM-dd HH:mm:ss") - private Instant expires; - - @Override - public HookType getHookType() { - return hookType; - } - - @Override - public JSONObject getContent() { - return content; - } - - public void setContent(JSONObject content) { - this.content = content; - } - - @Override - public Instant getExpires() { - return expires; - } - - @Override - public void setExpires(Instant expires) { - this.expires = expires; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java deleted file mode 100755 index 8bcde0a..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForServerStarted.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - -import com.alibaba.fastjson2.JSONObject; -import com.alibaba.fastjson2.annotation.JSONField; - -import java.time.Instant; - -/** - * hook璁㈤槄-娴佸彉鍖� - * @author lin - */ -public class HookSubscribeForServerStarted implements IHookSubscribe{ - - private HookType hookType = HookType.on_server_started; - - private JSONObject content; - - @JSONField(format="yyyy-MM-dd HH:mm:ss") - private Instant expires; - - @Override - public HookType getHookType() { - return hookType; - } - - @Override - public JSONObject getContent() { - return content; - } - - public void setContent(JSONObject content) { - this.content = content; - } - - @Override - public Instant getExpires() { - return expires; - } - - @Override - public void setExpires(Instant expires) { - this.expires = expires; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java deleted file mode 100755 index b73d74c..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamChange.java +++ /dev/null @@ -1,44 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - -import com.alibaba.fastjson2.JSONObject; -import com.alibaba.fastjson2.annotation.JSONField; - -import java.time.Instant; - -/** - * hook璁㈤槄-娴佸彉鍖� - * @author lin - */ -public class HookSubscribeForStreamChange implements IHookSubscribe{ - - private HookType hookType = HookType.on_stream_changed; - - private JSONObject content; - - @JSONField(format="yyyy-MM-dd HH:mm:ss") - private Instant expires; - - @Override - public HookType getHookType() { - return hookType; - } - - @Override - public JSONObject getContent() { - return content; - } - - public void setContent(JSONObject content) { - this.content = content; - } - - @Override - public Instant getExpires() { - return expires; - } - - @Override - public void setExpires(Instant expires) { - this.expires = expires; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamPush.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamPush.java deleted file mode 100644 index 6418134..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookSubscribeForStreamPush.java +++ /dev/null @@ -1,43 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - - -import com.alibaba.fastjson2.JSONObject; - -import java.time.Instant; - -/** - * hook璁㈤槄-寮�濮嬫帹娴� - * @author lin - */ -public class HookSubscribeForStreamPush implements IHookSubscribe{ - - private HookType hookType = HookType.on_publish; - - private JSONObject content; - - private Instant expires; - - @Override - public HookType getHookType() { - return hookType; - } - - @Override - public JSONObject getContent() { - return content; - } - - public void setContent(JSONObject content) { - this.content = content; - } - - @Override - public Instant getExpires() { - return expires; - } - - @Override - public void setExpires(Instant expires) { - this.expires = expires; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java deleted file mode 100755 index 235cea7..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/HookType.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - -/** - * hook绫诲瀷 - * @author lin - */ - -public enum HookType { - - on_flow_report, - on_http_access, - on_play, - on_publish, - on_record_mp4, - on_rtsp_auth, - on_rtsp_realm, - on_shell_login, - on_stream_changed, - on_stream_none_reader, - on_stream_not_found, - on_server_started, - - on_rtp_server_timeout, - on_server_keepalive, - on_send_rtp_stopped -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java deleted file mode 100755 index 7b76a95..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/IHookSubscribe.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - -import com.alibaba.fastjson2.JSONObject; - -import java.time.Instant; - -/** - * zlm hook浜嬩欢鐨勫弬鏁� - * @author lin - */ -public interface IHookSubscribe { - - /** - * 鑾峰彇hook绫诲瀷 - * @return hook绫诲瀷 - */ - HookType getHookType(); - - /** - * 鑾峰彇hook鐨勫叿浣撳唴瀹� - * @return hook鐨勫叿浣撳唴瀹� - */ - JSONObject getContent(); - - /** - * 璁剧疆杩囨湡鏃堕棿 - * @param instant 杩囨湡鏃堕棿 - */ - void setExpires(Instant instant); - - /** - * 鑾峰彇杩囨湡鏃堕棿 - * @return 杩囨湡鏃堕棿 - */ - Instant getExpires(); -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java deleted file mode 100644 index 4e0ffe9..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaServerItemLite.java +++ /dev/null @@ -1,168 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - - -/** - * 绮剧畝鐨凪ediaServerItem淇℃伅锛屾柟渚跨粰鍓嶇杩斿洖鏁版嵁 - */ -public class MediaServerItemLite { - - 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 String secret; - - private int recordAssistPort; - - - - public MediaServerItemLite(MediaServerItem mediaServerItem) { - this.id = mediaServerItem.getId(); - this.ip = mediaServerItem.getIp(); - this.hookIp = mediaServerItem.getHookIp(); - this.sdpIp = mediaServerItem.getSdpIp(); - this.streamIp = mediaServerItem.getStreamIp(); - this.httpPort = mediaServerItem.getHttpPort(); - this.httpSSlPort = mediaServerItem.getHttpSSlPort(); - this.rtmpPort = mediaServerItem.getRtmpPort(); - this.rtmpSSlPort = mediaServerItem.getRtmpSSlPort(); - this.rtpProxyPort = mediaServerItem.getRtpProxyPort(); - this.rtspPort = mediaServerItem.getRtspPort(); - this.rtspSSLPort = mediaServerItem.getRtspSSLPort(); - this.secret = mediaServerItem.getSecret(); - this.recordAssistPort = mediaServerItem.getRecordAssistPort(); - } - - 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 String getSecret() { - return secret; - } - - public void setSecret(String secret) { - this.secret = secret; - } - - public int getRecordAssistPort() { - return recordAssistPort; - } - - public void setRecordAssistPort(int recordAssistPort) { - this.recordAssistPort = recordAssistPort; - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java index ef77225..8b722a9 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/StreamAuthorityInfo.java @@ -1,7 +1,6 @@ package com.genersoft.iot.vmp.media.zlm.dto; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnPublishHookParam; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; /** * 娴佺殑閴存潈淇℃伅 @@ -97,21 +96,23 @@ this.sign = sign; } - public static StreamAuthorityInfo getInstanceByHook(OnPublishHookParam hookParam) { + public static StreamAuthorityInfo getInstanceByHook(String app, String stream, String id) { StreamAuthorityInfo streamAuthorityInfo = new StreamAuthorityInfo(); - streamAuthorityInfo.setApp(hookParam.getApp()); - streamAuthorityInfo.setStream(hookParam.getStream()); - streamAuthorityInfo.setId(hookParam.getId()); + streamAuthorityInfo.setApp(app); + streamAuthorityInfo.setStream(stream); + streamAuthorityInfo.setId(id); return streamAuthorityInfo; } - public static StreamAuthorityInfo getInstanceByHook(OnStreamChangedHookParam onStreamChangedHookParam) { + public static StreamAuthorityInfo getInstanceByHook(MediaArrivalEvent event) { StreamAuthorityInfo streamAuthorityInfo = new StreamAuthorityInfo(); - streamAuthorityInfo.setApp(onStreamChangedHookParam.getApp()); - streamAuthorityInfo.setStream(onStreamChangedHookParam.getStream()); - streamAuthorityInfo.setId(onStreamChangedHookParam.getMediaServerId()); - streamAuthorityInfo.setOriginType(onStreamChangedHookParam.getOriginType()); - streamAuthorityInfo.setOriginTypeStr(onStreamChangedHookParam.getOriginTypeStr()); + streamAuthorityInfo.setApp(event.getApp()); + streamAuthorityInfo.setStream(event.getStream()); + streamAuthorityInfo.setId(event.getMediaServer().getId()); + if (event.getMediaInfo() != null) { + streamAuthorityInfo.setOriginType(event.getMediaInfo().getOriginType()); + } + return streamAuthorityInfo; } } 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 6befe46..797286f 100755 --- 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 @@ -1,6 +1,8 @@ package com.genersoft.iot.vmp.media.zlm.dto; +import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.gb28181.bean.GbStream; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.utils.DateUtil; import io.swagger.v3.oas.annotations.media.Schema; @@ -150,6 +152,47 @@ - DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(streamPushItem.getCreateTime())).intValue(); } + public StreamPushItem getInstance(StreamInfo streamInfo) { + StreamPushItem streamPushItem = new StreamPushItem(); + streamPushItem.setApp(streamInfo.getApp()); + streamPushItem.setMediaServerId(streamInfo.getMediaServerId()); + streamPushItem.setStream(streamInfo.getStream()); + streamPushItem.setAliveSecond(streamInfo.getMediaInfo().getAliveSecond()); +// streamPushItem.setOriginSock(streamInfo.getMediaInfo().getOriginSock()); + streamPushItem.setTotalReaderCount(streamInfo.getMediaInfo().getReaderCount() + ""); + streamPushItem.setOriginType(streamInfo.getOriginType()); +// streamPushItem.setOriginTypeStr(streamInfo.getMediaInfo().getOriginTypeStr()); +// streamPushItem.setOriginUrl(streamInfo.getMediaInfo().getOriginUrl()); + streamPushItem.setCreateTime(DateUtil.getNow()); + streamPushItem.setAliveSecond(streamInfo.getMediaInfo().getAliveSecond()); + streamPushItem.setStatus(true); + streamPushItem.setStreamType("push"); +// streamPushItem.setVhost(streamInfo.getVhost()); + streamPushItem.setServerId(streamInfo.getMediaServerId()); + return streamPushItem; + + } + + public static StreamPushItem getInstance(MediaArrivalEvent event, String serverId){ + StreamPushItem streamPushItem = new StreamPushItem(); + streamPushItem.setApp(event.getApp()); + streamPushItem.setMediaServerId(event.getMediaServer().getId()); + streamPushItem.setStream(event.getStream()); + streamPushItem.setAliveSecond(event.getMediaInfo().getAliveSecond()); +// streamPushItem.setOriginSock(streamInfo.getMediaInfo().getOriginSock()); + streamPushItem.setTotalReaderCount(event.getMediaInfo().getReaderCount() + ""); + streamPushItem.setOriginType(event.getMediaInfo().getOriginType()); +// streamPushItem.setOriginTypeStr(streamInfo.getMediaInfo().getOriginTypeStr()); +// streamPushItem.setOriginUrl(streamInfo.getMediaInfo().getOriginUrl()); + streamPushItem.setCreateTime(DateUtil.getNow()); + streamPushItem.setAliveSecond(event.getMediaInfo().getAliveSecond()); + streamPushItem.setStatus(true); + streamPushItem.setStreamType("push"); +// streamPushItem.setVhost(streamInfo.getVhost()); + streamPushItem.setServerId(serverId); + return streamPushItem; + } + public static class MediaSchema { private String schema; private Long bytesSpeed; diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMServerConfig.java similarity index 99% rename from src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java rename to src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMServerConfig.java index 80910c0..8f77b63 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerConfig.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/ZLMServerConfig.java @@ -1,4 +1,4 @@ -package com.genersoft.iot.vmp.media.zlm; +package com.genersoft.iot.vmp.media.zlm.dto; import com.alibaba.fastjson2.annotation.JSONField; import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookParam.java index 46ccf22..ae3bd68 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookParam.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookParam.java @@ -7,6 +7,8 @@ public class HookParam { private String mediaServerId; + + public String getMediaServerId() { return mediaServerId; } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java index b327f13..dee9d66 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResult.java @@ -18,8 +18,8 @@ return new HookResult(0, "success"); } - public static HookResult Fail(){ - return new HookResult(-1, "fail"); + public static HookResultForOnPublish Fail(){ + return new HookResultForOnPublish(-1, "fail"); } public int getCode() { diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java index 55369e5..33f9856 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/HookResultForOnPublish.java @@ -1,5 +1,7 @@ package com.genersoft.iot.vmp.media.zlm.dto.hook; +import com.genersoft.iot.vmp.media.bean.ResultForOnPublish; + public class HookResultForOnPublish extends HookResult{ private boolean enable_audio; @@ -16,6 +18,17 @@ return new HookResultForOnPublish(0, "success"); } + public static HookResultForOnPublish getInstance(ResultForOnPublish resultForOnPublish){ + HookResultForOnPublish successResult = new HookResultForOnPublish(0, "success"); + successResult.setEnable_audio(resultForOnPublish.isEnable_audio()); + successResult.setEnable_mp4(resultForOnPublish.isEnable_mp4()); + successResult.setModify_stamp(resultForOnPublish.getModify_stamp()); + successResult.setStream_replace(resultForOnPublish.getStream_replace()); + successResult.setMp4_max_second(resultForOnPublish.getMp4_max_second()); + successResult.setMp4_save_path(resultForOnPublish.getMp4_save_path()); + return successResult; + } + public HookResultForOnPublish(int code, String msg) { setCode(code); setMsg(msg); diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java index ffca0d5..efd1454 100755 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/hook/OnStreamChangedHookParam.java @@ -32,7 +32,7 @@ /** * 瑙傜湅鎬讳汉鏁帮紝鍖呮嫭hls/rtsp/rtmp/http-flv/ws-flv */ - private String totalReaderCount; + private int totalReaderCount; /** * 鍗忚 鍖呮嫭hls/rtsp/rtmp/http-flv/ws-flv @@ -374,11 +374,11 @@ this.stream = stream; } - public String getTotalReaderCount() { + public int getTotalReaderCount() { return totalReaderCount; } - public void setTotalReaderCount(String totalReaderCount) { + public void setTotalReaderCount(int totalReaderCount) { this.totalReaderCount = totalReaderCount; } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerKeepaliveEvent.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerKeepaliveEvent.java new file mode 100644 index 0000000..b927062 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerKeepaliveEvent.java @@ -0,0 +1,24 @@ +package com.genersoft.iot.vmp.media.zlm.event; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import org.springframework.context.ApplicationEvent; + +/** + * zlm 蹇冭烦浜嬩欢 + */ +public class HookZlmServerKeepaliveEvent extends ApplicationEvent { + + public HookZlmServerKeepaliveEvent(Object source) { + super(source); + } + + private MediaServer mediaServerItem; + + public MediaServer getMediaServerItem() { + return mediaServerItem; + } + + public void setMediaServerItem(MediaServer mediaServerItem) { + this.mediaServerItem = mediaServerItem; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerStartEvent.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerStartEvent.java new file mode 100644 index 0000000..e1c28b1 --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/HookZlmServerStartEvent.java @@ -0,0 +1,24 @@ +package com.genersoft.iot.vmp.media.zlm.event; + +import com.genersoft.iot.vmp.media.bean.MediaServer; +import org.springframework.context.ApplicationEvent; + +/** + * zlm server_start浜嬩欢 + */ +public class HookZlmServerStartEvent extends ApplicationEvent { + + public HookZlmServerStartEvent(Object source) { + super(source); + } + + private MediaServer mediaServerItem; + + public MediaServer getMediaServerItem() { + return mediaServerItem; + } + + public void setMediaServerItem(MediaServer mediaServerItem) { + this.mediaServerItem = mediaServerItem; + } +} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOfflineEvent.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOfflineEvent.java deleted file mode 100755 index 8207bdd..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOfflineEvent.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.event; - -/** - * zlm绂荤嚎浜嬩欢绫� - */ -public class ZLMOfflineEvent extends ZLMEventAbstract { - - public ZLMOfflineEvent(Object source) { - super(source); - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOnlineEvent.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOnlineEvent.java deleted file mode 100755 index 612ff9d..0000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/event/ZLMOnlineEvent.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.event; - -/** - * zlm鍦ㄧ嚎浜嬩欢 - */ -public class ZLMOnlineEvent extends ZLMEventAbstract { - - public ZLMOnlineEvent(Object source) { - super(source); - } -} diff --git a/src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java b/src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java index c10313e..875140f 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/ICloudRecordService.java @@ -1,8 +1,7 @@ package com.genersoft.iot.vmp.service; import com.alibaba.fastjson2.JSONArray; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.bean.CloudRecordItem; import com.genersoft.iot.vmp.service.bean.DownloadFileInfo; import com.github.pagehelper.PageInfo; @@ -18,22 +17,17 @@ /** * 鍒嗛〉鍥炲幓浜戠褰曞儚鍒楄〃 */ - PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems); - - /** - * 鏍规嵁hook娑堟伅澧炲姞涓�鏉¤褰� - */ - void addRecord(OnRecordMp4HookParam param); + PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems); /** * 鑾峰彇鎵�鏈夌殑鏃ユ湡 */ - List<String> getDateList(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems); + List<String> getDateList(String app, String stream, int year, int month, List<MediaServer> mediaServerItems); /** * 娣诲姞鍚堝苟浠诲姟 */ - String addTask(String app, String stream, MediaServerItem mediaServerItem, String startTime, + String addTask(String app, String stream, MediaServer mediaServerItem, String startTime, String endTime, String callId, String remoteHost, boolean filterMediaServer); diff --git a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java b/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java deleted file mode 100755 index 2e6151d..0000000 --- a/src/main/java/com/genersoft/iot/vmp/service/IMediaServerService.java +++ /dev/null @@ -1,100 +0,0 @@ -package com.genersoft.iot.vmp.service; - -import com.genersoft.iot.vmp.common.CommonCallback; -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.ServerKeepaliveData; -import com.genersoft.iot.vmp.service.bean.MediaServerLoad; -import com.genersoft.iot.vmp.service.bean.SSRCInfo; -import com.genersoft.iot.vmp.vmanager.bean.RecordFile; - -import java.util.List; - -/** - * 濯掍綋鏈嶅姟鑺傜偣 - */ -public interface IMediaServerService { - - List<MediaServerItem> getAll(); - - List<MediaServerItem> getAllFromDatabase(); - - List<MediaServerItem> getAllOnline(); - - MediaServerItem getOne(String generalMediaServerId); - - void syncCatchFromDatabase(); - - /** - * 鏂扮殑鑺傜偣鍔犲叆 - * @param zlmServerConfig - * @return - */ - void zlmServerOnline(ZLMServerConfig zlmServerConfig); - - /** - * 鑺傜偣绂荤嚎 - * @param mediaServerId - * @return - */ - void zlmServerOffline(String mediaServerId); - - MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist); - - void setZLMConfig(MediaServerItem mediaServerItem, boolean restart); - - void updateVmServer(List<MediaServerItem> mediaServerItemList); - - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, - boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode); - - SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto); - - void closeRTPServer(MediaServerItem mediaServerItem, String streamId); - - void closeRTPServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback); - Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc); - - void closeRTPServer(String mediaServerId, String streamId); - - void clearRTPServer(MediaServerItem mediaServerItem); - - void update(MediaServerItem mediaSerItem); - - void addCount(String mediaServerId); - - void removeCount(String mediaServerId); - - void releaseSsrc(String mediaServerItemId, String ssrc); - - void clearMediaServerForOnline(); - - void add(MediaServerItem mediaSerItem); - - int addToDatabase(MediaServerItem mediaSerItem); - - int updateToDatabase(MediaServerItem mediaSerItem); - - void resetOnlineServerItem(MediaServerItem serverItem); - - MediaServerItem checkMediaServer(String ip, int port, String secret); - - boolean checkMediaRecordServer(String ip, int port); - - void delete(String id); - - void deleteDb(String id); - - MediaServerItem getDefaultMediaServer(); - - void updateMediaServerKeepalive(String mediaServerId, ServerKeepaliveData data); - - /** - * 鑾峰彇璐熻浇淇℃伅 - * @return - */ - MediaServerLoad getLoad(MediaServerItem mediaServerItem); - - List<MediaServerItem> getAllWithAssistPort(); - -} 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 82de3bb..26f1585 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IMediaService.java @@ -1,8 +1,7 @@ package com.genersoft.iot.vmp.service; -import com.alibaba.fastjson2.JSONArray; -import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.ResultForOnPublish; +import com.genersoft.iot.vmp.media.bean.MediaServer; /** * 濯掍綋淇℃伅涓氬姟 @@ -10,35 +9,11 @@ public interface IMediaService { /** - * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 閫氳繃zlm鎺ュ彛妫�鏌ユ槸鍚﹀瓨鍦� - * @param app - * @param stream - * @return + * 鎾斁閴存潈 */ - StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId,String addr, boolean authority); + boolean authenticatePlay(String app, String stream, String callId); + ResultForOnPublish authenticatePublish(MediaServer mediaServer, String app, String stream, String params); - /** - * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 閫氳繃zlm鎺ュ彛妫�鏌ユ槸鍚﹀瓨鍦�, 杩斿洖鐨刬p浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌 - * @param app - * @param stream - * @return - */ - StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority); - - /** - * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴 - * @param app - * @param stream - * @return - */ - StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaServerItem, String app, String stream, Object tracks, String callId); - - /** - * 鏍规嵁搴旂敤鍚嶅拰娴両D鑾峰彇鎾斁鍦板潃, 鍙槸鍦板潃鎷兼帴锛岃繑鍥炵殑ip浣跨敤杩滅▼璁块棶ip锛岄�傜敤涓巣lm涓巜vp鍦ㄤ竴鍙颁富鏈虹殑鎯呭喌 - * @param app - * @param stream - * @return - */ - StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId, boolean isPlay); + boolean closeStreamOnNoneReader(String mediaServerId, String app, String stream, String schema); } diff --git a/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java b/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java index f8486a8..79bdf78 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlatformService.java @@ -3,8 +3,8 @@ import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.bean.InviteTimeOutCallback; import com.genersoft.iot.vmp.gb28181.bean.SipTransactionInfo; import com.github.pagehelper.PageInfo; @@ -73,13 +73,13 @@ * @param errorEvent 淇′护閿欒浜嬩欢 * @param timeoutCallback 瓒呮椂浜嬩欢 */ - void broadcastInvite(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, ZlmHttpHookSubscribe.Event hookEvent, + void broadcastInvite(ParentPlatform platform, String channelId, MediaServer mediaServerItem, HookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, InviteTimeOutCallback timeoutCallback) throws InvalidArgumentException, ParseException, SipException; /** * 璇煶鍠婅瘽鍥炲BYE */ - void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream,boolean sendBye, MediaServerItem mediaServerItem); + void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream,boolean sendBye, MediaServer mediaServerItem); void addSimulatedSubscribeInfo(ParentPlatform parentPlatform); } 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 bb2e2be..b3cab0e 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IPlayService.java @@ -7,8 +7,8 @@ import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.bean.ErrorCallback; import com.genersoft.iot.vmp.service.bean.SSRCInfo; import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; @@ -26,20 +26,20 @@ */ public interface IPlayService { - void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channelId, + void play(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channelId, ErrorCallback<Object> callback); - SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback); + SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback); - StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId); + StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, MediaInfo mediaInfo, String deviceId, String channelId); - MediaServerItem getNewMediaServerItem(Device device); + MediaServer getNewMediaServerItem(Device device); void playBack(String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); - void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); + void playBack(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback); void zlmServerOffline(String mediaServerId); void download(String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback); - void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo,String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback); + void download(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback); StreamInfo getDownLoadInfo(String deviceId, String channelId, String stream); @@ -47,7 +47,7 @@ AudioBroadcastResult audioBroadcast(Device device, String channelId, Boolean broadcastMode); - boolean audioBroadcastCmd(Device device, String channelId, MediaServerItem mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException; + boolean audioBroadcastCmd(Device device, String channelId, MediaServer mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException; boolean audioBroadcastInUse(Device device, String channelId); @@ -59,10 +59,9 @@ void startPushStream(SendRtpItem sendRtpItem, SIPResponse sipResponse, ParentPlatform platform, CallIdHeader callIdHeader); - void startSendRtpStreamHand(SendRtpItem sendRtpItem, Object correlationInfo, - JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader); + void startSendRtpStreamFailHand(SendRtpItem sendRtpItem,ParentPlatform platform, CallIdHeader callIdHeader); - void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioBroadcastEvent event); + void talkCmd(Device device, String channelId, MediaServer mediaServerItem, String stream, AudioBroadcastEvent event); void stopTalk(Device device, String channelId, Boolean streamIsReady); 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 c4968a7..f3b5162 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamProxyService.java @@ -1,12 +1,14 @@ package com.genersoft.iot.vmp.service; -import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.common.GeneralCallback; import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.github.pagehelper.PageInfo; + +import java.util.Map; public interface IStreamProxyService { @@ -18,17 +20,19 @@ /** * 娣诲姞瑙嗛浠g悊鍒皕lm + * * @param param * @return */ - JSONObject addStreamProxyToZlm(StreamProxyItem param); + WVPResult<String> addStreamProxyToZlm(StreamProxyItem param); /** * 浠巣lm绉婚櫎瑙嗛浠g悊 + * * @param param * @return */ - JSONObject removeStreamProxyFromZlm(StreamProxyItem param); + Boolean removeStreamProxyFromZlm(StreamProxyItem param); /** * 鍒嗛〉鏌ヨ @@ -73,9 +77,10 @@ /** * 鑾峰彇ffmpeg.cmd妯℃澘 + * * @return */ - JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem); + Map<String, String> getFFmpegCMDs(MediaServer mediaServerItem); /** * 鏍规嵁app涓巗tream鑾峰彇streamProxy 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 10b1eff..1507331 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java +++ b/src/main/java/com/genersoft/iot/vmp/service/IStreamPushService.java @@ -1,9 +1,8 @@ package com.genersoft.iot.vmp.service; import com.genersoft.iot.vmp.gb28181.bean.GbStream; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; +import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; import com.github.pagehelper.PageInfo; @@ -15,8 +14,6 @@ * @author lin */ public interface IStreamPushService { - - List<StreamPushItem> handleJSON(String json, MediaServerItem mediaServerItem); /** * 灏嗗簲鐢ㄥ悕鍜屾祦ID鍔犲叆鍥芥爣鍏宠仈 diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java b/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java index 771e4c8..c9a54bc 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/CloudRecordItem.java @@ -1,5 +1,6 @@ package com.genersoft.iot.vmp.service.bean; +import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; /** @@ -76,18 +77,18 @@ */ private long timeLen; - public static CloudRecordItem getInstance(OnRecordMp4HookParam param) { + public static CloudRecordItem getInstance(MediaRecordMp4Event param) { CloudRecordItem cloudRecordItem = new CloudRecordItem(); cloudRecordItem.setApp(param.getApp()); cloudRecordItem.setStream(param.getStream()); - cloudRecordItem.setStartTime(param.getStart_time()*1000); - cloudRecordItem.setFileName(param.getFile_name()); - cloudRecordItem.setFolder(param.getFolder()); - cloudRecordItem.setFileSize(param.getFile_size()); - cloudRecordItem.setFilePath(param.getFile_path()); - cloudRecordItem.setMediaServerId(param.getMediaServerId()); - cloudRecordItem.setTimeLen((long) param.getTime_len() * 1000); - cloudRecordItem.setEndTime((param.getStart_time() + (long)param.getTime_len()) * 1000); + cloudRecordItem.setStartTime(param.getRecordInfo().getStartTime()*1000); + cloudRecordItem.setFileName(param.getRecordInfo().getFileName()); + cloudRecordItem.setFolder(param.getRecordInfo().getFolder()); + cloudRecordItem.setFileSize(param.getRecordInfo().getFileSize()); + cloudRecordItem.setFilePath(param.getRecordInfo().getFilePath()); + cloudRecordItem.setMediaServerId(param.getMediaServer().getId()); + cloudRecordItem.setTimeLen((long) param.getRecordInfo().getTimeLen() * 1000); + cloudRecordItem.setEndTime((param.getRecordInfo().getStartTime() + (long)param.getRecordInfo().getTimeLen()) * 1000); return cloudRecordItem; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java b/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java index 0a332ef..d7da931 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/PlayBackResult.java @@ -2,7 +2,7 @@ import com.alibaba.fastjson2.JSONObject; import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import java.util.EventObject; @@ -15,7 +15,7 @@ private String msg; private T data; - private MediaServerItem mediaServerItem; + private MediaServer mediaServerItem; private JSONObject response; private SipSubscribe.EventResult<EventObject> event; @@ -35,11 +35,11 @@ this.data = data; } - public MediaServerItem getMediaServerItem() { + public MediaServer getMediaServerItem() { return mediaServerItem; } - public void setMediaServerItem(MediaServerItem mediaServerItem) { + public void setMediaServerItem(MediaServer mediaServerItem) { this.mediaServerItem = mediaServerItem; } diff --git a/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java b/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java index 501621b..9d73384 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java +++ b/src/main/java/com/genersoft/iot/vmp/service/bean/ResponseSendItemMsg.java @@ -1,7 +1,7 @@ package com.genersoft.iot.vmp.service.bean; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; /** * redis娑堟伅锛氫笅绾у洖澶嶆帹閫佷俊鎭� @@ -11,7 +11,7 @@ private SendRtpItem sendRtpItem; - private MediaServerItem mediaServerItem; + private MediaServer mediaServerItem; public SendRtpItem getSendRtpItem() { return sendRtpItem; @@ -21,11 +21,11 @@ this.sendRtpItem = sendRtpItem; } - public MediaServerItem getMediaServerItem() { + public MediaServer getMediaServerItem() { return mediaServerItem; } - public void setMediaServerItem(MediaServerItem mediaServerItem) { + public void setMediaServerItem(MediaServer mediaServerItem) { this.mediaServerItem = mediaServerItem; } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java index a23252f..6ff0746 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/CloudRecordServiceImpl.java @@ -5,12 +5,12 @@ import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.media.event.media.MediaRecordMp4Event; import com.genersoft.iot.vmp.media.zlm.AssistRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; import com.genersoft.iot.vmp.service.ICloudRecordService; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.bean.CloudRecordItem; import com.genersoft.iot.vmp.service.bean.DownloadFileInfo; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -24,6 +24,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.time.*; @@ -51,7 +53,7 @@ private VideoStreamSessionManager streamSession; @Override - public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServerItem> mediaServerItems) { + public PageInfo<CloudRecordItem> getList(int page, int count, String query, String app, String stream, String startTime, String endTime, List<MediaServer> mediaServerItems) { // 寮�濮嬫椂闂村拰缁撴潫鏃堕棿鍦ㄦ暟鎹簱涓兘鏄互绉掍负鍗曚綅鐨� Long startTimeStamp = null; Long endTimeStamp = null; @@ -76,7 +78,7 @@ } @Override - public List<String> getDateList(String app, String stream, int year, int month, List<MediaServerItem> mediaServerItems) { + public List<String> getDateList(String app, String stream, int year, int month, List<MediaServer> mediaServerItems) { LocalDate startDate = LocalDate.of(year, month, 1); LocalDate endDate; if (month == 12) { @@ -99,19 +101,20 @@ return new ArrayList<>(resultSet); } - @Override - public void addRecord(OnRecordMp4HookParam param) { - CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(param); - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(param.getApp(), param.getStream()); + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaRecordMp4Event event) { + CloudRecordItem cloudRecordItem = CloudRecordItem.getInstance(event); + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(event.getApp(), event.getStream()); if (streamAuthorityInfo != null) { cloudRecordItem.setCallId(streamAuthorityInfo.getCallId()); } - logger.info("[娣诲姞褰曞儚璁板綍] {}/{} 鏂囦欢澶у皬锛歿}, 鏃堕暱锛� {}绉�", param.getApp(), param.getStream(), param.getFile_size(),param.getTime_len()); + logger.info("[娣诲姞褰曞儚璁板綍] {}/{} 鍐呭锛歿}", event.getApp(), event.getStream(), event.getRecordInfo()); cloudRecordServiceMapper.add(cloudRecordItem); } @Override - public String addTask(String app, String stream, MediaServerItem mediaServerItem, String startTime, String endTime, + public String addTask(String app, String stream, MediaServer mediaServerItem, String startTime, String endTime, String callId, String remoteHost, boolean filterMediaServer) { // 鍙傛暟鏍¢獙 assert app != null; @@ -128,7 +131,7 @@ endTimeStamp = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime); } - List<MediaServerItem> mediaServers = new ArrayList<>(); + List<MediaServer> mediaServers = new ArrayList<>(); mediaServers.add(mediaServerItem); // 妫�绱㈢浉鍏崇殑褰曞儚鏂囦欢 List<String> filePathList = cloudRecordServiceMapper.queryRecordFilePathList(app, stream, startTimeStamp, @@ -146,7 +149,7 @@ @Override public JSONArray queryTask(String app, String stream, String callId, String taskId, String mediaServerId, Boolean isEnd, String scheme) { - MediaServerItem mediaServerItem = null; + MediaServer mediaServerItem = null; if (mediaServerId == null) { mediaServerItem = mediaServerService.getDefaultMediaServer(); }else { @@ -183,10 +186,10 @@ } - List<MediaServerItem> mediaServerItems; + List<MediaServer> mediaServerItems; if (!ObjectUtils.isEmpty(mediaServerId)) { mediaServerItems = new ArrayList<>(); - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒版祦濯掍綋: " + mediaServerId); } @@ -229,7 +232,7 @@ throw new ControllerException(ErrorCode.ERROR400.getCode(), "璧勬簮涓嶅瓨鍦�"); } String filePath = recordItem.getFilePath(); - MediaServerItem mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId()); + MediaServer mediaServerItem = mediaServerService.getOne(recordItem.getMediaServerId()); return CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath); } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java index 2c2674f..8fb772d 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/DeviceServiceImpl.java @@ -14,12 +14,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.event.request.impl.message.response.cmd.CatalogResponseMessageHandler; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.IDeviceChannelService; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.service.IInviteStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.dao.DeviceChannelMapper; import com.genersoft.iot.vmp.storager.dao.DeviceMapper; @@ -54,6 +53,7 @@ @Autowired private SIPCommander cmder; + @Autowired private DynamicTask dynamicTask; @@ -101,9 +101,6 @@ @Autowired private AudioBroadcastManager audioBroadcastManager; - - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; @Override public void online(Device device, SipTransactionInfo sipTransactionInfo) { @@ -244,12 +241,8 @@ SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null); if (sendRtpItem != null) { redisCatchStorage.deleteSendRTPServer(deviceId, sendRtpItem.getChannelId(), null, null); - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - Map<String, Object> param = new HashMap<>(); - param.put("vhost", "__defaultVhost__"); - param.put("app", sendRtpItem.getApp()); - param.put("stream", sendRtpItem.getStream()); - zlmresTfulUtils.stopSendRtp(mediaInfo, param); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + mediaServerService.stopSendRtp(mediaInfo, sendRtpItem.getApp(), sendRtpItem.getStream(), null); } audioBroadcastManager.del(deviceId, audioBroadcastCatch.getChannelId()); diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java index 9dc86f8..6e00960 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/InviteStreamServiceImpl.java @@ -6,13 +6,18 @@ import com.genersoft.iot.vmp.common.InviteSessionStatus; import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; +import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent; import com.genersoft.iot.vmp.service.IInviteStreamService; import com.genersoft.iot.vmp.service.bean.ErrorCallback; +import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.List; @@ -31,6 +36,35 @@ @Autowired private RedisTemplate<Object, Object> redisTemplate; + @Autowired + private IVideoManagerStorage storage; + + /** + * 娴佸埌鏉ョ殑澶勭悊 + */ + @Async("taskExecutor") + @org.springframework.context.event.EventListener + public void onApplicationEvent(MediaArrivalEvent event) { +// if ("rtsp".equals(event.getSchema()) && "rtp".equals(event.getApp())) { +// +// } + } + + /** + * 娴佺寮�鐨勫鐞� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaDepartureEvent event) { + if ("rtsp".equals(event.getSchema()) && "rtp".equals(event.getApp())) { + InviteInfo inviteInfo = getInviteInfoByStream(null, event.getStream()); + if (inviteInfo != null && (inviteInfo.getType() == InviteSessionType.PLAY || inviteInfo.getType() == InviteSessionType.PLAYBACK)) { + removeInviteInfo(inviteInfo); + storage.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); + } + } + } + @Override public void updateInviteInfo(InviteInfo inviteInfo) { if (inviteInfo == null || (inviteInfo.getDeviceId() == null || inviteInfo.getChannelId() == null)) { 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 deleted file mode 100755 index 190d665..0000000 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ /dev/null @@ -1,756 +0,0 @@ -package com.genersoft.iot.vmp.service.impl; - -import com.alibaba.fastjson2.JSON; -import com.alibaba.fastjson2.JSONArray; -import com.alibaba.fastjson2.JSONObject; -import com.baomidou.dynamic.datasource.annotation.DS; -import com.genersoft.iot.vmp.common.CommonCallback; -import com.genersoft.iot.vmp.common.VideoManagerConstants; -import com.genersoft.iot.vmp.conf.DynamicTask; -import com.genersoft.iot.vmp.conf.SipConfig; -import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.conf.exception.ControllerException; -import com.genersoft.iot.vmp.gb28181.event.EventPublisher; -import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; -import com.genersoft.iot.vmp.media.zlm.*; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.ServerKeepaliveData; -import com.genersoft.iot.vmp.service.IInviteStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.bean.MediaServerLoad; -import com.genersoft.iot.vmp.service.bean.SSRCInfo; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.dao.MediaServerMapper; -import com.genersoft.iot.vmp.utils.DateUtil; -import com.genersoft.iot.vmp.utils.JsonUtil; -import com.genersoft.iot.vmp.utils.redis.RedisUtil; -import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; -import com.genersoft.iot.vmp.vmanager.bean.RecordFile; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.annotation.Value; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.jdbc.datasource.DataSourceTransactionManager; -import org.springframework.scheduling.annotation.Async; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; -import org.springframework.stereotype.Service; -import org.springframework.transaction.TransactionDefinition; -import org.springframework.transaction.TransactionStatus; -import org.springframework.util.Assert; -import org.springframework.util.ObjectUtils; - -import java.io.File; -import java.time.LocalDateTime; -import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; - -/** - * 濯掍綋鏈嶅姟鍣ㄨ妭鐐圭鐞� - */ -@Service -@DS("master") -public class MediaServerServiceImpl implements IMediaServerService { - - private final static Logger logger = LoggerFactory.getLogger(MediaServerServiceImpl.class); - - private final String zlmKeepaliveKeyPrefix = "zlm-keepalive_"; - - @Autowired - private SipConfig sipConfig; - - @Autowired - private SSRCFactory ssrcFactory; - - @Value("${server.ssl.enabled:false}") - private boolean sslEnabled; - - @Value("${server.port}") - private Integer serverPort; - - @Autowired - private UserSetting userSetting; - - @Autowired - private SendRtpPortManager sendRtpPortManager; - - @Autowired - private AssistRESTfulUtils assistRESTfulUtils; - - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; - - @Autowired - private MediaServerMapper mediaServerMapper; - - @Autowired - private DataSourceTransactionManager dataSourceTransactionManager; - - @Autowired - private TransactionDefinition transactionDefinition; - - - @Autowired - private ZLMServerFactory zlmServerFactory; - - @Autowired - private EventPublisher publisher; - - @Autowired - private DynamicTask dynamicTask; - - @Autowired - private IRedisCatchStorage redisCatchStorage; - - @Autowired - private IInviteStreamService inviteStreamService; - - @Autowired - private RedisTemplate<Object, Object> redisTemplate; - - @Qualifier("taskExecutor") - @Autowired - private ThreadPoolTaskExecutor taskExecutor; - - - - - - /** - * 鍒濆鍖� - */ - @Override - public void updateVmServer(List<MediaServerItem> mediaServerItemList) { - logger.info("[zlm] 缂撳瓨鍒濆鍖� "); - for (MediaServerItem mediaServerItem : mediaServerItemList) { - if (ObjectUtils.isEmpty(mediaServerItem.getId())) { - continue; - } - // 鏇存柊 - if (!ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { - ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); - } - // 鏌ヨredis鏄惁瀛樺湪姝ediaServer - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); - Boolean hasKey = redisTemplate.hasKey(key); - if (hasKey != null && ! hasKey) { - redisTemplate.opsForValue().set(key, mediaServerItem); - } - } - } - - - @Override - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String presetSsrc, boolean ssrcCheck, - boolean isPlayback, Integer port, Boolean onlyAuto, Boolean reUsePort, Integer tcpMode) { - if (mediaServerItem == null || mediaServerItem.getId() == null) { - logger.info("[openRTPServer] 澶辫触, mediaServerItem == null || mediaServerItem.getId() == null"); - return null; - } - // 鑾峰彇mediaServer鍙敤鐨剆src - String ssrc; - if (presetSsrc != null) { - ssrc = presetSsrc; - }else { - if (isPlayback) { - ssrc = ssrcFactory.getPlayBackSsrc(mediaServerItem.getId()); - }else { - ssrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); - } - } - - if (streamId == null) { - streamId = String.format("%08x", Long.parseLong(ssrc)).toUpperCase(); - } - if (ssrcCheck && tcpMode > 0) { - // 鐩墠zlm涓嶆敮鎸� tcp妯″紡鏇存柊ssrc锛屾殏鏃跺叧闂璼src鏍¢獙 - logger.warn("[openRTPServer] 骞冲彴瀵规帴鏃朵笅绾у彲鑳借嚜瀹氫箟ssrc锛屼絾鏄痶cp妯″紡zlm鏀舵祦鐩墠鏃犳硶鏇存柊ssrc锛屽彲鑳芥敹娴佽秴鏃讹紝姝ゆ椂璇蜂娇鐢╱dp鏀舵祦鎴栬�呭叧闂璼src鏍¢獙"); - } - int rtpServerPort; - if (mediaServerItem.isRtpEnable()) { - rtpServerPort = zlmServerFactory.createRTPServer(mediaServerItem, streamId, ssrcCheck ? Long.parseLong(ssrc) : 0, port, onlyAuto, reUsePort, tcpMode); - } else { - rtpServerPort = mediaServerItem.getRtpProxyPort(); - } - return new SSRCInfo(rtpServerPort, ssrc, streamId); - } - - @Override - public SSRCInfo openRTPServer(MediaServerItem mediaServerItem, String streamId, String ssrc, boolean ssrcCheck, boolean isPlayback, Integer port, Boolean onlyAuto) { - return openRTPServer(mediaServerItem, streamId, ssrc, ssrcCheck, isPlayback, port, onlyAuto, null, 0); - } - - - @Override - public void closeRTPServer(MediaServerItem mediaServerItem, String streamId) { - if (mediaServerItem == null) { - return; - } - zlmServerFactory.closeRtpServer(mediaServerItem, streamId); - } - - @Override - public void closeRTPServer(MediaServerItem mediaServerItem, String streamId, CommonCallback<Boolean> callback) { - if (mediaServerItem == null) { - callback.run(false); - return; - } - zlmServerFactory.closeRtpServer(mediaServerItem, streamId, callback); - } - - @Override - public void closeRTPServer(String mediaServerId, String streamId) { - MediaServerItem mediaServerItem = this.getOne(mediaServerId); - if (mediaServerItem != null && mediaServerItem.isRtpEnable()) { - closeRTPServer(mediaServerItem, streamId); - } - zlmresTfulUtils.closeStreams(mediaServerItem, "rtp", streamId); - } - - @Override - public Boolean updateRtpServerSSRC(MediaServerItem mediaServerItem, String streamId, String ssrc) { - return zlmServerFactory.updateRtpServerSSRC(mediaServerItem, streamId, ssrc); - } - - @Override - public void releaseSsrc(String mediaServerItemId, String ssrc) { - MediaServerItem mediaServerItem = getOne(mediaServerItemId); - if (mediaServerItem == null || ssrc == null) { - return; - } - ssrcFactory.releaseSsrc(mediaServerItemId, ssrc); - } - - /** - * zlm 閲嶅惎鍚庨噸缃粬鐨勬帹娴佷俊鎭紝 TODO 缁欐鍦ㄤ娇鐢ㄧ殑璁惧鍙戦�佸仠姝㈠懡浠� - */ - @Override - public void clearRTPServer(MediaServerItem mediaServerItem) { - ssrcFactory.reset(mediaServerItem.getId()); - - } - - - @Override - public void update(MediaServerItem mediaSerItem) { - mediaServerMapper.update(mediaSerItem); - MediaServerItem mediaServerItemInRedis = getOne(mediaSerItem.getId()); - MediaServerItem mediaServerItemInDataBase = mediaServerMapper.queryOne(mediaSerItem.getId()); - if (mediaServerItemInRedis == null || !ssrcFactory.hasMediaServerSSRC(mediaSerItem.getId())) { - ssrcFactory.initMediaServerSSRC(mediaServerItemInDataBase.getId(),null); - } - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItemInDataBase.getId(); - redisTemplate.opsForValue().set(key, mediaServerItemInDataBase); - } - - @Override - public List<MediaServerItem> getAll() { - List<MediaServerItem> result = new ArrayList<>(); - List<Object> mediaServerKeys = RedisUtil.scan(redisTemplate, String.format("%S*", VideoManagerConstants.MEDIA_SERVER_PREFIX+ userSetting.getServerId() + "_" )); - String onlineKey = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); - for (Object mediaServerKey : mediaServerKeys) { - String key = (String) mediaServerKey; - MediaServerItem mediaServerItem = JsonUtil.redisJsonToObject(redisTemplate, key, MediaServerItem.class); - if (Objects.isNull(mediaServerItem)) { - continue; - } - // 妫�鏌ョ姸鎬� - Double aDouble = redisTemplate.opsForZSet().score(onlineKey, mediaServerItem.getId()); - if (aDouble != null) { - mediaServerItem.setStatus(true); - } - result.add(mediaServerItem); - } - result.sort((serverItem1, serverItem2)->{ - int sortResult = 0; - LocalDateTime localDateTime1 = LocalDateTime.parse(serverItem1.getCreateTime(), DateUtil.formatter); - LocalDateTime localDateTime2 = LocalDateTime.parse(serverItem2.getCreateTime(), DateUtil.formatter); - - sortResult = localDateTime1.compareTo(localDateTime2); - return sortResult; - }); - return result; - } - - - @Override - public List<MediaServerItem> getAllFromDatabase() { - return mediaServerMapper.queryAll(); - } - - @Override - public List<MediaServerItem> getAllOnline() { - String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); - Set<Object> mediaServerIdSet = redisTemplate.opsForZSet().reverseRange(key, 0, -1); - - List<MediaServerItem> result = new ArrayList<>(); - if (mediaServerIdSet != null && mediaServerIdSet.size() > 0) { - for (Object mediaServerId : mediaServerIdSet) { - String mediaServerIdStr = (String) mediaServerId; - String serverKey = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerIdStr; - result.add((MediaServerItem) redisTemplate.opsForValue().get(serverKey)); - } - } - Collections.reverse(result); - return result; - } - - /** - * 鑾峰彇鍗曚釜zlm鏈嶅姟鍣� - * @param mediaServerId 鏈嶅姟id - * @return MediaServerItem - */ - @Override - public MediaServerItem getOne(String mediaServerId) { - if (mediaServerId == null) { - return null; - } - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerId; - return JsonUtil.redisJsonToObject(redisTemplate, key, MediaServerItem.class); - } - - - @Override - public MediaServerItem getDefaultMediaServer() { - return mediaServerMapper.queryDefault(); - } - - @Override - public void clearMediaServerForOnline() { - String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); - redisTemplate.delete(key); - } - - @Override - public void add(MediaServerItem mediaServerItem) { - mediaServerItem.setCreateTime(DateUtil.getNow()); - mediaServerItem.setUpdateTime(DateUtil.getNow()); - mediaServerItem.setHookAliveInterval(30f); - JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); - if (responseJSON != null) { - JSONArray data = responseJSON.getJSONArray("data"); - if (data != null && data.size() > 0) { - ZLMServerConfig zlmServerConfig= JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); - if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) { - throw new ControllerException(ErrorCode.ERROR100.getCode(),"淇濆瓨澶辫触锛屽獟浣撴湇鍔D [ " + zlmServerConfig.getGeneralMediaServerId() + " ] 宸插瓨鍦紝璇蜂慨鏀瑰獟浣撴湇鍔″櫒閰嶇疆"); - } - mediaServerItem.setId(zlmServerConfig.getGeneralMediaServerId()); - zlmServerConfig.setIp(mediaServerItem.getIp()); - mediaServerMapper.add(mediaServerItem); - zlmServerOnline(zlmServerConfig); - }else { - throw new ControllerException(ErrorCode.ERROR100.getCode(),"杩炴帴澶辫触"); - } - - }else { - throw new ControllerException(ErrorCode.ERROR100.getCode(),"杩炴帴澶辫触"); - } - } - - @Override - public int addToDatabase(MediaServerItem mediaSerItem) { - return mediaServerMapper.add(mediaSerItem); - } - - @Override - public int updateToDatabase(MediaServerItem mediaSerItem) { - int result = 0; - if (mediaSerItem.isDefaultServer()) { - TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition); - int delResult = mediaServerMapper.delDefault(); - if (delResult == 0) { - logger.error("绉婚櫎鏁版嵁搴撻粯璁lm鑺傜偣澶辫触"); - //浜嬪姟鍥炴粴 - dataSourceTransactionManager.rollback(transactionStatus); - return 0; - } - result = mediaServerMapper.add(mediaSerItem); - dataSourceTransactionManager.commit(transactionStatus); //鎵嬪姩鎻愪氦 - }else { - result = mediaServerMapper.update(mediaSerItem); - } - return result; - } - - /** - * 澶勭悊zlm涓婄嚎 - * @param zlmServerConfig zlm涓婄嚎鎼哄甫鐨勫弬鏁� - */ - @Override - public void zlmServerOnline(ZLMServerConfig zlmServerConfig) { - - MediaServerItem serverItem = mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()); - if (serverItem == null) { - logger.warn("[鏈敞鍐岀殑zlm] 鎷掓帴鎺ュ叆锛歿}鏉ヨ嚜{}锛歿}", zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() ); - logger.warn("璇锋鏌LM鐨�<general.mediaServerId>閰嶇疆鏄惁涓嶹VP鐨�<media.id>涓�鑷�"); - return; - }else { - logger.info("[ZLM] 姝e湪杩炴帴 : {} -> {}:{}", - zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); - } - serverItem.setHookAliveInterval(zlmServerConfig.getHookAliveInterval()); - if (serverItem.getHttpPort() == 0) { - serverItem.setHttpPort(zlmServerConfig.getHttpPort()); - } - if (serverItem.getHttpSSlPort() == 0) { - serverItem.setHttpSSlPort(zlmServerConfig.getHttpSSLport()); - } - if (serverItem.getRtmpPort() == 0) { - serverItem.setRtmpPort(zlmServerConfig.getRtmpPort()); - } - if (serverItem.getRtmpSSlPort() == 0) { - serverItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); - } - if (serverItem.getRtspPort() == 0) { - serverItem.setRtspPort(zlmServerConfig.getRtspPort()); - } - if (serverItem.getRtspSSLPort() == 0) { - serverItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); - } - if (serverItem.getRtpProxyPort() == 0) { - serverItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); - } - serverItem.setStatus(true); - - if (ObjectUtils.isEmpty(serverItem.getId())) { - logger.warn("[鏈敞鍐岀殑zlm] serverItem缂哄皯ID锛� 鏃犳硶鎺ュ叆锛歿}锛歿}", zlmServerConfig.getIp(),zlmServerConfig.getHttpPort() ); - return; - } - mediaServerMapper.update(serverItem); - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + zlmServerConfig.getGeneralMediaServerId(); - if (!ssrcFactory.hasMediaServerSSRC(serverItem.getId())) { - ssrcFactory.initMediaServerSSRC(zlmServerConfig.getGeneralMediaServerId(), null); - } - redisTemplate.opsForValue().set(key, serverItem); - resetOnlineServerItem(serverItem); - - - if (serverItem.isAutoConfig()) { - setZLMConfig(serverItem, "0".equals(zlmServerConfig.getHookEnable())); - } - final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + serverItem.getId(); - dynamicTask.stop(zlmKeepaliveKey); - dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(serverItem), (serverItem.getHookAliveInterval().intValue() + 5) * 1000); - publisher.zlmOnlineEventPublish(serverItem.getId()); - - logger.info("[ZLM] 杩炴帴鎴愬姛 {} - {}:{} ", - zlmServerConfig.getGeneralMediaServerId(), zlmServerConfig.getIp(), zlmServerConfig.getHttpPort()); - } - - class KeepAliveTimeoutRunnable implements Runnable{ - - private MediaServerItem serverItem; - - public KeepAliveTimeoutRunnable(MediaServerItem serverItem) { - this.serverItem = serverItem; - } - - @Override - public void run() { - logger.info("[zlm蹇冭烦鍒版湡]锛�" + serverItem.getId()); - // 鍙戣捣http璇锋眰楠岃瘉zlm鏄惁纭疄鏃犳硶杩炴帴锛屽鏋滅‘瀹炴棤娉曡繛鎺ュ垯鍙戦�佺绾夸簨浠讹紝鍚﹀垯涓嶄綔澶勭悊 - JSONObject mediaServerConfig = zlmresTfulUtils.getMediaServerConfig(serverItem); - if (mediaServerConfig != null && mediaServerConfig.getInteger("code") == 0) { - logger.info("[zlm蹇冭烦鍒版湡]锛歿}楠岃瘉鍚巣lm浠嶅湪绾匡紝鎭㈠蹇冭烦淇℃伅,璇锋鏌lm鏄惁鍙互姝e父鍚憌vp鍙戦�佸績璺�", serverItem.getId()); - // 娣诲姞zlm淇℃伅 - updateMediaServerKeepalive(serverItem.getId(), null); - }else { - publisher.zlmOfflineEventPublish(serverItem.getId()); - } - } - } - - - @Override - public void zlmServerOffline(String mediaServerId) { - delete(mediaServerId); - final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerId; - dynamicTask.stop(zlmKeepaliveKey); - } - - @Override - public void resetOnlineServerItem(MediaServerItem serverItem) { - // 鏇存柊缂撳瓨 - String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); - // 浣跨敤zset鐨勫垎鏁颁綔涓哄綋鍓嶅苟鍙戦噺锛� 榛樿鍊艰缃负0 - if (redisTemplate.opsForZSet().score(key, serverItem.getId()) == null) { // 涓嶅瓨鍦ㄥ垯璁剧疆榛樿鍊� 宸插瓨鍦ㄥ垯閲嶇疆 - redisTemplate.opsForZSet().add(key, serverItem.getId(), 0L); - // 鏌ヨ鏈嶅姟娴佹暟閲� - zlmresTfulUtils.getMediaList(serverItem, null, null, "rtsp",(mediaList ->{ - Integer code = mediaList.getInteger("code"); - if (code == 0) { - JSONArray data = mediaList.getJSONArray("data"); - if (data != null) { - redisTemplate.opsForZSet().add(key, serverItem.getId(), data.size()); - } - } - })); - }else { - clearRTPServer(serverItem); - } - } - - - @Override - public void addCount(String mediaServerId) { - if (mediaServerId == null) { - return; - } - String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); - redisTemplate.opsForZSet().incrementScore(key, mediaServerId, 1); - - } - - @Override - public void removeCount(String mediaServerId) { - String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); - redisTemplate.opsForZSet().incrementScore(key, mediaServerId, - 1); - } - - /** - * 鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣 - * @return MediaServerItem - */ - @Override - public MediaServerItem getMediaServerForMinimumLoad(Boolean hasAssist) { - String key = VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(); - Long size = redisTemplate.opsForZSet().zCard(key); - if (size == null || size == 0) { - logger.info("鑾峰彇璐熻浇鏈�浣庣殑鑺傜偣鏃舵棤鍦ㄧ嚎鑺傜偣"); - return null; - } - - // 鑾峰彇鍒嗘暟鏈�浣庣殑锛屽強骞跺彂鏈�浣庣殑 - Set<Object> objects = redisTemplate.opsForZSet().range(key, 0, -1); - ArrayList<Object> mediaServerObjectS = new ArrayList<>(objects); - MediaServerItem mediaServerItem = null; - if (hasAssist == null) { - String mediaServerId = (String)mediaServerObjectS.get(0); - mediaServerItem = getOne(mediaServerId); - }else if (hasAssist) { - for (Object mediaServerObject : mediaServerObjectS) { - String mediaServerId = (String)mediaServerObject; - MediaServerItem serverItem = getOne(mediaServerId); - if (serverItem.getRecordAssistPort() > 0) { - mediaServerItem = serverItem; - break; - } - } - }else if (!hasAssist) { - for (Object mediaServerObject : mediaServerObjectS) { - String mediaServerId = (String)mediaServerObject; - MediaServerItem serverItem = getOne(mediaServerId); - if (serverItem.getRecordAssistPort() == 0) { - mediaServerItem = serverItem; - break; - } - } - } - - return mediaServerItem; - } - - /** - * 瀵箊lm鏈嶅姟鍣ㄨ繘琛屽熀纭�閰嶇疆 - * @param mediaServerItem 鏈嶅姟ID - * @param restart 鏄惁閲嶅惎zlm - */ - @Override - public void setZLMConfig(MediaServerItem mediaServerItem, boolean restart) { - logger.info("[ZLM] 姝e湪璁剧疆 锛歿} -> {}:{}", - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); - String protocol = sslEnabled ? "https" : "http"; - String hookPrefix = String.format("%s://%s:%s/index/hook", protocol, mediaServerItem.getHookIp(), serverPort); - - Map<String, Object> param = new HashMap<>(); - param.put("api.secret",mediaServerItem.getSecret()); // -profile:v Baseline - if (mediaServerItem.getRtspPort() != 0) { - param.put("ffmpeg.snap", "%s -rtsp_transport tcp -i %s -y -f mjpeg -frames:v 1 %s"); - } - param.put("hook.enable","1"); - param.put("hook.on_flow_report",""); - param.put("hook.on_play",String.format("%s/on_play", hookPrefix)); - param.put("hook.on_http_access",""); - param.put("hook.on_publish", String.format("%s/on_publish", hookPrefix)); - 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", hookPrefix)); - param.put("hook.on_shell_login",""); - param.put("hook.on_stream_changed",String.format("%s/on_stream_changed", hookPrefix)); - param.put("hook.on_stream_none_reader",String.format("%s/on_stream_none_reader", hookPrefix)); - param.put("hook.on_stream_not_found",String.format("%s/on_stream_not_found", hookPrefix)); - param.put("hook.on_server_keepalive",String.format("%s/on_server_keepalive", hookPrefix)); - param.put("hook.on_send_rtp_stopped",String.format("%s/on_send_rtp_stopped", hookPrefix)); - param.put("hook.on_rtp_server_timeout",String.format("%s/on_rtp_server_timeout", hookPrefix)); - param.put("hook.on_record_mp4",String.format("%s/on_record_mp4", hookPrefix)); - param.put("hook.timeoutSec","20"); - // 鎺ㄦ祦鏂紑鍚庡彲浠ュ湪瓒呮椂鏃堕棿鍐呴噸鏂拌繛鎺ヤ笂缁х画鎺ㄦ祦锛岃繖鏍锋挱鏀惧櫒浼氭帴鐫�鎾斁銆� - // 缃�0鍏抽棴姝ょ壒鎬�(鎺ㄦ祦鏂紑浼氬鑷寸珛鍗虫柇寮�鎾斁鍣�) - // 姝ゅ弬鏁颁笉搴斿ぇ浜庢挱鏀惧櫒瓒呮椂鏃堕棿 - // 浼樺寲姝ゆ秷鎭互鏇村揩鐨勬敹鍒版祦娉ㄩ攢浜嬩欢 - param.put("protocol.continue_push_ms", "3000" ); - // 鏈�澶氱瓑寰呮湭鍒濆鍖栫殑Track鏃堕棿锛屽崟浣嶆绉掞紝瓒呮椂涔嬪悗浼氬拷鐣ユ湭鍒濆鍖栫殑Track, 璁剧疆姝ら�夐」浼樺寲閭d簺闊抽閿欒鐨勪笉瑙勮寖娴侊紝 - // 绛墇lm鏀寔缁欐瘡涓猺tpServer璁剧疆鍏抽棴闊抽鐨勬椂鍊欏彲浠ヤ笉璁剧疆姝ら�夐」 - if (mediaServerItem.isRtpEnable() && !ObjectUtils.isEmpty(mediaServerItem.getRtpPortRange())) { - param.put("rtp_proxy.port_range", mediaServerItem.getRtpPortRange().replace(",", "-")); - } - - if (!ObjectUtils.isEmpty(mediaServerItem.getRecordPath())) { - File recordPathFile = new File(mediaServerItem.getRecordPath()); - param.put("protocol.mp4_save_path", recordPathFile.getParentFile().getPath()); - param.put("protocol.downloadRoot", recordPathFile.getParentFile().getPath()); - param.put("record.appName", recordPathFile.getName()); - } - - JSONObject responseJSON = zlmresTfulUtils.setServerConfig(mediaServerItem, param); - - if (responseJSON != null && responseJSON.getInteger("code") == 0) { - if (restart) { - logger.info("[ZLM] 璁剧疆鎴愬姛,寮�濮嬮噸鍚互淇濊瘉閰嶇疆鐢熸晥 {} -> {}:{}", - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); - zlmresTfulUtils.restartServer(mediaServerItem); - }else { - logger.info("[ZLM] 璁剧疆鎴愬姛 {} -> {}:{}", - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); - } - - - }else { - logger.info("[ZLM] 璁剧疆zlm澶辫触 {} -> {}:{}", - mediaServerItem.getId(), mediaServerItem.getIp(), mediaServerItem.getHttpPort()); - } - - - } - - - @Override - public MediaServerItem checkMediaServer(String ip, int port, String secret) { - if (mediaServerMapper.queryOneByHostAndPort(ip, port) != null) { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "姝よ繛鎺ュ凡瀛樺湪"); - } - MediaServerItem mediaServerItem = new MediaServerItem(); - mediaServerItem.setIp(ip); - mediaServerItem.setHttpPort(port); - mediaServerItem.setSecret(secret); - JSONObject responseJSON = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); - if (responseJSON == null) { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "杩炴帴澶辫触"); - } - JSONArray data = responseJSON.getJSONArray("data"); - ZLMServerConfig zlmServerConfig = JSON.parseObject(JSON.toJSONString(data.get(0)), ZLMServerConfig.class); - if (zlmServerConfig == null) { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "璇诲彇閰嶇疆澶辫触"); - } - if (mediaServerMapper.queryOne(zlmServerConfig.getGeneralMediaServerId()) != null) { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "濯掍綋鏈嶅姟ID [" + zlmServerConfig.getGeneralMediaServerId() + " ] 宸插瓨鍦紝璇蜂慨鏀瑰獟浣撴湇鍔″櫒閰嶇疆"); - } - mediaServerItem.setHttpSSlPort(zlmServerConfig.getHttpPort()); - mediaServerItem.setRtmpPort(zlmServerConfig.getRtmpPort()); - mediaServerItem.setRtmpSSlPort(zlmServerConfig.getRtmpSslPort()); - mediaServerItem.setRtspPort(zlmServerConfig.getRtspPort()); - mediaServerItem.setRtspSSLPort(zlmServerConfig.getRtspSSlport()); - mediaServerItem.setRtpProxyPort(zlmServerConfig.getRtpProxyPort()); - mediaServerItem.setStreamIp(ip); - mediaServerItem.setHookIp(sipConfig.getIp().split(",")[0]); - mediaServerItem.setSdpIp(ip); - return mediaServerItem; - } - - @Override - public boolean checkMediaRecordServer(String ip, int port) { - boolean result = false; - OkHttpClient client = new OkHttpClient(); - String url = String.format("http://%s:%s/index/api/record", ip, port); - Request request = new Request.Builder() - .get() - .url(url) - .build(); - try { - Response response = client.newCall(request).execute(); - if (response != null) { - result = true; - } - } catch (Exception e) {} - - return result; - } - - @Override - public void delete(String id) { - redisTemplate.opsForZSet().remove(VideoManagerConstants.MEDIA_SERVERS_ONLINE_PREFIX + userSetting.getServerId(), id); - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + id; - redisTemplate.delete(key); - } - @Override - public void deleteDb(String id){ - //鍚屾鍒犻櫎鏁版嵁搴撲腑鐨勬暟鎹� - mediaServerMapper.delOne(id); - } - - @Override - public void updateMediaServerKeepalive(String mediaServerId, ServerKeepaliveData data) { - MediaServerItem mediaServerItem = getOne(mediaServerId); - if (mediaServerItem == null) { - // 缂撳瓨涓嶅瓨鍦紝浠庢暟鎹簱鏌ヨ锛屽鏋滄暟鎹簱涓嶅瓨鍦ㄥ垯鏄敊璇殑 - mediaServerItem = getOneFromDatabase(mediaServerId); - if (mediaServerItem == null) { - logger.warn("[鏇存柊ZLM 淇濇椿淇℃伅] 娴佸獟浣搟}灏氭湭鍔犲叆浣跨敤,璇锋鏌ヨ妭鐐逛腑鏄惁鍚湁姝ゆ祦濯掍綋 ", mediaServerId); - return; - } - // zlm杩炴帴閲嶈瘯 - logger.warn("[鏇存柊ZLM 淇濇椿淇℃伅]灏濊瘯閾炬帴zml id {}", mediaServerId); - ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); - String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); - redisTemplate.opsForValue().set(key, mediaServerItem); - resetOnlineServerItem(mediaServerItem); - clearRTPServer(mediaServerItem); - } - final String zlmKeepaliveKey = zlmKeepaliveKeyPrefix + mediaServerItem.getId(); - dynamicTask.stop(zlmKeepaliveKey); - dynamicTask.startDelay(zlmKeepaliveKey, new KeepAliveTimeoutRunnable(mediaServerItem), (mediaServerItem.getHookAliveInterval().intValue() + 5) * 1000); - } - - private MediaServerItem getOneFromDatabase(String mediaServerId) { - return mediaServerMapper.queryOne(mediaServerId); - } - - @Override - public void syncCatchFromDatabase() { - List<MediaServerItem> allInCatch = getAll(); - List<MediaServerItem> allInDatabase = mediaServerMapper.queryAll(); - Map<String, MediaServerItem> mediaServerItemMap = new HashMap<>(); - - for (MediaServerItem mediaServerItem : allInDatabase) { - mediaServerItemMap.put(mediaServerItem.getId(), mediaServerItem); - } - for (MediaServerItem mediaServerItem : allInCatch) { - if (!mediaServerItemMap.containsKey(mediaServerItem.getId())) { - delete(mediaServerItem.getId()); - } - } - } - - @Override - public MediaServerLoad getLoad(MediaServerItem mediaServerItem) { - MediaServerLoad result = new MediaServerLoad(); - result.setId(mediaServerItem.getId()); - result.setPush(redisCatchStorage.getPushStreamCount(mediaServerItem.getId())); - result.setProxy(redisCatchStorage.getProxyStreamCount(mediaServerItem.getId())); - - result.setGbReceive(inviteStreamService.getStreamInfoCount(mediaServerItem.getId())); - result.setGbSend(redisCatchStorage.getGbSendCount(mediaServerItem.getId())); - return result; - } - - @Override - public List<MediaServerItem> getAllWithAssistPort() { - return mediaServerMapper.queryAllWithAssistPort(); - } -} 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 784f43f..5c819e5 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServiceImpl.java @@ -1,109 +1,331 @@ package com.genersoft.iot.vmp.service.impl; -import com.alibaba.fastjson2.JSON; -import com.alibaba.fastjson2.JSONArray; -import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.common.StreamInfo; -import com.genersoft.iot.vmp.conf.MediaConfig; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.common.InviteInfo; +import com.genersoft.iot.vmp.common.InviteSessionType; +import com.genersoft.iot.vmp.common.VideoManagerConstants; +import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.conf.exception.ControllerException; +import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; +import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; +import com.genersoft.iot.vmp.media.bean.ResultForOnPublish; +import com.genersoft.iot.vmp.media.zlm.ZLMMediaListManager; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IMediaService; +import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; +import com.genersoft.iot.vmp.service.*; +import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; +import com.genersoft.iot.vmp.utils.DateUtil; +import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; +import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; +import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; +import javax.sip.InvalidArgumentException; +import javax.sip.SipException; +import java.text.ParseException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + @Service public class MediaServiceImpl implements IMediaService { + + private final static Logger logger = LoggerFactory.getLogger(MediaServiceImpl.class); @Autowired private IRedisCatchStorage redisCatchStorage; @Autowired + private IStreamProxyService streamProxyService; + + @Autowired + private UserSetting userSetting; + + @Autowired + private RedisTemplate<Object, Object> redisTemplate; + + @Autowired + private IUserService userService; + + @Autowired + private IInviteStreamService inviteStreamService; + + @Autowired + private VideoStreamSessionManager sessionManager; + + @Autowired private IVideoManagerStorage storager; @Autowired - private IMediaServerService mediaServerService; - + private ZLMMediaListManager zlmMediaListManager; @Autowired - private MediaConfig mediaConfig; + private IDeviceService deviceService; @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; + private ISIPCommanderForPlatform commanderForPlatform; - + @Autowired + private ISIPCommander commander; @Override - public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String callId) { - return getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, null, callId, true); + public boolean authenticatePlay(String app, String stream, String callId) { + if (app == null || stream == null) { + return false; + } + if ("rtp".equals(app)) { + return true; + } + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream); + if (streamAuthorityInfo == null || streamAuthorityInfo.getCallId() == null) { + return true; + } + return streamAuthorityInfo.getCallId().equals(callId); } @Override - public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, String addr, boolean authority) { - StreamInfo streamInfo = null; - if (mediaServerId == null) { - mediaServerId = mediaConfig.getId(); - } - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); - if (mediaInfo == null) { - return null; - } - String calld = null; - StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(app, stream); - if (streamAuthorityInfo != null) { - calld = streamAuthorityInfo.getCallId(); - } - 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; + public ResultForOnPublish authenticatePublish(MediaServer mediaServer, String app, String stream, String params) { + // 鎺ㄦ祦閴存潈鐨勫鐞� + if (!"rtp".equals(app)) { + StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, stream); + if (streamProxyItem != null) { + ResultForOnPublish result = new ResultForOnPublish(); + result.setEnable_audio(streamProxyItem.isEnableAudio()); + result.setEnable_mp4(streamProxyItem.isEnableMp4()); + return result; + } + if (userSetting.getPushAuthority()) { + // 瀵逛簬鎺ㄦ祦杩涜閴存潈 + Map<String, String> paramMap = urlParamToMap(params); + // 鎺ㄦ祦閴存潈 + if (params == null) { + logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯蹇呰鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)"); + throw new ControllerException(ErrorCode.ERROR401.getCode(), "Unauthorized"); } - JSONObject mediaJSON = data.getJSONObject(0); - JSONArray tracks = mediaJSON.getJSONArray("tracks"); - if (authority) { - streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr, calld, true); - }else { - streamInfo = getStreamInfoByAppAndStream(mediaInfo, app, stream, tracks, addr,null, true); + + String sign = paramMap.get("sign"); + if (sign == null) { + logger.info("鎺ㄦ祦閴存潈澶辫触锛� 缂哄皯蹇呰鍙傛暟锛歴ign=md5(user琛ㄧ殑pushKey)"); + throw new ControllerException(ErrorCode.ERROR401.getCode(), "Unauthorized"); + } + // 鎺ㄦ祦鑷畾涔夋挱鏀鹃壌鏉冪爜 + String callId = paramMap.get("callId"); + // 閴存潈閰嶇疆 + boolean hasAuthority = userService.checkPushAuthority(callId, sign); + if (!hasAuthority) { + logger.info("鎺ㄦ祦閴存潈澶辫触锛� sign 鏃犳潈闄�: callId={}. sign={}", callId, sign); + throw new ControllerException(ErrorCode.ERROR401.getCode(), "Unauthorized"); + } + StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(app, stream, mediaServer.getId()); + streamAuthorityInfo.setCallId(callId); + streamAuthorityInfo.setSign(sign); + // 閴存潈閫氳繃 + redisCatchStorage.updateStreamAuthorityInfo(app, stream, streamAuthorityInfo); + } + } else { + zlmMediaListManager.sendStreamEvent(app, stream, mediaServer.getId()); + } + + + ResultForOnPublish result = new ResultForOnPublish(); + result.setEnable_audio(true); + + // 鏄惁褰曞儚 + if ("rtp".equals(app)) { + result.setEnable_mp4(userSetting.getRecordSip()); + } else { + result.setEnable_mp4(userSetting.isRecordPushLive()); + } + // 鍥芥爣娴� + if ("rtp".equals(app)) { + + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, stream); + + // 鍗曠鍙fā寮忎笅淇敼娴� ID + if (!mediaServer.isRtpEnable() && inviteInfo == null) { + String ssrc = String.format("%010d", Long.parseLong(stream, 16)); + inviteInfo = inviteStreamService.getInviteInfoBySSRC(ssrc); + if (inviteInfo != null) { + result.setStream_replace(inviteInfo.getStream()); + logger.info("[ZLM HOOK]鎺ㄦ祦閴存潈 stream: {} 鏇挎崲涓� {}", stream, inviteInfo.getStream()); + stream = inviteInfo.getStream(); + } + } + + // 璁剧疆闊抽淇℃伅鍙婂綍鍒朵俊鎭� + List<SsrcTransaction> ssrcTransactionForAll = sessionManager.getSsrcTransactionForAll(null, null, null, stream); + if (ssrcTransactionForAll != null && ssrcTransactionForAll.size() == 1) { + + // 涓哄綍鍒跺浗鏍囨ā鎷熶竴涓壌鏉冧俊鎭�, 鏂逛究鍚庣画鍐欏叆褰曞儚鏂囦欢鏃朵娇鐢� + StreamAuthorityInfo streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(app, stream, mediaServer.getId()); + streamAuthorityInfo.setApp(app); + streamAuthorityInfo.setStream(ssrcTransactionForAll.get(0).getStream()); + streamAuthorityInfo.setCallId(ssrcTransactionForAll.get(0).getSipTransactionInfo().getCallId()); + + redisCatchStorage.updateStreamAuthorityInfo(app, ssrcTransactionForAll.get(0).getStream(), streamAuthorityInfo); + + String deviceId = ssrcTransactionForAll.get(0).getDeviceId(); + String channelId = ssrcTransactionForAll.get(0).getChannelId(); + DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); + if (deviceChannel != null) { + result.setEnable_audio(deviceChannel.isHasAudio()); + } + // 濡傛灉鏄綍鍍忎笅杞藉氨璁剧疆瑙嗛闂撮殧鍗佺 + if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.DOWNLOAD) { + // 鑾峰彇褰曞儚鐨勬�绘椂闀匡紝鐒跺悗璁剧疆涓鸿繖涓棰戠殑鏃堕暱 + InviteInfo inviteInfoForDownload = inviteStreamService.getInviteInfo(InviteSessionType.DOWNLOAD, deviceId, channelId, stream); + if (inviteInfoForDownload != null && inviteInfoForDownload.getStreamInfo() != null) { + String startTime = inviteInfoForDownload.getStreamInfo().getStartTime(); + String endTime = inviteInfoForDownload.getStreamInfo().getEndTime(); + long difference = DateUtil.getDifference(startTime, endTime) / 1000; + result.setMp4_max_second((int) difference); + result.setEnable_mp4(true); + // 璁剧疆涓�2淇濊瘉寰楀埌鐨刴p4鐨勬椂闀挎槸姝e父鐨� + result.setModify_stamp(2); + } + } + // 濡傛灉鏄痶alk瀵硅锛屽垯榛樿鑾峰彇澹伴煶 + if (ssrcTransactionForAll.get(0).getType() == InviteSessionType.TALK) { + result.setEnable_audio(true); + } + } + } else if (app.equals("broadcast")) { + result.setEnable_audio(true); + } else if (app.equals("talk")) { + result.setEnable_audio(true); + } + if (app.equalsIgnoreCase("rtp")) { + String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_" + stream; + OtherRtpSendInfo otherRtpSendInfo = (OtherRtpSendInfo) redisTemplate.opsForValue().get(receiveKey); + + String receiveKeyForPS = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_" + stream; + OtherPsSendInfo otherPsSendInfo = (OtherPsSendInfo) redisTemplate.opsForValue().get(receiveKeyForPS); + if (otherRtpSendInfo != null || otherPsSendInfo != null) { + result.setEnable_mp4(true); + } + } + return result; + } + + private Map<String, String> urlParamToMap(String params) { + HashMap<String, String> map = new HashMap<>(); + if (ObjectUtils.isEmpty(params)) { + return map; + } + String[] paramsArray = params.split("&"); + if (paramsArray.length == 0) { + return map; + } + for (String param : paramsArray) { + String[] paramArray = param.split("="); + if (paramArray.length == 2) { + map.put(paramArray[0], paramArray[1]); + } + } + return map; + } + + @Override + public boolean closeStreamOnNoneReader(String mediaServerId, String app, String stream, String schema) { + boolean result = false; + // 鍥芥爣绫诲瀷鐨勬祦 + if ("rtp".equals(app)) { + result = userSetting.getStreamOnDemand(); + // 鍥芥爣娴侊紝 鐐规挱/褰曞儚鍥炴斁/褰曞儚涓嬭浇 + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, stream); + // 鐐规挱 + if (inviteInfo != null) { + // 褰曞儚涓嬭浇 + if (inviteInfo.getType() == InviteSessionType.DOWNLOAD) { + return false; + } + // 鏀跺埌鏃犱汉瑙傜湅璇存槑娴佷篃娌℃湁鍦ㄥ線涓婄骇鎺ㄩ�� + if (redisCatchStorage.isChannelSendingRTP(inviteInfo.getChannelId())) { + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByChannelId( + inviteInfo.getChannelId()); + if (!sendRtpItems.isEmpty()) { + for (SendRtpItem sendRtpItem : sendRtpItems) { + ParentPlatform parentPlatform = storager.queryParentPlatByServerGBId(sendRtpItem.getPlatformId()); + try { + commanderForPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage()); + } + redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), + sendRtpItem.getCallId(), sendRtpItem.getStream()); + if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) { + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), + sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); + messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); + } + } + } + } + Device device = deviceService.getDevice(inviteInfo.getDeviceId()); + if (device != null) { + try { + // 澶氭煡璇竴娆¢槻姝㈠凡缁忚澶勭悊浜� + InviteInfo info = inviteStreamService.getInviteInfo(inviteInfo.getType(), + inviteInfo.getDeviceId(), inviteInfo.getChannelId(), inviteInfo.getStream()); + if (info != null) { + commander.streamByeCmd(device, inviteInfo.getChannelId(), + inviteInfo.getStream(), null); + } else { + logger.info("[鏃犱汉瑙傜湅] 鏈壘鍒拌澶囩殑鐐规挱淇℃伅锛� {}锛� 娴侊細{}", inviteInfo.getDeviceId(), stream); + } + } catch (InvalidArgumentException | ParseException | SipException | + SsrcTransactionNotFoundException e) { + logger.error("[鏃犱汉瑙傜湅]鐐规挱锛� 鍙戦�丅YE澶辫触 {}", e.getMessage()); + } + } else { + logger.info("[鏃犱汉瑙傜湅] 鏈壘鍒拌澶囷細 {}锛屾祦锛歿}", inviteInfo.getDeviceId(), stream); + } + + inviteStreamService.removeInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId(), + inviteInfo.getChannelId(), inviteInfo.getStream()); + storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); + return result; + } + SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(null, null, stream, null); + if (sendRtpItem != null && "talk".equals(sendRtpItem.getApp())) { + return false; + } + } else if ("talk".equals(app) || "broadcast".equals(app)) { + return false; + } else { + // 闈炲浗鏍囨祦 鎺ㄦ祦/鎷夋祦浠g悊 + // 鎷夋祦浠g悊 + StreamProxyItem streamProxyItem = streamProxyService.getStreamProxyByAppAndStream(app, stream); + if (streamProxyItem != null) { + if (streamProxyItem.isEnableRemoveNoneReader()) { + // 鏃犱汉瑙傜湅鑷姩绉婚櫎 + result = true; + streamProxyService.del(app, stream); + String url = streamProxyItem.getUrl() != null ? streamProxyItem.getUrl() : streamProxyItem.getSrcUrl(); + logger.info("[{}/{}]<-[{}] 鎷夋祦浠g悊鏃犱汉瑙傜湅宸茬粡绉婚櫎", app, stream, url); + } else if (streamProxyItem.isEnableDisableNoneReader()) { + // 鏃犱汉瑙傜湅鍋滅敤 + result = true; + // 淇敼鏁版嵁 + streamProxyService.stop(app, stream); + } else { + // 鏃犱汉瑙傜湅涓嶅仛澶勭悊 + result = false; } } } - return streamInfo; - } - - - - @Override - public StreamInfo getStreamInfoByAppAndStreamWithCheck(String app, String stream, String mediaServerId, boolean authority) { - return getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, null, authority); - } - - @Override - public StreamInfo getStreamInfoByAppAndStream(MediaServerItem mediaInfo, String app, String stream, Object tracks, String addr, String callId, boolean isPlay) { - StreamInfo streamInfoResult = new StreamInfo(); - streamInfoResult.setStream(stream); - streamInfoResult.setApp(app); - if (addr == null) { - addr = mediaInfo.getStreamIp(); - } - - streamInfoResult.setIp(addr); - streamInfoResult.setMediaServerId(mediaInfo.getId()); - String callIdParam = ObjectUtils.isEmpty(callId)?"":"?callId=" + callId; - streamInfoResult.setRtmp(addr, mediaInfo.getRtmpPort(),mediaInfo.getRtmpSSlPort(), app, stream, callIdParam); - streamInfoResult.setRtsp(addr, mediaInfo.getRtspPort(),mediaInfo.getRtspSSLPort(), app, stream, callIdParam); - streamInfoResult.setFlv(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam); - streamInfoResult.setFmp4(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam); - streamInfoResult.setHls(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam); - streamInfoResult.setTs(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam); - streamInfoResult.setRtc(addr, mediaInfo.getHttpPort(),mediaInfo.getHttpSSlPort(), app, stream, callIdParam, isPlay); - - streamInfoResult.setTracks(tracks); - return streamInfoResult; + return result; } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java index 06c621e..aa39f41 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlatformServiceImpl.java @@ -1,10 +1,7 @@ package com.genersoft.iot.vmp.service.impl; -import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.common.InviteInfo; -import com.genersoft.iot.vmp.common.InviteSessionStatus; -import com.genersoft.iot.vmp.common.InviteSessionType; import com.baomidou.dynamic.datasource.annotation.DS; +import com.genersoft.iot.vmp.common.*; import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; @@ -12,46 +9,38 @@ import com.genersoft.iot.vmp.gb28181.event.SipSubscribe; import com.genersoft.iot.vmp.gb28181.session.SSRCFactory; import com.genersoft.iot.vmp.gb28181.session.VideoStreamSessionManager; -import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommanderFroPlatform; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; +import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.media.event.hook.HookData; +import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent; +import com.genersoft.iot.vmp.media.event.mediaServer.MediaSendRtpStoppedEvent; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.IInviteStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IPlatformService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.bean.*; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; -import com.genersoft.iot.vmp.storager.dao.*; +import com.genersoft.iot.vmp.storager.dao.GbStreamMapper; +import com.genersoft.iot.vmp.storager.dao.ParentPlatformMapper; import com.genersoft.iot.vmp.utils.DateUtil; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; -import gov.nist.javax.sip.message.SIPRequest; import gov.nist.javax.sip.message.SIPResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import javax.sdp.*; import javax.sip.InvalidArgumentException; import javax.sip.ResponseEvent; -import javax.sip.PeerUnavailableException; import javax.sip.SipException; import java.text.ParseException; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.UUID; import java.util.*; /** @@ -81,7 +70,7 @@ private IMediaServerService mediaServerService; @Autowired - private SIPCommanderFroPlatform commanderForPlatform; + private ISIPCommanderForPlatform commanderForPlatform; @Autowired private DynamicTask dynamicTask; @@ -99,11 +88,10 @@ private UserSetting userSetting; @Autowired - private ZlmHttpHookSubscribe subscribe; + private HookSubscribe subscribe; @Autowired private VideoStreamSessionManager streamSession; - @Autowired private IPlayService playService; @@ -111,8 +99,56 @@ @Autowired private IInviteStreamService inviteStreamService; - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; + + /** + * 娴佺寮�鐨勫鐞� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaDepartureEvent event) { + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(event.getStream()); + if (!sendRtpItems.isEmpty()) { + for (SendRtpItem sendRtpItem : sendRtpItems) { + if (sendRtpItem != null && sendRtpItem.getApp().equals(event.getApp())) { + String platformId = sendRtpItem.getPlatformId(); + ParentPlatform platform = platformMapper.getParentPlatByServerGBId(platformId); + + try { + if (platform != null) { + commanderForPlatform.streamByeCmd(platform, sendRtpItem); + redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), + sendRtpItem.getCallId(), sendRtpItem.getStream()); + } + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鍙戦�丅YE: {}", e.getMessage()); + } + } + } + } + } + + + /** + * 鍙戞祦鍋滄 + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaSendRtpStoppedEvent event) { + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(event.getStream()); + if (sendRtpItems != null && !sendRtpItems.isEmpty()) { + for (SendRtpItem sendRtpItem : sendRtpItems) { + ParentPlatform parentPlatform = platformMapper.getParentPlatByServerGBId(sendRtpItem.getPlatformId()); + ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); + try { + commanderForPlatform.streamByeCmd(parentPlatform, sendRtpItem.getCallId()); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage()); + } + redisCatchStorage.deleteSendRTPServer(parentPlatform.getServerGBId(), sendRtpItem.getChannelId(), + sendRtpItem.getCallId(), sendRtpItem.getStream()); + } + } + } @Override @@ -400,7 +436,7 @@ for (SendRtpItem sendRtpItem : sendRtpItems) { ssrcFactory.releaseSsrc(sendRtpItem.getMediaServerId(), sendRtpItem.getSsrc()); redisCatchStorage.deleteSendRTPServer(platformId, sendRtpItem.getChannelId(), null, null); - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); Map<String, Object> param = new HashMap<>(3); param.put("vhost", "__defaultVhost__"); param.put("app", sendRtpItem.getApp()); @@ -463,7 +499,7 @@ } @Override - public void broadcastInvite(ParentPlatform platform, String channelId, MediaServerItem mediaServerItem, ZlmHttpHookSubscribe.Event hookEvent, + public void broadcastInvite(ParentPlatform platform, String channelId, MediaServer mediaServerItem, HookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, InviteTimeOutCallback timeoutCallback) throws InvalidArgumentException, ParseException, SipException { if (mediaServerItem == null) { @@ -474,19 +510,19 @@ if (inviteInfoForOld != null && inviteInfoForOld.getStreamInfo() != null) { // 濡傛灉zlm涓嶅瓨鍦ㄨ繖涓祦锛屽垯鍒犻櫎鏁版嵁鍗冲彲 - MediaServerItem mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfoForOld.getStreamInfo().getMediaServerId()); + MediaServer mediaServerItemForStreamInfo = mediaServerService.getOne(inviteInfoForOld.getStreamInfo().getMediaServerId()); if (mediaServerItemForStreamInfo != null) { - Boolean ready = zlmServerFactory.isStreamReady(mediaServerItemForStreamInfo, inviteInfoForOld.getStreamInfo().getApp(), inviteInfoForOld.getStreamInfo().getStream()); + Boolean ready = mediaServerService.isStreamReady(mediaServerItemForStreamInfo, inviteInfoForOld.getStreamInfo().getApp(), inviteInfoForOld.getStreamInfo().getStream()); if (!ready) { // 閿欒瀛樺湪浜巖edis涓殑鏁版嵁 inviteStreamService.removeInviteInfo(inviteInfoForOld); }else { // 娴佺‘瀹炲皻鍦ㄦ帹娴侊紝鐩存帴鍥炶皟缁撴灉 - OnStreamChangedHookParam hookParam = new OnStreamChangedHookParam(); - hookParam.setApp(inviteInfoForOld.getStreamInfo().getApp()); - hookParam.setStream(inviteInfoForOld.getStreamInfo().getStream()); - - hookEvent.response(mediaServerItemForStreamInfo, hookParam); + HookData hookData = new HookData(); + hookData.setApp(inviteInfoForOld.getStreamInfo().getApp()); + hookData.setStream(inviteInfoForOld.getStreamInfo().getStream()); + hookData.setMediaServer(mediaServerItemForStreamInfo); + hookEvent.response(hookData); return; } } @@ -506,7 +542,7 @@ } else { tcpMode = 0; } - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, ssrcCheck, false, null, true, false, tcpMode); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, null, ssrcCheck, false, null, true, false, false, tcpMode); if (ssrcInfo == null || ssrcInfo.getPort() < 0) { logger.info("[鍥芥爣绾ц仈] 鍙戣捣璇煶鍠婅瘽 寮�鍚鍙g洃鍚け璐ワ紝 platform: {}, channel锛� {}", platform.getServerGBId(), channelId); SipSubscribe.EventResult<Object> eventResult = new SipSubscribe.EventResult<>(); @@ -544,14 +580,14 @@ } } }, userSetting.getPlayTimeout()); - commanderForPlatform.broadcastInviteCmd(platform, channelId, mediaServerItem, ssrcInfo, (mediaServerItemForInvite, hookParam)->{ + commanderForPlatform.broadcastInviteCmd(platform, channelId, mediaServerItem, ssrcInfo, (hookData)->{ logger.info("[鍥芥爣绾ц仈] 鍙戣捣璇煶鍠婅瘽 鏀跺埌涓婄骇鎺ㄦ祦 deviceId: {}, channelId: {}", platform.getServerGBId(), channelId); dynamicTask.stop(timeOutTaskKey); // hook鍝嶅簲 - playService.onPublishHandlerForPlay(mediaServerItemForInvite, hookParam, platform.getServerGBId(), channelId); + playService.onPublishHandlerForPlay(hookData.getMediaServer(), hookData.getMediaInfo(), platform.getServerGBId(), channelId); // 鏀跺埌娴� if (hookEvent != null) { - hookEvent.response(mediaServerItem, hookParam); + hookEvent.response(hookData); } }, event -> { @@ -604,13 +640,12 @@ }); } - private void inviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, int tcpMode, boolean ssrcCheck, MediaServerItem mediaServerItem, + private void inviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, int tcpMode, boolean ssrcCheck, MediaServer mediaServerItem, ParentPlatform platform, String channelId, String timeOutTaskKey, ErrorCallback<Object> callback, InviteInfo inviteInfo, InviteSessionType inviteSessionType){ inviteInfo.setStatus(InviteSessionStatus.ok); ResponseEvent responseEvent = (ResponseEvent) eventResult.event; String contentString = new String(responseEvent.getResponse().getRawContent()); - System.out.println(1111); System.out.println(contentString); String ssrcInResponse = SipUtils.getSsrcFromSdp(contentString); // 鍏煎鍥炲鐨勬秷鎭腑缂哄皯ssrc(y瀛楁)鐨勬儏鍐� @@ -709,7 +744,7 @@ private void tcpActiveHandler(ParentPlatform platform, String channelId, String contentString, - MediaServerItem mediaServerItem, int tcpMode, boolean ssrcCheck, + MediaServer mediaServerItem, int tcpMode, boolean ssrcCheck, String timeOutTaskKey, SSRCInfo ssrcInfo, ErrorCallback<Object> callback){ if (tcpMode != 2) { return; @@ -737,8 +772,8 @@ } logger.info("[TCP涓诲姩杩炴帴瀵规柟] serverGbId: {}, channelId: {}, 杩炴帴瀵规柟鐨勫湴鍧�锛歿}:{}, SSRC: {}, SSRC鏍¢獙锛歿}", platform.getServerGBId(), channelId, sdp.getConnection().getAddress(), port, ssrcInfo.getSsrc(), ssrcCheck); - JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); - logger.info("[TCP涓诲姩杩炴帴瀵规柟] 缁撴灉锛� {}", jsonObject); + Boolean result = mediaServerService.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); + logger.info("[TCP涓诲姩杩炴帴瀵规柟] 缁撴灉锛� {}", result); } catch (SdpException e) { logger.error("[TCP涓诲姩杩炴帴瀵规柟] serverGbId: {}, channelId: {}, 瑙f瀽200OK鐨凷DP淇℃伅澶辫触", platform.getServerGBId(), channelId, e); dynamicTask.stop(timeOutTaskKey); @@ -757,7 +792,7 @@ } @Override - public void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream, boolean sendBye, MediaServerItem mediaServerItem) { + public void stopBroadcast(ParentPlatform platform, DeviceChannel channel, String stream, boolean sendBye, MediaServer mediaServerItem) { try { if (sendBye) { 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 9bd0547..7406483 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -1,11 +1,9 @@ package com.genersoft.iot.vmp.service.impl; -import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.common.*; import com.genersoft.iot.vmp.conf.DynamicTask; -import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.exception.ServiceException; @@ -18,17 +16,18 @@ import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommander; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; import com.genersoft.iot.vmp.gb28181.utils.SipUtils; +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.bean.RecordInfo; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookType; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; +import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent; +import com.genersoft.iot.vmp.media.event.media.MediaNotFoundEvent; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRecordMp4; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.HookParam; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRecordMp4HookParam; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.bean.*; import com.genersoft.iot.vmp.service.redisMsg.RedisGbPlayMsgListener; @@ -44,9 +43,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.data.redis.core.RedisTemplate; -import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; +import org.springframework.context.event.EventListener; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.util.ObjectUtils; @@ -87,22 +85,13 @@ private IRedisCatchStorage redisCatchStorage; @Autowired - private ZLMServerFactory zlmServerFactory; - - @Autowired private IInviteStreamService inviteStreamService; @Autowired - private ZlmHttpHookSubscribe subscribe; + private HookSubscribe subscribe; @Autowired private SendRtpPortManager sendRtpPortManager; - - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; - - @Autowired - private IMediaService mediaService; @Autowired private IMediaServerService mediaServerService; @@ -117,34 +106,164 @@ private IDeviceChannelService channelService; @Autowired - private SipConfig sipConfig; - - @Autowired private DynamicTask dynamicTask; @Autowired private ISIPCommanderForPlatform commanderForPlatform; - - @Qualifier("taskExecutor") - @Autowired - private ThreadPoolTaskExecutor taskExecutor; - @Autowired private RedisGbPlayMsgListener redisGbPlayMsgListener; @Autowired - private ZlmHttpHookSubscribe hookSubscribe; - - @Autowired private SSRCFactory ssrcFactory; - @Autowired - private RedisTemplate<Object, Object> redisTemplate; + /** + * 娴佸埌鏉ョ殑澶勭悊 + */ + @Async("taskExecutor") + @org.springframework.context.event.EventListener + public void onApplicationEvent(MediaArrivalEvent event) { + if ("broadcast".equals(event.getApp())) { + if (event.getStream().indexOf("_") > 0) { + String[] streamArray = event.getStream().split("_"); + if (streamArray.length == 2) { + String deviceId = streamArray[0]; + String channelId = streamArray[1]; + Device device = deviceService.getDevice(deviceId); + if (device == null) { + logger.info("[璇煶瀵硅/鍠婅瘽] 鏈壘鍒拌澶囷細{}", deviceId); + return; + } + if ("broadcast".equals(event.getApp())) { + if (audioBroadcastManager.exit(deviceId, channelId)) { + stopAudioBroadcast(deviceId, channelId); + } + // 寮�鍚闊冲璁查�氶亾 + try { + audioBroadcastCmd(device, channelId, event.getMediaServer(), + event.getApp(), event.getStream(), 60, false, (msg) -> { + logger.info("[璇煶瀵硅] 閫氶亾寤虹珛鎴愬姛, device: {}, channel: {}", deviceId, channelId); + }); + } catch (InvalidArgumentException | ParseException | SipException e) { + logger.error("[鍛戒护鍙戦�佸け璐 璇煶瀵硅: {}", e.getMessage()); + } + }else if ("talk".equals(event.getApp())) { + // 寮�鍚闊冲璁查�氶亾 + talkCmd(device, channelId, event.getMediaServer(), event.getStream(), (msg) -> { + logger.info("[璇煶瀵硅] 閫氶亾寤虹珛鎴愬姛, device: {}, channel: {}", deviceId, channelId); + }); + } + } + } + } + + + } + + /** + * 娴佺寮�鐨勫鐞� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaDepartureEvent event) { + List<SendRtpItem> sendRtpItems = redisCatchStorage.querySendRTPServerByStream(event.getStream()); + if (!sendRtpItems.isEmpty()) { + for (SendRtpItem sendRtpItem : sendRtpItems) { + if (sendRtpItem != null && sendRtpItem.getApp().equals(event.getApp())) { + String platformId = sendRtpItem.getPlatformId(); + Device device = deviceService.getDevice(platformId); + try { + if (device != null) { + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), event.getStream(), sendRtpItem.getCallId()); + if (sendRtpItem.getPlayType().equals(InviteStreamType.BROADCAST) + || sendRtpItem.getPlayType().equals(InviteStreamType.TALK)) { + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); + if (audioBroadcastCatch != null) { + // 鏉ヨ嚜涓婄骇骞冲彴鐨勫仠姝㈠璁� + logger.info("[鍋滄瀵硅] 鏉ヨ嚜涓婄骇锛屽钩鍙帮細{}, 閫氶亾锛歿}", sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); + audioBroadcastManager.del(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); + } + } + } + } catch (SipException | InvalidArgumentException | ParseException | + SsrcTransactionNotFoundException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鍙戦�丅YE: {}", e.getMessage()); + } + } + } + } + + if ("broadcast".equals(event.getApp()) || "talk".equals(event.getApp())) { + if (event.getStream().indexOf("_") > 0) { + String[] streamArray = event.getStream().split("_"); + if (streamArray.length == 2) { + String deviceId = streamArray[0]; + String channelId = streamArray[1]; + Device device = deviceService.getDevice(deviceId); + if (device == null) { + logger.info("[璇煶瀵硅/鍠婅瘽] 鏈壘鍒拌澶囷細{}", deviceId); + return; + } + if ("broadcast".equals(event.getApp())) { + stopAudioBroadcast(deviceId, channelId); + }else if ("talk".equals(event.getApp())) { + stopTalk(device, channelId, false); + } + } + } + } + } + + /** + * 娴佹湭鎵惧埌鐨勫鐞� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaNotFoundEvent event) { + if (!"rtp".equals(event.getApp())) { + return; + } + String[] s = event.getStream().split("_"); + if ((s.length != 2 && s.length != 4)) { + return; + } + String deviceId = s[0]; + String channelId = s[1]; + Device device = redisCatchStorage.getDevice(deviceId); + if (device == null || !device.isOnLine()) { + return; + } + DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); + if (deviceChannel == null) { + return; + } + if (s.length == 2) { + logger.info("[ZLM HOOK] 棰勮娴佹湭鎵惧埌, 鍙戣捣鑷姩鐐规挱锛歿}->{}->{}/{}", event.getMediaServer().getId(), event.getSchema(), event.getApp(), event.getStream()); + play(event.getMediaServer(), deviceId, channelId, null, null); + } else if (s.length == 4) { + // 姝ゆ椂涓哄綍鍍忓洖鏀撅紝 褰曞儚鍥炴斁鏍煎紡涓�> 璁惧ID_閫氶亾ID_寮�濮嬫椂闂確缁撴潫鏃堕棿 + String startTimeStr = s[2]; + String endTimeStr = s[3]; + if (startTimeStr == null || endTimeStr == null || startTimeStr.length() != 14 || endTimeStr.length() != 14) { + return; + } + String startTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(startTimeStr); + String endTime = DateUtil.urlToyyyy_MM_dd_HH_mm_ss(endTimeStr); + logger.info("[ZLM HOOK] 鍥炴斁娴佹湭鎵惧埌, 鍙戣捣鑷姩鐐规挱锛歿}->{}->{}/{}-{}-{}", + event.getMediaServer().getId(), event.getSchema(), + event.getApp(), event.getStream(), + startTime, endTime + ); + + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(event.getMediaServer(), event.getStream(), null, + device.isSsrcCheck(), true, 0, false, !deviceChannel.isHasAudio(), false, device.getStreamModeForParam()); + playBack(event.getMediaServer(), ssrcInfo, deviceId, channelId, startTime, endTime, null); + } + } @Override - public SSRCInfo play(MediaServerItem mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) { + public SSRCInfo play(MediaServer mediaServerItem, String deviceId, String channelId, String ssrc, ErrorCallback<Object> callback) { if (mediaServerItem == null) { logger.warn("[鐐规挱] 鏈壘鍒板彲鐢ㄧ殑zlm deviceId: {},channelId:{}", deviceId, channelId); throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒板彲鐢ㄧ殑zlm"); @@ -179,9 +298,8 @@ return inviteInfo.getSsrcInfo(); } String mediaServerId = streamInfo.getMediaServerId(); - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); - - Boolean ready = zlmServerFactory.isStreamReady(mediaInfo, "rtp", streamId); + MediaServer mediaInfo = mediaServerService.getOne(mediaServerId); + Boolean ready = mediaServerService.isStreamReady(mediaInfo, "rtp", streamId); if (ready != null && ready) { callback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, @@ -198,8 +316,8 @@ } } } - String streamId = String.format("%s_%s", device.getDeviceId(), channelId);; - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, false, device.getStreamModeForParam()); + String streamId = String.format("%s_%s", device.getDeviceId(), channelId); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(mediaServerItem, streamId, ssrc, device.isSsrcCheck(), false, 0, false, !channel.isHasAudio(), false, device.getStreamModeForParam()); if (ssrcInfo == null) { callback.run(InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getCode(), InviteErrorCode.ERROR_FOR_RESOURCE_EXHAUSTION.getMsg(), null); inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channelId, null, @@ -212,8 +330,8 @@ return ssrcInfo; } - private void talk(MediaServerItem mediaServerItem, Device device, String channelId, String stream, - ZlmHttpHookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, + private void talk(MediaServer mediaServerItem, Device device, String channelId, String stream, + HookSubscribe.Event hookEvent, SipSubscribe.Event errorEvent, Runnable timeoutCallback, AudioBroadcastEvent audioEvent) { String playSsrc = ssrcFactory.getPlaySsrc(mediaServerItem.getId()); @@ -269,38 +387,25 @@ } }, userSetting.getPlayTimeout()); - Map<String, Object> param = new HashMap<>(12); - param.put("vhost","__defaultVhost__"); - param.put("app", sendRtpItem.getApp()); - param.put("stream", sendRtpItem.getStream()); - param.put("ssrc", sendRtpItem.getSsrc()); - param.put("src_port", sendRtpItem.getLocalPort()); - param.put("pt", sendRtpItem.getPt()); - param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); - param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); - param.put("is_udp", sendRtpItem.isTcp() ? "0" : "1"); - param.put("recv_stream_id", sendRtpItem.getReceiveStream()); - param.put("close_delay_ms", userSetting.getPlayTimeout() * 1000); - - zlmServerFactory.startSendRtpPassive(mediaServerItem, param, jsonObject -> { - if (jsonObject == null || jsonObject.getInteger("code") != 0 ) { - mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); - logger.info("[璇煶瀵硅]澶辫触 deviceId: {}, channelId: {}", device.getDeviceId(), channelId); - audioEvent.call("澶辫触, " + jsonObject.getString("msg")); - // 鏌ョ湅鏄惁宸茬粡寤虹珛浜嗛�氶亾锛屽瓨鍦ㄥ垯鍙戦�乥ye - stopTalk(device, channelId); - } - }); + try { + mediaServerService.startSendRtpPassive(mediaServerItem, null, sendRtpItem, userSetting.getPlayTimeout() * 1000); + }catch (ControllerException e) { + mediaServerService.releaseSsrc(mediaServerItem.getId(), sendRtpItem.getSsrc()); + logger.info("[璇煶瀵硅]澶辫触 deviceId: {}, channelId: {}", device.getDeviceId(), channelId); + audioEvent.call("澶辫触, " + e.getMessage()); + // 鏌ョ湅鏄惁宸茬粡寤虹珛浜嗛�氶亾锛屽瓨鍦ㄥ垯鍙戦�乥ye + stopTalk(device, channelId); + } // 鏌ョ湅璁惧鏄惁宸茬粡鍦ㄦ帹娴� try { - cmder.talkStreamCmd(mediaServerItem, sendRtpItem, device, channelId, callId, (mediaServerItemInuse, hookParam) -> { - logger.info("[璇煶瀵硅] 娴佸凡鐢熸垚锛� 寮�濮嬫帹娴侊細 " + hookParam); + cmder.talkStreamCmd(mediaServerItem, sendRtpItem, device, channelId, callId, (hookData) -> { + logger.info("[璇煶瀵硅] 娴佸凡鐢熸垚锛� 寮�濮嬫帹娴侊細 " + hookData); dynamicTask.stop(timeOutTaskKey); // TODO 鏆備笉鍋氬鐞� - }, (mediaServerItemInuse, hookParam) -> { - logger.info("[璇煶瀵硅] 璁惧寮�濮嬫帹娴侊細 " + hookParam); + }, (hookData) -> { + logger.info("[璇煶瀵硅] 璁惧寮�濮嬫帹娴侊細 " + hookData); dynamicTask.stop(timeOutTaskKey); }, (event) -> { @@ -355,7 +460,7 @@ @Override - public void play(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, + public void play(MediaServer mediaServerItem, SSRCInfo ssrcInfo, Device device, DeviceChannel channel, ErrorCallback<Object> callback) { if (mediaServerItem == null || ssrcInfo == null) { @@ -410,8 +515,7 @@ streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); // 鍙栨秷璁㈤槄娑堟伅鐩戝惉 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed("rtp", ssrcInfo.getStream(), true, "rtsp", mediaServerItem.getId()); - subscribe.removeSubscribe(hookSubscribe); + subscribe.removeSubscribe(Hook.getInstance(HookType.on_media_arrival, "rtp", ssrcInfo.getStream(), mediaServerItem.getId())); } }else { logger.info("[鐐规挱瓒呮椂] 鏀舵祦瓒呮椂 deviceId: {}, channelId: {},鐮佹祦锛歿}锛岀鍙o細{}, SSRC: {}", @@ -426,11 +530,11 @@ }, userSetting.getPlayTimeout()); try { - cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channel, (mediaServerItemInuse, hookParam ) -> { - logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + hookParam); + cmder.playStreamCmd(mediaServerItem, ssrcInfo, device, channel, (hookData ) -> { + logger.info("鏀跺埌璁㈤槄娑堟伅锛� " + hookData); dynamicTask.stop(timeOutTaskKey); // hook鍝嶅簲 - StreamInfo streamInfo = onPublishHandlerForPlay(mediaServerItemInuse, hookParam, device.getDeviceId(), channel.getChannelId()); + StreamInfo streamInfo = onPublishHandlerForPlay(hookData.getMediaServer(), hookData.getMediaInfo(), device.getDeviceId(), channel.getChannelId()); if (streamInfo == null){ callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getMsg(), null); @@ -446,7 +550,7 @@ streamInfo); logger.info("[鐐规挱鎴愬姛] deviceId: {}, channelId:{}, 鐮佹祦绫诲瀷锛歿}", device.getDeviceId(), channel.getChannelId(), channel.getStreamIdentification()); - snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); + snapOnPlay(hookData.getMediaServer(), device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); }, (eventResult) -> { // 澶勭悊鏀跺埌200ok鍚庣殑TCP涓诲姩杩炴帴浠ュ強SSRC涓嶄竴鑷寸殑闂 InviteOKHandler(eventResult, ssrcInfo, mediaServerItem, device, channel.getChannelId(), @@ -460,8 +564,7 @@ streamSession.remove(device.getDeviceId(), channel.getChannelId(), ssrcInfo.getStream()); - callback.run(InviteErrorCode.ERROR_FOR_SIGNALLING_ERROR.getCode(), - String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg), null); + callback.run(event.statusCode, event.msg, null); inviteStreamService.call(InviteSessionType.PLAY, device.getDeviceId(), channel.getChannelId(), null, InviteErrorCode.ERROR_FOR_RESET_SSRC.getCode(), String.format("鐐规挱澶辫触锛� 閿欒鐮侊細 %s, %s", event.statusCode, event.msg), null); @@ -489,7 +592,7 @@ } private void tcpActiveHandler(Device device, String channelId, String contentString, - MediaServerItem mediaServerItem, + MediaServer mediaServerItem, String timeOutTaskKey, SSRCInfo ssrcInfo, ErrorCallback<Object> callback){ if (!device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE")) { return; @@ -516,9 +619,9 @@ } } logger.info("[TCP涓诲姩杩炴帴瀵规柟] deviceId: {}, channelId: {}, 杩炴帴瀵规柟鐨勫湴鍧�锛歿}:{}, 鏀舵祦妯″紡锛歿}, SSRC: {}, SSRC鏍¢獙锛歿}", device.getDeviceId(), channelId, sdp.getConnection().getAddress(), port, device.getStreamMode(), ssrcInfo.getSsrc(), device.isSsrcCheck()); - JSONObject jsonObject = zlmresTfulUtils.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); - logger.info("[TCP涓诲姩杩炴帴瀵规柟] 缁撴灉锛� {}" , jsonObject); - if (jsonObject.getInteger("code") != 0) { + Boolean result = mediaServerService.connectRtpServer(mediaServerItem, sdp.getConnection().getAddress(), port, ssrcInfo.getStream()); + logger.info("[TCP涓诲姩杩炴帴瀵规柟] 缁撴灉锛� {}" , result); + if (!result) { // 涓诲姩杩炴帴澶辫触锛岀粨鏉熸祦绋嬶紝 娓呯悊鏁版嵁 dynamicTask.stop(timeOutTaskKey); mediaServerService.closeRTPServer(mediaServerItem, ssrcInfo.getStream()); @@ -558,7 +661,7 @@ * @param channelId 閫氶亾 ID * @param stream ssrc */ - private void snapOnPlay(MediaServerItem mediaServerItemInuse, String deviceId, String channelId, String stream) { + private void snapOnPlay(MediaServer mediaServerItemInuse, String deviceId, String channelId, String stream) { String streamUrl; if (mediaServerItemInuse.getRtspPort() != 0) { streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", stream); @@ -569,14 +672,13 @@ String fileName = deviceId + "_" + channelId + ".jpg"; // 璇锋眰鎴浘 logger.info("[璇锋眰鎴浘]: " + fileName); - zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); + mediaServerService.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); } - public StreamInfo onPublishHandlerForPlay(MediaServerItem mediaServerItem, HookParam hookParam, String deviceId, String channelId) { + public StreamInfo onPublishHandlerForPlay(MediaServer mediaServerItem, MediaInfo mediaInfo, String deviceId, String channelId) { StreamInfo streamInfo = null; Device device = redisCatchStorage.getDevice(deviceId); - OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam)hookParam; - streamInfo = onPublishHandler(mediaServerItem, streamChangedHookParam, deviceId, channelId); + streamInfo = onPublishHandler(mediaServerItem, mediaInfo, deviceId, channelId); if (streamInfo != null) { DeviceChannel deviceChannel = storager.queryChannel(deviceId, channelId); if (deviceChannel != null) { @@ -594,9 +696,8 @@ } - private StreamInfo onPublishHandlerForPlayback(MediaServerItem mediaServerItem, HookParam param, String deviceId, String channelId, String startTime, String endTime) { - OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam) param; - StreamInfo streamInfo = onPublishHandler(mediaServerItem, streamChangedHookParam, deviceId, channelId); + private StreamInfo onPublishHandlerForPlayback(MediaServer mediaServerItem, MediaInfo mediaInfo, String deviceId, String channelId, String startTime, String endTime) { + StreamInfo streamInfo = onPublishHandler(mediaServerItem, mediaInfo, deviceId, channelId); if (streamInfo != null) { streamInfo.setStartTime(startTime); streamInfo.setEndTime(endTime); @@ -605,7 +706,7 @@ deviceChannel.setStreamId(streamInfo.getStream()); storager.startPlay(deviceId, channelId, streamInfo.getStream()); } - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, ((OnStreamChangedHookParam) param).getStream()); + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(InviteSessionType.PLAYBACK, mediaInfo.getStream()); if (inviteInfo != null) { inviteInfo.setStatus(InviteSessionStatus.ok); @@ -618,11 +719,11 @@ } @Override - public MediaServerItem getNewMediaServerItem(Device device) { + public MediaServer getNewMediaServerItem(Device device) { if (device == null) { return null; } - MediaServerItem mediaServerItem; + MediaServer mediaServerItem; if (ObjectUtils.isEmpty(device.getMediaServerId()) || "auto".equals(device.getMediaServerId())) { mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null); } else { @@ -643,7 +744,13 @@ throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒拌澶囷細" + deviceId); } - MediaServerItem newMediaServerItem = getNewMediaServerItem(device); + DeviceChannel channel = channelService.getOne(deviceId, channelId); + if (channel == null) { + logger.warn("[褰曞儚鍥炴斁] 鏈壘鍒伴�氶亾 deviceId: {},channelId:{}", deviceId, channelId); + throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒伴�氶亾锛�" + channelId); + } + + MediaServer newMediaServerItem = getNewMediaServerItem(device); if (device.getStreamMode().equalsIgnoreCase("TCP-ACTIVE") && ! newMediaServerItem.isRtpEnable()) { logger.warn("[褰曞儚鍥炴斁] 鍗曠鍙f敹娴佹椂涓嶆敮鎸乀CP涓诲姩鏂瑰紡鏀舵祦 deviceId: {},channelId:{}", deviceId, channelId); throw new ControllerException(ErrorCode.ERROR100.getCode(), "鍗曠鍙f敹娴佹椂涓嶆敮鎸乀CP涓诲姩鏂瑰紡鏀舵祦"); @@ -655,12 +762,12 @@ .replace(":", "") .replace(" ", ""); String stream = deviceId + "_" + channelId + "_" + startTimeStr + "_" + endTimeTimeStr; - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, stream, null, device.isSsrcCheck(), true, 0, false, !channel.isHasAudio(), false, device.getStreamModeForParam()); playBack(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, callback); } @Override - public void playBack(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, + public void playBack(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, ErrorCallback<Object> callback) { if (mediaServerItem == null || ssrcInfo == null) { @@ -711,10 +818,10 @@ inviteStreamService.removeInviteInfo(inviteInfo); }; - ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInuse, hookParam) -> { - logger.info("鏀跺埌鍥炴斁璁㈤槄娑堟伅锛� " + hookParam); + HookSubscribe.Event hookEvent = (hookData) -> { + logger.info("鏀跺埌鍥炴斁璁㈤槄娑堟伅锛� " + hookData); dynamicTask.stop(playBackTimeOutTaskKey); - StreamInfo streamInfo = onPublishHandlerForPlayback(mediaServerItemInuse, hookParam, deviceId, channelId, startTime, endTime); + StreamInfo streamInfo = onPublishHandlerForPlayback(hookData.getMediaServer(), hookData.getMediaInfo(), deviceId, channelId, startTime, endTime); if (streamInfo == null) { logger.warn("璁惧鍥炴斁API璋冪敤澶辫触锛�"); callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), @@ -744,7 +851,7 @@ } - private void InviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, MediaServerItem mediaServerItem, + private void InviteOKHandler(SipSubscribe.EventResult eventResult, SSRCInfo ssrcInfo, MediaServer mediaServerItem, Device device, String channelId, String timeOutTaskKey, ErrorCallback<Object> callback, InviteInfo inviteInfo, InviteSessionType inviteSessionType){ inviteInfo.setStatus(InviteSessionStatus.ok); @@ -840,7 +947,11 @@ if (device == null) { return; } - MediaServerItem newMediaServerItem = this.getNewMediaServerItem(device); + DeviceChannel channel = channelService.getOne(deviceId, channelId); + if (channel == null) { + return; + } + MediaServer newMediaServerItem = this.getNewMediaServerItem(device); if (newMediaServerItem == null) { callback.run(InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getCode(), InviteErrorCode.ERROR_FOR_ASSIST_NOT_READY.getMsg(), @@ -848,13 +959,13 @@ return; } // 褰曞儚涓嬭浇涓嶄娇鐢ㄥ浐瀹氭祦鍦板潃锛屽浐瀹氭祦鍦板潃浼氬鑷村鏋滃紑濮嬫椂闂翠笌缁撴潫鏃堕棿涓�鑷存椂鏂囦欢閿欒鐨勫彔鍔犲湪涓�璧� - SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,false, device.getStreamModeForParam()); + SSRCInfo ssrcInfo = mediaServerService.openRTPServer(newMediaServerItem, null, null, device.isSsrcCheck(), true, 0, false,!channel.isHasAudio(), false, device.getStreamModeForParam()); download(newMediaServerItem, ssrcInfo, deviceId, channelId, startTime, endTime, downloadSpeed, callback); } @Override - public void download(MediaServerItem mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) { + public void download(MediaServer mediaServerItem, SSRCInfo ssrcInfo, String deviceId, String channelId, String startTime, String endTime, int downloadSpeed, ErrorCallback<Object> callback) { if (mediaServerItem == null || ssrcInfo == null) { callback.run(InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getCode(), InviteErrorCode.ERROR_FOR_PARAMETER_ERROR.getMsg(), @@ -900,10 +1011,10 @@ streamSession.remove(device.getDeviceId(), channelId, ssrcInfo.getStream()); inviteStreamService.removeInviteInfo(inviteInfo); }; - ZlmHttpHookSubscribe.Event hookEvent = (mediaServerItemInuse, hookParam) -> { - logger.info("[褰曞儚涓嬭浇]鏀跺埌璁㈤槄娑堟伅锛� " + hookParam); + HookSubscribe.Event hookEvent = (hookData) -> { + logger.info("[褰曞儚涓嬭浇]鏀跺埌璁㈤槄娑堟伅锛� " + hookData); dynamicTask.stop(downLoadTimeOutTaskKey); - StreamInfo streamInfo = onPublishHandlerForDownload(mediaServerItemInuse, hookParam, deviceId, channelId, startTime, endTime); + StreamInfo streamInfo = onPublishHandlerForDownload(hookData.getMediaServer(), hookData.getMediaInfo(), deviceId, channelId, startTime, endTime); if (streamInfo == null) { logger.warn("[褰曞儚涓嬭浇] 鑾峰彇娴佸湴鍧�淇℃伅澶辫触"); callback.run(InviteErrorCode.ERROR_FOR_STREAM_PARSING_EXCEPTIONS.getCode(), @@ -921,26 +1032,24 @@ downLoadTimeOutTaskKey, callback, inviteInfo, InviteSessionType.DOWNLOAD); // 娉ㄥ唽褰曞儚鍥炶皟浜嬩欢锛屽綍鍍忎笅杞界粨鏉熷悗鍐欏叆涓嬭浇鍦板潃 - ZlmHttpHookSubscribe.Event hookEventForRecord = (mediaServerItemInuse, hookParam) -> { + HookSubscribe.Event hookEventForRecord = (hookData) -> { logger.info("[褰曞儚涓嬭浇] 鏀跺埌褰曞儚鍐欏叆纾佺洏娑堟伅锛� 锛� {}/{}-{}", inviteInfo.getDeviceId(), inviteInfo.getChannelId(), ssrcInfo.getStream()); - logger.info("[褰曞儚涓嬭浇] 鏀跺埌褰曞儚鍐欏叆纾佺洏娑堟伅鍐呭锛� " + hookParam); - OnRecordMp4HookParam recordMp4HookParam = (OnRecordMp4HookParam)hookParam; - String filePath = recordMp4HookParam.getFile_path(); + logger.info("[褰曞儚涓嬭浇] 鏀跺埌褰曞儚鍐欏叆纾佺洏娑堟伅鍐呭锛� " + hookData); + RecordInfo recordInfo = hookData.getRecordInfo(); + String filePath = recordInfo.getFilePath(); DownloadFileInfo downloadFileInfo = CloudRecordUtils.getDownloadFilePath(mediaServerItem, filePath); InviteInfo inviteInfoForNew = inviteStreamService.getInviteInfo(inviteInfo.getType(), inviteInfo.getDeviceId() , inviteInfo.getChannelId(), inviteInfo.getStream()); inviteInfoForNew.getStreamInfo().setDownLoadFilePath(downloadFileInfo); inviteStreamService.updateInviteInfo(inviteInfoForNew); }; - HookSubscribeForRecordMp4 hookSubscribe = HookSubscribeFactory.on_record_mp4( - mediaServerItem.getId(), "rtp", ssrcInfo.getStream()); - + Hook hook = Hook.getInstance(HookType.on_record_mp4, "rtp", ssrcInfo.getStream(), mediaServerItem.getId()); // 璁剧疆杩囨湡鏃堕棿锛屼笅杞藉け璐ユ椂鑷姩澶勭悊璁㈤槄鏁版嵁 // long difference = DateUtil.getDifference(startTime, endTime)/1000; // Instant expiresInstant = Instant.now().plusSeconds(TimeUnit.MINUTES.toSeconds(difference * 2)); // hookSubscribe.setExpires(expiresInstant); - subscribe.addSubscribe(hookSubscribe, hookEventForRecord); + subscribe.addSubscribe(hook, hookEventForRecord); }); } catch (InvalidArgumentException | SipException | ParseException e) { logger.error("[鍛戒护鍙戦�佸け璐 褰曞儚涓嬭浇: {}", e.getMessage()); @@ -967,7 +1076,7 @@ // 鑾峰彇褰撳墠宸蹭笅杞芥椂闀� String mediaServerId = inviteInfo.getStreamInfo().getMediaServerId(); - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem == null) { logger.warn("[鑾峰彇涓嬭浇杩涘害] 鏌ヨ褰曞儚淇℃伅鏃跺彂鐜拌妭鐐逛笉瀛樺湪"); return null; @@ -978,30 +1087,13 @@ logger.warn("[鑾峰彇涓嬭浇杩涘害] 涓嬭浇宸茬粨鏉�"); return null; } - - JSONObject mediaListJson= zlmresTfulUtils.getMediaList(mediaServerItem, "rtp", stream); - if (mediaListJson == null) { - logger.warn("[鑾峰彇涓嬭浇杩涘害] 浠巣lm鏌ヨ杩涘害澶辫触"); + String app = "rtp"; + MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServerItem, app, stream); + if (mediaInfo == null) { + logger.warn("[鑾峰彇涓嬭浇杩涘害] 鏌ヨ杩涘害澶辫触, 鑺傜偣Id锛� {}锛� {}/{}", mediaServerId, app, stream); return null; } - if (mediaListJson.getInteger("code") != 0) { - logger.warn("[鑾峰彇涓嬭浇杩涘害] 浠巣lm鏌ヨ杩涘害鍑虹幇閿欒锛� {}", mediaListJson.getString("msg")); - return null; - } - JSONArray data = mediaListJson.getJSONArray("data"); - if (data == null) { - logger.warn("[鑾峰彇涓嬭浇杩涘害] 浠巣lm鏌ヨ杩涘害鏃舵湭杩斿洖鏁版嵁"); - return null; - } - JSONObject mediaJSON = data.getJSONObject(0); - JSONArray tracks = mediaJSON.getJSONArray("tracks"); - if (tracks.isEmpty()) { - logger.warn("[鑾峰彇涓嬭浇杩涘害] 浠巣lm鏌ヨ杩涘害鏃舵湭杩斿洖鏁版嵁"); - return null; - } - JSONObject jsonObject = tracks.getJSONObject(0); - long duration = jsonObject.getLongValue("duration"); - if (duration == 0) { + if (mediaInfo.getDuration() == 0) { inviteInfo.getStreamInfo().setProgress(0); } else { String startTime = inviteInfo.getStreamInfo().getStartTime(); @@ -1010,7 +1102,7 @@ long start = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(startTime); long end = DateUtil.yyyy_MM_dd_HH_mm_ssToTimestamp(endTime); - BigDecimal currentCount = new BigDecimal(duration); + BigDecimal currentCount = new BigDecimal(mediaInfo.getDuration()); BigDecimal totalCount = new BigDecimal((end - start) * 1000); BigDecimal divide = currentCount.divide(totalCount, 2, RoundingMode.HALF_UP); double process = divide.doubleValue(); @@ -1023,9 +1115,8 @@ return inviteInfo.getStreamInfo(); } - private StreamInfo onPublishHandlerForDownload(MediaServerItem mediaServerItemInuse, HookParam hookParam, String deviceId, String channelId, String startTime, String endTime) { - OnStreamChangedHookParam streamChangedHookParam = (OnStreamChangedHookParam) hookParam; - StreamInfo streamInfo = onPublishHandler(mediaServerItemInuse, streamChangedHookParam, deviceId, channelId); + private StreamInfo onPublishHandlerForDownload(MediaServer mediaServerItemInuse, MediaInfo mediaInfo, String deviceId, String channelId, String startTime, String endTime) { + StreamInfo streamInfo = onPublishHandler(mediaServerItemInuse, mediaInfo, deviceId, channelId); if (streamInfo != null) { streamInfo.setProgress(0); streamInfo.setStartTime(startTime); @@ -1042,8 +1133,8 @@ } - public StreamInfo onPublishHandler(MediaServerItem mediaServerItem, OnStreamChangedHookParam hookParam, String deviceId, String channelId) { - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", hookParam.getStream(), hookParam.getTracks(), null); + public StreamInfo onPublishHandler(MediaServer mediaServerItem, MediaInfo mediaInfo, String deviceId, String channelId) { + StreamInfo streamInfo = mediaServerService.getStreamInfoByAppAndStream(mediaServerItem, "rtp", mediaInfo.getStream(), mediaInfo, null); streamInfo.setDeviceID(deviceId); streamInfo.setChannelId(channelId); return streamInfo; @@ -1099,7 +1190,7 @@ logger.warn("寮�鍚闊冲箍鎾殑鏃跺�欐湭鎵惧埌閫氶亾锛� {}", channelId); return null; } - MediaServerItem mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null); + MediaServer mediaServerItem = mediaServerService.getMediaServerForMinimumLoad(null); if (broadcastMode == null) { broadcastMode = true; } @@ -1108,13 +1199,13 @@ AudioBroadcastResult audioBroadcastResult = new AudioBroadcastResult(); audioBroadcastResult.setApp(app); audioBroadcastResult.setStream(stream); - audioBroadcastResult.setStreamInfo(new StreamContent(mediaService.getStreamInfoByAppAndStream(mediaServerItem, app, stream, null, null, null, false))); + audioBroadcastResult.setStreamInfo(new StreamContent(mediaServerService.getStreamInfoByAppAndStream(mediaServerItem, app, stream, null, null, null, false))); audioBroadcastResult.setCodec("G.711"); return audioBroadcastResult; } @Override - public boolean audioBroadcastCmd(Device device, String channelId, MediaServerItem mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException { + public boolean audioBroadcastCmd(Device device, String channelId, MediaServer mediaServerItem, String app, String stream, int timeout, boolean isFromPlatform, AudioBroadcastEvent event) throws InvalidArgumentException, ParseException, SipException { if (device == null || channelId == null) { return false; } @@ -1130,7 +1221,7 @@ SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { // 鏌ヨ娴佹槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯璁や负鏄紓甯哥姸鎬� - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream()); + Boolean streamReady = mediaServerService.isStreamReady(mediaServerItem, sendRtpItem.getApp(), sendRtpItem.getStream()); if (streamReady) { logger.warn("璇煶骞挎挱宸茬粡寮�鍚細 {}", channelId); event.call("璇煶骞挎挱宸茬粡寮�鍚�"); @@ -1140,18 +1231,6 @@ } } } -// SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); -// if (sendRtpItem != null) { -// MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); -// Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); -// if (streamReady) { -// logger.warn("[璇煶瀵硅] 杩涜涓細 {}", channelId); -// event.call("璇煶瀵硅杩涜涓�"); -// return false; -// } else { -// stopTalk(device, channelId); -// } -// } // 鍙戦�侀�氱煡 cmder.audioBroadcastCmd(device, channelId, eventResultForOk -> { @@ -1182,8 +1261,8 @@ SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { // 鏌ヨ娴佹槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯璁や负鏄紓甯哥姸鎬� - MediaServerItem mediaServerServiceOne = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerServiceOne, sendRtpItem.getApp(), sendRtpItem.getStream()); + MediaServer mediaServerServiceOne = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + Boolean streamReady = mediaServerService.isStreamReady(mediaServerServiceOne, sendRtpItem.getApp(), sendRtpItem.getStream()); if (streamReady) { logger.warn("璇煶骞挎挱閫氶亾浣跨敤涓細 {}", channelId); return true; @@ -1212,12 +1291,8 @@ SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(deviceId, audioBroadcastCatch.getChannelId(), null, null); if (sendRtpItem != null) { redisCatchStorage.deleteSendRTPServer(deviceId, sendRtpItem.getChannelId(), null, null); - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - Map<String, Object> param = new HashMap<>(); - param.put("vhost", "__defaultVhost__"); - param.put("app", sendRtpItem.getApp()); - param.put("stream", sendRtpItem.getStream()); - zlmresTfulUtils.stopSendRtp(mediaInfo, param); + MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + mediaServerService.stopSendRtp(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream(), null); try { cmder.streamByeCmdForDeviceInvite(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null); } catch (InvalidArgumentException | ParseException | SipException | @@ -1293,7 +1368,7 @@ } inviteInfo.getStreamInfo().setPause(true); inviteStreamService.updateInviteInfo(inviteInfo); - MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); + MediaServer mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); if (null == mediaServerItem) { logger.warn("mediaServer 涓嶅瓨鍦�!"); throw new ServiceException("mediaServer涓嶅瓨鍦�"); @@ -1304,8 +1379,8 @@ if (!mediaServerItem.isRtpEnable()) { streamKey = Long.toHexString(Long.parseLong(inviteInfo.getSsrcInfo().getSsrc())).toUpperCase(); } - JSONObject jsonObject = zlmresTfulUtils.pauseRtpCheck(mediaServerItem, streamKey); - if (jsonObject == null || jsonObject.getInteger("code") != 0) { + Boolean result = mediaServerService.pauseRtpCheck(mediaServerItem, streamKey); + if (!result) { throw new ServiceException("鏆傚仠RTP鎺ユ敹澶辫触"); } Device device = storager.queryVideoDevice(inviteInfo.getDeviceId()); @@ -1321,7 +1396,7 @@ } inviteInfo.getStreamInfo().setPause(false); inviteStreamService.updateInviteInfo(inviteInfo); - MediaServerItem mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); + MediaServer mediaServerItem = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); if (null == mediaServerItem) { logger.warn("mediaServer 涓嶅瓨鍦�!"); throw new ServiceException("mediaServer涓嶅瓨鍦�"); @@ -1332,8 +1407,8 @@ if (!mediaServerItem.isRtpEnable()) { streamKey = Long.toHexString(Long.parseLong(inviteInfo.getSsrcInfo().getSsrc())).toUpperCase(); } - JSONObject jsonObject = zlmresTfulUtils.resumeRtpCheck(mediaServerItem, streamKey); - if (jsonObject == null || jsonObject.getInteger("code") != 0) { + boolean result = mediaServerService.resumeRtpCheck(mediaServerItem, streamKey); + if (!result) { throw new ServiceException("缁х画RTP鎺ユ敹澶辫触"); } Device device = storager.queryVideoDevice(inviteInfo.getDeviceId()); @@ -1343,24 +1418,7 @@ @Override public void startPushStream(SendRtpItem sendRtpItem, SIPResponse sipResponse, ParentPlatform platform, CallIdHeader callIdHeader) { // 寮�濮嬪彂娴� - String is_Udp = sendRtpItem.isTcp() ? "0" : "1"; - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - logger.info("[寮�濮嬫帹娴乚 rtp/{}, 鐩爣={}:{}锛孲SRC={}, RTCP={}", sendRtpItem.getStream(), - sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isRtcp()); - Map<String, Object> param = new HashMap<>(12); - param.put("vhost", "__defaultVhost__"); - param.put("app", sendRtpItem.getApp()); - param.put("stream", sendRtpItem.getStream()); - param.put("ssrc", sendRtpItem.getSsrc()); - param.put("src_port", sendRtpItem.getLocalPort()); - param.put("pt", sendRtpItem.getPt()); - param.put("use_ps", sendRtpItem.isUsePs() ? "1" : "0"); - param.put("only_audio", sendRtpItem.isOnlyAudio() ? "1" : "0"); - param.put("is_udp", is_Udp); - if (!sendRtpItem.isTcp()) { - // udp妯″紡涓嬪紑鍚痳tcp淇濇椿 - param.put("udp_rtcp_timeout", sendRtpItem.isRtcp() ? "1" : "0"); - } + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); if (mediaInfo == null) { RequestPushStreamMsg requestPushStreamMsg = RequestPushStreamMsg.getInstance( @@ -1368,80 +1426,55 @@ sendRtpItem.getIp(), sendRtpItem.getPort(), sendRtpItem.getSsrc(), sendRtpItem.isTcp(), sendRtpItem.getLocalPort(), sendRtpItem.getPt(), sendRtpItem.isUsePs(), sendRtpItem.isOnlyAudio()); redisGbPlayMsgListener.sendMsgForStartSendRtpStream(sendRtpItem.getServerId(), requestPushStreamMsg, json -> { - startSendRtpStreamHand(sendRtpItem, platform, json, param, callIdHeader); + startSendRtpStreamFailHand(sendRtpItem, platform, callIdHeader); }); } else { - // 濡傛灉鏄弗鏍兼ā寮忥紝闇�瑕佸叧闂鍙e崰鐢� - JSONObject startSendRtpStreamResult = null; - if (sendRtpItem.getLocalPort() != 0) { + try { if (sendRtpItem.isTcpActive()) { - startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); + mediaServerService.startSendRtpPassive(mediaInfo, platform, sendRtpItem, null); } else { - param.put("dst_url", sendRtpItem.getIp()); - param.put("dst_port", sendRtpItem.getPort()); - startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); + mediaServerService.startSendRtpStream(mediaInfo, platform, sendRtpItem); } - } else { - if (sendRtpItem.isTcpActive()) { - startSendRtpStreamResult = zlmServerFactory.startSendRtpPassive(mediaInfo, param); - } else { - param.put("dst_url", sendRtpItem.getIp()); - param.put("dst_port", sendRtpItem.getPort()); - startSendRtpStreamResult = zlmServerFactory.startSendRtpStream(mediaInfo, param); - } + }catch (ControllerException e) { + logger.error("RTP鎺ㄦ祦澶辫触: {}", e.getMessage()); + startSendRtpStreamFailHand(sendRtpItem, platform, callIdHeader); + return; } - if (startSendRtpStreamResult != null) { - startSendRtpStreamHand(sendRtpItem, platform, startSendRtpStreamResult, param, callIdHeader); - } + + logger.info("RTP鎺ㄦ祦鎴愬姛[ {}/{} ]锛寋}, ", sendRtpItem.getApp(), sendRtpItem.getStream(), + sendRtpItem.isTcpActive()?"琚姩鍙戞祦": sendRtpItem.getIp() + ":" + sendRtpItem.getPort()); + } } @Override - public void startSendRtpStreamHand(SendRtpItem sendRtpItem, Object correlationInfo, - JSONObject jsonObject, Map<String, Object> param, CallIdHeader callIdHeader) { - if (jsonObject == null) { - logger.error("RTP鎺ㄦ祦澶辫触: 璇锋鏌LM鏈嶅姟"); - } else if (jsonObject.getInteger("code") == 0) { - logger.info("璋冪敤ZLM鎺ㄦ祦鎺ュ彛, 缁撴灉锛� {}", jsonObject); - logger.info("RTP鎺ㄦ祦鎴愬姛[ {}/{} ]锛寋}->{}, ", param.get("app"), param.get("stream"), jsonObject.getString("local_port"), - sendRtpItem.isTcpActive()?"琚姩鍙戞祦": param.get("dst_url") + ":" + param.get("dst_port")); - if (sendRtpItem.getPlayType() == InviteStreamType.PUSH && correlationInfo instanceof ParentPlatform) { - ParentPlatform platform = (ParentPlatform)correlationInfo; - MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, sendRtpItem.getApp(), sendRtpItem.getStream(), - sendRtpItem.getChannelId(), platform.getServerGBId(), platform.getName(), userSetting.getServerId(), - sendRtpItem.getMediaServerId()); - messageForPushChannel.setPlatFormIndex(platform.getId()); - redisCatchStorage.sendPlatformStartPlayMsg(messageForPushChannel); + public void startSendRtpStreamFailHand(SendRtpItem sendRtpItem, ParentPlatform platform, CallIdHeader callIdHeader) { + if (sendRtpItem.isOnlyAudio()) { + Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); + AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); + if (audioBroadcastCatch != null) { + try { + cmder.streamByeCmd(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null); + } catch (SipException | ParseException | InvalidArgumentException | + SsrcTransactionNotFoundException exception) { + logger.error("[鍛戒护鍙戦�佸け璐 鍋滄璇煶瀵硅: {}", exception.getMessage()); + } } } else { - logger.error("RTP鎺ㄦ祦澶辫触: {}, 鍙傛暟锛歿}", jsonObject.getString("msg"), JSONObject.toJSONString(param)); - if (sendRtpItem.isOnlyAudio()) { - Device device = deviceService.getDevice(sendRtpItem.getDeviceId()); - AudioBroadcastCatch audioBroadcastCatch = audioBroadcastManager.get(sendRtpItem.getDeviceId(), sendRtpItem.getChannelId()); - if (audioBroadcastCatch != null) { - try { - cmder.streamByeCmd(device, sendRtpItem.getChannelId(), audioBroadcastCatch.getSipTransactionInfo(), null); - } catch (SipException | ParseException | InvalidArgumentException | - SsrcTransactionNotFoundException e) { - logger.error("[鍛戒护鍙戦�佸け璐 鍋滄璇煶瀵硅: {}", e.getMessage()); - } - } - } else { + if (platform != null) { // 鍚戜笂绾у钩鍙� - if (correlationInfo instanceof ParentPlatform) { - try { - ParentPlatform parentPlatform = (ParentPlatform)correlationInfo; - commanderForPlatform.streamByeCmd(parentPlatform, callIdHeader.getCallId()); - } catch (SipException | InvalidArgumentException | ParseException e) { - logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage()); - } + try { + commanderForPlatform.streamByeCmd(platform, callIdHeader.getCallId()); + } catch (SipException | InvalidArgumentException | ParseException e) { + logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage()); } } + } } @Override - public void talkCmd(Device device, String channelId, MediaServerItem mediaServerItem, String stream, AudioBroadcastEvent event) { + public void talkCmd(Device device, String channelId, MediaServer mediaServerItem, String stream, AudioBroadcastEvent event) { if (device == null || channelId == null) { return; } @@ -1458,8 +1491,8 @@ SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, null, null); if (sendRtpItem != null && sendRtpItem.isOnlyAudio()) { // 鏌ヨ娴佹槸鍚﹀瓨鍦紝涓嶅瓨鍦ㄥ垯璁や负鏄紓甯哥姸鎬� - MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); + MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + Boolean streamReady = mediaServerService.isStreamReady(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream()); if (streamReady) { logger.warn("[璇煶瀵硅] 姝e湪璇煶骞挎挱锛屾棤娉曞紑鍚闊抽�氳瘽锛� {}", channelId); event.call("姝e湪璇煶骞挎挱"); @@ -1472,8 +1505,8 @@ SendRtpItem sendRtpItem = redisCatchStorage.querySendRTPServer(device.getDeviceId(), channelId, stream, null); if (sendRtpItem != null) { - MediaServerItem mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServer, "rtp", sendRtpItem.getReceiveStream()); + MediaServer mediaServer = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + Boolean streamReady = mediaServerService.isStreamReady(mediaServer, "rtp", sendRtpItem.getReceiveStream()); if (streamReady) { logger.warn("[璇煶瀵硅] 杩涜涓細 {}", channelId); event.call("璇煶瀵硅杩涜涓�"); @@ -1483,7 +1516,7 @@ } } - talk(mediaServerItem, device, channelId, stream, (mediaServerItem1, hookParam) -> { + talk(mediaServerItem, device, channelId, stream, (hookData) -> { logger.info("[璇煶瀵硅] 鏀跺埌璁惧鍙戞潵鐨勬祦"); }, eventResult -> { logger.warn("[璇煶瀵硅] 澶辫触锛寋}/{}, 閿欒鐮� {} {}", device.getDeviceId(), channelId, eventResult.statusCode, eventResult.msg); @@ -1517,15 +1550,10 @@ return; } - MediaServerItem mediaServer = mediaServerService.getOne(mediaServerId); + MediaServer mediaServer = mediaServerService.getOne(mediaServerId); if (streamIsReady == null || streamIsReady) { - Map<String, Object> param = new HashMap<>(); - param.put("vhost", "__defaultVhost__"); - param.put("app", sendRtpItem.getApp()); - param.put("stream", sendRtpItem.getStream()); - param.put("ssrc", sendRtpItem.getSsrc()); - zlmServerFactory.stopSendRtpStream(mediaServer, param); + mediaServerService.stopSendRtp(mediaServer, sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getSsrc()); } ssrcFactory.releaseSsrc(mediaServerId, sendRtpItem.getSsrc()); @@ -1552,7 +1580,7 @@ if (inviteInfo != null) { if (inviteInfo.getStreamInfo() != null) { // 宸插瓨鍦ㄧ嚎鐩存帴鎴浘 - MediaServerItem mediaServerItemInuse = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); + MediaServer mediaServerItemInuse = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); String streamUrl; if (mediaServerItemInuse.getRtspPort() != 0) { streamUrl = String.format("rtsp://127.0.0.1:%s/%s/%s", mediaServerItemInuse.getRtspPort(), "rtp", inviteInfo.getStreamInfo().getStream()); @@ -1562,7 +1590,7 @@ String path = "snap"; // 璇锋眰鎴浘 logger.info("[璇锋眰鎴浘]: " + fileName); - zlmresTfulUtils.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); + mediaServerService.getSnap(mediaServerItemInuse, streamUrl, 15, 1, path, fileName); File snapFile = new File(path + File.separator + fileName); if (snapFile.exists()) { errorCallback.run(InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), snapFile.getAbsoluteFile()); @@ -1573,7 +1601,7 @@ } } - MediaServerItem newMediaServerItem = getNewMediaServerItem(device); + MediaServer newMediaServerItem = getNewMediaServerItem(device); play(newMediaServerItem, deviceId, channelId, null, (code, msg, data)->{ if (code == InviteErrorCode.SUCCESS.getCode()) { InviteInfo inviteInfoForPlay = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, deviceId, channelId); 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 f0230f7..6692aa8 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java @@ -1,6 +1,5 @@ package com.genersoft.iot.vmp.service.impl; -import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import com.baomidou.dynamic.datasource.annotation.DS; import com.genersoft.iot.vmp.common.GeneralCallback; @@ -9,17 +8,19 @@ import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookType; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; +import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent; +import com.genersoft.iot.vmp.media.event.media.MediaNotFoundEvent; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.service.IGbStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; @@ -29,11 +30,14 @@ import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.ResourceBaseInfo; +import com.genersoft.iot.vmp.vmanager.bean.WVPResult; import com.github.pagehelper.PageInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.scheduling.annotation.Async; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Service; import org.springframework.transaction.TransactionDefinition; @@ -59,12 +63,6 @@ @Autowired private IVideoManagerStorage videoManagerStorager; - - @Autowired - private IMediaService mediaService; - - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; @Autowired private ZLMServerFactory zlmServerFactory; @@ -94,7 +92,7 @@ private IMediaServerService mediaServerService; @Autowired - private ZlmHttpHookSubscribe hookSubscribe; + private HookSubscribe hookSubscribe; @Autowired private DynamicTask dynamicTask; @@ -105,31 +103,62 @@ @Autowired TransactionDefinition transactionDefinition; + /** + * 娴佸埌鏉ョ殑澶勭悊 + */ + @Async("taskExecutor") + @org.springframework.context.event.EventListener + public void onApplicationEvent(MediaArrivalEvent event) { + if ("rtsp".equals(event.getSchema())) { + updateStatus(true, event.getApp(), event.getStream()); + } + } + + /** + * 娴佺寮�鐨勫鐞� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaDepartureEvent event) { + if ("rtsp".equals(event.getSchema())) { + updateStatus(false, event.getApp(), event.getStream()); + } + } + + /** + * 娴佺寮�鐨勫鐞� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaNotFoundEvent event) { + if ("rtp".equals(event.getApp())) { + return; + } + // 鎷夋祦浠g悊 + StreamProxyItem streamProxyByAppAndStream = getStreamProxyByAppAndStream(event.getApp(), event.getStream()); + if (streamProxyByAppAndStream != null && streamProxyByAppAndStream.isEnableDisableNoneReader()) { + start(event.getApp(), event.getStream()); + } + } + @Override public void save(StreamProxyItem param, GeneralCallback<StreamInfo> callback) { - MediaServerItem mediaInfo; + MediaServer mediaServer; if (ObjectUtils.isEmpty(param.getMediaServerId()) || "auto".equals(param.getMediaServerId())){ - mediaInfo = mediaServerService.getMediaServerForMinimumLoad(null); + mediaServer = mediaServerService.getMediaServerForMinimumLoad(null); }else { - mediaInfo = mediaServerService.getOne(param.getMediaServerId()); + mediaServer = mediaServerService.getOne(param.getMediaServerId()); } - if (mediaInfo == null) { + if (mediaServer == null) { logger.warn("淇濆瓨浠g悊鏈壘鍒板湪绾跨殑ZLM..."); throw new ControllerException(ErrorCode.ERROR100.getCode(), "淇濆瓨浠g悊鏈壘鍒板湪绾跨殑ZLM"); } String dstUrl; if ("ffmpeg".equalsIgnoreCase(param.getType())) { - JSONObject jsonObject = zlmresTfulUtils.getMediaServerConfig(mediaInfo); - if (jsonObject.getInteger("code") != 0) { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "鑾峰彇娴佸獟浣撻厤缃け璐�"); - } - JSONArray dataArray = jsonObject.getJSONArray("data"); - JSONObject mediaServerConfig = dataArray.getJSONObject(0); - if (ObjectUtils.isEmpty(param.getFfmpegCmdKey())) { - param.setFfmpegCmdKey("ffmpeg.cmd"); - } - String ffmpegCmd = mediaServerConfig.getString(param.getFfmpegCmdKey()); + + String ffmpegCmd = mediaServerService.getFfmpegCmd(mediaServer, param.getFfmpegCmdKey()); + if (ffmpegCmd == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "ffmpeg鎷夋祦浠g悊鏃犳硶鑾峰彇ffmpeg cmd"); } @@ -140,25 +169,25 @@ int port; String schemaForUri; if (schema.equalsIgnoreCase("rtsp")) { - port = mediaInfo.getRtspPort(); + port = mediaServer.getRtspPort(); schemaForUri = schema; }else if (schema.equalsIgnoreCase("flv")) { - port = mediaInfo.getRtmpPort(); + port = mediaServer.getRtmpPort(); schemaForUri = schema; }else { - port = mediaInfo.getRtmpPort(); + port = mediaServer.getRtmpPort(); schemaForUri = schema; } dstUrl = String.format("%s://%s:%s/%s/%s", schemaForUri, "127.0.0.1", port, param.getApp(), param.getStream()); }else { - dstUrl = String.format("rtsp://%s:%s/%s/%s", "127.0.0.1", mediaInfo.getRtspPort(), param.getApp(), + dstUrl = String.format("rtsp://%s:%s/%s/%s", "127.0.0.1", mediaServer.getRtspPort(), param.getApp(), param.getStream()); } param.setDstUrl(dstUrl); logger.info("[鎷夋祦浠g悊] 杈撳嚭鍦板潃涓猴細{}", dstUrl); - param.setMediaServerId(mediaInfo.getId()); + param.setMediaServerId(mediaServer.getId()); boolean saveResult; // 鏇存柊 if (videoManagerStorager.queryStreamProxy(param.getApp(), param.getStream()) != null) { @@ -170,17 +199,17 @@ callback.run(ErrorCode.ERROR100.getCode(), "淇濆瓨澶辫触", null); return; } - HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed(param.getApp(), param.getStream(), true, "rtsp", mediaInfo.getId()); - hookSubscribe.addSubscribe(hookSubscribeForStreamChange, (mediaServerItem, response) -> { - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( - mediaInfo, param.getApp(), param.getStream(), null, null); + Hook hook = Hook.getInstance(HookType.on_media_arrival, param.getApp(), param.getStream(), mediaServer.getId()); + hookSubscribe.addSubscribe(hook, (hookData) -> { + StreamInfo streamInfo = mediaServerService.getStreamInfoByAppAndStream( + mediaServer, param.getApp(), param.getStream(), null, null); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); }); if (param.isEnable()) { String talkKey = UUID.randomUUID().toString(); String delayTalkKey = UUID.randomUUID().toString(); dynamicTask.startDelay(delayTalkKey, ()->{ - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false); + StreamInfo streamInfo = mediaServerService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaServer.getId(), false); if (streamInfo != null) { callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); }else { @@ -188,12 +217,12 @@ callback.run(ErrorCode.ERROR100.getCode(), "瓒呮椂", null); } }, 7000); - JSONObject jsonObject = addStreamProxyToZlm(param); - if (jsonObject != null && jsonObject.getInteger("code") == 0) { - hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); + WVPResult<String> result = addStreamProxyToZlm(param); + if (result != null && result.getCode() == 0) { + hookSubscribe.removeSubscribe(hook); dynamicTask.stop(talkKey); - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( - mediaInfo, param.getApp(), param.getStream(), null, null); + StreamInfo streamInfo = mediaServerService.getStreamInfoByAppAndStream( + mediaServer, param.getApp(), param.getStream(), null, null); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); }else { param.setEnable(false); @@ -203,16 +232,16 @@ }else { updateStreamProxy(param); } - if (jsonObject == null){ + if (result == null){ callback.run(ErrorCode.ERROR100.getCode(), "璁板綍宸蹭繚瀛橈紝鍚敤澶辫触", null); }else { - callback.run(ErrorCode.ERROR100.getCode(), jsonObject.getString("msg"), null); + callback.run(ErrorCode.ERROR100.getCode(), result.getMsg(), null); } } } else{ - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( - mediaInfo, param.getApp(), param.getStream(), null, null); + StreamInfo streamInfo = mediaServerService.getStreamInfoByAppAndStream( + mediaServer, param.getApp(), param.getStream(), null, null); callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); } } @@ -308,38 +337,34 @@ } @Override - public JSONObject addStreamProxyToZlm(StreamProxyItem param) { - JSONObject result = null; - MediaServerItem mediaServerItem = null; + public WVPResult<String> addStreamProxyToZlm(StreamProxyItem param) { + WVPResult<String> result = null; + MediaServer mediaServer = null; if (param.getMediaServerId() == null) { logger.warn("娣诲姞浠g悊鏃禡ediaServerId 涓簄ull"); return null; }else { - mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); + mediaServer = mediaServerService.getOne(param.getMediaServerId()); } - if (mediaServerItem == null) { + if (mediaServer == null) { return null; } - if (zlmServerFactory.isStreamReady(mediaServerItem, param.getApp(), param.getStream())) { - zlmresTfulUtils.closeStreams(mediaServerItem, param.getApp(), param.getStream()); + if (mediaServerService.isStreamReady(mediaServer, param.getApp(), param.getStream())) { + mediaServerService.closeStreams(mediaServer, param.getApp(), param.getStream()); } + String msgResult; if ("ffmpeg".equalsIgnoreCase(param.getType())){ - result = zlmresTfulUtils.addFFmpegSource(mediaServerItem, param.getSrcUrl().trim(), param.getDstUrl(), - param.getTimeoutMs() + "", param.isEnableAudio(), param.isEnableMp4(), + result = mediaServerService.addFFmpegSource(mediaServer, param.getSrcUrl().trim(), param.getDstUrl(), + param.getTimeoutMs(), param.isEnableAudio(), param.isEnableMp4(), param.getFfmpegCmdKey()); }else { - result = zlmresTfulUtils.addStreamProxy(mediaServerItem, param.getApp(), param.getStream(), param.getUrl().trim(), + result = mediaServerService.addStreamProxy(mediaServer, param.getApp(), param.getStream(), param.getUrl().trim(), param.isEnableAudio(), param.isEnableMp4(), param.getRtpType()); } - if (result != null && result.getInteger("code") == 0) { - JSONObject data = result.getJSONObject("data"); - if (data == null) { - logger.warn("[鑾峰彇鎷夋祦浠g悊鐨勭粨鏋滄暟鎹瓺ata] 澶辫触锛� {}", result ); - return result; - } - String key = data.getString("key"); + if (result != null && result.getCode() == 0) { + String key = result.getData(); if (key == null) { - logger.warn("[鑾峰彇鎷夋祦浠g悊鐨勭粨鏋滄暟鎹瓺ata涓殑KEY] 澶辫触锛� {}", result ); + logger.warn("[鑾峰彇鎷夋祦浠g悊鐨勭粨鏋滄暟鎹瓺ata] 澶辫触锛� {}", result ); return result; } param.setStreamKey(key); @@ -349,16 +374,23 @@ } @Override - public JSONObject removeStreamProxyFromZlm(StreamProxyItem param) { + public Boolean removeStreamProxyFromZlm(StreamProxyItem param) { if (param ==null) { return null; } - MediaServerItem mediaServerItem = mediaServerService.getOne(param.getMediaServerId()); - JSONObject result = null; + MediaServer mediaServer = mediaServerService.getOne(param.getMediaServerId()); + if (mediaServer == null) { + return null; + } + List<StreamInfo> mediaList = mediaServerService.getMediaList(mediaServer, param.getApp(), param.getStream(), null); + if (mediaList == null || mediaList.isEmpty()) { + return true; + } + Boolean result = false; if ("ffmpeg".equalsIgnoreCase(param.getType())){ - result = zlmresTfulUtils.delFFmpegSource(mediaServerItem, param.getStreamKey()); + result = mediaServerService.delFFmpegSource(mediaServer, param.getStreamKey()); }else { - result = zlmresTfulUtils.delStreamProxy(mediaServerItem, param.getStreamKey()); + result = mediaServerService.delStreamProxy(mediaServer, param.getStreamKey()); } return result; } @@ -379,8 +411,8 @@ gbStreamMapper.del(app, stream); videoManagerStorager.deleteStreamProxy(app, stream); redisCatchStorage.removeStream(streamProxyItem.getMediaServerId(), "PULL", app, stream); - JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyItem); - if (jsonObject != null && jsonObject.getInteger("code") == 0) { + Boolean result = removeStreamProxyFromZlm(streamProxyItem); + if (result != null && result) { logger.info("[绉婚櫎浠g悊]锛� 浠g悊锛� {}/{}, 浠巣lm绉婚櫎鎴愬姛", app, stream); }else { logger.info("[绉婚櫎浠g悊]锛� 浠g悊锛� {}/{}, 浠巣lm绉婚櫎澶辫触", app, stream); @@ -393,16 +425,16 @@ boolean result = false; StreamProxyItem streamProxy = videoManagerStorager.queryStreamProxy(app, stream); if (streamProxy != null && !streamProxy.isEnable() ) { - JSONObject jsonObject = addStreamProxyToZlm(streamProxy); - if (jsonObject == null) { + WVPResult<String> wvpResult = addStreamProxyToZlm(streamProxy); + if (wvpResult == null) { return false; } - if (jsonObject.getInteger("code") == 0) { + if (wvpResult.getCode() == 0) { result = true; streamProxy.setEnable(true); updateStreamProxy(streamProxy); }else { - logger.info("鍚敤浠g悊澶辫触锛� {}/{}->{}({})", app, stream, jsonObject.getString("msg"), + logger.info("鍚敤浠g悊澶辫触锛� {}/{}->{}({})", app, stream, wvpResult.getMsg(), streamProxy.getSrcUrl() == null? streamProxy.getUrl():streamProxy.getSrcUrl()); } } else if (streamProxy != null && streamProxy.isEnable()) { @@ -416,8 +448,8 @@ boolean result = false; StreamProxyItem streamProxyDto = videoManagerStorager.queryStreamProxy(app, stream); if (streamProxyDto != null && streamProxyDto.isEnable()) { - JSONObject jsonObject = removeStreamProxyFromZlm(streamProxyDto); - if (jsonObject != null && jsonObject.getInteger("code") == 0) { + Boolean removed = removeStreamProxyFromZlm(streamProxyDto); + if (removed != null && removed) { streamProxyDto.setEnable(false); result = updateStreamProxy(streamProxyDto); } @@ -426,20 +458,8 @@ } @Override - public JSONObject getFFmpegCMDs(MediaServerItem mediaServerItem) { - JSONObject result = new JSONObject(); - JSONObject mediaServerConfigResuly = zlmresTfulUtils.getMediaServerConfig(mediaServerItem); - if (mediaServerConfigResuly != null && mediaServerConfigResuly.getInteger("code") == 0 - && mediaServerConfigResuly.getJSONArray("data").size() > 0){ - JSONObject mediaServerConfig = mediaServerConfigResuly.getJSONArray("data").getJSONObject(0); - - for (String key : mediaServerConfig.keySet()) { - if (key.startsWith("ffmpeg.cmd")){ - result.put(key, mediaServerConfig.getString(key)); - } - } - } - return result; + public Map<String, String> getFFmpegCMDs(MediaServer mediaServer) { + return mediaServerService.getFFmpegCMDs(mediaServer); } @@ -465,8 +485,8 @@ mediaServerId, true); for (StreamProxyItem streamProxyDto : streamProxyListForEnable) { logger.info("鎭㈠娴佷唬鐞嗭紝" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); - JSONObject jsonObject = addStreamProxyToZlm(streamProxyDto); - if (jsonObject == null) { + WVPResult<String> wvpResult = addStreamProxyToZlm(streamProxyDto); + if (wvpResult == null) { // 璁剧疆涓虹绾� logger.info("鎭㈠娴佷唬鐞嗗け璐�" + streamProxyDto.getApp() + "/" + streamProxyDto.getStream()); updateStatus(false, streamProxyDto.getApp(), streamProxyDto.getStream()); @@ -516,44 +536,30 @@ } private void syncPullStream(String mediaServerId){ - MediaServerItem mediaServer = mediaServerService.getOne(mediaServerId); + MediaServer mediaServer = mediaServerService.getOne(mediaServerId); if (mediaServer != null) { List<OnStreamChangedHookParam> allPullStream = redisCatchStorage.getStreams(mediaServerId, "PULL"); - if (allPullStream.size() > 0) { - zlmresTfulUtils.getMediaList(mediaServer, jsonObject->{ - Map<String, StreamInfo> stringStreamInfoMap = new HashMap<>(); - if (jsonObject.getInteger("code") == 0) { - JSONArray data = jsonObject.getJSONArray("data"); - if(data != null && data.size() > 0) { - for (int i = 0; i < data.size(); i++) { - JSONObject streamJSONObj = data.getJSONObject(i); - if ("rtsp".equals(streamJSONObj.getString("schema"))) { - StreamInfo streamInfo = new StreamInfo(); - String app = streamJSONObj.getString("app"); - String stream = streamJSONObj.getString("stream"); - streamInfo.setApp(app); - streamInfo.setStream(stream); - stringStreamInfoMap.put(app+stream, streamInfo); - } - } + if (!allPullStream.isEmpty()) { + List<StreamInfo> mediaList = mediaServerService.getMediaList(mediaServer, null, null, null); + Map<String, StreamInfo> stringStreamInfoMap = new HashMap<>(); + if (mediaList != null && !mediaList.isEmpty()) { + for (StreamInfo streamInfo : mediaList) { + stringStreamInfoMap.put(streamInfo.getApp() + streamInfo.getStream(), streamInfo); + } + } + if (stringStreamInfoMap.isEmpty()) { + redisCatchStorage.removeStream(mediaServerId, "PULL"); + }else { + for (String key : stringStreamInfoMap.keySet()) { + StreamInfo streamInfo = stringStreamInfoMap.get(key); + if (stringStreamInfoMap.get(streamInfo.getApp() + streamInfo.getStream()) == null) { + redisCatchStorage.removeStream(mediaServerId, "PULL", streamInfo.getApp(), + streamInfo.getStream()); } } - if (stringStreamInfoMap.size() == 0) { - redisCatchStorage.removeStream(mediaServerId, "PULL"); - }else { - for (String key : stringStreamInfoMap.keySet()) { - StreamInfo streamInfo = stringStreamInfoMap.get(key); - if (stringStreamInfoMap.get(streamInfo.getApp() + streamInfo.getStream()) == null) { - redisCatchStorage.removeStream(mediaServerId, "PULL", streamInfo.getApp(), - streamInfo.getStream()); - } - } - } - }); + } } - } - } @Override @@ -569,13 +575,13 @@ @Scheduled(cron = "* 0/10 * * * ?") public void asyncCheckStreamProxyStatus() { - List<MediaServerItem> all = mediaServerService.getAllOnline(); + List<MediaServer> all = mediaServerService.getAllOnline(); if (CollectionUtils.isEmpty(all)){ return; } - Map<String, MediaServerItem> serverItemMap = all.stream().collect(Collectors.toMap(MediaServerItem::getId, Function.identity(), (m1, m2) -> m1)); + Map<String, MediaServer> serverItemMap = all.stream().collect(Collectors.toMap(MediaServer::getId, Function.identity(), (m1, m2) -> m1)); List<StreamProxyItem> list = videoManagerStorager.getStreamProxyListForEnable(true); @@ -585,15 +591,14 @@ for (StreamProxyItem streamProxyItem : list) { - MediaServerItem mediaServerItem = serverItemMap.get(streamProxyItem.getMediaServerId()); + MediaServer mediaServerItem = serverItemMap.get(streamProxyItem.getMediaServerId()); - // TODO 鏀寔鍏朵粬 schema - JSONObject mediaInfo = zlmresTfulUtils.isMediaOnline(mediaServerItem, streamProxyItem.getApp(), streamProxyItem.getStream(), "rtsp"); + MediaInfo mediaInfo = mediaServerService.getMediaInfo(mediaServerItem, streamProxyItem.getApp(), streamProxyItem.getStream()); if (mediaInfo == null){ streamProxyItem.setStatus(false); } else { - if (mediaInfo.getInteger("code") == 0 && mediaInfo.getBoolean("online")) { + if (mediaInfo.getOnline() != null && mediaInfo.getOnline()) { streamProxyItem.setStatus(true); } else { streamProxyItem.setStatus(false); 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 e2d7e68..652bcdd 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamPushServiceImpl.java @@ -1,21 +1,25 @@ package com.genersoft.iot.vmp.service.impl; -import com.alibaba.fastjson2.JSON; -import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; -import com.alibaba.fastjson2.TypeReference; import com.baomidou.dynamic.datasource.annotation.DS; +import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.MediaConfig; import com.genersoft.iot.vmp.conf.UserSetting; -import com.genersoft.iot.vmp.gb28181.bean.*; +import com.genersoft.iot.vmp.gb28181.bean.GbStream; +import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; +import com.genersoft.iot.vmp.gb28181.bean.PlatformCatalog; import com.genersoft.iot.vmp.gb28181.event.EventPublisher; import com.genersoft.iot.vmp.gb28181.event.subscribe.catalog.CatalogEvent; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.dto.*; +import com.genersoft.iot.vmp.media.bean.MediaInfo; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; +import com.genersoft.iot.vmp.media.event.media.MediaDepartureEvent; +import com.genersoft.iot.vmp.media.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.media.zlm.dto.hook.OriginType; import com.genersoft.iot.vmp.service.IGbStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.bean.StreamPushItemFromRedis; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -27,7 +31,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.event.EventListener; import org.springframework.jdbc.datasource.DataSourceTransactionManager; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.TransactionDefinition; import org.springframework.transaction.TransactionStatus; @@ -67,9 +73,6 @@ private EventPublisher eventPublisher; @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; - - @Autowired private IRedisCatchStorage redisCatchStorage; @Autowired @@ -87,33 +90,125 @@ @Autowired private MediaConfig mediaConfig; - - @Override - public List<StreamPushItem> handleJSON(String jsonData, MediaServerItem mediaServerItem) { - if (jsonData == null) { - return null; + /** + * 娴佸埌鏉ョ殑澶勭悊 + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaArrivalEvent event) { + MediaInfo mediaInfo = event.getMediaInfo(); + if (mediaInfo == null) { + return; + } + if (mediaInfo.getOriginType() != OriginType.RTMP_PUSH.ordinal() + && mediaInfo.getOriginType() != OriginType.RTSP_PUSH.ordinal() + && mediaInfo.getOriginType() != OriginType.RTC_PUSH.ordinal()) { + return; } + StreamAuthorityInfo streamAuthorityInfo = redisCatchStorage.getStreamAuthorityInfo(event.getApp(), event.getStream()); + if (streamAuthorityInfo == null) { + streamAuthorityInfo = StreamAuthorityInfo.getInstanceByHook(event); + } else { + streamAuthorityInfo.setOriginType(mediaInfo.getOriginType()); + } + redisCatchStorage.updateStreamAuthorityInfo(event.getApp(), event.getStream(), streamAuthorityInfo); + StreamPushItem transform = StreamPushItem.getInstance(event, userSetting.getServerId()); + transform.setPushIng(true); + transform.setUpdateTime(DateUtil.getNow()); + transform.setPushTime(DateUtil.getNow()); + transform.setSelf(true); + StreamPushItem pushInDb = getPush(event.getApp(), event.getStream()); + if (pushInDb == null) { + transform.setCreateTime(DateUtil.getNow()); + streamPushMapper.add(transform); + }else { + streamPushMapper.update(transform); + gbStreamMapper.updateMediaServer(event.getApp(), event.getStream(), event.getMediaServer().getId()); + } + // TODO 鐩稿叧鐨勪簨浠惰嚜琛岀鐞嗭紝涓嶉渶瑕佸啓鍏LMMediaListManager +// ChannelOnlineEvent channelOnlineEventLister = getChannelOnlineEventLister(transform.getApp(), transform.getStream()); +// if ( channelOnlineEventLister != null) { +// try { +// channelOnlineEventLister.run(transform.getApp(), transform.getStream(), transform.getServerId());; +// } catch (ParseException e) { +// logger.error("addPush: ", e); +// } +// removedChannelOnlineEventLister(transform.getApp(), transform.getStream()); +// } + // 鍐椾綑鏁版嵁锛岃嚜宸辩郴缁熶腑鑷敤 + redisCatchStorage.addPushListItem(event.getApp(), event.getStream(), event); + + // 鍙戦�佹祦鍙樺寲redis娑堟伅 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("serverId", userSetting.getServerId()); + jsonObject.put("app", event.getApp()); + jsonObject.put("stream", event.getStream()); + jsonObject.put("register", true); + jsonObject.put("mediaServerId", event.getMediaServer().getId()); + redisCatchStorage.sendStreamChangeMsg(OriginType.values()[event.getMediaInfo().getOriginType()].getType(), jsonObject); + } + + /** + * 娴佺寮�鐨勫鐞� + */ + @Async("taskExecutor") + @EventListener + public void onApplicationEvent(MediaDepartureEvent event) { + // 鍏煎娴佹敞閿�鏃剁被鍨嬩粠redis璁板綍鑾峰彇 + OnStreamChangedHookParam onStreamChangedHookParam = redisCatchStorage.getStreamInfo( + event.getApp(), event.getStream(), event.getMediaServer().getId()); + if (onStreamChangedHookParam != null) { + String type = OriginType.values()[onStreamChangedHookParam.getOriginType()].getType(); + redisCatchStorage.removeStream(event.getMediaServer().getId(), type, event.getApp(), event.getStream()); + if ("PUSH".equalsIgnoreCase(type)) { + // 鍐椾綑鏁版嵁锛岃嚜宸辩郴缁熶腑鑷敤 + redisCatchStorage.removePushListItem(event.getApp(), event.getStream(), event.getMediaServer().getId()); + } + if (type != null) { + // 鍙戦�佹祦鍙樺寲redis娑堟伅 + JSONObject jsonObject = new JSONObject(); + jsonObject.put("serverId", userSetting.getServerId()); + jsonObject.put("app", event.getApp()); + jsonObject.put("stream", event.getStream()); + jsonObject.put("register", false); + jsonObject.put("mediaServerId", event.getMediaServer().getId()); + redisCatchStorage.sendStreamChangeMsg(type, jsonObject); + } + } + GbStream gbStream = gbStreamMapper.selectOne(event.getApp(), event.getStream()); + if (gbStream != null) { + if (userSetting.isUsePushingAsStatus()) { + streamPushMapper.updatePushStatus(event.getApp(), event.getStream(), false); + eventPublisher.catalogEventPublishForStream(null, gbStream, CatalogEvent.OFF); + } + }else { + streamPushMapper.del(event.getApp(), event.getStream()); + } + } + + + private List<StreamPushItem> handleJSON(List<StreamInfo> streamInfoList) { + if (streamInfoList == null || streamInfoList.isEmpty()) { + return null; + } Map<String, StreamPushItem> result = new HashMap<>(); - - List<OnStreamChangedHookParam> onStreamChangedHookParams = JSON.parseObject(jsonData, new TypeReference<List<OnStreamChangedHookParam>>() {}); - for (OnStreamChangedHookParam item : onStreamChangedHookParams) { - + for (StreamInfo streamInfo : streamInfoList) { // 涓嶄繚瀛樺浗鏍囨帹鐞嗕互鍙婃媺娴佷唬鐞嗙殑娴� - if (item.getOriginType() == OriginType.RTSP_PUSH.ordinal() - || item.getOriginType() == OriginType.RTMP_PUSH.ordinal() - || item.getOriginType() == OriginType.RTC_PUSH.ordinal() ) { - String key = item.getApp() + "_" + item.getStream(); + if (streamInfo.getOriginType() == OriginType.RTSP_PUSH.ordinal() + || streamInfo.getOriginType() == OriginType.RTMP_PUSH.ordinal() + || streamInfo.getOriginType() == OriginType.RTC_PUSH.ordinal() ) { + String key = streamInfo.getApp() + "_" + streamInfo.getStream(); StreamPushItem streamPushItem = result.get(key); if (streamPushItem == null) { - streamPushItem = transform(item); + streamPushItem = streamPushItem.getInstance(streamInfo); result.put(key, streamPushItem); } } } - return new ArrayList<>(result.values()); } + @Override public StreamPushItem transform(OnStreamChangedHookParam item) { StreamPushItem streamPushItem = new StreamPushItem(); @@ -122,7 +217,7 @@ streamPushItem.setStream(item.getStream()); streamPushItem.setAliveSecond(item.getAliveSecond()); streamPushItem.setOriginSock(item.getOriginSock()); - streamPushItem.setTotalReaderCount(item.getTotalReaderCount()); + streamPushItem.setTotalReaderCount(item.getTotalReaderCount() + ""); streamPushItem.setOriginType(item.getOriginType()); streamPushItem.setOriginTypeStr(item.getOriginTypeStr()); streamPushItem.setOriginUrl(item.getOriginUrl()); @@ -164,15 +259,10 @@ gbStreamService.sendCatalogMsg(stream, CatalogEvent.DEL); platformGbStreamMapper.delByAppAndStream(stream.getApp(), stream.getStream()); int del = gbStreamMapper.del(stream.getApp(), stream.getStream()); - MediaServerItem mediaInfo = mediaServerService.getOne(stream.getMediaServerId()); - JSONObject mediaList = zlmresTfulUtils.getMediaList(mediaInfo, stream.getApp(), stream.getStream()); - if (mediaList != null) { - if (mediaList.getInteger("code") == 0) { - JSONArray data = mediaList.getJSONArray("data"); - if (data == null) { - streamPushMapper.del(stream.getApp(), stream.getStream()); - } - } + MediaServer mediaInfo = mediaServerService.getOne(stream.getMediaServerId()); + List<StreamInfo> mediaList = mediaServerService.getMediaList(mediaInfo, stream.getApp(), stream.getStream(), null); + if (mediaList != null && mediaList.isEmpty()) { + streamPushMapper.del(stream.getApp(), stream.getStream()); } return del > 0; } @@ -195,8 +285,8 @@ gbStreamMapper.del(app, streamId); int delStream = streamPushMapper.del(app, streamId); if (delStream > 0) { - MediaServerItem mediaServerItem = mediaServerService.getOne(streamPushItem.getMediaServerId()); - zlmresTfulUtils.closeStreams(mediaServerItem,app, streamId); + MediaServer mediaServerItem = mediaServerService.getOne(streamPushItem.getMediaServerId()); + mediaServerService.closeStreams(mediaServerItem,app, streamId); } return true; } @@ -204,7 +294,7 @@ @Override public void zlmServerOnline(String mediaServerId) { // 鍚屾zlm鎺ㄦ祦淇℃伅 - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem == null) { return; } @@ -232,71 +322,61 @@ for (StreamAuthorityInfo streamAuthorityInfo : allStreamAuthorityInfo) { streamAuthorityInfoInfoMap.put(streamAuthorityInfo.getApp() + streamAuthorityInfo.getStream(), streamAuthorityInfo); } - zlmresTfulUtils.getMediaList(mediaServerItem, (mediaList ->{ - if (mediaList == null) { - return; + List<StreamInfo> mediaList = mediaServerService.getMediaList(mediaServerItem, null, null, null); + if (mediaList == null) { + return; + } + List<StreamPushItem> streamPushItems = handleJSON(mediaList); + if (streamPushItems != null) { + for (StreamPushItem streamPushItem : streamPushItems) { + pushItemMap.remove(streamPushItem.getApp() + streamPushItem.getStream()); + streamInfoPushItemMap.remove(streamPushItem.getApp() + streamPushItem.getStream()); + streamAuthorityInfoInfoMap.remove(streamPushItem.getApp() + streamPushItem.getStream()); } - String dataStr = mediaList.getString("data"); - - Integer code = mediaList.getInteger("code"); - List<StreamPushItem> streamPushItems = null; - if (code == 0 ) { - if (dataStr != null) { - streamPushItems = handleJSON(dataStr, mediaServerItem); - } - } - - if (streamPushItems != null) { - for (StreamPushItem streamPushItem : streamPushItems) { - pushItemMap.remove(streamPushItem.getApp() + streamPushItem.getStream()); - streamInfoPushItemMap.remove(streamPushItem.getApp() + streamPushItem.getStream()); - streamAuthorityInfoInfoMap.remove(streamPushItem.getApp() + streamPushItem.getStream()); - } - } - List<StreamPushItem> offlinePushItems = new ArrayList<>(pushItemMap.values()); - if (offlinePushItems.size() > 0) { - String type = "PUSH"; - int runLimit = 300; - if (offlinePushItems.size() > runLimit) { - for (int i = 0; i < offlinePushItems.size(); i += runLimit) { - int toIndex = i + runLimit; - if (i + runLimit > offlinePushItems.size()) { - toIndex = offlinePushItems.size(); - } - List<StreamPushItem> streamPushItemsSub = offlinePushItems.subList(i, toIndex); - streamPushMapper.delAll(streamPushItemsSub); + } + List<StreamPushItem> offlinePushItems = new ArrayList<>(pushItemMap.values()); + if (offlinePushItems.size() > 0) { + String type = "PUSH"; + int runLimit = 300; + if (offlinePushItems.size() > runLimit) { + for (int i = 0; i < offlinePushItems.size(); i += runLimit) { + int toIndex = i + runLimit; + if (i + runLimit > offlinePushItems.size()) { + toIndex = offlinePushItems.size(); } - }else { - streamPushMapper.delAll(offlinePushItems); + List<StreamPushItem> streamPushItemsSub = offlinePushItems.subList(i, toIndex); + streamPushMapper.delAll(streamPushItemsSub); } - - } - Collection<OnStreamChangedHookParam> offlineOnStreamChangedHookParamList = streamInfoPushItemMap.values(); - if (offlineOnStreamChangedHookParamList.size() > 0) { - String type = "PUSH"; - for (OnStreamChangedHookParam offlineOnStreamChangedHookParam : offlineOnStreamChangedHookParamList) { - JSONObject jsonObject = new JSONObject(); - jsonObject.put("serverId", userSetting.getServerId()); - jsonObject.put("app", offlineOnStreamChangedHookParam.getApp()); - jsonObject.put("stream", offlineOnStreamChangedHookParam.getStream()); - jsonObject.put("register", false); - jsonObject.put("mediaServerId", mediaServerId); - redisCatchStorage.sendStreamChangeMsg(type, jsonObject); - // 绉婚櫎redis鍐呮祦鐨勪俊鎭� - redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream()); - // 鍐椾綑鏁版嵁锛岃嚜宸辩郴缁熶腑鑷敤 - redisCatchStorage.removePushListItem(offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream(), mediaServerItem.getId()); - } + }else { + streamPushMapper.delAll(offlinePushItems); } - Collection<StreamAuthorityInfo> streamAuthorityInfos = streamAuthorityInfoInfoMap.values(); - if (streamAuthorityInfos.size() > 0) { - for (StreamAuthorityInfo streamAuthorityInfo : streamAuthorityInfos) { - // 绉婚櫎redis鍐呮祦鐨勪俊鎭� - redisCatchStorage.removeStreamAuthorityInfo(streamAuthorityInfo.getApp(), streamAuthorityInfo.getStream()); - } + } + Collection<OnStreamChangedHookParam> offlineOnStreamChangedHookParamList = streamInfoPushItemMap.values(); + if (offlineOnStreamChangedHookParamList.size() > 0) { + String type = "PUSH"; + for (OnStreamChangedHookParam offlineOnStreamChangedHookParam : offlineOnStreamChangedHookParamList) { + JSONObject jsonObject = new JSONObject(); + jsonObject.put("serverId", userSetting.getServerId()); + jsonObject.put("app", offlineOnStreamChangedHookParam.getApp()); + jsonObject.put("stream", offlineOnStreamChangedHookParam.getStream()); + jsonObject.put("register", false); + jsonObject.put("mediaServerId", mediaServerId); + redisCatchStorage.sendStreamChangeMsg(type, jsonObject); + // 绉婚櫎redis鍐呮祦鐨勪俊鎭� + redisCatchStorage.removeStream(mediaServerItem.getId(), "PUSH", offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream()); + // 鍐椾綑鏁版嵁锛岃嚜宸辩郴缁熶腑鑷敤 + redisCatchStorage.removePushListItem(offlineOnStreamChangedHookParam.getApp(), offlineOnStreamChangedHookParam.getStream(), mediaServerItem.getId()); } - })); + } + + Collection<StreamAuthorityInfo> streamAuthorityInfos = streamAuthorityInfoInfoMap.values(); + if (streamAuthorityInfos.size() > 0) { + for (StreamAuthorityInfo streamAuthorityInfo : streamAuthorityInfos) { + // 绉婚櫎redis鍐呮祦鐨勪俊鎭� + redisCatchStorage.removeStreamAuthorityInfo(streamAuthorityInfo.getApp(), streamAuthorityInfo.getStream()); + } + } } @Override @@ -470,8 +550,8 @@ int delStream = streamPushMapper.delAllForGbStream(gbStreams); if (delStream > 0) { for (GbStream gbStream : gbStreams) { - MediaServerItem mediaServerItem = mediaServerService.getOne(gbStream.getMediaServerId()); - zlmresTfulUtils.closeStreams(mediaServerItem, gbStream.getApp(), gbStream.getStream()); + MediaServer mediaServerItem = mediaServerService.getOne(gbStream.getMediaServerId()); + mediaServerService.closeStreams(mediaServerItem, gbStream.getApp(), gbStream.getStream()); } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java index 3b990f0..14287e0 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisGbPlayMsgListener.java @@ -6,12 +6,12 @@ import com.genersoft.iot.vmp.conf.DynamicTask; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookType; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.bean.*; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.utils.redis.RedisUtil; @@ -61,9 +61,9 @@ */ public static final int ERROR_CODE_TIMEOUT = -3; - private Map<String, PlayMsgCallback> callbacks = new ConcurrentHashMap<>(); - private Map<String, PlayMsgCallbackForStartSendRtpStream> callbacksForStartSendRtpStream = new ConcurrentHashMap<>(); - private Map<String, PlayMsgErrorCallback> callbacksForError = new ConcurrentHashMap<>(); + private final Map<String, PlayMsgCallback> callbacks = new ConcurrentHashMap<>(); + private final Map<String, PlayMsgCallbackForStartSendRtpStream> callbacksForStartSendRtpStream = new ConcurrentHashMap<>(); + private final Map<String, PlayMsgErrorCallback> callbacksForError = new ConcurrentHashMap<>(); @Autowired private UserSetting userSetting; @@ -87,9 +87,9 @@ @Autowired - private ZlmHttpHookSubscribe subscribe; + private HookSubscribe subscribe; - private ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); + private final ConcurrentLinkedQueue<Message> taskQueue = new ConcurrentLinkedQueue<>(); @Qualifier("taskExecutor") @Autowired @@ -219,7 +219,7 @@ * 澶勭悊鏀跺埌鐨勮姹傛帹娴佺殑璇锋眰 */ private void requestPushStreamMsgHand(RequestPushStreamMsg requestPushStreamMsg, String fromId, String serial) { - MediaServerItem mediaInfo = mediaServerService.getOne(requestPushStreamMsg.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(requestPushStreamMsg.getMediaServerId()); if (mediaInfo == null) { // TODO 鍥炲閿欒 return; @@ -258,7 +258,7 @@ * 澶勭悊鏀跺埌鐨勮姹俿endItem鐨勮姹� */ private void requestSendItemMsgHand(RequestSendItemMsg content, String toId, String serial) { - MediaServerItem mediaServerItem = mediaServerService.getOne(content.getMediaServerId()); + MediaServer mediaServerItem = mediaServerService.getOne(content.getMediaServerId()); if (mediaServerItem == null) { logger.info("[鍥炲鎺ㄦ祦淇℃伅] 娴佸獟浣搟}涓嶅瓨鍦� ", content.getMediaServerId()); @@ -274,7 +274,7 @@ return; } // 纭畾娴佹槸鍚﹀湪绾� - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, content.getApp(), content.getStream()); + Boolean streamReady = mediaServerService.isStreamReady(mediaServerItem, content.getApp(), content.getStream()); if (streamReady != null && streamReady) { logger.info("[鍥炲鎺ㄦ祦淇℃伅] {}/{}", content.getApp(), content.getStream()); responseSendItem(mediaServerItem, content, toId, serial); @@ -297,9 +297,8 @@ }, userSetting.getPlatformPlayTimeout()); // 娣诲姞璁㈤槄 - HookSubscribeForStreamChange hookSubscribe = HookSubscribeFactory.on_stream_changed(content.getApp(), content.getStream(), true, "rtsp", mediaServerItem.getId()); - - subscribe.addSubscribe(hookSubscribe, (mediaServerItemInUse, hookParam)->{ + Hook hook = Hook.getInstance(HookType.on_media_arrival, content.getApp(), content.getStream(), content.getMediaServerId()); + subscribe.addSubscribe(hook, (hookData)->{ dynamicTask.stop(taskKey); responseSendItem(mediaServerItem, content, toId, serial); }); @@ -317,7 +316,7 @@ /** * 灏嗚幏鍙栧埌鐨剆endItem鍙戦�佸嚭鍘� */ - private void responseSendItem(MediaServerItem mediaServerItem, RequestSendItemMsg content, String toId, String serial) { + private void responseSendItem(MediaServer mediaServerItem, RequestSendItemMsg content, String toId, String serial) { SendRtpItem sendRtpItem = zlmServerFactory.createSendRtpItem(mediaServerItem, content.getIp(), content.getPort(), content.getSsrc(), content.getPlatformId(), content.getApp(), content.getStream(), content.getChannelId(), @@ -449,7 +448,7 @@ logger.info("[REDIS 鎵ц鍏朵粬骞冲彴鐨勮姹傚仠姝㈡帹娴乚 澶辫触锛� sendRtpItem涓篘ULL"); return; } - MediaServerItem mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); if (mediaInfo == null) { // TODO 鍥炲閿欒 return; diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java index a031573..e7cba6b 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamCloseResponseListener.java @@ -2,12 +2,14 @@ import com.alibaba.fastjson2.JSON; import com.genersoft.iot.vmp.conf.UserSetting; +import com.genersoft.iot.vmp.gb28181.bean.InviteStreamType; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatform; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; import com.genersoft.iot.vmp.gb28181.transmit.cmd.ISIPCommanderForPlatform; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; 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.service.bean.MessageForPushChannel; import com.genersoft.iot.vmp.service.bean.MessageForPushChannelResponse; @@ -23,6 +25,7 @@ import javax.sip.InvalidArgumentException; import javax.sip.SipException; import java.text.ParseException; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -83,6 +86,26 @@ logger.error("[鍛戒护鍙戦�佸け璐 鍥芥爣绾ц仈 鍙戦�丅YE: {}", e.getMessage()); } } + if (push.isSelf()) { + // 鍋滄鍚戜笂绾ф帹娴� + String streamId = sendRtpItem.getStream(); + Map<String, Object> param = new HashMap<>(); + param.put("vhost","__defaultVhost__"); + param.put("app",sendRtpItem.getApp()); + param.put("stream",streamId); + param.put("ssrc",sendRtpItem.getSsrc()); + logger.info("[REDIS娑堟伅-鎺ㄦ祦缁撴潫] 鍋滄鍚戜笂绾ф帹娴侊細{}", streamId); + MediaServer mediaInfo = mediaServerService.getOne(sendRtpItem.getMediaServerId()); + redisCatchStorage.deleteSendRTPServer(sendRtpItem.getPlatformId(), sendRtpItem.getChannelId(), sendRtpItem.getCallId(), sendRtpItem.getStream()); + zlmServerFactory.stopSendRtpStream(mediaInfo, param); + if (InviteStreamType.PUSH == sendRtpItem.getPlayType()) { + MessageForPushChannel messageForPushChannel = MessageForPushChannel.getInstance(0, + sendRtpItem.getApp(), sendRtpItem.getStream(), sendRtpItem.getChannelId(), + sendRtpItem.getPlatformId(), parentPlatform.getName(), userSetting.getServerId(), sendRtpItem.getMediaServerId()); + messageForPushChannel.setPlatFormIndex(parentPlatform.getId()); + redisCatchStorage.sendPlatformStopPlayMsg(messageForPushChannel); + } + } } } } diff --git a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java index dc342b0..49ffd75 100755 --- a/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java +++ b/src/main/java/com/genersoft/iot/vmp/service/redisMsg/RedisPushStreamStatusListMsgListener.java @@ -5,7 +5,7 @@ import com.genersoft.iot.vmp.gb28181.bean.GbStream; import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.service.IGbStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.utils.DateUtil; import org.slf4j.Logger; 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 66db103..c483db6 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/IRedisCatchStorage.java @@ -6,8 +6,10 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; @@ -89,7 +91,7 @@ * @param app * @param streamId */ - void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, OnStreamChangedHookParam item); + void addStream(MediaServer mediaServerItem, String type, String app, String streamId, OnStreamChangedHookParam item); /** * 绉婚櫎娴佷俊鎭粠redis @@ -209,9 +211,9 @@ void sendPlatformStopPlayMsg(MessageForPushChannel messageForPushChannel); - void addPushListItem(String app, String stream, OnStreamChangedHookParam param); + void addPushListItem(String app, String stream, MediaArrivalEvent param); - OnStreamChangedHookParam getPushListItem(String app, String stream); + StreamPushItem getPushListItem(String app, String stream); void removePushListItem(String app, String stream, String mediaServerId); diff --git a/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java b/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java index 08f67ba..22f2ce0 100644 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/CloudRecordServiceMapper.java @@ -1,6 +1,6 @@ package com.genersoft.iot.vmp.storager.dao; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.bean.CloudRecordItem; import org.apache.ibatis.annotations.*; @@ -55,7 +55,7 @@ " </script>") List<CloudRecordItem> getList(@Param("query") String query, @Param("app") String app, @Param("stream") String stream, @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp, - @Param("callId")String callId, List<MediaServerItem> mediaServerItemList); + @Param("callId")String callId, List<MediaServer> mediaServerItemList); @Select(" <script>" + @@ -73,7 +73,7 @@ " </script>") List<String> queryRecordFilePathList(@Param("app") String app, @Param("stream") String stream, @Param("startTimeStamp")Long startTimeStamp, @Param("endTimeStamp")Long endTimeStamp, - @Param("callId")String callId, List<MediaServerItem> mediaServerItemList); + @Param("callId")String callId, List<MediaServer> mediaServerItemList); @Update(" <script>" + "update wvp_cloud_record set collect = #{collect} where file_path in " + 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 index 4678591..d34657f 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/dao/MediaServerMapper.java @@ -1,6 +1,6 @@ package com.genersoft.iot.vmp.storager.dao; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import org.apache.ibatis.annotations.*; import org.apache.ibatis.annotations.Param; import org.springframework.stereotype.Repository; @@ -24,6 +24,10 @@ "rtmp_ssl_port,"+ "rtp_proxy_port,"+ "rtsp_port,"+ + "flv_port," + + "flv_ssl_port," + + "ws_flv_port," + + "ws_flv_ssl_port," + "rtsp_ssl_port,"+ "auto_config,"+ "secret,"+ @@ -34,6 +38,7 @@ "record_day,"+ "record_path,"+ "default_server,"+ + "type,"+ "create_time,"+ "update_time,"+ "hook_alive_interval"+ @@ -50,6 +55,10 @@ "#{rtmpSSlPort}, " + "#{rtpProxyPort}, " + "#{rtspPort}, " + + "#{flvPort}, " + + "#{flvSSLPort}, " + + "#{wsFlvPort}, " + + "#{wsFlvSSLPort}, " + "#{rtspSSLPort}, " + "#{autoConfig}, " + "#{secret}, " + @@ -60,10 +69,11 @@ "#{recordDay}, " + "#{recordPath}, " + "#{defaultServer}, " + + "#{type}, " + "#{createTime}, " + "#{updateTime}, " + "#{hookAliveInterval})") - int add(MediaServerItem mediaServerItem); + int add(MediaServer mediaServerItem); @Update(value = {" <script>" + "UPDATE wvp_media_server " + @@ -79,6 +89,10 @@ "<if test=\"rtpProxyPort != null\">, rtp_proxy_port=#{rtpProxyPort}</if>" + "<if test=\"rtspPort != null\">, rtsp_port=#{rtspPort}</if>" + "<if test=\"rtspSSLPort != null\">, rtsp_ssl_port=#{rtspSSLPort}</if>" + + "<if test=\"flvPort != null\">, flv_port=#{flvPort}</if>" + + "<if test=\"flvSSLPort != null\">, flv_ssl_port=#{flvSSLPort}</if>" + + "<if test=\"wsFlvPort != null\">, ws_flv_port=#{wsFlvPort}</if>" + + "<if test=\"wsFlvSSLPort != null\">, ws_flv_ssl_port=#{wsFlvSSLPort}</if>" + "<if test=\"autoConfig != null\">, auto_config=#{autoConfig}</if>" + "<if test=\"rtpEnable != null\">, rtp_enable=#{rtpEnable}</if>" + "<if test=\"rtpPortRange != null\">, rtp_port_range=#{rtpPortRange}</if>" + @@ -88,9 +102,10 @@ "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" + "<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" + "<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" + + "<if test=\"type != null\">, type=#{type}</if>" + "WHERE id=#{id}"+ " </script>"}) - int update(MediaServerItem mediaServerItem); + int update(MediaServer mediaServerItem); @Update(value = {" <script>" + "UPDATE wvp_media_server " + @@ -105,6 +120,10 @@ "<if test=\"rtpProxyPort != null\">, rtp_proxy_port=#{rtpProxyPort}</if>" + "<if test=\"rtspPort != null\">, rtsp_port=#{rtspPort}</if>" + "<if test=\"rtspSSLPort != null\">, rtsp_ssl_port=#{rtspSSLPort}</if>" + + "<if test=\"flvPort != null\">, flv_port=#{flvPort}</if>" + + "<if test=\"flvSSLPort != null\">, flv_ssl_port=#{flvSSLPort}</if>" + + "<if test=\"wsFlvPort != null\">, ws_flv_port=#{wsFlvPort}</if>" + + "<if test=\"wsFlvSSLPort != null\">, ws_flv_ssl_port=#{wsFlvSSLPort}</if>" + "<if test=\"autoConfig != null\">, auto_config=#{autoConfig}</if>" + "<if test=\"rtpEnable != null\">, rtp_enable=#{rtpEnable}</if>" + "<if test=\"rtpPortRange != null\">, rtp_port_range=#{rtpPortRange}</if>" + @@ -113,16 +132,17 @@ "<if test=\"recordAssistPort != null\">, record_assist_port=#{recordAssistPort}</if>" + "<if test=\"recordDay != null\">, record_day=#{recordDay}</if>" + "<if test=\"recordPath != null\">, record_path=#{recordPath}</if>" + + "<if test=\"type != null\">, type=#{type}</if>" + "<if test=\"hookAliveInterval != null\">, hook_alive_interval=#{hookAliveInterval}</if>" + "WHERE ip=#{ip} and http_port=#{httpPort}"+ " </script>"}) - int updateByHostAndPort(MediaServerItem mediaServerItem); + int updateByHostAndPort(MediaServer mediaServerItem); @Select("SELECT * FROM wvp_media_server WHERE id=#{id}") - MediaServerItem queryOne(String id); + MediaServer queryOne(String id); @Select("SELECT * FROM wvp_media_server") - List<MediaServerItem> queryAll(); + List<MediaServer> queryAll(); @Delete("DELETE FROM wvp_media_server WHERE id=#{id}") void delOne(String id); @@ -134,12 +154,12 @@ int delDefault(); @Select("SELECT * FROM wvp_media_server WHERE ip=#{host} and http_port=#{port}") - MediaServerItem queryOneByHostAndPort(@Param("host") String host, @Param("port") int port); + MediaServer queryOneByHostAndPort(@Param("host") String host, @Param("port") int port); @Select("SELECT * FROM wvp_media_server WHERE default_server=true") - MediaServerItem queryDefault(); + MediaServer queryDefault(); @Select("SELECT * FROM wvp_media_server WHERE record_assist_port > 0") - List<MediaServerItem> queryAllWithAssistPort(); + List<MediaServer> queryAllWithAssistPort(); } 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 1eac4df..b17b4d7 100755 --- a/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/storager/impl/RedisCatchStorageImpl.java @@ -9,8 +9,10 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.ParentPlatformCatch; import com.genersoft.iot.vmp.gb28181.bean.SendRtpItem; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.event.media.MediaArrivalEvent; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; +import com.genersoft.iot.vmp.media.zlm.dto.StreamPushItem; import com.genersoft.iot.vmp.media.zlm.dto.hook.OnStreamChangedHookParam; import com.genersoft.iot.vmp.service.bean.GPSMsgInfo; import com.genersoft.iot.vmp.service.bean.MessageForPushChannel; @@ -313,7 +315,7 @@ } @Override - public void addStream(MediaServerItem mediaServerItem, String type, String app, String streamId, OnStreamChangedHookParam onStreamChangedHookParam) { + public void addStream(MediaServer mediaServerItem, String type, String app, String streamId, OnStreamChangedHookParam onStreamChangedHookParam) { // 鏌ユ壘鏄惁浣跨敤浜哻allID StreamAuthorityInfo streamAuthorityInfo = getStreamAuthorityInfo(app, streamId); String key = VideoManagerConstants.WVP_SERVER_STREAM_PREFIX + userSetting.getServerId() + "_" + type + "_" + app + "_" + streamId + "_" + mediaServerItem.getId(); @@ -651,21 +653,22 @@ } @Override - public void addPushListItem(String app, String stream, OnStreamChangedHookParam param) { + public void addPushListItem(String app, String stream, MediaArrivalEvent event) { String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream; - redisTemplate.opsForValue().set(key, param); + StreamPushItem streamPushItem = StreamPushItem.getInstance(event, userSetting.getServerId()); + redisTemplate.opsForValue().set(key, streamPushItem); } @Override - public OnStreamChangedHookParam getPushListItem(String app, String stream) { + public StreamPushItem getPushListItem(String app, String stream) { String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream; - return (OnStreamChangedHookParam)redisTemplate.opsForValue().get(key); + return (StreamPushItem)redisTemplate.opsForValue().get(key); } @Override public void removePushListItem(String app, String stream, String mediaServerId) { String key = VideoManagerConstants.PUSH_STREAM_LIST + app + "_" + stream; - OnStreamChangedHookParam param = (OnStreamChangedHookParam)redisTemplate.opsForValue().get(key); + StreamPushItem param = (StreamPushItem)redisTemplate.opsForValue().get(key); if (param != null && param.getMediaServerId().equalsIgnoreCase(mediaServerId)) { redisTemplate.delete(key); } diff --git a/src/main/java/com/genersoft/iot/vmp/utils/CloudRecordUtils.java b/src/main/java/com/genersoft/iot/vmp/utils/CloudRecordUtils.java index 8954bd7..10cb620 100644 --- a/src/main/java/com/genersoft/iot/vmp/utils/CloudRecordUtils.java +++ b/src/main/java/com/genersoft/iot/vmp/utils/CloudRecordUtils.java @@ -1,11 +1,11 @@ package com.genersoft.iot.vmp.utils; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.bean.DownloadFileInfo; public class CloudRecordUtils { - public static DownloadFileInfo getDownloadFilePath(MediaServerItem mediaServerItem, String filePath) { + public static DownloadFileInfo getDownloadFilePath(MediaServer mediaServerItem, String filePath) { DownloadFileInfo downloadFileInfo = new DownloadFileInfo(); String pathTemplate = "%s://%s:%s/index/api/downloadFile?file_path=" + filePath; diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java index 4974209..193c95d 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/bean/StreamContent.java @@ -1,6 +1,7 @@ package com.genersoft.iot.vmp.vmanager.bean; import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.media.bean.MediaInfo; import com.genersoft.iot.vmp.service.bean.DownloadFileInfo; import io.swagger.v3.oas.annotations.media.Schema; @@ -86,7 +87,7 @@ private String mediaServerId; @Schema(description = "娴佺紪鐮佷俊鎭�") - private Object tracks; + private MediaInfo mediaInfo; @Schema(description = "寮�濮嬫椂闂�") private String startTime; @@ -170,7 +171,7 @@ } this.mediaServerId = streamInfo.getMediaServerId(); - this.tracks = streamInfo.getTracks(); + this.mediaInfo = streamInfo.getMediaInfo(); this.startTime = streamInfo.getStartTime(); this.endTime = streamInfo.getEndTime(); this.progress = streamInfo.getProgress(); @@ -388,12 +389,12 @@ this.mediaServerId = mediaServerId; } - public Object getTracks() { - return tracks; + public MediaInfo getMediaInfo() { + return mediaInfo; } - public void setTracks(Object tracks) { - this.tracks = tracks; + public void setMediaInfo(MediaInfo mediaInfo) { + this.mediaInfo = mediaInfo; } public String getStartTime() { diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java index b37a3d9..da8bbc8 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/cloudRecord/CloudRecordController.java @@ -3,9 +3,9 @@ import com.alibaba.fastjson2.JSONArray; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.security.JwtUtils; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.ICloudRecordService; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.bean.CloudRecordItem; import com.genersoft.iot.vmp.service.bean.DownloadFileInfo; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; @@ -67,16 +67,16 @@ if (ObjectUtils.isEmpty(month)) { month = calendar.get(Calendar.MONTH) + 1; } - List<MediaServerItem> mediaServerItems; + List<MediaServer> mediaServerItems; if (!ObjectUtils.isEmpty(mediaServerId)) { mediaServerItems = new ArrayList<>(); - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒版祦濯掍綋: " + mediaServerId); } mediaServerItems.add(mediaServerItem); } else { - mediaServerItems = mediaServerService.getAll(); + mediaServerItems = mediaServerService.getAllOnlineList(); } if (mediaServerItems.isEmpty()) { return new ArrayList<>(); @@ -110,16 +110,16 @@ logger.info("[浜戠褰曞儚] 鏌ヨ app->{}, stream->{}, mediaServerId->{}, page->{}, count->{}, startTime->{}, endTime->{}", app, stream, mediaServerId, page, count, startTime, endTime); - List<MediaServerItem> mediaServerItems; + List<MediaServer> mediaServerItems; if (!ObjectUtils.isEmpty(mediaServerId)) { mediaServerItems = new ArrayList<>(); - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒版祦濯掍綋: " + mediaServerId); } mediaServerItems.add(mediaServerItem); } else { - mediaServerItems = mediaServerService.getAll(); + mediaServerItems = mediaServerService.getAllOnlineList(); } if (mediaServerItems.isEmpty()) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "褰撳墠鏃犳祦濯掍綋"); @@ -162,7 +162,7 @@ @RequestParam(required = false) String callId, @RequestParam(required = false) String remoteHost ){ - MediaServerItem mediaServerItem; + MediaServer mediaServerItem; if (mediaServerId == null) { mediaServerItem = mediaServerService.getDefaultMediaServer(); }else { 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 56d192e..26e9685 100755 --- 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 @@ -5,6 +5,7 @@ import com.genersoft.iot.vmp.conf.security.JwtUtils; import com.genersoft.iot.vmp.conf.security.SecurityUtils; import com.genersoft.iot.vmp.conf.security.dto.LoginUser; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.media.zlm.dto.StreamAuthorityInfo; import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IStreamProxyService; @@ -36,9 +37,10 @@ private IRedisCatchStorage redisCatchStorage; @Autowired - private IMediaService mediaService; - @Autowired private IStreamProxyService streamProxyService; + + @Autowired + private IMediaServerService mediaServerService; /** @@ -85,9 +87,9 @@ String host = request.getHeader("Host"); String localAddr = host.split(":")[0]; logger.info("浣跨敤{}浣滀负杩斿洖娴佺殑ip", localAddr); - streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, localAddr, authority); + streamInfo = mediaServerService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, localAddr, authority); }else { - streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); + streamInfo = mediaServerService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); } if (streamInfo != null){ @@ -105,9 +107,9 @@ String host = request.getHeader("Host"); String localAddr = host.split(":")[0]; logger.info("浣跨敤{}浣滀负杩斿洖娴佺殑ip", localAddr); - streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, localAddr, authority); + streamInfo = mediaServerService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, localAddr, authority); }else { - streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); + streamInfo = mediaServerService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); } if (streamInfo != null){ return new StreamContent(streamInfo); 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 97a5baa..1ed3197 100755 --- 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 @@ -2,7 +2,6 @@ import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.common.InviteInfo; import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.common.StreamInfo; import com.genersoft.iot.vmp.conf.UserSetting; @@ -14,14 +13,11 @@ import com.genersoft.iot.vmp.gb28181.transmit.callback.DeferredResultHolder; import com.genersoft.iot.vmp.gb28181.transmit.callback.RequestMessage; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.media.zlm.ZLMRESTfulUtils; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IInviteStreamService; -import com.genersoft.iot.vmp.service.IMediaServerService; -import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IPlayService; import com.genersoft.iot.vmp.service.bean.InviteErrorCode; -import com.genersoft.iot.vmp.storager.IRedisCatchStorage; import com.genersoft.iot.vmp.storager.IVideoManagerStorage; import com.genersoft.iot.vmp.utils.DateUtil; import com.genersoft.iot.vmp.vmanager.bean.AudioBroadcastResult; @@ -66,22 +62,13 @@ private IVideoManagerStorage storager; @Autowired - private IRedisCatchStorage redisCatchStorage; - - @Autowired private IInviteStreamService inviteStreamService; - - @Autowired - private ZLMRESTfulUtils zlmresTfulUtils; @Autowired private DeferredResultHolder resultHolder; @Autowired private IPlayService playService; - - @Autowired - private IMediaService mediaService; @Autowired private IMediaServerService mediaServerService; @@ -99,7 +86,7 @@ logger.info("[寮�濮嬬偣鎾璢 deviceId锛歿}, channelId锛歿}, ", deviceId, channelId); // 鑾峰彇鍙敤鐨剒lm Device device = storager.queryVideoDevice(deviceId); - MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); + MediaServer newMediaServerItem = playService.getNewMediaServerItem(device); RequestMessage requestMessage = new RequestMessage(); String key = DeferredResultHolder.CALLBACK_CMD_PLAY + deviceId + channelId; @@ -181,50 +168,6 @@ json.put("channelId", channelId); return json; } - - /** - * 灏嗕笉鏄痟264鐨勮棰戦�氳繃ffmpeg 杞爜涓篽264 + aac - * @param streamId 娴両D - */ - @Operation(summary = "灏嗕笉鏄痟264鐨勮棰戦�氳繃ffmpeg 杞爜涓篽264 + aac", security = @SecurityRequirement(name = JwtUtils.HEADER)) - @Parameter(name = "streamId", description = "瑙嗛娴両D", required = true) - @PostMapping("/convert/{streamId}") - public JSONObject playConvert(@PathVariable String streamId) { -// StreamInfo streamInfo = redisCatchStorage.queryPlayByStreamId(streamId); - - InviteInfo inviteInfo = inviteStreamService.getInviteInfoByStream(null, streamId); - if (inviteInfo == null || inviteInfo.getStreamInfo() == null) { - logger.warn("瑙嗛杞爜API璋冪敤澶辫触锛�, 瑙嗛娴佸凡缁忓仠姝�!"); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒拌棰戞祦淇℃伅, 瑙嗛娴佸彲鑳藉凡缁忓仠姝�"); - } - MediaServerItem mediaInfo = mediaServerService.getOne(inviteInfo.getStreamInfo().getMediaServerId()); - JSONObject rtpInfo = zlmresTfulUtils.getRtpInfo(mediaInfo, streamId); - if (!rtpInfo.getBoolean("exist")) { - logger.warn("瑙嗛杞爜API璋冪敤澶辫触锛�, 瑙嗛娴佸凡鍋滄鎺ㄦ祦!"); - throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒拌棰戞祦淇℃伅, 瑙嗛娴佸彲鑳藉凡鍋滄鎺ㄦ祦"); - } else { - 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(mediaInfo, srcUrl, dstUrl, "1000000", true, false, null); - logger.info(jsonObject.toJSONString()); - if (jsonObject != null && jsonObject.getInteger("code") == 0) { - JSONObject data = jsonObject.getJSONObject("data"); - if (data != null) { - JSONObject result = new JSONObject(); - result.put("key", data.getString("key")); - StreamInfo streamInfoResult = mediaService.getStreamInfoByAppAndStreamWithCheck("convert", streamId, mediaInfo.getId(), false); - result.put("StreamInfo", streamInfoResult); - return result; - }else { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "杞爜澶辫触"); - } - }else { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "杞爜澶辫触"); - } - } - } - /** * 缁撴潫杞爜 */ @@ -236,18 +179,12 @@ if (mediaServerId == null) { throw new ControllerException(ErrorCode.ERROR400.getCode(), "娴佸獟浣擄細" + mediaServerId + "涓嶅瓨鍦�" ); } - MediaServerItem mediaInfo = mediaServerService.getOne(mediaServerId); + MediaServer mediaInfo = mediaServerService.getOne(mediaServerId); if (mediaInfo == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "浣跨敤鐨勬祦濯掍綋宸茬粡鍋滄杩愯" ); }else { - JSONObject jsonObject = zlmresTfulUtils.delFFmpegSource(mediaInfo, key); - logger.info(jsonObject.toJSONString()); - if (jsonObject != null && jsonObject.getInteger("code") == 0) { - JSONObject data = jsonObject.getJSONObject("data"); - if (data == null || data.getBoolean("flag") == null || !data.getBoolean("flag")) { - throw new ControllerException(ErrorCode.ERROR100 ); - } - }else { + Boolean deleted = mediaServerService.delFFmpegSource(mediaInfo, key); + if (!deleted) { throw new ControllerException(ErrorCode.ERROR100 ); } } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java index dbbc7b0..6401a8c 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/ps/PsController.java @@ -6,15 +6,13 @@ import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.security.JwtUtils; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookType; import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRtpServerTimeoutHookParam; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.OtherPsSendInfo; @@ -50,7 +48,7 @@ private ZLMServerFactory zlmServerFactory; @Autowired - private ZlmHttpHookSubscribe hookSubscribe; + private HookSubscribe hookSubscribe; @Autowired private IMediaServerService mediaServerService; @@ -83,7 +81,7 @@ logger.info("[绗笁鏂筆S鏈嶅姟瀵规帴->寮�鍚敹娴佸拰鑾峰彇鍙戞祦淇℃伅] isSend->{}, ssrc->{}, callId->{}, stream->{}, tcpMode->{}, callBack->{}", isSend, ssrc, callId, stream, tcpMode==0?"UDP":"TCP琚姩", callBack); - MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); + MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer(); if (mediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(),"娌℃湁鍙敤鐨凪ediaServer"); } @@ -108,12 +106,11 @@ } // 娉ㄥ唽鍥炶皟濡傛灉rtp鏀舵祦瓒呮椂鍒欓�氳繃鍥炶皟鍙戦�侀�氱煡 if (callBack != null) { - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(stream, String.valueOf(ssrcInt), mediaServerItem.getId()); + Hook hook = Hook.getInstance(HookType.on_rtp_server_timeout, "rtp", stream, mediaServerItem.getId()); // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁� - hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, - (mediaServerItemInUse, hookParam)->{ - OnRtpServerTimeoutHookParam serverTimeoutHookParam = (OnRtpServerTimeoutHookParam) hookParam; - if (stream.equals(serverTimeoutHookParam.getStream_id())) { + hookSubscribe.addSubscribe(hook, + (hookData)->{ + if (stream.equals(hookData.getStream())) { logger.info("[绗笁鏂筆S鏈嶅姟瀵规帴->寮�鍚敹娴佸拰鑾峰彇鍙戞祦淇℃伅] 绛夊緟鏀舵祦瓒呮椂 callId->{}, 鍙戦�佸洖璋�", callId); // 灏嗕俊鎭啓鍏edis涓紝浠ュ鍚庣敤 redisTemplate.delete(receiveKey); @@ -126,7 +123,7 @@ } catch (IOException e) { logger.error("[绗笁鏂筆S鏈嶅姟瀵规帴->寮�鍚敹娴佸拰鑾峰彇鍙戞祦淇℃伅] 绛夊緟鏀舵祦瓒呮椂 callId->{}, 鍙戦�佸洖璋冨け璐�", callId, e); } - hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout); + hookSubscribe.removeSubscribe(hook); } }); } @@ -158,7 +155,7 @@ @Parameter(name = "stream", description = "娴佺殑ID", required = true) public void closeRtpServer(String stream) { logger.info("[绗笁鏂筆S鏈嶅姟瀵规帴->鍏抽棴鏀舵祦] stream->{}", stream); - MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); + MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer(); zlmServerFactory.closeRtpServer(mediaServerItem,stream); String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_PS_INFO + userSetting.getServerId() + "_*_" + stream; List<Object> scan = RedisUtil.scan(redisTemplate, receiveKey); @@ -201,7 +198,7 @@ app, stream, callId); - MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); + MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer(); String key = VideoManagerConstants.WVP_OTHER_SEND_PS_INFO + userSetting.getServerId() + "_" + callId; OtherPsSendInfo sendInfo = (OtherPsSendInfo)redisTemplate.opsForValue().get(key); if (sendInfo == null) { @@ -227,7 +224,7 @@ param.put("src_port", sendInfo.getSendLocalPort()); - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream); + Boolean streamReady = mediaServerService.isStreamReady(mediaServerItem, app, stream); if (streamReady) { JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, param); if (jsonObject.getInteger("code") == 0) { @@ -241,18 +238,18 @@ }else { logger.info("[绗笁鏂筆S鏈嶅姟瀵规帴->鍙戦�佹祦] 娴佷笉瀛樺湪锛岀瓑寰呮祦涓婄嚎锛宑allId->{}", callId); String uuid = UUID.randomUUID().toString(); - HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed(app, stream, true, "rtsp", mediaServerItem.getId()); + Hook hook = Hook.getInstance(HookType.on_media_arrival, app, stream, mediaServerItem.getId()); dynamicTask.startDelay(uuid, ()->{ logger.info("[绗笁鏂筆S鏈嶅姟瀵规帴->鍙戦�佹祦] 绛夊緟娴佷笂绾胯秴鏃� callId->{}", callId); redisTemplate.delete(key); - hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); + hookSubscribe.removeSubscribe(hook); }, 10000); // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁� OtherPsSendInfo finalSendInfo = sendInfo; - hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); - hookSubscribe.addSubscribe(hookSubscribeForStreamChange, - (mediaServerItemInUse, response)->{ + hookSubscribe.removeSubscribe(hook); + hookSubscribe.addSubscribe(hook, + (hookData)->{ dynamicTask.stop(uuid); logger.info("[绗笁鏂筆S鏈嶅姟瀵规帴->鍙戦�佹祦] 娴佷笂绾匡紝寮�濮嬪彂娴� callId->{}", callId); try { @@ -269,7 +266,7 @@ logger.info("[绗笁鏂筆S鏈嶅姟瀵规帴->鍙戦�佹祦] 瑙嗛娴佸彂娴佸け璐ワ紝callId->{}, {}", callId, jsonObject.getString("msg")); throw new ControllerException(ErrorCode.ERROR100.getCode(), "[瑙嗛娴佸彂娴佸け璐 " + jsonObject.getString("msg")); } - hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); + hookSubscribe.removeSubscribe(hook); }); } } @@ -290,7 +287,7 @@ param.put("app",sendInfo.getPushApp()); param.put("stream",sendInfo.getPushStream()); param.put("ssrc",sendInfo.getPushSSRC()); - MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); + MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer(); Boolean result = zlmServerFactory.stopSendRtpStream(mediaServerItem, param); if (!result) { logger.info("[绗笁鏂筆S鏈嶅姟瀵规帴->鍏抽棴鍙戦�佹祦] 澶辫触 callId->{}", callId); @@ -305,7 +302,7 @@ @GetMapping(value = "/getTestPort") @ResponseBody public int getTestPort() { - MediaServerItem defaultMediaServer = mediaServerService.getDefaultMediaServer(); + MediaServer defaultMediaServer = mediaServerService.getDefaultMediaServer(); // for (int i = 0; i <300; i++) { // new Thread(() -> { diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java index 5bd4b9d..f42d153 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java @@ -6,15 +6,13 @@ import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.security.JwtUtils; +import com.genersoft.iot.vmp.media.event.hook.Hook; +import com.genersoft.iot.vmp.media.event.hook.HookType; import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; import com.genersoft.iot.vmp.media.zlm.ZLMServerFactory; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeFactory; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForRtpServerTimeout; -import com.genersoft.iot.vmp.media.zlm.dto.HookSubscribeForStreamChange; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; -import com.genersoft.iot.vmp.media.zlm.dto.hook.OnRtpServerTimeoutHookParam; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.event.hook.HookSubscribe; +import com.genersoft.iot.vmp.media.bean.MediaServer; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.utils.redis.RedisUtil; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.OtherRtpSendInfo; @@ -54,7 +52,7 @@ private final static Logger logger = LoggerFactory.getLogger(RtpController.class); @Autowired - private ZlmHttpHookSubscribe hookSubscribe; + private HookSubscribe hookSubscribe; @Autowired private IMediaServerService mediaServerService; @@ -83,7 +81,7 @@ logger.info("[绗笁鏂规湇鍔″鎺�->寮�鍚敹娴佸拰鑾峰彇鍙戞祦淇℃伅] isSend->{}, ssrc->{}, callId->{}, stream->{}, tcpMode->{}, callBack->{}", isSend, ssrc, callId, stream, tcpMode==0?"UDP":"TCP琚姩", callBack); - MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); + MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer(); if (mediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(),"娌℃湁鍙敤鐨凪ediaServer"); } @@ -109,12 +107,11 @@ } // 娉ㄥ唽鍥炶皟濡傛灉rtp鏀舵祦瓒呮椂鍒欓�氳繃鍥炶皟鍙戦�侀�氱煡 if (callBack != null) { - HookSubscribeForRtpServerTimeout hookSubscribeForRtpServerTimeout = HookSubscribeFactory.on_rtp_server_timeout(stream, String.valueOf(ssrcInt), mediaServerItem.getId()); + Hook hook = Hook.getInstance(HookType.on_rtp_server_timeout, "rtp", stream, mediaServerItem.getId()); // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁� - hookSubscribe.addSubscribe(hookSubscribeForRtpServerTimeout, - (mediaServerItemInUse, hookParam)->{ - OnRtpServerTimeoutHookParam serverTimeoutHookParam = (OnRtpServerTimeoutHookParam) hookParam; - if (stream.equals(serverTimeoutHookParam.getStream_id())) { + hookSubscribe.addSubscribe(hook, + (hookData)->{ + if (stream.equals(hookData.getStream())) { logger.info("[寮�鍚敹娴佸拰鑾峰彇鍙戞祦淇℃伅] 绛夊緟鏀舵祦瓒呮椂 callId->{}, 鍙戦�佸洖璋�", callId); OkHttpClient.Builder httpClientBuilder = new OkHttpClient.Builder(); OkHttpClient client = httpClientBuilder.build(); @@ -125,7 +122,7 @@ } catch (IOException e) { logger.error("[绗笁鏂规湇鍔″鎺�->寮�鍚敹娴佸拰鑾峰彇鍙戞祦淇℃伅] 绛夊緟鏀舵祦瓒呮椂 callId->{}, 鍙戦�佸洖璋冨け璐�", callId, e); } - hookSubscribe.removeSubscribe(hookSubscribeForRtpServerTimeout); + hookSubscribe.removeSubscribe(hook); } }); } @@ -162,7 +159,7 @@ @Parameter(name = "stream", description = "娴佺殑ID", required = true) public void closeRtpServer(String stream) { logger.info("[绗笁鏂规湇鍔″鎺�->鍏抽棴鏀舵祦] stream->{}", stream); - MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); + MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer(); zlmServerFactory.closeRtpServer(mediaServerItem,stream); zlmServerFactory.closeRtpServer(mediaServerItem,stream + "_a"); String receiveKey = VideoManagerConstants.WVP_OTHER_RECEIVE_RTP_INFO + userSetting.getServerId() + "_*_" + stream; @@ -225,7 +222,7 @@ if (!((dstPortForAudio > 0 && !ObjectUtils.isEmpty(dstPortForAudio) || (dstPortForVideo > 0 && !ObjectUtils.isEmpty(dstIpForVideo))))) { throw new ControllerException(ErrorCode.ERROR400.getCode(), "鑷冲皯搴旇瀛樺湪涓�缁勯煶棰戞垨瑙嗛鍙戦�佸弬鏁�"); } - MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); + MediaServer mediaServer = mediaServerService.getDefaultMediaServer(); String key = VideoManagerConstants.WVP_OTHER_SEND_RTP_INFO + userSetting.getServerId() + "_" + callId; OtherRtpSendInfo sendInfo = (OtherRtpSendInfo)redisTemplate.opsForValue().get(key); if (sendInfo == null) { @@ -278,10 +275,10 @@ paramForVideo = null; } - Boolean streamReady = zlmServerFactory.isStreamReady(mediaServerItem, app, stream); + Boolean streamReady = mediaServerService.isStreamReady(mediaServer, app, stream); if (streamReady) { if (paramForVideo != null) { - JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, paramForVideo); + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServer, paramForVideo); if (jsonObject.getInteger("code") == 0) { logger.info("[绗笁鏂规湇鍔″鎺�->鍙戦�佹祦] 瑙嗛娴佸彂娴佹垚鍔燂紝callId->{}锛宲aram->{}", callId, paramForVideo); redisTemplate.opsForValue().set(key, sendInfo); @@ -292,7 +289,7 @@ } } if(paramForAudio != null) { - JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, paramForAudio); + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServer, paramForAudio); if (jsonObject.getInteger("code") == 0) { logger.info("[绗笁鏂规湇鍔″鎺�->鍙戦�佹祦] 闊抽娴佸彂娴佹垚鍔燂紝callId->{}锛宲aram->{}", callId, paramForAudio); redisTemplate.opsForValue().set(key, sendInfo); @@ -305,18 +302,18 @@ }else { logger.info("[绗笁鏂规湇鍔″鎺�->鍙戦�佹祦] 娴佷笉瀛樺湪锛岀瓑寰呮祦涓婄嚎锛宑allId->{}", callId); String uuid = UUID.randomUUID().toString(); - HookSubscribeForStreamChange hookSubscribeForStreamChange = HookSubscribeFactory.on_stream_changed(app, stream, true, "rtsp", mediaServerItem.getId()); + Hook hook = Hook.getInstance(HookType.on_media_arrival, app, stream, mediaServer.getId()); dynamicTask.startDelay(uuid, ()->{ logger.info("[绗笁鏂规湇鍔″鎺�->鍙戦�佹祦] 绛夊緟娴佷笂绾胯秴鏃� callId->{}", callId); redisTemplate.delete(key); - hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); + hookSubscribe.removeSubscribe(hook); }, 10000); // 璁㈤槄 zlm鍚姩浜嬩欢, 鏂扮殑zlm涔熶細浠庤繖閲岃繘鍏ョ郴缁� OtherRtpSendInfo finalSendInfo = sendInfo; - hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); - hookSubscribe.addSubscribe(hookSubscribeForStreamChange, - (mediaServerItemInUse, response)->{ + hookSubscribe.removeSubscribe(hook); + hookSubscribe.addSubscribe(hook, + (hookData)->{ dynamicTask.stop(uuid); logger.info("[绗笁鏂规湇鍔″鎺�->鍙戦�佹祦] 娴佷笂绾匡紝寮�濮嬪彂娴� callId->{}", callId); try { @@ -325,7 +322,7 @@ throw new RuntimeException(e); } if (paramForVideo != null) { - JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, paramForVideo); + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServer, paramForVideo); if (jsonObject.getInteger("code") == 0) { logger.info("[绗笁鏂规湇鍔″鎺�->鍙戦�佹祦] 瑙嗛娴佸彂娴佹垚鍔燂紝callId->{}锛宲aram->{}", callId, paramForVideo); redisTemplate.opsForValue().set(key, finalSendInfo); @@ -336,7 +333,7 @@ } } if(paramForAudio != null) { - JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServerItem, paramForAudio); + JSONObject jsonObject = zlmServerFactory.startSendRtpStream(mediaServer, paramForAudio); if (jsonObject.getInteger("code") == 0) { logger.info("[绗笁鏂规湇鍔″鎺�->鍙戦�佹祦] 闊抽娴佸彂娴佹垚鍔燂紝callId->{}锛宲aram->{}", callId, paramForAudio); redisTemplate.opsForValue().set(key, finalSendInfo); @@ -346,7 +343,7 @@ throw new ControllerException(ErrorCode.ERROR100.getCode(), "[闊抽娴佸彂娴佸け璐 " + jsonObject.getString("msg")); } } - hookSubscribe.removeSubscribe(hookSubscribeForStreamChange); + hookSubscribe.removeSubscribe(hook); }); } } @@ -367,7 +364,7 @@ param.put("app",sendInfo.getPushApp()); param.put("stream",sendInfo.getPushStream()); param.put("ssrc",sendInfo.getPushSSRC()); - MediaServerItem mediaServerItem = mediaServerService.getDefaultMediaServer(); + MediaServer mediaServerItem = mediaServerService.getDefaultMediaServer(); Boolean result = zlmServerFactory.stopSendRtpStream(mediaServerItem, param); if (!result) { logger.info("[绗笁鏂规湇鍔″鎺�->鍏抽棴鍙戦�佹祦] 澶辫触 callId->{}", callId); 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 d1c72fc..a7d6041 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java @@ -9,10 +9,8 @@ import com.genersoft.iot.vmp.conf.VersionInfo; import com.genersoft.iot.vmp.conf.exception.ControllerException; import com.genersoft.iot.vmp.conf.security.JwtUtils; -import com.genersoft.iot.vmp.media.zlm.SendRtpPortManager; -import com.genersoft.iot.vmp.media.zlm.ZlmHttpHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.IHookSubscribe; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.service.IMediaServerService; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.*; import com.genersoft.iot.vmp.service.bean.MediaServerLoad; import com.genersoft.iot.vmp.storager.IRedisCatchStorage; @@ -39,8 +37,6 @@ @RequestMapping("/api/server") public class ServerController { - @Autowired - private ZlmHttpHookSubscribe zlmHttpHookSubscribe; @Autowired private IMediaServerService mediaServerService; @@ -75,21 +71,19 @@ @Autowired private IRedisCatchStorage redisCatchStorage; - @Autowired - private SendRtpPortManager sendRtpPortManager; @GetMapping(value = "/media_server/list") @ResponseBody @Operation(summary = "娴佸獟浣撴湇鍔″垪琛�", security = @SecurityRequirement(name = JwtUtils.HEADER)) - public List<MediaServerItem> getMediaServerList() { + public List<MediaServer> getMediaServerList() { return mediaServerService.getAll(); } @GetMapping(value = "/media_server/online/list") @ResponseBody @Operation(summary = "鍦ㄧ嚎娴佸獟浣撴湇鍔″垪琛�", security = @SecurityRequirement(name = JwtUtils.HEADER)) - public List<MediaServerItem> getOnlineMediaServerList() { + public List<MediaServer> getOnlineMediaServerList() { return mediaServerService.getAllOnline(); } @@ -97,7 +91,7 @@ @ResponseBody @Operation(summary = "鍋滄瑙嗛鍥炴斁", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "id", description = "娴佸獟浣撴湇鍔D", required = true) - public MediaServerItem getMediaServer(@PathVariable String id) { + public MediaServer getMediaServer(@PathVariable String id) { return mediaServerService.getOne(id); } @@ -107,8 +101,8 @@ @Parameter(name = "secret", description = "娴佸獟浣撴湇鍔ecret", required = true) @GetMapping(value = "/media_server/check") @ResponseBody - public MediaServerItem checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret) { - return mediaServerService.checkMediaServer(ip, port, secret); + public MediaServer checkMediaServer(@RequestParam String ip, @RequestParam int port, @RequestParam String secret, @RequestParam String type) { + return mediaServerService.checkMediaServer(ip, port, secret, type); } @Operation(summary = "娴嬭瘯娴佸獟浣撳綍鍍忕鐞嗘湇鍔�", security = @SecurityRequirement(name = JwtUtils.HEADER)) @@ -127,8 +121,8 @@ @Parameter(name = "mediaServerItem", description = "娴佸獟浣撲俊鎭�", required = true) @PostMapping(value = "/media_server/save") @ResponseBody - public void saveMediaServer(@RequestBody MediaServerItem mediaServerItem) { - MediaServerItem mediaServerItemInDatabase = mediaServerService.getOne(mediaServerItem.getId()); + public void saveMediaServer(@RequestBody MediaServer mediaServerItem) { + MediaServer mediaServerItemInDatabase = mediaServerService.getOneFromDatabase(mediaServerItem.getId()); if (mediaServerItemInDatabase != null) { mediaServerService.update(mediaServerItem); @@ -142,11 +136,7 @@ @DeleteMapping(value = "/media_server/delete") @ResponseBody public void deleteMediaServer(@RequestParam String id) { - if (mediaServerService.getOne(id) == null) { - throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏈壘鍒版鑺傜偣"); - } mediaServerService.delete(id); - mediaServerService.deleteDb(id); } @@ -220,13 +210,6 @@ return jsonObject; } - @GetMapping(value = "/hooks") - @ResponseBody - @Operation(summary = "鑾峰彇褰撳墠鎵�鏈塰ook") - public List<IHookSubscribe> getHooks() { - return zlmHttpHookSubscribe.getAll(); - } - @GetMapping(value = "/system/info") @ResponseBody @Operation(summary = "鑾峰彇绯荤粺淇℃伅") @@ -241,11 +224,11 @@ @Operation(summary = "鑾峰彇璐熻浇淇℃伅") public List<MediaServerLoad> getMediaLoad() { List<MediaServerLoad> result = new ArrayList<>(); - List<MediaServerItem> allOnline = mediaServerService.getAllOnline(); + List<MediaServer> allOnline = mediaServerService.getAllOnline(); if (allOnline.size() == 0) { return result; }else { - for (MediaServerItem mediaServerItem : allOnline) { + for (MediaServer mediaServerItem : allOnline) { result.add(mediaServerService.getLoad(mediaServerItem)); } } 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 9565000..dd5e703 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/streamProxy/StreamProxyController.java @@ -7,9 +7,9 @@ import com.genersoft.iot.vmp.conf.security.JwtUtils; 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.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.media.zlm.dto.StreamProxyItem; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IStreamProxyService; import com.genersoft.iot.vmp.vmanager.bean.ErrorCode; import com.genersoft.iot.vmp.vmanager.bean.StreamContent; @@ -27,6 +27,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.context.request.async.DeferredResult; +import java.util.Map; import java.util.UUID; @SuppressWarnings("rawtypes") @@ -135,10 +136,10 @@ @ResponseBody @Operation(summary = "鑾峰彇ffmpeg.cmd妯℃澘", security = @SecurityRequirement(name = JwtUtils.HEADER)) @Parameter(name = "mediaServerId", description = "娴佸獟浣揑D", required = true) - public JSONObject getFFmpegCMDs(@RequestParam String mediaServerId){ + public Map<String, String> getFFmpegCMDs(@RequestParam String mediaServerId){ logger.debug("鑾峰彇鑺傜偣[ {} ]ffmpeg.cmd妯℃澘", mediaServerId ); - MediaServerItem mediaServerItem = mediaServerService.getOne(mediaServerId); + MediaServer mediaServerItem = mediaServerService.getOne(mediaServerId); if (mediaServerItem == null) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "娴佸獟浣擄細 " + mediaServerId + "鏈壘鍒�"); } diff --git a/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java b/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java index 8202bf5..309cd69 100755 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/streamPush/StreamPushController.java @@ -13,7 +13,7 @@ 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.dto.StreamPushItem; -import com.genersoft.iot.vmp.service.IMediaServerService; +import com.genersoft.iot.vmp.media.service.IMediaServerService; import com.genersoft.iot.vmp.service.IMediaService; import com.genersoft.iot.vmp.service.IStreamPushService; import com.genersoft.iot.vmp.service.impl.StreamPushUploadFileHandler; @@ -249,7 +249,7 @@ if (push != null && !push.isSelf()) { throw new ControllerException(ErrorCode.ERROR100.getCode(), "鏉ヨ嚜鍏朵粬骞冲彴鐨勬帹娴佷俊鎭�"); } - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); + StreamInfo streamInfo = mediaServerService.getStreamInfoByAppAndStreamWithCheck(app, stream, mediaServerId, authority); if (streamInfo == null){ throw new ControllerException(ErrorCode.ERROR100.getCode(), "鑾峰彇鎾斁鍦板潃澶辫触"); } diff --git a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java index 63d9f31..be740c1 100644 --- a/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java +++ b/src/main/java/com/genersoft/iot/vmp/web/gb28181/ApiStreamController.java @@ -9,7 +9,7 @@ import com.genersoft.iot.vmp.gb28181.bean.Device; import com.genersoft.iot.vmp.gb28181.bean.DeviceChannel; import com.genersoft.iot.vmp.gb28181.transmit.cmd.impl.SIPCommander; -import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; +import com.genersoft.iot.vmp.media.bean.MediaServer; import com.genersoft.iot.vmp.service.IDeviceService; import com.genersoft.iot.vmp.service.IInviteStreamService; import com.genersoft.iot.vmp.service.IPlayService; @@ -114,7 +114,7 @@ result.setResult(resultJSON); return result; } - MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); + MediaServer newMediaServerItem = playService.getNewMediaServerItem(device); playService.play(newMediaServerItem, serial, code, null, (errorCode, msg, data) -> { if (errorCode == InviteErrorCode.SUCCESS.getCode()) { diff --git a/web_src/src/components/MediaServerManger.vue b/web_src/src/components/MediaServerManger.vue index 1d3c057..4d6b6bf 100755 --- a/web_src/src/components/MediaServerManger.vue +++ b/web_src/src/components/MediaServerManger.vue @@ -10,7 +10,8 @@ <el-row :gutter="12"> <el-col :span="num" v-for="item in mediaServerList" :key="item.id"> <el-card shadow="hover" :body-style="{ padding: '0px'}" class="server-card"> - <div class="card-img-zlm"></div> + <div v-if="item.type === 'zlm'" class="card-img-zlm"></div> + <div v-if="item.type === 'abl'" class="card-img-abl"></div> <div style="padding: 14px;text-align: left"> <span style="font-size: 16px">{{item.id}}</span> <el-button v-if="!item.defaultServer" icon="el-icon-edit" style="padding: 0;float: right;" type="text" @click="edit(item)">缂栬緫</el-button> @@ -154,6 +155,13 @@ background-size: contain; margin: 0 auto; } + .card-img-abl{ + width: 200px; height: 200px; + background: url('~@static/images/abl-logo.jpg') no-repeat center; + background-position: center; + background-size: contain; + margin: 0 auto; + } .server-card-status-online{ position: absolute; right: 20px; diff --git a/web_src/src/components/dialog/MediaServerEdit.vue b/web_src/src/components/dialog/MediaServerEdit.vue index 9808a1c..9d8491e 100755 --- a/web_src/src/components/dialog/MediaServerEdit.vue +++ b/web_src/src/components/dialog/MediaServerEdit.vue @@ -20,6 +20,12 @@ <el-form-item label="SECRET" prop="secret"> <el-input v-model="mediaServerForm.secret" placeholder="濯掍綋鏈嶅姟SECRET" clearable :disabled="mediaServerForm.defaultServer"></el-input> </el-form-item> + <el-form-item label="绫诲瀷" prop="type"> + <el-select v-model="mediaServerForm.type" style="float: left; width: 100%" > + <el-option key="zlm" label="ZLMediaKit" value="zlm"></el-option> + <el-option key="abl" label="ABLMediaServer" value="abl"></el-option> + </el-select> + </el-form-item> <el-form-item> <div style="float: right;"> <el-button type="primary" v-if="currentStep === 1 && serverCheck === 1" @click="next" >涓嬩竴姝�</el-button> @@ -170,7 +176,7 @@ hookIp: "", sdpIp: "", streamIp: "", - secret: "035c73f7-bb6b-4889-a715-d9eb2d1925cc", + secret: "", httpPort: "", httpSSlPort: "", recordAssistPort: "", @@ -182,6 +188,7 @@ rtpProxyPort: "", rtspPort: "", rtspSSLPort: "", + type: "zlm", }, rtpPortRange1:30000, rtpPortRange2:30500, @@ -330,7 +337,7 @@ hookIp: "", sdpIp: "", streamIp: "", - secret: "035c73f7-bb6b-4889-a715-d9eb2d1925cc", + secret: "", httpPort: "", httpSSlPort: "", recordAssistPort: "", diff --git a/web_src/src/components/service/MediaServer.js b/web_src/src/components/service/MediaServer.js index d4446f0..b049537 100755 --- a/web_src/src/components/service/MediaServer.js +++ b/web_src/src/components/service/MediaServer.js @@ -45,7 +45,8 @@ params: { ip: param.ip, port: param.httpPort, - secret: param.secret + secret: param.secret, + type: param.type } }).then(function (res) { if (typeof (callback) == "function") callback(res.data) diff --git a/web_src/static/images/abl-logo.jpg b/web_src/static/images/abl-logo.jpg new file mode 100644 index 0000000..82a564d --- /dev/null +++ b/web_src/static/images/abl-logo.jpg Binary files differ diff --git "a/\346\225\260\346\215\256\345\272\223/\345\210\235\345\247\213\345\214\226-mysql.sql" "b/\346\225\260\346\215\256\345\272\223/2.7.1/\345\210\235\345\247\213\345\214\226-mysql-2.7.0.sql" similarity index 97% rename from "\346\225\260\346\215\256\345\272\223/\345\210\235\345\247\213\345\214\226-mysql.sql" rename to "\346\225\260\346\215\256\345\272\223/2.7.1/\345\210\235\345\247\213\345\214\226-mysql-2.7.0.sql" index f3247c1..cf614d9 100644 --- "a/\346\225\260\346\215\256\345\272\223/\345\210\235\345\247\213\345\214\226-mysql.sql" +++ "b/\346\225\260\346\215\256\345\272\223/2.7.1/\345\210\235\345\247\213\345\214\226-mysql-2.7.0.sql" @@ -155,8 +155,13 @@ rtp_proxy_port integer, rtsp_port integer, rtsp_ssl_port integer, + flv_port integer, + flv_ssl_port integer, + ws_flv_port integer, + ws_flv_ssl_port integer, auto_config bool default false, secret character varying(50), + type character varying(50) default 'zlm', rtp_enable bool default false, rtp_port_range character varying(50), send_rtp_port_range character varying(50), @@ -198,6 +203,7 @@ update_time character varying(50), as_message_channel bool default false, auto_push_channel bool default false, + send_stream_ip character varying(50), constraint uk_platform_unique_server_gb_id unique (server_gb_id) ); diff --git "a/\346\225\260\346\215\256\345\272\223/\345\210\235\345\247\213\345\214\226-postgresql-kingbase.sql" "b/\346\225\260\346\215\256\345\272\223/2.7.1/\345\210\235\345\247\213\345\214\226-postgresql-kingbase-2.7.0.sql" similarity index 97% rename from "\346\225\260\346\215\256\345\272\223/\345\210\235\345\247\213\345\214\226-postgresql-kingbase.sql" rename to "\346\225\260\346\215\256\345\272\223/2.7.1/\345\210\235\345\247\213\345\214\226-postgresql-kingbase-2.7.0.sql" index 17ef270..317e9e0 100644 --- "a/\346\225\260\346\215\256\345\272\223/\345\210\235\345\247\213\345\214\226-postgresql-kingbase.sql" +++ "b/\346\225\260\346\215\256\345\272\223/2.7.1/\345\210\235\345\247\213\345\214\226-postgresql-kingbase-2.7.0.sql" @@ -155,8 +155,13 @@ rtp_proxy_port integer, rtsp_port integer, rtsp_ssl_port integer, + flv_port integer, + flv_ssl_port integer, + ws_flv_port integer, + ws_flv_ssl_port integer, auto_config bool default false, secret character varying(50), + type character varying(50) default 'zlm', rtp_enable bool default false, rtp_port_range character varying(50), send_rtp_port_range character varying(50), @@ -198,6 +203,7 @@ update_time character varying(50), as_message_channel bool default false, auto_push_channel bool default false, + send_stream_ip character varying(50), constraint uk_platform_unique_server_gb_id unique (server_gb_id) ); diff --git "a/\346\225\260\346\215\256\345\272\223/2.7.1/\346\233\264\346\226\260-mysql-2.7.0.sql" "b/\346\225\260\346\215\256\345\272\223/2.7.1/\346\233\264\346\226\260-mysql-2.7.0.sql" new file mode 100644 index 0000000..9a527cb --- /dev/null +++ "b/\346\225\260\346\215\256\345\272\223/2.7.1/\346\233\264\346\226\260-mysql-2.7.0.sql" @@ -0,0 +1,11 @@ +alter table wvp_media_server + add type character varying(50) default 'zlm'; + +alter table wvp_media_server + add flv_port integer; +alter table wvp_media_server + add flv_ssl_port integer; +alter table wvp_media_server + add ws_flv_port integer; +alter table wvp_media_server + add ws_flv_ssl_port integer; \ No newline at end of file diff --git "a/\346\225\260\346\215\256\345\272\223/2.7.1/\346\233\264\346\226\260-postgresql-kingbase-2.7.0.sql" "b/\346\225\260\346\215\256\345\272\223/2.7.1/\346\233\264\346\226\260-postgresql-kingbase-2.7.0.sql" new file mode 100644 index 0000000..9a527cb --- /dev/null +++ "b/\346\225\260\346\215\256\345\272\223/2.7.1/\346\233\264\346\226\260-postgresql-kingbase-2.7.0.sql" @@ -0,0 +1,11 @@ +alter table wvp_media_server + add type character varying(50) default 'zlm'; + +alter table wvp_media_server + add flv_port integer; +alter table wvp_media_server + add flv_ssl_port integer; +alter table wvp_media_server + add ws_flv_port integer; +alter table wvp_media_server + add ws_flv_ssl_port integer; \ No newline at end of file -- Gitblit v1.8.0