From cb24ce13da8b97e9e524fae55cd3b5263e6722d6 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 17 Jul 2023 17:33:19 +0800 Subject: [PATCH 01/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E7=BC=BA=E5=B0=91?= =?UTF-8?q?=E7=9A=84sql=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sql/初始化.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/初始化.sql b/sql/初始化.sql index 7b8be660..95104006 100644 --- a/sql/初始化.sql +++ b/sql/初始化.sql @@ -285,6 +285,7 @@ CREATE TABLE `media_server` ( `secret` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `rtpEnable` int NOT NULL, `rtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, + `sendRtpPortRange` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, `recordAssistPort` int NOT NULL, `defaultServer` int NOT NULL, `createTime` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL, From 41d9c347bf648a49fc11fbd4c451298f164230ec Mon Sep 17 00:00:00 2001 From: tonyjianhua <575414312@qq.com> Date: Wed, 19 Jul 2023 13:33:53 +0800 Subject: [PATCH 02/10] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=8B=89=E6=B5=81?= =?UTF-8?q?=E4=BB=A3=E7=90=86=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/impl/StreamProxyServiceImpl.java | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) 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 a1c5b1c4..d699bbcd 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/StreamProxyServiceImpl.java @@ -161,25 +161,24 @@ public class StreamProxyServiceImpl implements IStreamProxyService { return; } - String talkKey = UUID.randomUUID().toString(); - dynamicTask.startCron(talkKey, ()->{ - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false); - if (streamInfo != null) { - callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); - } - }, 1000); - String delayTalkKey = UUID.randomUUID().toString(); - dynamicTask.startDelay(delayTalkKey, ()->{ - StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false); - if (streamInfo != null) { - callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); - }else { - dynamicTask.stop(talkKey); - callback.run(ErrorCode.ERROR100.getCode(), "超时", null); - } - }, 5000); - if (param.isEnable()) { + String talkKey = UUID.randomUUID().toString(); + dynamicTask.startCron(talkKey, ()->{ + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false); + if (streamInfo != null) { + callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); + } + }, 1000); + String delayTalkKey = UUID.randomUUID().toString(); + dynamicTask.startDelay(delayTalkKey, ()->{ + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStreamWithCheck(param.getApp(), param.getStream(), mediaInfo.getId(), false); + if (streamInfo != null) { + callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); + }else { + dynamicTask.stop(talkKey); + callback.run(ErrorCode.ERROR100.getCode(), "超时", null); + } + }, 5000); JSONObject jsonObject = addStreamProxyToZlm(param); if (jsonObject != null && jsonObject.getInteger("code") == 0) { dynamicTask.stop(talkKey); @@ -196,13 +195,16 @@ public class StreamProxyServiceImpl implements IStreamProxyService { } if (jsonObject == null){ callback.run(ErrorCode.ERROR100.getCode(), "记录已保存,启用失败", null); - return; }else { callback.run(ErrorCode.ERROR100.getCode(), jsonObject.getString("msg"), null); - return; } } } + else{ + StreamInfo streamInfo = mediaService.getStreamInfoByAppAndStream( + mediaInfo, param.getApp(), param.getStream(), null, null); + callback.run(ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg(), streamInfo); + } } private String getSchemaFromFFmpegCmd(String ffmpegCmd) { From 77d9da25c4cbd8fe9cf609b5795f704fb7927818 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Wed, 19 Jul 2023 20:48:15 +0800 Subject: [PATCH 03/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8DcivilCode=E5=88=A4?= =?UTF-8?q?=E6=96=AD=E9=94=99=E8=AF=AF=E5=AF=BC=E8=87=B4civilCode=E4=B8=A2?= =?UTF-8?q?=E5=A4=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java index a08231c8..8c96a8e8 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/utils/XmlUtil.java @@ -344,7 +344,7 @@ public class XmlUtil { if (!ObjectUtils.isEmpty(civilCode) && civilCode.length() <= 8 && NumberUtils.isParsable(civilCode) - && Integer.parseInt(civilCode)%2 == 0 + && civilCode.length()%2 == 0 ) { deviceChannel.setCivilCode(civilCode); } From a39ac45bcc7fbddbb578e0ab39fd109e30d214a4 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 20 Jul 2023 17:18:11 +0800 Subject: [PATCH 04/10] =?UTF-8?q?=E6=89=A9=E5=B1=95=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E6=8E=A5=E5=8F=A3=EF=BC=8C=E6=94=AF=E6=8C=81HTTPS=E6=8E=A5?= =?UTF-8?q?=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../request/impl/NotifyRequestForCatalogProcessor.java | 2 +- .../genersoft/iot/vmp/web/gb28181/ApiStreamController.java | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java index 90a58936..7a506282 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/transmit/event/request/impl/NotifyRequestForCatalogProcessor.java @@ -239,7 +239,7 @@ public class NotifyRequestForCatalogProcessor extends SIPRequestProcessorParent } private void executeSave(){ - System.out.println("定时存储数据"); + executeSaveForAdd(); executeSaveForUpdate(); executeSaveForDelete(); executeSaveForOnline(); 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 72a1b5da..8a1d079d 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 @@ -120,11 +120,17 @@ public class ApiStreamController { result.put("ChannelName", deviceChannel.getName()); result.put("ChannelCustomName", ""); result.put("FLV", streamInfo.getFlv().getUrl()); + result.put("HTTPS_FLV", streamInfo.getHttps_flv().getUrl()); result.put("WS_FLV", streamInfo.getWs_flv().getUrl()); + result.put("WSS_FLV", streamInfo.getWss_flv().getUrl()); result.put("RTMP", streamInfo.getRtmp().getUrl()); + result.put("RTMPS", streamInfo.getRtmps().getUrl()); result.put("HLS", streamInfo.getHls().getUrl()); + result.put("HTTPS_HLS", streamInfo.getHttps_hls().getUrl()); result.put("RTSP", streamInfo.getRtsp().getUrl()); + result.put("RTSPS", streamInfo.getRtsps().getUrl()); result.put("WEBRTC", streamInfo.getRtc().getUrl()); + result.put("HTTPS_WEBRTC", streamInfo.getRtcs().getUrl()); result.put("CDN", ""); result.put("SnapURL", ""); result.put("Transport", device.getTransport()); From 48a1a247697b5c25d3803b1d228b6df11c3715bc Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 20 Jul 2023 17:29:36 +0800 Subject: [PATCH 05/10] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/all-application.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/all-application.yml b/src/main/resources/all-application.yml index 90cde6f1..ceaa82f7 100644 --- a/src/main/resources/all-application.yml +++ b/src/main/resources/all-application.yml @@ -128,6 +128,8 @@ media: enable: true # [可选] 在此范围内选择端口用于媒体流传输, 必须提前在zlm上配置该属性,不然自动配置此属性可能不成功 port-range: 30000,30500 # 端口范围 + # [可选] 国标级联在此范围内选择端口发送媒体流,请不要与收流端口范围重合 + send-port-range: 50502,50506 # 端口范围 # 录像辅助服务, 部署此服务可以实现zlm录像的管理与下载, 0 表示不使用 record-assist-port: 0 From bac9aca311dba1b8796c6166d6618462fc7aa3a5 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Thu, 20 Jul 2023 17:56:04 +0800 Subject: [PATCH 06/10] =?UTF-8?q?=E5=90=88=E5=B9=B6=E5=88=86=E6=94=AF?= =?UTF-8?q?=E6=96=B0=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vmp/web/gb28181/ApiStreamController.java | 126 ++++++++++-------- 1 file changed, 71 insertions(+), 55 deletions(-) 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 8a1d079d..39f6388f 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 @@ -1,7 +1,8 @@ package com.genersoft.iot.vmp.web.gb28181; import com.alibaba.fastjson2.JSONObject; -import com.genersoft.iot.vmp.common.StreamInfo; +import com.genersoft.iot.vmp.common.InviteInfo; +import com.genersoft.iot.vmp.common.InviteSessionType; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.exception.SsrcTransactionNotFoundException; import com.genersoft.iot.vmp.gb28181.bean.Device; @@ -9,13 +10,18 @@ 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.service.IDeviceService; +import com.genersoft.iot.vmp.service.IInviteStreamService; 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 org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; import javax.sip.InvalidArgumentException; @@ -51,6 +57,9 @@ public class ApiStreamController { @Autowired private IPlayService playService; + @Autowired + private IInviteStreamService inviteStreamService; + /** * 实时直播 - 开始直播 * @param serial 设备编号 @@ -83,7 +92,7 @@ public class ApiStreamController { result.put("error","device[ " + serial + " ]未找到"); resultDeferredResult.setResult(result); return resultDeferredResult; - }else if (device.getOnline() == 0) { + }else if (device.isOnLine()) { JSONObject result = new JSONObject(); result.put("error","device[ " + code + " ]offline"); resultDeferredResult.setResult(result); @@ -104,59 +113,66 @@ public class ApiStreamController { result.put("error","channel[ " + code + " ]未找到"); resultDeferredResult.setResult(result); return resultDeferredResult; - }else if (deviceChannel.getStatus() == 0) { + }else if (!deviceChannel.isStatus()) { JSONObject result = new JSONObject(); result.put("error","channel[ " + code + " ]offline"); resultDeferredResult.setResult(result); return resultDeferredResult; } MediaServerItem newMediaServerItem = playService.getNewMediaServerItem(device); - playService.play(newMediaServerItem, serial, code, (mediaServerItem, response)->{ - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code); - JSONObject result = new JSONObject(); - result.put("StreamID", streamInfo.getStream()); - result.put("DeviceID", device.getDeviceId()); - result.put("ChannelID", code); - result.put("ChannelName", deviceChannel.getName()); - result.put("ChannelCustomName", ""); - result.put("FLV", streamInfo.getFlv().getUrl()); - result.put("HTTPS_FLV", streamInfo.getHttps_flv().getUrl()); - result.put("WS_FLV", streamInfo.getWs_flv().getUrl()); - result.put("WSS_FLV", streamInfo.getWss_flv().getUrl()); - result.put("RTMP", streamInfo.getRtmp().getUrl()); - result.put("RTMPS", streamInfo.getRtmps().getUrl()); - result.put("HLS", streamInfo.getHls().getUrl()); - result.put("HTTPS_HLS", streamInfo.getHttps_hls().getUrl()); - result.put("RTSP", streamInfo.getRtsp().getUrl()); - result.put("RTSPS", streamInfo.getRtsps().getUrl()); - result.put("WEBRTC", streamInfo.getRtc().getUrl()); - result.put("HTTPS_WEBRTC", streamInfo.getRtcs().getUrl()); - result.put("CDN", ""); - result.put("SnapURL", ""); - result.put("Transport", device.getTransport()); - result.put("StartAt", ""); - result.put("Duration", ""); - result.put("SourceVideoCodecName", ""); - result.put("SourceVideoWidth", ""); - result.put("SourceVideoHeight", ""); - result.put("SourceVideoFrameRate", ""); - result.put("SourceAudioCodecName", ""); - result.put("SourceAudioSampleRate", ""); - result.put("AudioEnable", ""); - result.put("Ondemand", ""); - result.put("InBytes", ""); - result.put("InBitRate", ""); - result.put("OutBytes", ""); - result.put("NumOutputs", ""); - result.put("CascadeSize", ""); - result.put("RelaySize", ""); - result.put("ChannelPTZType", "0"); - resultDeferredResult.setResult(result); - }, (eventResult) -> { - JSONObject result = new JSONObject(); - result.put("error", "channel[ " + code + " ] " + eventResult.msg); - resultDeferredResult.setResult(result); - }, null); + + + playService.play(newMediaServerItem, serial, code, null, (errorCode, msg, data) -> { + if (errorCode == InviteErrorCode.SUCCESS.getCode()) { + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, serial, code); + if (inviteInfo != null && inviteInfo.getStreamInfo() != null) { + JSONObject result = new JSONObject(); + result.put("StreamID", inviteInfo.getStreamInfo().getStream()); + result.put("DeviceID", device.getDeviceId()); + result.put("ChannelID", code); + result.put("ChannelName", deviceChannel.getName()); + result.put("ChannelCustomName", ""); + result.put("FLV", inviteInfo.getStreamInfo().getFlv().getUrl()); + result.put("HTTPS_FLV", inviteInfo.getStreamInfo().getHttps_flv().getUrl()); + result.put("WS_FLV", inviteInfo.getStreamInfo().getWs_flv().getUrl()); + result.put("WSS_FLV", inviteInfo.getStreamInfo().getWss_flv().getUrl()); + result.put("RTMP", inviteInfo.getStreamInfo().getRtmp().getUrl()); + result.put("RTMPS", inviteInfo.getStreamInfo().getRtmps().getUrl()); + result.put("HLS", inviteInfo.getStreamInfo().getHls().getUrl()); + result.put("HTTPS_HLS", inviteInfo.getStreamInfo().getHttps_hls().getUrl()); + result.put("RTSP", inviteInfo.getStreamInfo().getRtsp().getUrl()); + result.put("RTSPS", inviteInfo.getStreamInfo().getRtsps().getUrl()); + result.put("WEBRTC", inviteInfo.getStreamInfo().getRtc().getUrl()); + result.put("HTTPS_WEBRTC", inviteInfo.getStreamInfo().getRtcs().getUrl()); + result.put("CDN", ""); + result.put("SnapURL", ""); + result.put("Transport", device.getTransport()); + result.put("StartAt", ""); + result.put("Duration", ""); + result.put("SourceVideoCodecName", ""); + result.put("SourceVideoWidth", ""); + result.put("SourceVideoHeight", ""); + result.put("SourceVideoFrameRate", ""); + result.put("SourceAudioCodecName", ""); + result.put("SourceAudioSampleRate", ""); + result.put("AudioEnable", ""); + result.put("Ondemand", ""); + result.put("InBytes", ""); + result.put("InBitRate", ""); + result.put("OutBytes", ""); + result.put("NumOutputs", ""); + result.put("CascadeSize", ""); + result.put("RelaySize", ""); + result.put("ChannelPTZType", "0"); + resultDeferredResult.setResult(result); + } + }else { + JSONObject result = new JSONObject(); + result.put("error", "channel[ " + code + " ] " + msg); + resultDeferredResult.setResult(result); + } + }); + return resultDeferredResult; } @@ -177,8 +193,8 @@ public class ApiStreamController { ){ - StreamInfo streamInfo = redisCatchStorage.queryPlayByDevice(serial, code); - if (streamInfo == null) { + InviteInfo inviteInfo = inviteStreamService.getInviteInfoByDeviceAndChannel(InviteSessionType.PLAY, serial, code); + if (inviteInfo == null) { JSONObject result = new JSONObject(); result.put("error","未找到流信息"); return result; @@ -190,14 +206,14 @@ public class ApiStreamController { return result; } try { - cmder.streamByeCmd(device, code, streamInfo.getStream(), null); + cmder.streamByeCmd(device, code, inviteInfo.getStream(), null); } catch (InvalidArgumentException | ParseException | SipException | SsrcTransactionNotFoundException e) { JSONObject result = new JSONObject(); result.put("error","发送BYE失败:" + e.getMessage()); return result; } - redisCatchStorage.stopPlay(streamInfo); - storager.stopPlay(streamInfo.getDeviceID(), streamInfo.getChannelId()); + inviteStreamService.removeInviteInfo(inviteInfo); + storager.stopPlay(inviteInfo.getDeviceId(), inviteInfo.getChannelId()); return null; } From 7d7528cc275aec9962afd8ee38e6aaaa25b4392c Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 21 Jul 2023 15:55:49 +0800 Subject: [PATCH 07/10] =?UTF-8?q?=E6=9B=B4=E6=96=B0readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 10cd12a2..bbe44d2d 100644 --- a/README.md +++ b/README.md @@ -107,6 +107,10 @@ https://gitee.com/pan648540858/wvp-GB28181-pro.git - [X] 支持Mysql,Postgresql,金仓等数据库 - [X] 支持Onvif(目前在onvif分支,需要安装onvif服务,服务请在知识星球获取) +# 非开源的内容 +- [X] ONVIF设备的接入,支持点播,云台控制,国标级联点播,自动点播。在[知识星球](https://t.zsxq.com/10WAnH2MP)放了试用安装包以及使用教程,没有使用时间限制,需要源码可以星球私信我或者邮箱联系。 + + # 授权协议 本项目自有代码使用宽松的MIT协议,在保留版权信息的情况下可以自由应用于各自商用、非商业的项目。 但是本项目也零碎的使用了一些其他的开源代码,在商用的情况下请自行替代或剔除; 由于使用本项目而产生的商业纠纷或侵权行为一概与本项目及开发者无关,请自行承担法律风险。 在使用本项目代码时,也应该在授权协议中同时表明本项目依赖的第三方库的协议 From 97fef952ee4206ccce4d37b7a0ef9d12dcaa12ec Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 21 Jul 2023 19:57:49 +0800 Subject: [PATCH 08/10] =?UTF-8?q?=E4=BC=98=E5=8C=96sip=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E6=A0=88=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java | 2 +- .../com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index 90b5291e..f8e86778 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -63,7 +63,7 @@ public class SipLayer implements CommandLineRunner { private void addListeningPoint(String monitorIp, int port){ SipStackImpl sipStack; try { - sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties(monitorIp, userSetting.getSipLog())); + sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties( userSetting.getSipLog())); sipStack.setMessageParserFactory(new GbStringMsgParserFactory()); } catch (PeerUnavailableException e) { logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java index 7e355e54..ac2f5479 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java @@ -12,10 +12,10 @@ import java.util.Properties; */ public class DefaultProperties { - public static Properties getProperties(String ip, boolean sipLog) { + public static Properties getProperties(boolean sipLog) { Properties properties = new Properties(); properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); - properties.setProperty("javax.sip.IP_ADDRESS", ip); +// properties.setProperty("javax.sip.IP_ADDRESS", ip); // 关闭自动会话 properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); /** From 0cb68938b82953fc07a8ae37a59fa18974dd3642 Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Fri, 21 Jul 2023 20:01:01 +0800 Subject: [PATCH 09/10] =?UTF-8?q?=E4=BC=98=E5=8C=96sip=E5=8D=8F=E8=AE=AE?= =?UTF-8?q?=E6=A0=88=E8=B0=83=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java | 2 +- .../com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java index f8e86778..0c77fc18 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/SipLayer.java @@ -63,7 +63,7 @@ public class SipLayer implements CommandLineRunner { private void addListeningPoint(String monitorIp, int port){ SipStackImpl sipStack; try { - sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties( userSetting.getSipLog())); + sipStack = (SipStackImpl)SipFactory.getInstance().createSipStack(DefaultProperties.getProperties("GB28181_SIP", userSetting.getSipLog())); sipStack.setMessageParserFactory(new GbStringMsgParserFactory()); } catch (PeerUnavailableException e) { logger.error("[SIP SERVER] SIP服务启动失败, 监听地址{}失败,请检查ip是否正确", monitorIp); diff --git a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java index ac2f5479..e2c9ef58 100644 --- a/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java +++ b/src/main/java/com/genersoft/iot/vmp/gb28181/conf/DefaultProperties.java @@ -12,9 +12,9 @@ import java.util.Properties; */ public class DefaultProperties { - public static Properties getProperties(boolean sipLog) { + public static Properties getProperties(String name, boolean sipLog) { Properties properties = new Properties(); - properties.setProperty("javax.sip.STACK_NAME", "GB28181_SIP"); + properties.setProperty("javax.sip.STACK_NAME", name); // properties.setProperty("javax.sip.IP_ADDRESS", ip); // 关闭自动会话 properties.setProperty("javax.sip.AUTOMATIC_DIALOG_SUPPORT", "off"); From d48f89eee40c58b2f0b69aaf4d7fab469dc4657b Mon Sep 17 00:00:00 2001 From: 648540858 <648540858@qq.com> Date: Mon, 24 Jul 2023 09:04:47 +0800 Subject: [PATCH 10/10] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E7=AB=AF=E5=8F=A3?= =?UTF-8?q?=E5=88=86=E9=85=8D=E7=9A=84=E5=B9=B6=E5=8F=91=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../iot/vmp/common/CommonGbChannel.java | 191 ++++++++++++++++++ .../iot/vmp/media/zlm/SendRtpPortManager.java | 93 +++++---- .../iot/vmp/media/zlm/ZLMServerFactory.java | 4 +- .../media/zlm/dto/MediaSendRtpPortInfo.java | 50 ----- .../service/impl/MediaServerServiceImpl.java | 28 --- .../iot/vmp/service/impl/PlayServiceImpl.java | 2 +- .../iot/vmp/vmanager/rtp/RtpController.java | 4 +- .../vmp/vmanager/server/ServerController.java | 12 ++ 8 files changed, 265 insertions(+), 119 deletions(-) create mode 100644 src/main/java/com/genersoft/iot/vmp/common/CommonGbChannel.java delete mode 100644 src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaSendRtpPortInfo.java diff --git a/src/main/java/com/genersoft/iot/vmp/common/CommonGbChannel.java b/src/main/java/com/genersoft/iot/vmp/common/CommonGbChannel.java new file mode 100644 index 00000000..b289a14a --- /dev/null +++ b/src/main/java/com/genersoft/iot/vmp/common/CommonGbChannel.java @@ -0,0 +1,191 @@ +package com.genersoft.iot.vmp.common; + +import io.swagger.v3.oas.annotations.media.Schema; + +public class CommonGbChannel { + + /** + * 国标字段:归属 + */ + @Schema(description = "归属") + private String owner; + + /** + * 国标字段:行政区划 + */ + @Schema(description = "行政区划") + private String civilCode; + + /** + * 国标字段:安装地址 + */ + @Schema(description = "安装地址") + private String address; + + /** + * 国标字段:经度 + */ + @Schema(description = "经度") + private Double longitude; + + /** + * 国标字段:纬度 + */ + @Schema(description = "纬度") + private Double latitude; + + /** + * 国标字段:摄像机类型: + * 1-球机; + * 2-半球; + * 3-固定枪机; + * 4-遥控枪机 + */ + @Schema(description = "摄像机类型") + private Integer ptzType; + + /** + * 国标字段:摄像机位置类型扩展。 + * 1-省际检查站、 + * 2-党政机关、 + * 3-车站码头、 + * 4-中心广场、 + * 5-体育场馆、 + * 6-商业中心、 + * 7-宗教场所、 + * 8-校园周边、 + * 9-治安复杂区域、 + * 10-交通干线 + */ + @Schema(description = "摄像机位置类型扩展") + private Integer positionType; + + /** + * 国标字段:安装位置室外、室内属性 + * 1-室外、 + * 2-室内 + */ + @Schema(description = "安装位置室外、室内属性") + private Integer roomType; + + /** + * 国标字段:用途 + * 1-治安、 + * 2-交通、 + * 3-重点、 + */ + @Schema(description = "用途") + private Integer useType; + + /** + * 国标字段:补光属性 + * 1-无补光、 + * 2-红外补光、 + * 3-白光补光 + */ + @Schema(description = "补光属性") + private Integer supplyLightType; + + /** + * 摄像机监视方位属性。 + * 1-东、 + * 2-西、 + * 3-南、 + * 4-北、 + * 5-东南、 + * 6-东北、 + * 7-西南、 + * 8-西北 + * + */ + @Schema(description = "方位") + private Integer directionType; + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public String getCivilCode() { + return civilCode; + } + + public void setCivilCode(String civilCode) { + this.civilCode = civilCode; + } + + public String getAddress() { + return address; + } + + public void setAddress(String address) { + this.address = address; + } + + public Double getLongitude() { + return longitude; + } + + public void setLongitude(Double longitude) { + this.longitude = longitude; + } + + public Double getLatitude() { + return latitude; + } + + public void setLatitude(Double latitude) { + this.latitude = latitude; + } + + public Integer getPtzType() { + return ptzType; + } + + public void setPtzType(Integer ptzType) { + this.ptzType = ptzType; + } + + public Integer getPositionType() { + return positionType; + } + + public void setPositionType(Integer positionType) { + this.positionType = positionType; + } + + public Integer getRoomType() { + return roomType; + } + + public void setRoomType(Integer roomType) { + this.roomType = roomType; + } + + public Integer getUseType() { + return useType; + } + + public void setUseType(Integer useType) { + this.useType = useType; + } + + public Integer getSupplyLightType() { + return supplyLightType; + } + + public void setSupplyLightType(Integer supplyLightType) { + this.supplyLightType = supplyLightType; + } + + public Integer getDirectionType() { + return directionType; + } + + public void setDirectionType(Integer directionType) { + this.directionType = directionType; + } +} 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 893e52a0..f960c7dc 100644 --- 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,12 +3,14 @@ package com.genersoft.iot.vmp.media.zlm; 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.MediaSendRtpPortInfo; +import com.genersoft.iot.vmp.media.zlm.dto.MediaServerItem; import com.genersoft.iot.vmp.utils.redis.RedisUtil; +import org.apache.commons.lang3.math.NumberUtils; 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.data.redis.support.atomic.RedisAtomicInteger; import org.springframework.stereotype.Component; import java.util.HashMap; @@ -26,23 +28,14 @@ public class SendRtpPortManager { @Autowired private RedisTemplate redisTemplate; - private final String KEY = "VM_MEDIA_SEND_RTP_PORT_RANGE_"; + private final String KEY = "VM_MEDIA_SEND_RTP_PORT_"; - - public void initServerPort(String mediaServerId, int startPort, int endPort){ - String key = KEY + userSetting.getServerId() + "_" + mediaServerId; - MediaSendRtpPortInfo mediaSendRtpPortInfo = new MediaSendRtpPortInfo(startPort, endPort, mediaServerId); - redisTemplate.opsForValue().set(key, mediaSendRtpPortInfo); - } - - public int getNextPort(String mediaServerId) { - String sendIndexKey = KEY + userSetting.getServerId() + "_" + mediaServerId; - MediaSendRtpPortInfo mediaSendRtpPortInfo = (MediaSendRtpPortInfo)redisTemplate.opsForValue().get(sendIndexKey); - if (mediaSendRtpPortInfo == null) { - logger.warn("[发送端口管理] 获取{}的发送端口时未找到端口信息", mediaServerId); - return 0; + public int getNextPort(MediaServerItem mediaServer) { + if (mediaServer == null) { + logger.warn("[发送端口管理] 参数错误,mediaServer为NULL"); + return -1; } - + String sendIndexKey = KEY + userSetting.getServerId() + "_" + mediaServer.getId(); String key = VideoManagerConstants.PLATFORM_SEND_RTP_INFO_PREFIX + userSetting.getServerId() + "_*"; List queryResult = RedisUtil.scan(redisTemplate, key); @@ -54,14 +47,39 @@ public class SendRtpPortManager { sendRtpItemMap.put(sendRtpItem.getLocalPort(), sendRtpItem); } } + String sendRtpPortRange = mediaServer.getSendRtpPortRange(); + int startPort; + int endPort; + if (sendRtpPortRange == null) { + logger.warn("{}未设置发送端口默认值,自动使用40000-50000作为端口范围", mediaServer.getId()); + String[] portArray = sendRtpPortRange.split(","); + if (portArray.length != 2 || !NumberUtils.isParsable(portArray[0]) || !NumberUtils.isParsable(portArray[1])) { + logger.warn("{}发送端口配置格式错误,自动使用40000-50000作为端口范围", mediaServer.getId()); + startPort = 50000; + endPort = 60000; + }else { - int port = getPort(mediaSendRtpPortInfo.getCurrent(), - mediaSendRtpPortInfo.getStart(), - mediaSendRtpPortInfo.getEnd(), checkPort -> sendRtpItemMap.get(checkPort) == null); - - mediaSendRtpPortInfo.setCurrent(port); - redisTemplate.opsForValue().set(sendIndexKey, mediaSendRtpPortInfo); - return port; + if ( Integer.parseInt(portArray[1]) - Integer.parseInt(portArray[0]) < 1) { + logger.warn("{}发送端口配置错误,结束端口至少比开始端口大一,自动使用40000-50000作为端口范围", mediaServer.getId()); + startPort = 50000; + endPort = 60000; + }else { + startPort = Integer.parseInt(portArray[0]); + endPort = Integer.parseInt(portArray[1]); + } + } + }else { + startPort = 50000; + endPort = 60000; + } + if (redisTemplate == null || redisTemplate.getConnectionFactory() == null) { + logger.warn("{}获取redis连接信息失败", mediaServer.getId()); + return -1; + } + RedisAtomicInteger redisAtomicInteger = new RedisAtomicInteger(sendIndexKey , redisTemplate.getConnectionFactory()); + return redisAtomicInteger.getAndUpdate((current)->{ + return getPort(current, startPort, endPort, checkPort-> !sendRtpItemMap.containsKey(checkPort)); + }); } interface CheckPortCallback{ @@ -69,22 +87,25 @@ public class SendRtpPortManager { } private int getPort(int current, int start, int end, CheckPortCallback checkPortCallback) { - int port; - if (current %2 != 0) { - port = current + 1; - }else { - port = current + 2; - } - if (port > end) { - if (start %2 != 0) { - port = start + 1; + if (current <= 0) { + if (start%2 == 0) { + current = start; }else { - port = start; + current = start + 1; + } + }else { + current += 2; + if (current > end) { + if (start%2 == 0) { + current = start; + }else { + current = start + 1; + } } } - if (!checkPortCallback.check(port)) { - return getPort(port, start, end, checkPortCallback); + if (!checkPortCallback.check(current)) { + return getPort(current + 2, start, end, checkPortCallback); } - return port; + return current; } } 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 7fe92ae3..34acf152 100644 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java +++ b/src/main/java/com/genersoft/iot/vmp/media/zlm/ZLMServerFactory.java @@ -167,7 +167,7 @@ public class ZLMServerFactory { // 默认为随机端口 int localPort = 0; if (userSetting.getGbSendStreamStrict()) { - localPort = sendRtpPortManager.getNextPort(serverItem.getId()); + localPort = sendRtpPortManager.getNextPort(serverItem); if (localPort == 0) { return null; } @@ -203,7 +203,7 @@ public class ZLMServerFactory { // 默认为随机端口 int localPort = 0; if (userSetting.getGbSendStreamStrict()) { - localPort = sendRtpPortManager.getNextPort(serverItem.getId()); + localPort = sendRtpPortManager.getNextPort(serverItem); if (localPort == 0) { return null; } diff --git a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaSendRtpPortInfo.java b/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaSendRtpPortInfo.java deleted file mode 100644 index 2e9f6317..00000000 --- a/src/main/java/com/genersoft/iot/vmp/media/zlm/dto/MediaSendRtpPortInfo.java +++ /dev/null @@ -1,50 +0,0 @@ -package com.genersoft.iot.vmp.media.zlm.dto; - -public class MediaSendRtpPortInfo { - - private int start; - private int end; - private String mediaServerId; - - private int current; - - - public MediaSendRtpPortInfo(int start, int end, String mediaServerId) { - this.start = start; - this.current = start; - this.end = end; - this.mediaServerId = mediaServerId; - } - - public int getStart() { - return start; - } - - public void setStart(int start) { - this.start = start; - } - - public int getEnd() { - return end; - } - - public void setEnd(int end) { - this.end = end; - } - - public String getMediaServerId() { - return mediaServerId; - } - - public void setMediaServerId(String mediaServerId) { - this.mediaServerId = mediaServerId; - } - - public int getCurrent() { - return current; - } - - public void setCurrent(int current) { - this.current = current; - } -} 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 index a79b4108..142b8100 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/MediaServerServiceImpl.java @@ -119,34 +119,6 @@ public class MediaServerServiceImpl implements IMediaServerService { if (ssrcFactory.hasMediaServerSSRC(mediaServerItem.getId())) { ssrcFactory.initMediaServerSSRC(mediaServerItem.getId(), null); } - if (userSetting.getGbSendStreamStrict()) { - int startPort = 50000; - int endPort = 60000; - String sendRtpPortRange = mediaServerItem.getSendRtpPortRange(); - if (sendRtpPortRange == null) { - logger.warn("[zlm] ] 未配置发流端口范围,默认使用50000到60000"); - }else { - String[] sendRtpPortRangeArray = sendRtpPortRange.trim().split(","); - if (sendRtpPortRangeArray.length != 2) { - logger.warn("[zlm] ] 发流端口范围错误,默认使用50000到60000"); - }else { - try { - startPort = Integer.parseInt(sendRtpPortRangeArray[0]); - endPort = Integer.parseInt(sendRtpPortRangeArray[1]); - if (endPort <= startPort) { - logger.warn("[zlm] ] 发流端口范围错误,结束端口应大于开始端口,使用默认端口"); - startPort = 50000; - endPort = 60000; - } - - }catch (NumberFormatException e) { - logger.warn("[zlm] ] 发流端口范围错误,默认使用50000到60000"); - } - } - } - logger.info("[[zlm] ] 配置发流端口范围,{}-{}", startPort, endPort); - sendRtpPortManager.initServerPort(mediaServerItem.getId(), startPort, endPort); - } // 查询redis是否存在此mediaServer String key = VideoManagerConstants.MEDIA_SERVER_PREFIX + userSetting.getServerId() + "_" + mediaServerItem.getId(); Boolean hasKey = redisTemplate.hasKey(key); 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 e0494bcf..4f487ad9 100644 --- a/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java +++ b/src/main/java/com/genersoft/iot/vmp/service/impl/PlayServiceImpl.java @@ -269,7 +269,7 @@ public class PlayServiceImpl implements IPlayService { InviteErrorCode.SUCCESS.getCode(), InviteErrorCode.SUCCESS.getMsg(), streamInfo); - logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), + logger.info("[点播成功] deviceId: {}, channelId:{}, 码流类型:{}", device.getDeviceId(), channelId, device.isSwitchPrimarySubStream() ? "辅码流" : "主码流"); snapOnPlay(mediaServerItemInuse, device.getDeviceId(), channelId, ssrcInfo.getStream()); }, (event) -> { 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 513e940f..638ed3ff 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/rtp/RtpController.java @@ -139,8 +139,8 @@ public class RtpController { redisTemplate.opsForValue().set(receiveKey, otherRtpSendInfo); if (isSend != null && isSend) { // 预创建发流信息 - int portForVideo = sendRtpPortManager.getNextPort(mediaServerItem.getId()); - int portForAudio = sendRtpPortManager.getNextPort(mediaServerItem.getId()); + int portForVideo = sendRtpPortManager.getNextPort(mediaServerItem); + int portForAudio = sendRtpPortManager.getNextPort(mediaServerItem); otherRtpSendInfo.setSendLocalIp(mediaServerItem.getSdpIp()); otherRtpSendInfo.setSendLocalPortForVideo(portForVideo); 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 bef7ffb9..f4bcb1a9 100644 --- a/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java +++ b/src/main/java/com/genersoft/iot/vmp/vmanager/server/ServerController.java @@ -8,6 +8,7 @@ import com.genersoft.iot.vmp.conf.SipConfig; import com.genersoft.iot.vmp.conf.UserSetting; import com.genersoft.iot.vmp.conf.VersionInfo; import com.genersoft.iot.vmp.conf.exception.ControllerException; +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; @@ -72,6 +73,9 @@ public class ServerController { @Autowired private IRedisCatchStorage redisCatchStorage; + @Autowired + private SendRtpPortManager sendRtpPortManager; + @GetMapping(value = "/media_server/list") @ResponseBody @@ -262,4 +266,12 @@ public class ServerController { return result; } + + @PostMapping(value = "/test/getPort") + @ResponseBody + public int getPort() { + int result = sendRtpPortManager.getNextPort(mediaServerService.getDefaultMediaServer()); + System.out.println(result); + return result; + } }